[翻譯]重構讓世界更美好(Making the world better via refactoring - Intro)

這些文章翻譯自Sho Kuwamoto的ActionScript Refactoring 三部曲,經過原作者同意翻譯之。
本文原文連結在此。

我非常喜歡 Ely的一個作品:DragTile 元件( demo )。 為了做出不同的效果,我想延伸它原有的功能行為,並且使其更具彈性。我第一個想到的就是:Refactoring( 譯註: 中文通常翻譯為:”重構”,為重新建構之意,筆者在此保留原文,免除翻譯的差異 )。 如果你不常或輩子從沒做過refactoring,那麼,且聽我一步步道來,很有趣的。

何謂Refactoring?

Refactoring :在不改變原有外部功能的前提下,以漸進地手法改寫程式碼的結構。”不改變原有功能“聽起來很怪,卻是精隨所在。
分成兩部份來看: coding and refactoring,coding階段時,我們加上了新的功能(functionality);refactoring階段,我們重新調整程式碼結構,同時確保功能運行依舊。請牢記”不改變原有功能”的前提,這會讓你在進行調整程式碼時,不會迷失方向,當新的程式碼運作功能與舊的一樣,就是一次成功的refactoring。

有Refactoring有彈性

通常來說,refactoring 要讓現有的程式碼更有彈性,有些時候,你要refactoring的目標很明顯;有些情形下,你必須在refactoring前好好地思考規劃該如何改寫程式碼。
在Ely的例子裡,我們想要讓畫面的排版(layout)方式更容易被改變,看看DragTile的原始碼,有些部份不論排版如何,都是一樣;有些部份隨著排版而變動,因為排版的演算法(algorithm)在不同案例下會有不同變化,因此我們可以把它抽離出來,獨立成另一個類別(Class)。

Tip 1:

Cleanly separate out the code that you think will need to change often into a separate class.
技巧一: 把你認為會常常變動的程式碼分離出來

我們用繼承的手法,將DragTile裡關於排版的程式碼分開,建立成如下的關係:
DragTile Inherit
(圖1 繼承)
FlexibleContainer, 負責一般的行為,如: 過場動畫、滑鼠互動等。
DragTile, 負責特定的排版方式,運算物件的位置。
把這些工作分離開後,我們可以更容易地建立新的類別以達成新的排版方式(比如排成一個圓之類的),而其他程式碼:item renderer的溝通、動畫等等還可繼續沿用。

另一個手法:合成(Composition)
DragTile using Composition
(圖2 合成)
FlexibleContainer是一個容器,它包括了許多子元件,子元件一般行為的程式碼都會在這裡。
TileLayout管理排版的helper Class, 任何排版相關的計算都是它的責任。

如圖所示,Container類別將排版的任務委派(Delegate)給TileLayout來處理,本手法有一些好處:

  1. 以”委派”的觀念實作,通常可以使物件行為得以動態改變。承上,我們可以抽換其中一個Container的排版而不需重新調整繼承關係(reparenting)。
  2. 將大型類別拆解成數個小類別的合成(非繼承),將有助於調整、擴充程式結構,如同各個擊破一般。相對繼承手法來看,如果我們把FlexibleContainer再分離成兩個類別:一個是輕量化的Container專門為下載效率設計;另一個處理快取(cache)、本地化(localization),那麼,DragTile該繼承哪一個類別呢? 這將是一個難題,然而,如果你採用了委派的作法,將排版的工作委派給Layout類別,你不會有這個困擾。
  3. 合成手法,通常可以讓系統更分工(decoupling)更具彈性。舉例來說,你正在做照片管理的模組,如果你用了最上面說的繼承手法,你很難建立一個專門排版的模組,相對地,用合成手法,排版的功能是可以依使用者需要而直接改變的。

概觀上述所言,有技巧如下:

Tip 2: Think hard before using inheritance. Composition is almost always a better way to separate out the flexible part of a class from the invariant part.
技巧二: 你真的要用繼承嗎? 請三思。合成往往是比較好的選擇。

現在我們有refactoring的基礎概念了,在下一篇我們將深入探討程式碼。

Leave a Reply