閱讀50行代碼還是使用提取方法重構? - 來自Derek Comartin的見解
在軟體開發的世界中,重構是必不可少的。 其中一種最常見且被鼓勵的技術是方法提取重構——將大型程式碼片段拆分成較小的可重複使用的方法,以提高可讀性和可重用性。 雖然這在理論上聽起來很理想,但Derek Comartin在他的视频"我寧願讀50行而不是方法提取重構"中,提供了一個新穎且批判性的觀點。
本文將帶您逐步了解Derek對方法提取重構的分析,提供實際情境和實用建議。我們將遵循他的論點和程式碼結構,了解什麼時候以及如何應用提取重構——以及其實施細節和潛在缺點。
範例:聊天系統中的用戶註冊
在視頻的開始,Derek 提出了一个例子:聊天系統的註冊功能。 這是一個大約50行的緊湊但現實的程式碼區塊,進行幾個任務:
-
檢查用戶名是否不為空
-
驗證用戶名是否已被占用
-
處理年齡限制管道
-
保存新用戶對象
- 發送包含啟用鏈接的電子郵件
這段程式碼位於一個函數中,乍看之下似乎是方法提取重構的理想對象。 但Derek警告說,盲目重構而不了解影響實際上可能會降低清晰度。
以重構為起點:選擇方法提取
Derek從許多開發者開始的地方開始——將程式碼片段分解成較小的部分。 他展示了如何在大多數IDE或程式碼編輯器中通過上下文菜單或鍵盤快捷鍵選擇提取方法。
他提取了:
-
validateUsername用於驗證用戶名不為空
-
existingSignUpNotActivated用於檢查未啟用的賬戶
-
validateExistingUser用於處理所有現有用戶檢查
-
filterAgeRestrictedChannels用於處理未滿18歲用戶的管道
- sendEmail用於發送歡迎電子郵件
他給每個新函數一個有意義的名稱,這是清潔代碼實踐中經常提到的最佳建議之一。 但當他走過這些修改後的版本時,Derek開始指出邏輯中的裂縫——不是在功能上,而是在可讀性和控制流程上。
問題1:隱藏的實施細節
Derek突顯的第一個紅旗之一是實施細節現在被提取出的方法隱藏起來了。
例如,validateUsername和validateExistingUser方法實際上會拋出異常。 但作為閱讀重構代碼的開發者,您將毫不知情,除非您查看其內部。
這種重構可能會隱藏控制邏輯,導致錯誤或遺漏驗證。 範圍和流程不再明顯。 不是讓程式碼更清晰,而是創造了一個抽象的迷宮,像異常或修改變量這樣的副作用不再可見於原始邏輯所在的地方。
問題2:間接和鏈式提取
接下来,Derek指出間接的問題——當一個提取方法調用另一個時,如此等等。 他展示了validateExistingUser方法自身由existingSignUpNotActivated組成。
您不再閱讀一個簡單的自上而下的程式碼塊。 您在方法,文件和類之間跳躍,只是為了跟踪發生了什麼。 即使編輯器可能幫助導航這個流程,它仍然增加了讀者的認知負擔。
在更大的系統中,這變得更為麻煩,重構跨越多個文件或組件。 突然,您的"清潔代碼"比原始的"混亂"50行更難以追蹤。
問題3:局部變量和狀態變動
此视频中最重要的课程之一來自局部變量和狀態變動的處理。
Derek聚焦於filterAgeRestrictedChannels方法。 它不返回結果——它直接修改了傳遞進來的管道列表。 這意味著您正在從不同的方法中修改局部狀態,除非您仔細檢查該方法,這種更改會被隱藏。
這打破了函數要麼是純粹的操作,要麼清楚地信號化它正在改變什麼的期望。 當您用一個不返回值而是內部改變它們的新方法取代邏輯時,您正在引入風險和混淆。
Derek的重構替代方案
那麼Derek究竟是如何重構他的旧代码的呢?
他提出了一种更簡單的方法:
-
讓自我解釋的邏輯內聯。 檢查空用戶名的初始檢查保留在主方法中,因為它易於理解,不會使程式庫混亂。
-
返回結果而不是變動。 而不是修改管道列表,filterAgeAppropriateChannels 函数现在返回一个过滤后的列表。這使得資料流清晰,防止意外的副作用。
-
使用簡單、可預測的提取方法。 只有另一個提取方法是isExistingUserAlreadyActivated,這清楚地返回一個布爾值而不拋出異常。 它封裝了邏輯而不隱藏細節。
- 避免內聯的副作用,如發送電子郵件。 Derek留下了電子郵件邏輯以作為示範,但建議在实际系统中,這應通過事件在一個單獨的過程或線程中處理——而不是直接與使用者表單提交綁定。
總計,Derek僅使用兩個提取方法,其餘邏輯保留內聯——因為它更容易閱讀,推理和控制。
方法提取重構的最终提示
Derek 的視頻給我們留下了一些實用指南,讓我們有效地使用提取方法重構:
-
使用有意義的名稱正確描述方法的作用。
-
避免副作用,如狀態變動或異常拋出,除非它們非常明顯。
-
返回值而不是修改輸入參數。
-
不要將邏輯隱藏在多層抽象之後。
- 如果在原始形式中方法看起來可讀,不要僅僅為重構而強迫將它變成多個函数。
有時,最好的抽象是不抽象——特別是當它以清晰度和範圍意識為代價的時候。
結束語
Derek Comartin的做法挑戰了重構總是改善代碼的觀念。 在方法提取重構的情況下,少即是多。 與其過度使用選擇提取方法來切割邏輯,不如評估什麼能增加價值,什麼能讓代碼更易於理解,什麼隱藏了重要細節。
通過清楚的例子和對現實代碼的直接洞察,Derek在他的视频中展示了有時候單個方法中的50行,像故事一樣自上而下閱讀,比分布於程式庫中的十個小方法更好。
如果您曾經壓下那個鍵盤快捷鍵來創建新方法,請記住Derek的建議:稍作停頓,評估,並確保重構是為讀者服務的—而不只是為了IDE。
