識別代碼中的壞味道(一)

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在前面的文章中,我們介紹了 "},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/141134580","title":""},"content":[{"type":"text","text":"《提升編程效率:重構》"}]},{"type":"text","text":" 以及 "},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/141184662","title":""},"content":[{"type":"text","text":"《何時開始重構?》"}]},{"type":"text","text":"。瞭解了那些能夠更好的輔助團隊或者個人進行重構,但是要讓重構真正產生作用是需要能夠代碼中的壞味道,並消除代碼中的壞味道。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如下圖是工作中常見的代碼的壞味道:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/69/69e5856550643d0276da2029112f2628.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上圖中的壞味道出自《重構》這本書,雖然並不是全部,但是涵蓋了日常中最常見的一些代碼壞味道。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接觸這些壞代碼可以分爲三類:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"見名知意的代碼壞味道:"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"稍微解釋即可掌握的代碼壞味道;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"通過一些例子即可掌握的代碼的壞味道;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文主要聚焦在“見名知意的代碼壞味道”,後續兩類壞味道將在後續的文章中解釋說明:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1. 重複代碼"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"簡單的複製/粘貼,或者無意間添加了相同邏輯的代碼都是有可能的導致重複代碼出現的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"那麼爲什麼重複的代碼是一種壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最明顯的就是重複的代碼容易造成修改時的遺漏,修改遺漏導致一個問題需要修改多次才能才能確定最終修改完成。如果有一部分修改了,另外一部分沒有修改且沒有被發現,日後再遇到感覺類似,實則不同的代碼會花費大量的時間確定業務上的需求,實現上應該如何處理。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"重複代碼這類壞味道產生的成本很低,但是帶來的影響卻是很大。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如何解決重複代碼問題?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"Simple Design 爲我們提供了參考參考原則:“通過測試,揭示意圖,消除重複,最少元素”。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"如果重複代碼發生在一個類中,且兩段代碼完全重複,可以藉助 Extract Method (提煉函數)這個重構手法來消除重複;提煉函數時 IDE 一般都會自動提示是否同時修改重複的代碼,減少重構的工作量。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"如果重複代碼發生在一個類中,且兩段代碼之後部分重複。那麼可以將部分重複的代碼通過 Extract Method 的手法,提煉到單獨的方法中,並替換掉部分重複的代碼。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"如果重複的代碼在不同的類中,且這些類是兄弟類,可以使用 Pull Up Method,將重複的代碼提煉到父類,並讓原本的類繼承父類。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"如果重複的代碼在不同的類中,且這些類之間關聯性不大,那麼可以 Extract Class,將重複的挪動到一個新的類中,原本出現重複的地方來調用這個新產生的類的方法。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"消除重複之後,檢測代碼表達的意圖是否準確、完成,Extract Method 時可以通過良好的方法名來解釋提煉的函數的作用和意圖。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2 長函數"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"顧名思義,長度過長的函數。其中包括兩種情況,橫向過長,縱向過長。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"爲什麼長函數是一種壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"橫向過長時,往往一眼無法快速瞭解該行代碼要表達的意思和中間的過程。當出現 Bug 定位問題時也不容易一次性定位到問題所在。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"縱向過長時,往往會感覺某個函數內部邏輯複雜、晦澀難懂。修改代碼中也會因爲無法照顧到要修改的方法中的其他行代碼,而顧此失彼,最終導致難度難修改。經過多次修改後甚至原有的基本結構都會遭到破壞,導致後續修改難度逐漸增加。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如何解決長函數的問題?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"橫向過長的代碼,可以通過代碼格式化、CheckStyle插件來發現和消除。比如,Lambda 表達式,可以選擇在出現第一個“.”時就就開始換行。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"~~~java"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"List nodes = items.stream().filter(Item::isFree).filter(Item::notWork).map(Formater::format).filter(Node::hadChildren).filter(Node::hadMarked).collection(Collectors.toList());"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"~~~"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這行代碼我們需要仔細讀 才能清楚中間的過程。採用首個“.”出現換行的將會是如下格式:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"~~~java"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"List nodes = items"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" .stream()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" .filter(Item::isFree)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" .filter(Item::notWork)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" .map(Formater::format)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" .filter(Node::hadChildren)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" .filter(Node::hadMarked)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" .collection(Collectors.toList());"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"~~~"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過對橫向代碼格式化能夠爲代碼帶來更好的可讀性。當然你可以在提交代碼到倉庫時勾選上 commit 時自動格式化代碼的選項,避免沒有 Check Style 等工具來守護代碼,遺漏掉格式問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"縱向過長的代碼。往往多個實現細節堆疊在一個方法中造成的,這種情況下使用 Inline Temp(內聯局部變量)、 Extract Method 的重構手法來提煉小的函數。一個類中有很多零散的小函數也是常見的,因此提煉函數的同時記住,提煉函數的也是也是考慮創建新的類時候,將不同作用的函數提煉到響應職責的類中。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"縱向過長的代碼,往往存在職責不夠單一的情況,保持方法職責的單一有助於維護代碼的可讀性。通過 2 中 提到的 Extract Method,那麼某個具體實現細節可以被提煉到一個小函數中,而原來的函數則職責就編程調度作用。所以方法的單一職責,更清晰的描述應該是一類事情,要麼只在處理實現細節,要麼處理調度協調代碼調用。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class OrderService{\n \n ...\n \n public Order create(OrderDTO orderDTO) {\n // 創建條件是否符合 4 行\n ...\n\n // 貨幣轉換 4 行\n ...\n\n // 折扣計算 5 行\n ...\n\n // 將 OrderDTO 轉換爲 Order 對3行\n ...\n\n // 存儲 Order 1 行\n ... \n\n // 通知下有業務 5 行\n ...\n\n return order;\n }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看遺留系統時和麪試作業的時候,總是看到這類代碼,可以通過提煉函數並遵守方法的單一職責原則,就能夠簡單的重構實現一個邏輯更爲清晰的代碼結構,如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class OrderService {\n \n ...\n\n public Order create(OrderDTO orderDTO) {\n verify(orderDTO);\n\n Order order = orderRepository.save(orderMapper.toOrder()); \n\n notifyService.notify(order);\n\n return order;\n }\n\n\n private void verify(OrderDTO orderDTO) {\n // 創建條件是否符合 4 行\n ...\n }\n}\n\n\npublic interface OrderMapper {\n ...\n public Order toOrder() {\n // 將 OrderDTO 轉換爲 Order 對3行\n Currency currency = CurrentyTranslator.translator(currency); // 貨幣轉換\n BigDecimal price = currentyTranslator.calculate(products); // 提煉函數\n ...\n }\n}\n\n\npublic class CurrentyTranslator {\n\t\tpublic static Currency translate (Currency currency) {\n \t// 貨幣轉換 4 行\n \t\t\t...\n }\n}\n\npublic class PriceService {\n \n \tpublic BigDecimal calculate(List products) {\n \t\t// 折扣計算 5 行\n \t\t...\n \treturn xxx;\n \t}\n \n}\n\npublic class NotifyService {\n private void notify(Order order){\n \t // 通知下有業務 5 行\n \t\t ...\n }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面只是一個簡單的重構方法,其中涉及到的重構手法:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​\t\tMove Field(搬移函數)將上下文相關的變量挪動的一起;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​\t\tExtract Method (提煉函數) 將某個具體的實現提煉到一個職責單一的方法中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​\t\tExtract Method (提煉類)一個類尤其單獨的職責,因此將那些和原本的該類的職責關聯性不大的邏輯方法提煉到特定的類中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​\t\tInline Field(內聯臨時變量)如果一個變量對語意理解並沒有什麼幫助,那麼就可以採用內聯臨時變量的方法,消除顯示的定義變量,從而減少代碼的行數,同時閱讀代碼時也會更加清爽、聚焦。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"更具實際業務場景還可以藉助一些註解、工具類、AOP 來讓驗證、轉換、通知部分變得更加簡潔。通過提煉函數的重構手法,能夠讓後續的重構更加方便可靠。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果翻閱一些開發規範會發現有的團隊規定一個方法不超過 15 行,其實知道這個規範只能獲取到一個參考量,注意到行數多對,更重要的時候發現問題後的小步重構。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3 過大的類"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"顧名思義就是一個類做了太多的事情。SOLID 原則告訴我們類的職責應該是單一的,而一個過大類很可能意味着承擔了多個/多類職責。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"過大的類爲什麼是一種壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於過大的類承擔了過多的職責,很容易導致 重複代碼 且 重複代碼 不容易被發現,而這往往是壞味道的開始。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果過大的類對外提供服務發生了變動,並不容易快速響應這樣的變化,可以對比一下一個小而職責單一的類中進行修改方便還是在多很多職責。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當過大的類因爲某個地方發生變化,很可能導致不相關的調用方的代碼也會發生變化,這是一種耦合性的表現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當過大的類被繼承時很可能導致其他的壞味道,例如遺留的饋贈。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,保持小而職責單一的類將會對系統的設計有很大的幫助。當然也可以參考 Simple Design,避免過度設計的前提下保持簡單的設計。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如何解決過大的類的代碼壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"觀察這個過大的類的屬性,看是否有關聯的幾個屬性能夠代表一定的業務意思,如果可以使用 Extract Class,將這幾個屬性挪動到一個新的類中,並將相關操作挪動到新的類中。循環往復,這樣一個大的類能夠拆分成多個小的且職責較爲單一的類。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"觀察這個大類中的方法,看是否存在兄弟關係的方法,如果有可以使用 Extract Subclass (提煉子類)的方法,將相關方法提煉到子類中,並考慮使用繼承父類還是面向接口使用 Extract Interface(提煉接口)。這樣相似行爲的行爲聚集在一個類中,拆分到多個類中,並可以進一步和方法的調用發來解耦。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"進一步觀察剩餘類的行爲,如果這些行爲在處理一類事情,那麼可以停止了,在處理多類事情,可以按照處理邏輯的類型進一步拆分。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"簡而言之,使用一個亙古不變的法則:分治法。將過大的類,拆分成多個職責單一的小類,手段是 Extract Class,Extract Subclass,Extract Interface。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4 過長參數列表"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當方法的參數列表過長時這也是一種代碼的壞味道。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"\u0013"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"爲什麼參數過長是一種壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"參數過長和過大的類、過長的函數、重複代碼一樣,起初並不會導致什麼錯誤,但是代碼隨着時間向前演變過程,會給代碼帶來很多麻煩。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"長參數函數的可讀性很差,尤其是存在多個類似長參數方法時,並不容易判斷出應該使用哪個方法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當需要爲長參數函數添加新的參數時,將會促使調用方發生變化,且新參數的位置也將讓這個方法更加難以理解。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如何解決長參數的代碼壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"如果傳遞的幾個參數都出自一個對象,那麼可以選擇使用 Preserve Whole Object(保持完整對象)直接傳遞該對象。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"如果方法的參數來自不同的對象,可以選擇使用 Introduce Parameter Object(引入參數對象)將多個參數放入一個新的類中,原來方法傳遞多個分開的參數,現在傳遞一個包含多個屬性的一個對象。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"如果調用者先計算調用 A 方法得到計算結果,然後將計算結果在傳遞給這個長參數函數,那麼可以考慮去除這個參數,改爲在長參數函數中直接調用 A 得到結果,從而消除傳遞的部分參數,這個重構過程可以參考 Replace Parameter With Method(使函數替換參數)\u0013\u0013。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"需要的注意的是,有些情況下長參數的存在也是合理的,因爲在一定程度上可以避免某些依賴關係的產生。可以通過觀察長參數函數變化的頻率,並採用“事不過三,三則重構“的原則,保持進行重構的準備。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5 Switch 語句"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Switch 語句代表一類語句,比如 if...else, switch... case 語句都是 switch 語句。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"爲什麼 Switch 語句是一種代碼壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先並不是所有的 Switch 語句都是壞味道,Swith 語句開發中常見的語句。這裏帶有壞味道的 Switch 語句指的是那些造成重複代碼的 Switch語句。例如:根據某個狀態來判斷執行執行哪個動作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"public Order nextStep(...) {\n\t\tif (state == 1) {\n\t\t\t\t// do something\n\t\t} else if (state == 2) {\n\t\t\t\t// do something\n\t\t} else if (state == 3) {\n\t\t\t\t// do something\n\t\t} else {\n\t\t\t\t// do something\n\t\t}\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種實現方法很多代碼中都會出現,但是多數人使用這種方式添加代碼,並不意味着這是一種好的代碼。這樣的實現方式很容易造成長函數,而且每次修改的位置要非常精準,需要在多個條件中逐個遍歷找到最終需要的那個,再修改,可讀性上無疑也是很差的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何處理 Switch 語句這種代碼壞味道呢?**"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"如果 swtich 語句是某個方法的一部分,那麼不妨使用 Extract Method(提煉函數)將其先提煉出一個單獨的方法,縮小上下文範圍。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"觀察多個條件中的動作的關聯關係,是否符合多態,如果是將符合多態的幾個條件創建對應的類,並使用 Move Method (移動函數)移動到新創建的類中。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"使用狀態模式、枚舉等多種實現手段消除其中的 swtich 語句。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果對有限狀態機感興趣可以參考文章:"},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/97442825","title":""},"content":[{"type":"text","text":"《Java有限狀態機的4種實現對比》"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總而言之,一旦打算通過疊加新的 swtich case 來添加新邏輯,那麼就應該關注一下代碼設計,因爲這種操作很有可能就是爲後續的代碼在挖坑。同時理解清楚那些swtich 語句是具有壞味道的語句。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"6 誇誇其談的未來性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是工作中最常見的一類問題,比如如果你聽到這句話“我將文件上傳的實現做了調整 ... 未來再使用的時候將會 ...”就應該警覺起來。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"爲什麼誇誇其談的未來型是一種代碼壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"未來意味着當下並不是必須的,過度的抽象和提升複雜性也會讓系統難以理解和維護,同時也容易分散團隊的注意力,如果用不到,那麼就不值得做。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除非你在進行假設驅動開發,否則代碼上總是談未來容易綁架團隊的思想,拿未來不確定的事情來解釋事情的合理,會讓那些務實者,關注投入產出比的抉擇。並且容易讓團隊進入一個假象。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當業務上變動時,並不能及時的將代碼進行變動,因爲原來的代碼中包含了一種對未來假設的實現,無形中增加了代碼的複雜度,而且很容易增加團隊溝通成本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如何解決誇誇其談的未來性的代碼壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Simple Design (簡單設計原則)能夠幫助我們作出抉擇。當實現業務代碼時考慮”通過測試、揭示意圖、消除重複、最少元素“。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當發現爲未來而寫的代碼時,可以:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"刪除那些覺的未來有用的參數、代碼、方法調用。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"修正方法名,使方法名揭示當下業務場景的意圖,避免抽象的技術描述詞。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過上面兩個過程將代碼原本的要表達的意思還原回來。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"工作中有兩類未來性。一類是假設調用方可以怎麼使用;一類是未來必然發生的業務功能。代碼的壞味道更多的指的是第一種情況,第二種情況可以開發之前體現進行簡單設計和拆分,從而避免過度設計,同時可以避免談未來性,來讓代碼隨着功能一起小步重構並演進。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"7 令人迷惑的臨時字段"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在一些場景下爲了在實現上的臨時方便性,有的開發者會直接在某個對象上添加一個屬性,後續使用在需要的時候使用該屬性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"令人迷惑的臨時字段的是什麼代碼壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個類包含屬性和方法,屬性都是該類相關的。而臨時向類中添加的字段,雖然臨時有關聯性,但是單獨來看這個類中的屬性時,卻會讓人覺得非常費解。有些接口的返回值就是也是類似原因導致的結果,每次爲了方便像類中直接添加一些臨時屬性,滿足了當時的需要,但是後續再使用的時候卻並不能區分哪些屬性時必須的,哪些是不必須的,以及哪些被添加的字段的上下文分別是什麼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如何解決令人迷惑的臨時字段?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"問題的原因是隨意向類上添加字段,解決的方法就是將這個臨時字段移走,可以爲這個字段找到一個合適的類來存放,也可以使用 Extract Class (提煉類)將這個字段添加到一個新類中,然後將該字段的相關的邏輯移動到該類中,並確定該類的職責。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"可以將臨時字段作爲參數進行傳遞,但是爲了避免過長參數的出現,可以選擇將臨時字段提煉到一個新的類中。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"8 過多的註釋"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是註釋降低代碼可讀性,甚至誤導了代碼要要表達的意圖。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"爲什麼過多的註釋是一種代碼壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先並不是所有的注視都是壞味道。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果想通過註釋來表達代碼的意思,那麼代碼修改了註釋也需要同步進行修改,如果代碼修改了但是沒有修正這是註釋就有可能導致誤導。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還有一種註釋的壞味道,指的是不使用的代碼通過註釋掉來表示其棄用。後續代碼的閱讀者會經常收到斷斷續續的註釋掉的代碼影響。降低讀代碼和改代碼的速度。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 《Clean Code》 中羅列了一些註釋的壞味道:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"喃喃自語"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"多餘的註釋"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"3","normalizeStart":"3"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"誤導性註釋"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"4","normalizeStart":"4"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"循規方註釋"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"5","normalizeStart":"5"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"日誌式註釋"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"6","normalizeStart":"6"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"text","text":"廢話註釋"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"7","normalizeStart":"7"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"text","text":"用註釋來解釋變量意思"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"8","normalizeStart":"8"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"text","text":"用來標記位置的註釋"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"9","normalizeStart":"9"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":9,"align":null,"origin":null},"content":[{"type":"text","text":"類的歸屬的註釋"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"10","normalizeStart":"10"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":10,"align":null,"origin":null},"content":[{"type":"text","text":"註釋掉的代碼"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" ..."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如何解決過多的註釋的代碼壞味道?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"造成使用註釋的原因很多,可以考慮移除這些註釋:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"刪除被註釋掉不再使用的代碼"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"如果某段代碼沒有辦法輕鬆的解釋清楚,可以使用 Extract Method 來,並使用提煉的方法名來表達意圖。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"刪除多餘的註釋,誤導性註釋,如有必要可以將方法重命名,解釋意圖。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"用來說明變量意思的註釋刪除掉,對變量進行重命名,如果這個變量並不是必須的可以選擇將變量進行 Inline Temp。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面介紹了代碼中常見的 8 中代碼壞味道,這些壞味道見名知意,每種壞味道通過簡單的幾步重構即可解決。面對這些壞味道應該避免延遲解決,隨時保持代碼的整潔。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章