編程入門的第一課——建立編程思維

引子

寫這篇文章的起因源於我和我老婆的一次討論。上半年,她在學校里教Matlab。有一次我幫她解答一道上機的習題,大概用了50行代碼左右。在解釋完答案後,她就問我,「你一步一步是怎麼想的?我好像就沒有這種思維。」,這可把我問住了,因為那對我來說更接近於一種下意識的行動,很自然的就寫出來了。這個回答她自然不滿意了,那麼這種思維到底是什麼呢?

什麼是程序

先讓我們從什麼是程序談起。上大學時,估計大部分人都學過C語言,我清楚的記得譚浩強的那本書在開篇里提到,程序 = 數據結構 + 演算法。從專業角度上來說,這個定義真是絕了,但相信對很多剛接觸編程的人來說,會馬上問什麼是數據結構?演算法又是什麼呀? 所以在這裡,我們先提出一個的通俗的解釋。一個程序的作用就是接受輸入,進行處理,然後產生輸出,套用李笑來對寫作的定義,程序也可以定義為:

程序 = 輸入 + 處理 + 輸出。

其中的處理代表著一系列有條理的操作,即流程化

發現事物的流程

什麼是流程化?

以生活中的炒菜為例,食材是輸入,最後的菜品就是輸出。而下廚過程中的洗菜、切菜(預處理),然後下鍋、翻炒、調味進行加工(處理),最後出鍋、裝盤(後處理)就是這個處理的全過程。

如果這個例子讓你覺得離編程世界太遠了,下面我們再來分析下笑來老師多次提到過一個例子。他在寫第一本書《托福辭彙21天突破》時,是運用編程統計出了高頻單詞。按照我的理解,這個程序的輸入是歷年來的試卷的電子版,然後按照按照空格進行分詞,接著統計每個單詞出現的次數,排除常用的簡單辭彙,再把同一單詞的不同形式(比如,如果是動詞就有第三人稱,過去時,完成時等多種形式,如果是名詞,至少有單複數兩種區分,還有相應的動詞,形容詞)出現的次數加起來作為這個單詞的出現的總次數,最後按照這個統計次數的高低排序,輸出的結果就是高頻辭彙集合了。

流程化是建立編程思維的基礎,發現事物的流程,是開始編碼的第一步。但只知道根據流程來編碼,寫出的代碼估計會像流水賬式的文章,有很多冗餘,要想寫出優雅的代碼,下面一步就需要識別出流程中變化和不變的部分,並對變化的部分進行封裝,常見的方式是提取函數。

識別變化與不變的部分

你是不是在想,咦,流程中還分變化和不變的部分?這怎麼理解。

下面讓我們接著聊炒菜這件事,以流程中的洗菜、切菜這一步為例,洗和切這兩個動作不變的,菜是變化,因為我們不管不做什麼菜,都需要先洗再切,但是每次的菜是可以不同呀,於是我們就可以封裝菜這個變化的點,從而提取出兩個函數:

函數名:洗

輸入:菜

輸出: 洗好的菜

函數名:切

輸入:洗好的菜

輸出:切好的菜

(如果你在想為什麼不是一個函數?原因是單一職責原則啦,這個我們後面的文章中再講)

順著這個思路,我們再來看加調料這一步,炒一個菜,通常需要加不同的調料,比如說糖,醋,鹽。每種調料需要加的多少也是不一樣的,比如說20克,10克和5克。於是加調料這一步也可以封裝成一個函數:

函數名:加調料

輸入:1.調料名 2.重量

輸出:添加指定重量的指定調料

再來笑來老師的計算高頻辭彙的程序,它有哪些變化的部分呢?請想想再看下文。這裡我想到的一個點是統計單詞出現次數的部分,統計的方法是一樣的,不一樣的是統計的單詞,於是可以得到以下這樣一個函數:

函數名:統計單詞出現次數

輸入:某個單詞

輸出:這個單詞到目前為止出現的次數

當你能夠準確識別出流程中變化和不變的部分時,你就可以得心應手的的寫出百行左右的小程序。如果你要再進一步寫出一個軟體,那麼需要的就是抽象能力了。

確定抽象與具體的界限

抽象這個詞本身就很抽象,編程中到底需要抽象些什麼呢?我的理解是抽象是指抽象實體或者職責。遺憾的是這個可能已經不屬於入門的階段要了解的知識了,我後續準備再補寫章討論這些地方。在這裡,我只想提一點,在你開始運用抽象能力的時候,一定要注意確定抽象和具體之間的界限是否合適。

比如說,一個抽象的流程可以這樣描述,一個任務可以通過預處理、處理和後處理三步完成。你會發現無論做香辣蝦,統計詞頻都可以用這三步完成。做香辣蝦時清洗大蝦是預處理,下鍋翻炒,調味是處理,擺盤算是後處理了。統計詞頻中按空格分詞是預處理,統計每個單詞出現的次數是處理,按出現次數大小排序就算後處理了。這樣的抽象就屬於抽象程序比較高的,它的優點是可以適配的諸多場景;缺點也很明顯,太過抽象以至於只看這三步時,根本不知道要做什麼。

而我們在前面指出的炒菜的流程,先是洗菜、切菜(預處理),然後下鍋、翻炒、調味進行加工(處理),最後出鍋、裝盤(後處理)。相比來說就是更加具體的抽象了,因為它沒有說明要做什麼菜,但是做任何一道菜都需要這些步驟。

上述兩種抽象的方法到底哪個好,則要結合具體的場景來分析。如果只是炒菜,那麼第二個更好;如果是為處理任務提供一個通用的方法,第一個則要勝出了。所以在實際編程中,合理的確定抽象和具體之間的界限就是編程思維中最重要的一環。

總結

如果我們把程序定義為, 程序 = 輸入 + 處理 +輸出。那麼編程思維,就是先發現事物的流程,然後識別變化與不變的部分,最後確定抽象和具體之間的界限。

我是海之方,一個正在踐行寫作的程序員,如果你喜歡我的文章,請關注我的個人公眾號《踐行思考再踐行》。

aHR0cDovL3dlaXhpbi5xcS5jb20vci83amdUQzJQRWJ6NFFyU2RvOTIzOA== (二維碼自動識別)


推薦閱讀:

C語言基礎:地址與指針
學編程有前途嗎?
現在學編程,晚么?
百家爭鳴,誰是王者?

TAG:編程 | 編程入門 | 自學編程 |