再讀整潔架構之道(二)程式設計範式

Tommy Cheese | · 閱讀約需 4 分鐘

再讀整潔架構之道(二)

程式設計範式指的是程式的編寫模式,它告訴我們應該在什麼時候採用什麼樣的程式碼結構。

截止目前,一共出現了三種程式設計範式:結構化程式設計範式、物件導向程式設計範式和函數語言程式設計。

作者認為,每種程式設計方式不是在給架構設計者的武器庫進行擴充,相反,架構師和程式設計師的武器已經夠多了,這三種程式設計範式是在對他們利用的武器進行限制,這也是為什麼他們叫做“範式”。

結構化程式設計範式

結構化程式設計對程式控制權的直接轉移進行了限制和規範,特別指的是限制了程式中goto的隨意使用。

分解程式

Dijkstra希望使用數學推導方法對程式進行推理證明:讓程式就成為了一種歐幾里得結構,這樣可以用一些已經證明的結構串聯起新的程式,從而進一步推導整個程式的正確性。

他還發現,如果程式中包含大量的goto,那麼程式會變得難以分解,而goto語句的作用完全可以依靠分支和迴圈來完成。

這樣,結構化程式設計範式表明,程式可以進行降解拆分,一個大型問題拆分為一系列高階函式的組合,而這些高階函式各自又可以繼續被拆分為一系列低階函式,如此無限遞迴。更重要的是,每個被拆分出來的函式也都可以用結構化程式設計範式來書寫。

但是,這種形式化證明的程式設計方式沒有成為主流,科學證明法是目前使用較多的方法。

科學證明法

科學理論和科學定律可以被證偽,但是沒有辦法被證明,類似的,程式只能測試證偽,不能證明,即“測試只能展示Bug的存在,並不能證明不存在Bug”。因此,利用科學證明法,結構化程式設計範式就可以促使我們先將一段程式遞迴降解為一系列可證明的小函式,然後再編寫相關的測試來試圖證明這些函式是錯誤的。如果這些測試無法證偽這些函式,那麼我們就可以認為這些函式是足夠正確的,進而推導整個程式是正確的。

物件導向程式設計範式

物件導向程式設計對程式控制權的間接轉移進行了限制和規範。

具體來說,物件導向程式設計凡事使用多型特性限制了函式指標的使用。這可以理解為函式指標只能進行有限制的指向,比如java中的多型一般出現在有繼承關係的兩個類的物件之間。

作者也認為多型是OOP的最大特性,利用多型可以做到依賴反轉

依賴反轉即引入介面,完全控制系統中所有原始碼的依賴關係,而不需要收到系統控制流的制約。

依賴反轉保證了我們可以對系統進行外掛式的開發,如將web UI和資料庫與業務邏輯之間的依賴進行反轉,可以保證主業務邏輯與UI和資料庫的解耦,這樣UI和資料庫就成了主業務邏輯的外掛。

物件導向程式設計就是以多型為手段來對原始碼中的依賴關係進行控制的能力,這種能力讓軟體架構師可以構建出某種外掛式架構,讓高層策略性元件與底層實現性元件相分離,底層元件可以被編譯成外掛,實現獨立於高層元件的開發和部署。

函數語言程式設計範式

函數語言程式設計對程式中的賦值進行了限制和規範。

換句話說,函數語言程式設計語言中變數是不可變的。

作者有以下的觀點,這一段話來自原文:

“所有的競爭問題、死鎖問題、併發更新問題都是由可變變數導致的。如果變數永遠不會被更改,那就不可能產生競爭或者併發更新問題。如果鎖狀態是不可變的,那就永遠不會產生死鎖問題"

如果不考慮儲存器與處理器的速度限制,那麼不可變性是可行的,但實際上我們必須考慮這些因素,因此可變性只能在一定程度上可行,需要讓不可變性在一定程度上可行需要完成可變性的隔離

可變性的隔離

可變性隔離的一種常見方式是將應用程式,或者是應用程式的內部服務進行切分,劃分為可變的和不可變的兩種元件。不可變元件用純函式的方式來執行任務,期間不更改任何狀態。這些不可變的元件將通過與一個或多個非函式式元件(即可變元件)通訊的方式來修改變數狀態。

一個例子是GIT版本管理工具。它通過移動指標來記錄檔案的變化:增刪改,但實際上檔案並沒有被真正的修改和刪除,只存在增加和檢索查詢兩種情況,這不就是不可變性的一個例子嗎。

同時,mysql中的事務管理、事務性記憶體的工作也都運用了這個思想。

總結

三種程式設計範式與軟體架構具有密切的關係:

  • 多型是我們跨越邊界的手段;
  • 函數語言程式設計是我們規範和限制資料存放位置與訪問許可權的手段;
  • 結構化程式設計則是個模組的實現基礎;

三種程式設計範式與軟體架構的三大關注重點不謀而合:元件獨立性(物件導向)、資料管理(函式式)以及功能性(結構)。

再次思考

三種程式設計範式都對程式設計師提出了新的限制。每個範式都約束了某種編寫程式碼的方式,沒有一個程式設計範式是在增加新能力。也就是說,程式設計範式帶來的是——什麼不應該做。

(第二篇完)

comments powered by Disqus