Blog Cover Image

Inspire you to have New thinking, Walk out your unique Road.

[後端小菜鳥]初階工程師魔鬼訓練(5) - 淺談重構Refactoring

Posted onDec 26, 2018

你還埋沒在那不知如何解決的三層 for 迴圈嗎?

還在被前輩唸嗎?

如何擺脫菜鳥的名號?

這些都可以被解決!

本來是想要在每週會議的分享會當中分享「重構」,不曉得還會不會分享,先記錄下來

當新手離開學習程式階段後,下個階段,開始實行大量練習撰寫程式碼,開始寫出破洞百出,錯節盤根,Bug 滋生,不斷重複的程式碼

在這個階段,首要任務已經不是熟悉語法,剛進公司的新手工程師,前輩們都會當你很熟悉語法,開始要學習更多凌駕於程式語言上的知識,究竟如何從程式新手晉升成 Junior 呢? 重構是必學的一環

原本我以為熟悉程式語言後就會是大師,結果沒想到後頭的路卻有更多的觀念及知識累積在需能熟悉運用程式語言上
讓我深刻體會到程式語言真的如同教授所說「只是工具」

以下開始講解

重構 Refactoring

所有的內容都來至於重構 --- 改善既有的程式設計

螢幕快照 2018-12-19 上午10.27.12

而我要講解的索引如下

  • What is Refactoring?
  • Why Refactoring?
  • When Refactoring?
  • Bad smell

我會在每個講解過程中,獻上我菜鳥時期的程式碼,殘害各位的雙眼 XD

What is Refactoring?

根據維基百科所說,「重構」是在不影響程式輸出/ 結果的前提下,整理程式碼,讓其可讀性提高。

讓原本雜草叢生,凌亂不堪的程式碼,重構過後,變成整齊,可閱讀的文本。

還是新手熟悉語法,並不會學習到這個概念,等到與前輩們,團隊合作後,經過前輩的教導,接觸了重構。

你可能會覺得你已經渾身解術寫出能動能跑的程式就很開心了

但真的要增進功力以及讓團員跟你合作美好

您必須讓團隊合作的團員看得懂你寫的程式碼,可以讓人一目瞭然,也可以讓人迅速抓出臭蟲(Bugs),這是當你熟悉程式語言後,即將要學習的新觀念。

來貼張我以前寫的程式給大家欣賞

螢幕快照 2018-12-29 下午12.37.39

乍看之下,好像沒有我想像中想呈現的樣子,但依這張圖片來看,裡面包著三層 For 迴圈加上 if/ else,看起來沒有很複雜,但除錯的時候會很痛苦,你得一層一層檢查看變數有沒有帶下去,萬一遇到 6, 7, 8 個 for 迴圈再一起時,一定會瘋掉的!

Why Refactoring?

根據書上列出的四大優點

  1. 重構使改進軟體設計

  2. 重構使軟體更易被理解

  3. 重構助你找到臭蟲

  4. 重構助你提高編成速度

    Why Refactoring Works — Kent Beck

    程式有兩面價值「今天可以為你做什麼」「明天可以為你做什麼」

    If you emphasis today’s code, you can work with this code tomorrow.

    If you found that today’s code is not suit for tomorrow, you have to make some choose.

是什麼讓程式難以相與? 有四個原因

  1. 難以閱讀的程式,難以修改

  2. 邏輯重複(duplicated logic)的程式,難以修改

  3. 添加新行為時需要修改既有程式碼者,難以修改

  4. 帶著複雜條件邏輯的程式(complex conditional logic),難以修改

因此,我們希望程式

  1. 容易閱讀

  2. 所有邏輯都只在唯一地點指定

  3. 新的改動不會危及現有行為

  4. 盡可能簡單表達條件邏輯(conditional logic)

When Refactoring?

時時牢記的三條規則 (The Rule Of Three)

  • 添加功能時一併重構
  • 修補錯誤時一併重構
  • 複審程式碼時一併重構

Bad Smell 程式碼的壞味道

經過上述簡單將 What, Why, When 交代清楚了,但你未必知道哪些程式碼需要重構,因此你需要懂得分辨程式碼的壞味道,哪些程式碼一看就知道需要重構,在這我不會分享所有的分類,我會介紹書中幾個技巧配上我的範例介紹給大家

Duplicate Code (重複的程式碼)

當你看到有重複的程式碼時,代表著你可以將這些重複的程式碼合而為一,會使程式更精簡。

接下來再度殘害大家的雙眼:

看著這優美又規律的重複程式碼,也許是因為他的 SQL 碼不夠長,無法造成震撼

還記得同事第一次看到我寫的複製好幾行又臭又長的程式碼,差點在旁昏倒在地

要 Insert 幾筆資料就複製幾行呀!!!!!

螢幕快照 2018-12-29 下午12.51.49

事實上,僅僅需要合成一個函式利用 For 迴圈塞相同的資料

或者用 Format+ Random... 等函數來製作浮動的假資料


Long Method (過長函式)

來看看上上週寫的 Excel 轉成 Json 小工具

我只寫了一個 to_json 的函式,接著就把所有的功能都擠在一起寫上去

除了除錯困難外,連看 Code 的人都要看完一遍還須釐清個幾次才會了解

螢幕快照 2018-12-29 下午12.46.17

後來的作法則是使用 Extract Method 將幾個功能提煉成不同的函式(或稱方法),例如下圖

將 Excel 轉換成 Json 分成

讀取 > 轉換 > 寫入

三種方法(函式),再來針對各個方法撰寫函式,這樣也可以讓看的人馬上了解,寫程式的人是如何構想與實作的!

螢幕快照 2018-12-29 下午1.15.05


Large Class (過大類別)

過大類別就是制定一個 Class 物件,Class 為因應不同的物件所需會有不同的函式時,而延生出一個 Class 裡有一堆不同的函式

我已經不知道我在說什麼了,但目前在寫的程式跟過大類別相似,卻不知該如何分享

只好想像有個物件是判斷貓科(Felidae)動物,可是貓科動物有很多不同的動物,總不能將所有跟判斷貓科的條件都寫在同樣一個 Class 裡,這樣會造成這個 Class(判斷),會包含很多函式(條件, 依據)

Class <strong>Felidae(object):
    def legs():
       ....

    def hair():
       ....

    def color():
       ....</strong>

可以設定SubClass 子類別或超類別來幫助判斷

Class <strong>Felidae(object):

    @abstractmethod
    def criteria():
        pass

    @abstractmethod
    def rule():
        pass

    @abstractmethod
    def must_have():
        pass</strong>


Class <strong>Cat(object):
    def criteria():
        ....

    def rule():
        ....

    def must_have():
        ....</strong>

Class <strong>Lion(object):
    def criteria():
        ....

    def rule():
        ....

    def must_have():
        ....</strong>

可以用 Extract Method 或 SubClass 來幫助避免過大類別發生

雖然定義的有點簡陋 XD 但有把意思解釋到比較重要


Refactoring + Unit Test + Design Pattern

最後我要講一下重構(Refactor)還需搭配單元測試(Unit Test),才能更迅速抓出臭蟲,以及檢視程式碼

必要時還需要學習 Design Pattern, 這個稱為程式語言連續技的知識,搭配起來讓您寫的程式好懂又漂亮