使用NDepend衡量代碼的SOLID程度

SOLID是面向對象的軟件開發中的5條準則,也是開發人員可以提升自己代碼質量的準則。那麼如何衡量自己的代碼是否符合SOLID準則呢?NDepend這款工具也許可以幫得上忙。本文將介紹一些NDepend的規則,這些規則可以幫助你來衡量你的代碼的SOLID程度,並且提供一些可以讓你的代碼變得更好的建議。

原文連接:Use NDepend to Measure How SOLID Your Code Is - NDepend
作者 Carlos Schults。授權翻譯,轉載請保留原文鏈接。

https://www.ndepend.com/

NDepend和SRP

我們將首先處理SOLID中的“ S”:單一責任原則。這可能是SOLID原則中最容易被誤解的東西,公平地說,這似乎是有原因的。關於什麼構成責任存在一定程度的主觀性。那麼NDepend如何幫助解決這個難題呢?

避免類型過大

顧名思義,這條規則建議你保持較小的類型。保證你的類較小並不一定會使它們只承擔一種責任,但是肯定會引導事情朝着這個方向發展。

聽上去不錯,但是“太大”有多大?根據規則的文檔,超過200條邏輯代碼行的類就屬於過大了。

避免太多方法的類型

你可能會認爲,鑑於前一個規則,這條規則有些多餘,但事實並非如此。 除了大量方法外,類型還可能由於其他原因而過大,例如它可能有很多其他成員,或者可能只有一個巨大的方法。

但是,按照以前的規則,我們不得不問:“太多”是多少? 該規則的文檔指出,如果每種類型有20個或更多的方法則被視爲擁有太多方法,並補充說,諸如構造函數,屬性和事件訪問器之類的方法不被視爲計數的一部分。

避免太多字段的類型

作爲“避免太多...”系列的規則,這條規則涉及到了字段。該規則的文檔說,它針對具有15個以上字段的類型,並且不考慮常量和只讀靜態字段以及枚舉類型。

避免過大和過於複雜的方法

在這裏,我們繼續遵循鼓勵簡化設計的規則,但是現在我們關注的是方法級別。那麼,方法的情況如何呢?我們是否只是要重複使用剛剛看到的相同規則,但是將“類型”替換爲“方法”?

不,不是那麼容易。在處理方法時,事情會變得有些複雜。首先讓我們看看“避免方法過大和過於複雜”規則的文檔說了些什麼:

//<b> This rule matches methods where *ILNestingDepth* > 2
</b>//<b> and (*NbLinesOfCode* > 35
</b>//<b> or *CyclomaticComplexity* > 20
</b>//<b> or *ILCyclomaticComplexity* > 60)
</b>//<b> Such method is typically hard to understand and maintain.</b>

簡而言之,該規則擔心嵌套深度大於2且也符合其他幾種條件之一的方法,例如代碼行和循環複雜度。

避免使用參數過多的方法

該規則的名字已經表明了它的內容。我們真正需要做的是量化。多少是太多?

同樣,我們必須求助於文檔,這次文檔中描述了參數過多指的是超過8個參數。調用這樣的方法會十分痛苦。同樣需要注意的是,一個有很多參數的方法是否也有可能本身的邏輯已經十分冗雜,處理多個事務了呢?有這樣方法的類,應該使用單一職責原則來進行重構。

避免使用過多局部變量的方法

終於,最後一條用來幫助你使用單一職責原則檢查自己代碼的規則。就像之前介紹過的大多數規則一樣,這條規則的名字也說明了它的內容。並且,這條規則只需要定義它所謂的“過多”是多少。而這個問題的答案,根據文檔,是15個。

通過這一節的介紹,我們大致介紹了NDepend中可以幫助你使用SOLID原則中的單一職責原則的規則。

OCP 開閉原則

很多人認爲開閉原則是所有原則中最難理解和應用的。所謂的開閉原則,指的是你的類型應該對拓展開放,但是對修改關閉。換句話說,對子類的增加一定不能導致父類的任何修改。NDEpend中的“基類不應該使用派生”規則通過指示基類永遠不要提及其子類來幫助我們防止這種情況。

LSP 里氏替換原則

Robert Martin在一篇文章中對里氏替換原則下過如下定義:

派生類必須可以替代其基類。

當面對這樣一條定義時,一些人會認爲里氏替換原則多此一舉,顯得多餘。那麼這條原則的意義是什麼呢?

好吧,這條原則的關鍵是人們一直在違反它!一種非常常見(也許是最常見)的情況是,讓一個類實現一個或多個接口,然後拋出某種方式不適用的方法。

而NDepend恰好有一條規則可以警告你這種情況,這條規則被相當恰當地稱爲“實現拋出NotImplementedException的方法。”

你會發現,在使用TDD時,此異常最有用。這是一個非常常見的情況,如下所示:

  • 爲一段代碼編寫測試時,你將調用一些不存在的方法。
  • 此時編譯器會抱怨,而這是一件好事。
  • 然後你接受了Visual Studio的建議並生成了一個方法存根,因爲你現在也不希望立即實現該方法。

如果你以後忘記實現該方法,則測試將失敗,而這會提醒你。

這是NotImplementedException的可接受用法。如果你使用此(或其他)異常來避免實現某個接口,那麼你將破壞LSP準則。

ISP 接口隔離原則

接口隔離原則指的是:

不應強迫客戶端依賴於不使用的接口。

爲了遵循此原理,你應該使接口儘可能的小和精細。換句話說,你應該避免接口太大,這是我們現在要討論的NDepend規則的確切名稱。

“太大”有多大?根據NDepend的文檔:10。也就是說,該規則將提示具有10種以上方法的接口。

關於此規則的一件好事是,它也可以幫助你遵守之前提到過的里氏替換原則。如果使接口儘可能小,則可以降低客戶端必須提供有意義的實現的可能性。一石二鳥!

DIP 依賴反轉原則

所謂的依賴反轉原則指的是:抽象接口不應該依賴於具體實現。而具體實現則應該依賴於抽象接口。

假設你有一個應用程序緊密耦合使用Microsoft SQL Server作爲持久性解決方案。如果之後你需要更改使用另一個RDBMS,將​​會發生什麼?這注定是一個痛苦的過渡過程。

反過來,如果你的應用程序的業務邏輯甚至沒有意識到數據庫的存在(通過採用適當的體系結構是可能的),則無需進行任何更改即可進行過渡。

爲了幫助您解決此問題,NDepend制定了一個規則,即“高凝聚,低耦合”。 “高凝聚,低耦合”類似於“關注點分離”,簡而言之,你希望你的軟件具有很高的內聚性(“做一件事情並做好”),同時彼此之間的耦合性也很低。

這條NDepend規則通過鼓勵你將包含抽象的命名空間與包含具體內容的命名空間(即所述抽象的實現)分開來幫助你實現此目的。

準備好編寫更多SOLID代碼了嗎?

我們上面介紹的規則只是NDepend提供的規則中的一部分。它們足以使您的應用程序符合SOLID原則嗎?當然不會。沒有任何工具或技術可以保證一定改善你的代碼。

但是,雖然規則本身並不能自動使你的代碼完美無缺,但它們鼓勵你編寫較小,集中且不太複雜的類型,從而爲你提供極大的幫助。

除此之外,通過不斷閱讀和研究SOLID原理,適當的架構以及通用的最佳實踐和模式,你便可以正確地編寫出色的應用程序。


 

閱讀更多:

https://docs.microsoft.com/en-au/learn/?WT.mc_id=DT-MVP-5001664

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章