鮑勃大爺:SOLID概念解釋

banq發表於2020-10-24

SOLID原則與90年代(甚至更早於20世紀90年代)一樣,在今天同樣重要。這是因為軟體在這些年中並沒有發生太大變化:因為自1945年Turing編寫電子計算機的第一行程式碼以來,軟體並沒有發生太大變化。軟體仍然是if語句,while迴圈和賦值語句、Sequence,Selection和Iteration。
每次新一代都喜歡認為自己的世界與前一代大不相同。這是錯誤的。
因此,讓我們一步一步地講解這些原則。以下是針對Dan North在SOLID上的觀點:為什麼SOLID的每個元素都不正確?只需編寫簡單的程式碼即可。”
 

SRP)單一責任原則。
將因相同原因而發生變化的事物聚集在一起。將因不同原因而改變的事物分開。
很難想象這個原理與軟體無關。我們不會將業務規則與GUI程式碼混合在一起。我們不會將SQL查詢與通訊協議混合使用。我們將因不同原因而更改的程式碼分開存放,以便對一個部分進行更改而不會破壞其他部分。我們確保因不同原因而更改的模組不具有使它們糾纏的依賴性。
微服務無法解決此問題。如果您混合了由於不同原因而更改的程式碼,則可以建立一個複雜的微服務或一個複雜的微服務集。
丹·諾斯(Dan North)的幻燈片完全錯過了這一點,並讓我確信他根本不瞭解該原理。他對SRP的回答是“寫簡單程式碼”。我同意。SRP是我們使程式碼保持簡單的方法之一。
 

OCP)開放-封閉原則。
一個模組應該可以擴充套件,但是可以關閉以進行修改。
在所有原則中,任何人都會對此提出質疑的想法使我對我們行業的未來充滿了恐懼。當然,我們希望建立無需擴充套件即可擴充套件的模組。您能想象在沒有裝置獨立性的系統中工作嗎?在該系統中,寫入磁碟檔案與寫入印表機,螢幕或管道根本不同?我們是否希望看到if語句分散在我們的程式碼中以處理所有小細節?
還是……我們要將抽象概念與詳細概念分開嗎?我們是否要使業務規則與GUI的煩瑣細節,微服務通訊協議以及資料庫的任意行為隔離開來?當然可以!
同樣,Dan的幻燈片完全錯了。當需求更改時,僅現有程式碼的一部分是錯誤的。現有的許多程式碼仍然正確。而且,我們希望確保不必為了使錯誤的程式碼再次起作用而更改正確的程式碼。丹的答案是“編寫簡單的程式碼”。我再次同意。而且,具有諷刺意味的是,他是對的。 簡單的程式碼既是開啟的又是關閉的。
 

LSP)Liskov替代原則。
使用介面的程式一定不要與該介面的實現混淆。
人們(包括我)都犯了一個錯誤,那就是繼承。它不是。它是關於子型別的。介面的所有實現都是介面的子型別。所有Duck型別都是隱式介面的子型別。並且,基本介面的每個使用者,無論是宣告的還是隱含的,都必須同意該介面的含義。如果實現使基本型別的使用者感到困惑,則if/switch語句將激增。
這個原則是關於使抽象保持清晰和定義良好。不可能相信這是一個過時的概念。
丹的幻燈片在該主題上是完全正確的。他只是錯過了原則的要點。簡單程式碼是保持清晰的子型別關係的程式碼。
 

ISP)介面隔離原理。
保持介面較小,以使使用者最終不必依賴於他們不需要的東西。
我們仍然使用編譯語言。我們仍然依靠修改日期來確定應重新編譯和重新部署哪些模組。只要這是真的,我們就必須面對這樣一個問題:當模組A在編譯時依賴於模組B ,而在執行時不依賴於模組B時,對模組B的更改將迫使模組A重新編譯和重新部署。
在靜態型別的語言(例如Java,C#,C ++,GO,Swift等)中,此問題尤其嚴重。動態型別的語言受到的影響要小得多。但仍然不能倖免。Maven和Leiningen的存在就是證明。
丹在這個主題上的幻燈片被證明是錯誤的。客戶端確實依賴於他們不呼叫的方法,如果在修改其中一種方法時必須重新編譯和重新部署它們的話。就此原則而言,Dan關於此原則的最終觀點是可以的。是的,如果您可以將具有兩個介面的類拆分為兩個單獨的類,那麼這樣做(SRP)是個好主意。但是這種分離通常是不可行的,甚至是不希望的。
 

DIP)依賴倒置原則。
取決於抽象的方向。高階模組不應依賴於低階細節。
很難想象沒有大量使用此原理的體系結構。我們不希望我們的高階業務規則取決於低階詳細資訊。我希望這是顯而易見的。我們不希望那些為我們賺錢的計算受到SQL或低階驗證或格式問題的汙染。我們希望將高階抽象與低階細節隔離開來。這種分離是透過仔細管理系統中的依賴關係來實現的,以便所有原始碼依賴關係(尤其是那些跨越體系結構邊界的原始碼)都指向高階抽象而不是低階細節。
在以上每種情況下,Dan的幻燈片都以結尾:只編寫簡單的程式碼。這是個好建議。但是,如果這些年來教會了我們什麼,那麼簡單需要有簡單的原則。正是這些原則約束了程式設計師生成傾向於簡單的程式碼。
使一個複雜的混亂變得最好的方法是告訴每個人“簡單”,不要給他們進一步的指導。
 

相關文章