天天看點

會做菜就會程式設計?一篇寫給從未程式設計過的人的入門教程程式設計是什麼?程式設計的核心是什麼?程式設計的複雜性小結

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

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

學會程式設計沒有你想象中的那麼複雜。

程式設計是什麼?

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

程式設計 = 算法 + 資料結構
           

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

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

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

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

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

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

程式設計的核心是什麼?

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

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

做飯->開始();
           

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

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

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

做飯->開始();           

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

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

程式設計的複雜性

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

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

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

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

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

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

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

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

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

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

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

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

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

小結

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

當然,作為程式員最苦惱的事情,并不是程式設計本身,而是需求的變化。比如當你做好了這頓飯,卻發現家人在外面吃過了,此時的你就隻能含着淚,一個人吃完這桌難以下咽的飯菜了。

繼續閱讀