5個使您的軟體難以維護的C#常見錯誤 - Derek Comartin解釋
編寫乾淨、可維護且高效的程式碼是專業C#開發者的標誌。 然而,C#程式語言中的許多常見錯誤使代碼庫隨著時間的推移變得難以處理。在本文中,我們將通過總結Derek Comartin在其名為"5 Mistakes That Make Your Code Unmaintainable"的影片中的觀點,來探討這些錯誤。
Derek分享了他在建立大型商業系統中的見解,並指出開發者——尤其是使用C#的開發者——經常犯下的五個重要軟體設計錯誤。 讓我們深入了解這些問題,以Derek的影片為指南。
1. 缺乏對狀態的擁有權
Derek首先指出一個錯誤,即允許多個邊界或服務更新共享數據而沒有明確的擁有權。他舉了一個例子,說明了帳單系統進入應用程式的另一部分並更改狀態。 這會導致數據一致性問題,特別是當該對象位於系統中不同位置時。
這種不受控制的方式會造成錯誤,開發者會問:"為什麼這個數據不正確?"或"是誰改了它?"Derek強調必須定義擁有權。系統的每個部分都應該公開一個定義良好的API或方法,負責管理狀態。
而不是允許應用程序的任何部分修改共享數據,Derek建議創建明確的命令和查詢。 例如,當您要更新一個發貨時,您通過專用的界面發出一個命令。 這提供了結構,並避免由於不可追蹤的變更而造成的資源洩漏。
2. 隱含代碼與明確工作流
根據Derek的說法,許多系統過度依賴CRUD操作(創建、讀取、更新、刪除),但這導致隱含的工作流。 代碼在技術上是功能性的,但缺乏對其作用的明確性。 如果您的類別僅支持泛型操作,實際的業務工作流程會被隱藏。
看看下面這個例子:一位司機拿起包裹,並生成一張提單。 如果系統只是運行UpdateShipment,則無法確定字符串更改(例如提單號碼)是由於取件還是修正。 Derek指出,我們應該用明確的操作代替模糊的更新,比如PickupStopLoaded。
這可以使代碼更具可讀性。 這也有助於異常處理,因為當一個異常例如ex發生時,堆棧跟蹤會清楚地指示哪個操作失敗。 明確的方法還支持更好的編碼標準,因為每個功能都有單一的責任。
3. 增加無用的間接層
Derek接著討論間接層——在調用者和目標方法之間插入不必要的層。 他用數據庫連接來說明這一點。 控制器可能調用一個服務,該服務調用一個幫助器,後者又調用另一個服務,最終通過Entity Framework執行查詢。
這種抽象的金字塔讓問題更難追蹤,並且使性能提升更加困難。 儘管創建抽象可以有助於,更好地管理資源,例如包裝IDisposable接口,但Derek警告不要過度這麼做。 問問自己,您的抽象層是否簡化了API,還是僅僅隱藏了一個只存在於一個地方的第三方依賴。
Derek建議不要為了分層而分層,應直接管理耦合。 過多的間接層不僅會使代碼混亂,還會增加内存洩漏的潛力,削弱垃圾回收的好處。
4. 玩"假設"遊戲
接下來,Derek指出的錯誤是為可能永遠不會發生的假設用例做準備——他稱之為"假設遊戲"。許多C#開發者為未來需求撰寫靈活的類和函數。 例如:"如果我們需要支持兩種語言呢?"或者"如果我們需要切換技術呢?"
Derek警告說,這種心態會導致框架臃腫以及過於泛化的代碼。 他提到遇到字符串連接邏輯和沒有人理解的引用類型包裝器,因為它們僅服務於一個實際的用例。
與其為未知做準備,Derek建議將注意力集中在實際需求上。 每個方法和變量都應該有當前、合理的用途。 未使用的功能只增加維護成本。Derek說,這不僅僅是開發時間——這是擁有成本。如果您的公共布爾Equals實現,例如,涵蓋了您能想像的每個邊界情況,但實際上沒有一個真的發生過——您就浪費了寶貴的時間。
5. 沒有正確管理工作流
最後,Derek討論了將工作流視為程序塊而非模塊化步驟的錯誤。 他用一個真實的例子說明:在線下單。用戶完成結帳後,系統收款,然後發送確認電子郵件。
如果一個步驟失敗——例如支付流程——您的代碼如何反應? 是否回退訂單? 顯示錯誤? 發送失敗電子郵件? Derek解釋說,將這些整合為一塊會造成無法管理的複雜性。
他建議將工作流設計為小的、隔離的單元,通過消息進行通信。 使用異步任務操作和yield return使這些步驟易於管理。 此外,在諸如文件訪問或數據庫連接等外部資源周圍使用using語句和using塊可以幫助防止內存洩漏。
例如,環繞流的using塊可以確保其被正確處置——這是處理IDisposable接口時的一個重要點。 當工作流變得複雜時,這些最佳實踐確保異常被有效捕捉和處理,從而保持性能和可維護性。
總結:編寫乾淨、可維護的代碼
在他視頻的12:45處,Derek總結這些錯誤,他回顧這些不僅是他看到過的問題,也是他在構建大型商業系統時親身犯下的錯誤。 這些都是通過經驗獲得的教訓,他鼓勵觀眾在評論中分享自己的錯誤。
Derek的建議不僅適用於C#,也適用於許多其他語言。 無論您是在進行字符串比較、Equals()方法,抑或設計新功能,關鍵在於清晰、意圖和保持代碼的可維護性。
如果您有興趣提升您的C#技能並避免這些常見的陷阱,Derek的頻道提供了許多有關系統架構、設計模式和現實世界程式語言建議的免費資源。避免其中一個錯誤就能顯著提高您的專案質量。
所以,下次您開始撰寫代碼時,請記得Derek的話並問自己:"我是否讓這個比需要的更複雜?"
欲獲得更多類似內容,請查看Derek Martin的CodeOpinion YouTube頻道。

