1. 程式人生 > >思考:宣告式程式設計與指令式程式設計

思考:宣告式程式設計與指令式程式設計

引用一下維基百科的定義:

1.宣告式程式設計 Declarative Programing

In computer science, declarative programming is a programming paradigm — a style of building the structure and elements of computer programs—that expresses the logic of a computation without describing its control flow.

This is in contrast with imperative programming, which implements algorithms in explicit steps.

2.指令式程式設計 Imperative Programming

In computer science, imperative programming is a programming paradigm that uses statements that change a program's state. In much the same way that the imperative mood in natural languages expresses commands, an imperative program consists of commands for the computer to perform. Imperative programming focuses on describing how a program operates.

The term is often used in contrast to declarative programming, which focuses on what the program should accomplish without specifying how the program should achieve the result.

  這一大堆英文怎麼理解呢?   想象一下,在家的時候,你對媽媽說,‘媽,我要吃糖醋排骨!’。顯而易見,你只是想要吃糖醋排骨,至於糖醋排骨是你媽媽忙活一番做出來的,還是你媽媽點了外賣,外賣小哥冒著風雪送來的,只要糖醋排骨能讓你滿意,其它的你也許都不關心。   同樣的,公司領導對你說,你這個月的業績要上千。至於你是加班加點累死累活,還是輕鬆悠哉看看劇就能做出這個業績,說實在的,領導並不關心。   又或者,操作html的DOM結構時,你想獲取class包含beautiful的所有DOM元素,你只需要宣告一下document.querySelectorAll('.beautiful'),而不用關心js引擎怎麼去把DOM tree翻得底朝天,將這些元素都給找出來返回給你。   以上,結論是:   在家時,你關注的是糖醋排骨,媽媽操心怎麼給你弄來糖醋排骨,你是在做宣告式程式設計,而你媽媽是在做指令式程式設計。   在公司時,領導關注的是業績,你操心的是怎麼把業績做到上千,領導是在做宣告式程式設計,而你是在做指令式程式設計。   操作DOM時,你關注的是結果,而js操心的是怎麼把你要的結果都找到和拿回來,你是在做宣告式程式設計,而js引擎是在做指令式程式設計。   宣告式程式設計,關注的是what to do,即做什麼。 指令式程式設計,關注的是how to do,即怎麼做。   這兩種程式設計正規化,都能在生活和程式碼裡隨處可見。   每天上課或上班之前,給自己寫的便籤,上面羅列了一堆要做的事。是宣告式程式設計。   禮拜天想燉個湯,給自己補補身子,按食譜上的一步步說明來做。是指令式程式設計。   .....   太多例子,就不逐一說明了。   現在,我們大概是理解宣告式程式設計與指令式程式設計的含義與區別了。   不過,光理解,是遠遠不夠的,程式設計程式設計,既然是程式設計,那就是要編寫程式用起來的。在我們編寫程式的時候,怎麼運用它們呢?它們能給我們帶來什麼樣的啟發和思考呢?   上述例子裡,想必是做媽媽的比較煩心,做員工的你比較煩心,js引擎也比較煩心,因為大家都要幹很多髒活累活,方方面面都思考和準備了許多,怕不是頭髮都要掉光了。相反,宣告式程式設計的人們就快活多了,只需要說一兩句話,表明一下自己的想法,就能實現願望。   於是,我們會期望,“偉大的阿拉丁神燈啊,能幫我把程式碼都寫了麼?”,阿拉丁神燈就說:“孩子啊,程式碼就不用寫了,帝都二環的十套別墅已經給你準備好,請安心享受人生吧!”   開個玩笑,能宣告式地寫程式碼,那當然會很舒心,可宣告式程式設計顯然是建立在指令式程式設計的基礎上的,髒活累活沒人乾的話,一堆堆宣告就只是擺設,沒啥用。   程式設計早期,sql這東西還沒出現,大家都是自己幹苦力活,要查什麼資料都是擼一遍又一遍的迴圈,還要操心各種鎖啊,事務啊等等亂七八糟的問題,簡直天天懷疑人生。後來sql出現了,想要啥資料,只需要對資料庫說 SELECT XX FROM XXX,多簡單,多愜意。   不過,隨著時代的發展,網頁內容越來越豐富,從資料庫裡查資料雖然簡單,但將資料以特定的結構組裝起來,通過介面返回給瀏覽器展示可是很煩人的事情,介面少還能忍受,可介面一多,大概也還能忍?然而要改變一堆堆介面的資料結構呢?大概是想掀桌子打人老子不幹愛誰誰幹的感覺?   究其原因,是因為寫介面(給前端呼叫的介面)這件事,是髒活累活,是命令式的程式設計。那麼,能不能把它變成宣告式的程式設計?   老祖宗教導過我們,在計算機的世界裡,沒有什麼問題是新增一箇中間層解決不了的事情,不信看看OSI標準模型,或者TCP/IP協議棧?當然,真要解決不了,那就再加一層唄。   於是,幾十年過去,終於有人想起要把寫介面的大部分髒活累活都承包了下來,封裝成一層,叫
GraphQL
。   從此,寫介面只需要宣告自己要什麼樣的資料,而不用操心那些改來改去的煩心事了。(現在的GraphQL還有諸多缺陷,比如N+1、許可權控制等問題,不過這些都會逐漸改進的)   當然,不止寫介面這件事,在我們日常的工作中,也存在許許多多類似的情況。例如,初始化一個工程或專案,如果沒有相應的腳手架工具,要自己一遍遍按部就班地搭基礎設施得多累?有了腳手架,宣告一個專案,就能給你把demo搭出來。可以說是半自動化了。自動化是為了什麼?還不是為了解放生產力?此外,也是為了更好地降低出錯概率,以減少因為出錯導致的成本。畢竟相對於人來說,機器出錯的概率實在是低得多了。   又比如,我們是不是時不時會被一些專案困擾?那些煩人的糟糕的架構設計,程式碼裡層出不窮的BUG,產品經理不斷帶來的改來改去的需求,所有這些,都可以歸根為指令式程式設計帶來的問題:繁瑣、脆弱、多變。   有沒有那麼一些解決方案,能把這些指令式程式設計的髒活累活都幹了,抽象出對人類友好的宣告式介面。就像令無數人頭疼的正則表示式一樣,存不存這麼一種宣告式的正則引擎,例如,宣告 [提取出所有十二位數的手機號碼],正則引擎就像資料庫一樣給出我們想要的結果?   看起來像人工智慧?大概就是這樣了。   從指令式程式設計到宣告式程式設計的過渡, 是技術不斷髮展進化的過程。   ----------------   後記:指令式程式設計與宣告式程式設計並無優劣之分,使用物件是我們人類的時候,宣告式程式設計的風格自然是更好的,這是人的惰性決定的。但對機器而言,指令式程式設計顯然更好理解,更準確來說,一大串010111的機器碼是更方便理解的。另外,從程式碼除錯的角度來看,宣告式程式設計不好除錯,甚至無從除錯,比如js引擎,當querySelectorAll接口出錯的時候,你還能直接斷進去除錯?所以這要求我們在做命令式的髒活的時候,要提供穩定、靠譜的服務。