C#中的DRY原則:為何代碼重複損害了您的代碼庫 - Derek Comartin解釋
當我們談論在C#中撰寫可維護代碼時,一個經常出現的基本概念是DRY原則——不重複自己。 這是一個軟體開發的支柱,旨在消除冗餘,減少代碼重複性,並提高代碼的可維護性。
但像許多設計原則一樣,DRY可能會被誤解甚至誤用。 在他的视频中 "DRY principle is why your codebase sucks?",來自CodeOpinion.com的Derek Comartin提供了一個坦誠而務實的觀點,講述DRY原則的正確和錯誤使用——尤其是在.NET Core或類似的生態系統開發中。
在本文中,我們將深入探討Derek的解釋,並通過他在視頻中的示例和評論進行講解。 無論您是要在Visual Studio中開始新專案,維護現有代碼庫,或者只是為了更好的代碼重用性進行重構,Derek的見解都是實用且相關的。
DRY 原則的定義
在視頻開始時,Derek介紹了許多開發人員面臨的情況:處理一個難以修改的系統——充滿重複代碼和冗餘邏輯的糾結問題。
他介紹了在C#中的DRY原則,作為一種減少代碼重複的策略,但警告說這常常被誤解。 正如Derek在0:28解釋的:
當DRY成功應用時,對系統中的任何單一元素的修改不需要更改任何邏輯上無關的元素。
這一區別是至關重要的。 DRY原則的目標不僅僅是避免重複代碼,而是在於促進關注點分離和正確代碼重用——從而導致可維護的、乾燥的代碼,這更易於測試和重構。
實際範例:距離轉換
為了直觀,Derek提供了一個用C#設計的簡單範例。 他編寫了兩個方法:
-
ShipDistance
- TollDistance
每個方法計算英里距離,然後將其轉換為公里數——在這兩個方法中使用了相同的邏輯。 這是經典的代碼重複。
與其在多個地方有相同的代碼,Derek展示了如何將轉換邏輯提取到一個私有方法——MilesToKilometers()——這是重構代碼以提高可重用性的一種基本但有效的方法。
他使用典型的控制台應用程序結構來說明這一點:一個包含靜態void Main的Program類。 這是許多開發者在測試邏輯或體驗新的用戶輸入場景時(例如公共int年齡,字符串用戶名,字符串密碼等)會使用的結構。
DRY與過度耦合
雖然將邏輯抽象成一個可重用的方法或獨立類別聽起來很理想,但Derek提醒要小心。 過度使用DRY,尤其是在整個應用程序中,可能會導致危險的耦合程度。
例如,如果您將轉換邏輯放入一個多個項目共享的工具中,然後更改其進位行為或小數精度,該更改可能會意外地影響許多地方。 正如Derek在2:31所指出的:
客戶是否期望有兩位小數? 如果我們將其改為零會怎樣?
這是一個橫切關心點——一個被系統多個部分重用的邏輯——它說明了過早或沒有明確界限的集中化的風險。
Derek在這裡的建議回響著單一責任原則和依賴反轉原則,這是保持代碼可適應和模塊化的兩個其他SOLID原則。
來自DRY使用不當的代碼膨脹
DRY誤用的另一個問題是代碼膨脹——試圖抽象一切導致膨脹的工具類或過於泛用的方法。 Derek警告說,過度DRY化邏輯會導致更多的問題而不是幫助,特別是在大型系統中,一個地方的錯誤修正可能會因共享依賴關係而打破其他部分。
Derek認為關鍵在於知道什麼時候不共享代碼——特別是如果它會導致模組之間緊密耦合的話。 DRY不是一條規則; 它是一個必須結合上下文使用的指導原則。
DRY 應用於實體:複雜性的配方
Derek指出開發人員的一個常見問題:將系統完全圍繞卡車、訂單、駕駛員和貨運等實體組織起來。 雖然重用相同的類別或對象在不同的方法中很有誘惑力,但這通常會導致重複概念和不需要的耦合。
他主張業務能力——而不只是數據結構——應該驅動架構。 例如,"派送訂單"與"解挂拖車"是不同的問題,即使它們涉及相同的實體。
在4:45,Derek解釋道:
系統中的單一實體不需要成為多個概念的表現。
這突出了一個更深層的架構見解:具有相同名稱的實體(如車輛、拖車)可能在不同工作流中代表不同的責任。 交換使用它們會造成混淆並使不相關的業務邏輯緊密耦合。
DRY與業務能力
為了解決這一問題,Derek引入了垂直切片架構(VSA)——一種圍繞業務能力而不是層次結構來構建應用程序的模式。 每個"切片"都包括為特定操作或用例所需的一切——從請求到數據庫——都是封裝和自我包含的。
他強調,DRY代碼在切片內——個單一位置內是好的,但在切片間應用DRY可能會導致交織的依賴性。 在6:44指出:
這只是在於減少耦合,增加内聚力…… 以及這樣做的一種方式是:不要在邊界內重複概念。
這種由邊界驅動的思考給予您靈活性。 您可能在一個切片中擁有完整的域模型,而在另一个切片中只需轻量的数据模型。 這取决於切片的需求——一種務實的方法,符合實用程式師哲學。
最後的思考
Derek的總結是將DRY重新定位為工具,而非法律。 正如他在7:00時所言:
這只是要理解您如何應用它。 如果您大量應用它,您可能會面臨更多的耦合。
因此,在提取驗證邏輯、連接串,或者將重複代碼轉換為獨立方法之前,考慮這樣做是否真的能使整個代碼庫更具可維護性——或只是使其更難更改。
結束語
Derek Comartin在C#中對DRY原則的解析展示了一條看似簡單的規則如何在應用時不夠細緻而造成反效果。 通過展示代碼示例,討論實際場景並強調軟體設計原則,他揭示了重用性與模塊化之間所需的平衡。
要顯著增強您的開發過程,請記住:
-
在清晰的邊界內使用DRY重構冗餘代碼。
-
不要將不同業務用途的實體DRY化。
-
中央化邏輯時尊重上下文——尤其是在多個地方或项目。
- 考慮單元測試以及依賴注入如何影響共享代碼。
通過應用這些學到的知識,您將撰寫出更加高效、模塊化且可維護的C#代碼——並避免將您的代碼庫變成充滿重複邏輯和糾結依賴的雜亂之物。
您可以觀看Derek Martin的完整視頻以獲取更多來自CodeOpinion的YouTube頻道的見解。
