什麼樣的人適合做程式設計師?

ThoughtWorks發表於2016-07-18

本文的起源是因為思考一個問題:什麼樣的人適合做程式設計師?

我曾經苦苦思索這個問題,直到我在SICP上看到了答案。說的白話一點就是,能像機器一樣思考的人就適合做程式設計師。 那麼“計算機”這臺機器是怎麼思考的呢?這裡是我的答案:

什麼樣的人適合做程式設計師?

我們所有的計算機,都可以用下面這個模型來表示,江湖人稱“馮・諾伊曼體系”。

從這個模型上我們看到了什麼嗎?嗯,可能太多干擾了,看的不夠清楚,我給你們再抽象一層:

什麼樣的人適合做程式設計師?

現在清楚了吧?計算機在中間,兩邊是輸入輸出。所有的問題都從輸入和輸出的角度去思考,這就是“計算機”這臺機器的思考方式。也就是說你能做到這樣思考,你就會像機器一樣思考了。 很簡單吧?但是新的問題又產生了,處理自然要處理輸入、產生輸出了,輸入、輸出是些什麼呢?這就要在微觀層面理解機器是怎麼思考的,這一部分叫:機器在加工什麼?

SICP中又說了,“非形式的講,我們只在處理兩種東西,資料和過程,他們之間並沒有明確的區分。”先不管是否有明確區分,我們回看模型,中間處理的部分其實就是過程,輸入和輸出則是資料。(在馮諾伊曼體系裡,資料和過程被稱為資料和指令)那說到資料,我們有一門學科叫做資料結構,它很好的解釋了什麼是資料。我們還有物件導向、型別系統之類的知識,他們都能幫助我們更好的定義資料。

各位看官估計心裡犯嘀咕了,扯了這麼多,還是無法想象怎麼就算像機器一樣思考了。不急,下面我們拿幾個例子來學習一下。

我們來寫一個加法函式,接受兩個引數作為加數和被加數,返回一個和,這個太簡單了,幾乎任何一個程式設計師都可以在幾秒鐘內寫完。拆成機器的思維是什麼樣呢?

加法函式

大概就長這樣,輸入是a和b,輸出是一個結果,我們起名叫result。它到底表達了個啥樣的程式碼呢?大概長這樣(本文所有的程式碼都會採用javascript描述,但是不代表本文內容,只適合描述前端開發):

咦?result哪去了?在你呼叫的地方可能會有一行程式碼:var result = add(1,2); 這個表達方式不僅僅可以用來描述函式定義,還可以用來描述表示式。比如,如果我們把前面的輸入輸出思維描述改為加法表示式。你會發現這段描述“編譯”成程式碼大概長這樣:

所以不僅僅可以用來描述函式定義,還可以描述程式碼塊。

但是到這裡就結束了嗎?感覺好像對資料的表述不夠細緻啊。確實,我們忘了加型別了。不加型別這描述簡直萬靈丹啊,反正倆引數一個返回值的都能用,這不行,我們還得把型別加上看著才清楚點。加上型別就變成了這樣:

這看著就好多了,是不是比剛才更加理解上文所講的“像機器一樣思考”了呢?好吧,你可能會說,“這玩意有啥用啊,我有分析的這個空,我程式碼都寫完了啊。”不急,我們接著往後看。

剛才那個題目有點太簡單了,我們做一個稍微複雜的。比如下面這個:寫一個函式,可以選出一個由數字組成的集合當中所有的偶數的最大值。

這回一步做出來可能就有點難了,沒關係,我們可以分成兩步:

  1. 選出集合中的偶數
  2. 選出偶數中的最大值 這兩步呢,按照我們之前的格式寫一下,大概是下面這個樣子:

哎呀,突然發覺不知道該怎麼描述集合呢。Javascript裡就用陣列就好了,但是還是不知道怎麼描述陣列啊。這個其實很簡單,這不是一個由數字組成的陣列嗎?我們只要寫成[Number]就可以了。因為我們的一個好習慣是一個集合裡不要放兩種型別的元素,所以就這麼寫就好了。那麼加上去的話,大概就長這樣:

咦,第二步的evenArray沒有寫型別。嗯,因為evenArray是第一步的輸出,我就把它省了,相信大家也能看明白。 耐著性子看到這裡,你估計已經發現了,我還是沒有回答你“思維方式有什麼用”這個問題。我很想忽悠著你再做一道題,不過估計你堅持不完就會轉身離開了。那我們就這兩道題試著講一講。

第一道題,我們只是展示了這個思維,第二道題,我們才開始發揮出它的威力。儘管這道題也不復雜,但是思考過程還是展示了:

  1. 分解問題;
  2. 找到子問題之間的關聯(通過輸入、輸出關聯起來);
  3. 找到問題的邊界,明確假設與結果。

上述三點看著簡單,卻是思維清楚與否的關鍵。我們管這個能力叫Analytical Thinking。

思維清楚帶來的收益是什麼?這些步驟可以直接轉化為工作的任務列表,而且可測試。這樣分解出來的任務列表,完成效率是極高的。我們曾經做過實驗,按這個思路分解過問題的人,比沒有分解過的人效率要高3倍以上,而且前者只學了一週的程式設計。 一個完全不會寫程式的人,只要學會了這個思維,就可以開始程式設計之旅了,而且威力非常巨大。

聽起來好簡單啊,有那麼神嗎?不是程式設計的人都應該會嗎?然而並不是的,很多人思考程式設計這件事情是靠感覺的。 我前幾天面了40多個外包公司外派來的人,只有5個人,可以按照輸入輸出來對問題進行分解。所以我覺得我還是有必要寫點東西來講講這個。

除了對初學者有益之外,對Team Lead也是有益的。當你覺得你遇到的人沒sense的時候,你可以試著讓他們這麼表達一下程式。一般就會發現一些問題。

題外話-1:

我們像機器一樣思考,不就都變成機器了嗎?嗯,其實不是的。所謂我們像機器一樣思考,那機器這種思考方式又是從哪裡來的呢?機器的思考模型是一個叫“圖靈機”的計算模型,而圖靈機則是圖靈祖師爺模擬人思考而發明出來的。所以,其實不存在什麼像機器一樣思考,只不過是學會一種人類的思考方式而已。 考慮到圖靈只能以自己和自己周圍的天才科學家的作為人類的具體例項來抽象圖靈機,所以我們學習的其實不是什麼機器的思考方式,而是天才的思考方式,這篇文章其實應該叫《像天才一樣思考》。

題外話-2:

這個不就是程式導向程式設計嗎?如果你的思考僅僅停在這裡,那就是程式導向程式設計了。如果我們接著想下去,當資料複雜到一定程度的時候,我們會自然的引入封裝,於是物件導向誕生了。回到資料與過程不嚴格區分那半句,當我們試圖模糊資料和過程的界限,將過程像資料一樣納入輸入輸出的範疇,我們就走上了函數語言程式設計之路。

題外話-3:

有人覺得練習不夠嗎?請留言,如果感興趣的人多,我就加緊寫更多練習的解析。

相關文章