會做菜就會編程?一篇寫給從未編程過的人的入門教程

簡介: 編程沒有那麼難,會做菜就會編程。

平時工作之餘,很多螞蟻技術同學也樂於分享技術心得和經驗感悟,我們會不定期精選其中的優秀文章,分享給大家。

不少同學對於編程感到好奇,但一看到厚厚的教程就打退堂鼓,我就曾經被問過:“外行需要多長時間才能學會這玩意兒呀?”這個問題不知道該如何回答,因爲我並不認同“外行”這個詞。我始終認爲,在編程這件事情上,每個人都是內行,每個人也都是外行。

學會編程沒有你想象中的那麼複雜。

編程是什麼?

編程,說得簡單一點,就是通過一系列邏輯將你想做的事情或者想描述的物體表達清楚,然後讓它展現出來,或者運動起來。說得專業一點:

編程 = 算法 + 數據結構

什麼是算法?就是解決問題的辦法,或者說通過幾個步驟來解決一個問題的過程描述;那麼什麼是數據結構呢?咱們在解決問題的時候經常需要去放置一些物件,比如把書放到書架上,那麼書架就是一種數據結構,把書放到櫃子裏,櫃子就是一種數據結構,書架和櫃子就是數據的不同呈現/儲存方式。

其實,每個人對編程都不陌生,你進過廚房吧,17:00 回到家,怎麼讓家人在 18:30 之前喫上飯?這裏頭的算法就多了去了,你可以先煮上飯然後去買菜,也可以買完菜再回來煮飯,那麼哪種方式更好呢?下面我們用程序語言來分析這道題:

編程問題:17:00 回到家,怎麼讓家人在 18:30 之前喫上飯?
算法一:先煮上飯然後去買菜
算法二:買完菜再回來煮飯

這裏的做飯是一個程序實體,它包含了煮飯、買菜、切菜、做菜,這個程序實體的表達方式是:

做飯 = {
  煮飯() {},
  買菜() {},
  切菜() {},
  做菜() {},
}

把中文換成英文不就是你平時看到的程序代碼麼?所以說呀,編程對你其實並不陌生,它也沒你想象中的那麼複雜。

編程的核心是什麼?

爲什麼人跟人之間編寫出來的代碼有這麼大的差異,或者說,爲什麼存在小白和專家的區別?編程確實不復雜,複雜的原因是很多人不能把問題思考周全,我舉個例子你就知道了:

做飯 = {
  開始() {
    煮飯(); 買菜(); 切菜(); 做菜();
  },
  煮飯() {},
  買菜() {},
  切菜() {},
  做菜() {
    if (家裏沒有油了) { 買油(); 炒菜(); } 
    else { 炒菜(); }
  }
}

做飯->開始();

我們定義了一個程序實體叫做「做飯」,包含了幾個步驟,開始、煮飯、買菜、切菜和做菜,在編程語言裏頭,我們把「做飯」稱之爲對象,這幾個步驟稱之爲方法,「做飯」這個對象擁有 5 個方法,我們可以一個個地調用它。首先我們調用了「開始」方法,在這個方法裏,又依次調用了「煮飯」、「買菜」、「切菜」和「做菜」。

在「做菜」方法裏,我們看到了一個細節,那就是“家裏沒油了”,咋整,這個人是這麼考慮的:先去「買油」,然後回來「炒菜」。很顯然,這人不靠譜,你看,菜都要下鍋了,纔想起沒有油。但是下面這個人就不一樣了:

做飯 = {
  開始() {
    煮飯(); 
    檢查結果 = 檢查();
    買菜(檢查結果); 切菜(); 做菜();
  },
  檢查() {
    if (家裏沒有油了) { 買菜的時候要買油  } 
    if (家裏沒有辣椒了) { 買菜的時候要買辣椒  } 
  },
  煮飯() {},
  買菜() {},
  切菜() {},
  做菜() {},
}

做飯->開始();

他的程序裏多了個步驟叫做「檢查」,在出門買菜之前,先在家裏掃一眼,缺了什麼,用小本本記下來,然後「買菜」的時候,帶上這個小本本,這樣「買菜」就不會有遺漏了。

你看,這就是我們所謂的小白和專家,他們的區別就是後者能夠把事情想得更加周全,在解決問題的時候,不遺留任何細節,並且呢,能夠讓事情可以更流暢、更快、更好地得到解決,消耗的資源最少,解決的問題最多。

編程的複雜性

不要以爲我上面寫的東西不是代碼,稍微調整下細節,這串代碼是可以在電腦上真實跑起來的,是不是特別簡單啊?你還敢說自己不懂編程麼?還會懼怕編程麼?

但是也不要把編程想的太簡單了,上面的程序表達的只是一個十分粗略的做飯過程,或者說一個做飯的思路,真正要把做飯的程序實現出來,還要考慮很多的問題,比如如何在程序中表達我要做辣椒炒肉、紅燒獅子頭、剁椒魚頭等等好幾個菜呢?這裏就涉及到“抽象”的概念,我們需要把很多相似的步驟都抽象成一種行爲,然後不斷重複這種行爲:

做飯 = {
  開始(菜單) {
    煮飯();
    買菜(菜單);
    菜單->逐一(做菜);
  },
  買菜() {},
  煮飯() {},
  做菜(菜品) {
     洗菜(菜品);
     切菜(菜品);
     炒菜(菜品);
   }
}

菜單 = 辣椒炒肉、紅燒獅子頭、剁椒魚頭;
做飯->開始(菜單);

好了,上面的代碼相信也不是很難理解,我們把做飯分爲三個事情,「煮飯」、「買菜」和「做菜」,首先我們想好了一個“菜單”,然後抽象了一個「做菜」的方法,這個方法裏面包含了「洗菜」、「切菜」和「炒菜」三個步驟,每一道菜都會執行這三個步驟。

如果沒有這層抽象會有什麼問題?你會發現你的代碼是這麼寫的:

做飯 = {
  煮飯() {},
  買菜() {},
  洗菜() {},
  切菜() {},
  做菜() {},
}

做飯->煮飯();
做飯->買菜();

做飯->洗菜(辣椒炒肉);
做飯->切菜(辣椒炒肉);
做飯->炒菜(辣椒炒肉);

做飯->洗菜(紅燒獅子頭);
做飯->切菜(紅燒獅子頭);
做飯->炒菜(紅燒獅子頭);

做飯->洗菜(剁椒魚頭);
做飯->切菜(剁椒魚頭);
做飯->炒菜(剁椒魚頭);

代碼本身沒有什麼問題,但是看起來會十分冗長,如果你今天要做 10 個菜,那麼代碼就得寫 10 遍;可如果你用到了抽象思維,你就只需要去擴展“菜單”就行了,因爲在程序裏有一個叫做 「逐一」的邏輯。

程序裏面涉及到的邏輯並不多,諸如「條件判斷」、「循環」、「遍歷/逐一」等,很少,但是也就是這麼幾個少量的邏輯,構築了豐富多彩的網絡世界。

小結

好了,本文並不是想教會你如何編程,而是想告訴你,編程是一件十分簡單的事情,但是想寫出好的程序卻是一件無比有難度的事情,這需要你想出足夠好的算法,同時也需要你對程序的執行環境有基本的瞭解,知道怎麼寫程序跑的快、怎麼寫程序會很卡,等等。

當然,作爲程序員最苦惱的事情,並不是編程本身,而是需求的變化。比如當你做好了這頓飯,卻發現家人在外面喫過了,此時的你就只能含着淚,一個人喫完這桌難以下嚥的飯菜了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章