軟體發展至今,無論是程式設計語言,還是軟體工程,乃至是互連網的趨勢發展,都是飛速發展。於是,我們便迷茫於這樣形形色色的語言和概念之間,無所適從。其實,我們不妨返璞歸真,回到最初,讓我們從語義出發,來討論這形形色色的種種,你是否恍然大悟呢?
5. 面向過程是先總後分的行文順序
相信大多數程式員都和我一樣,C語言都是自己的第一門語言,那麼面向過程的這個概念也自然深入人心。其實,我相信,每個人心中的思維都是面向過程的。
“我們應該先幹嘛,再幹嘛”。這是每個人在做一件事情前的常規思維,編程時也是一樣,我們在實現一個方法,或者在完成一個功能時,都會去想,應該先做什麼,再做什麼,然後我們會相應地把一個方法拆分成若干個子方法,這就是我們傳統的面向過程的編程。
我們把這種方式稱之為“自頂向下”的編程思維。在做一件事情之前,我們要瞭解這件事情是什麼,然後再去想這件事情應該怎麼做。
這種與我們常規的對應叫做記敘文,說得難聽一些我們可以稱之為流水賬。
我們不妨說得偏激一點,面向過程的核心不在於方法,而在於過程。面向過程本是沒有方法的,後來為了可讀性才增加了方法這個概念。本就是輔助,當然可有可無。
概括起來,面向過程的編程方式是先總後分的行文方式,Crowdsourced Security Testing道總體意思,再逐條去寫。
6. 物件導向是先分後總的行文順序
逐漸地,我們開始接觸了Java,C#等物件導向的語言,但是我們是否卻始終沒有辦法扭轉思維,來找到如何來物件導向呢?抑或是我們經常為了物件導向而物件導向呢?
我們究竟錯在了哪?我就是按照常規的語義來分析整個的項目,那為什麼無法物件導向呢?錯只錯在我們解析文法的角度出現了問題。
在上文中,我提到了我在高中時非常常用的一種記敘方式,就是我會在文章的題記前,先把開場的主人公全部都陳列出來,其中包括他們的主要性格,以及簡要概括他們的陳年往事。如此做的原因是因為文章的故事結構比較複雜。
那麼我會做的是,首先在提綱上列去所有的主人公,然後想清楚他的主要性格,之後再去根據他的性格來為他設定一些事件,最後根據這些事件安排這些主人公的出場順序,以及人物之間的關係。
這也得出了我對物件導向的核心思想的概述:以人為本。這裡的人不僅僅是人,是指所有存在的生物,乃至非生物。換句話說,所有需要有行為的物體。可以是人,可以是電腦,甚至可以是一個衣櫃。
物件導向的核心不在於商務邏輯的過程,而在於找到所有的“人”,然後知道每個人都能做什麼,最後我們再把這些行為加以組裝而已。
概括起來,物件導向的編程方式是先分後總的行文方式,在文章伊始,每件事情都不知道自己是在幹嘛,只是在表達著自己。知道最後,才會發現,原來這些事情的作用是這個樣子的。
有這樣一本書,叫像堆積木一樣做軟體。我不清楚這本書的內容是什麼,但是這個題目很形象,物件導向的基礎實現過程實際上就是在做積木,每個積木都不知道自己未來會幹嘛,而當積木都做好了之後,堆積木就變得簡單而易行了。
7. 並髮式編程是交錯式的行文順序
隨著軟體對效能要求的逐漸提升,並發已經成為了我們不可迴避的話題,從Erlang到C#4.0的並行庫,再到顯卡編程的盛行,並發編程已經逐漸走到了我們的面前。
在高中時,有一種文體非常盛行,我也曾多次嘗試,最後的分數也還不錯。這種問題是在行文時,分別描述兩件事情或多件事情,這幾件看上去毫無關係,只是由每一段的ABCD,abcd等不同的符號來標識,然而這些事情到最後卻揭示的同一道理,或者是最後他們在同一情境匯聚,來構成了故事的結局。
這種文體在新概念作文大賽上屢有出現。其實這就對應著我們常規意義上的並發編程。每件事情和每件事情之間從局部上沒有著直接聯絡,但是最後宏觀上,他們都是在為了做同一件事情,達到同一個目的。就像裝配腦袋某天在群裡討論的冒泡排序的並發版——奇偶排序一樣,從微觀上,對奇數排序和對偶數排序沒有必然聯絡,實則他們在完成著同一項工作。
8. 重談總體行文
我一直在編程中都很強調一點,語義的重要性!
完美的程式設計語言應該是與自然語言完全對應的,可以把一篇文章翻譯成與之對應的電腦語言,發展到那時,程式員就真的變成了翻譯工作,只需要把對應的需求文檔無需設計,翻譯成電腦認識的一串串代碼就可以了。
我們究竟如何分析一個軟體需求。在我看來,軟體的創造過程實則就是語義的分析過程。
當拿到一份需求時,按照物件導向的軟體工程思想,我們應該首先做到提取出這份需求文檔中所有的“主人公”,然後找到這些主人公每個人都可以幹嘛,能幹嘛,要幹嘛。然後為之建立模型。這是物件導向的過程。
然後是每個行為的分析過程,要做這個行為,我們要先怎麼做,再怎麼做,為這個行為建立相應的流程圖,這是面向過程的分析過程。
接下來,我們可以分析某個行為怎麼做,是否可以一邊幹嘛,一邊幹嘛。這是面向並發的建模過程。
當我們要描述某個演算法時,我們可以說這個演算法要怎麼做,只是基於語義的描述,例如斐波那契數列要用第一個數加上第二個數,這其實就很有可能是一個函數式編程的產生過程。
最後是組裝,也就是堆積木的過程。我們的積木都已經做好了,我們只需要按照不同的商務邏輯,去把這些積木搭起來就可以了。
也就是說,當我們建立一個項目時,首先建立人物傳記(物件導向),然後對人物的經曆進行描述(面向過程)。最後成文時,我們可以用交錯式行文方式對其重組(並髮式)。
那麼好,我們概括下整個的過程:物件導向分析-->面向過程分析--->在過程的細節上並發或者函數式--->組裝時再次考慮並發。
9. 小議過時說
經常會聽到這樣的聲音,未來是面向服務的,未來是物件導向的,面向函數的,面向過程已經過時了之類的話。
其實,看過我上面的分析過程,一個完整的工程只靠著某一種編程範式是行不通的,一個工程的搭建需要的是各種範式的配合使用,每種範式都有著它所擅長的部分。
就像物件導向再好用,也無法脫離了面向過程而單獨存在,哪怕你的原子拆分得再細,也無法逃開對每件事情進行分析的過程,況且還有著商務邏輯組裝過程的存在。
而面向函數,面向並發再強大,他也無法取代物件導向在分析一個大型項目中自底向上這樣巨大的優勢。因此任何編程範式皆無過時說。就像語言之爭一樣,每種語言都有著其合適的應用範圍,談語言優劣,過時與否,我覺得毫無必要。
下文簡介:
在下文中,我會對對全文進行一個總體的總結,以及語義與物件導向的關係,設計模式與語義的關係,並且會淺談個人認為未來語言的發展方向等等,敬請關注,謝謝。