商業需求對於Refactor的重要性

Michelle Hung
6 min readJul 4, 2021

自從大學畢業進到第一份工作時才開始接觸refactor, 從如何消除code smell到理解什麼是好的refactor

Refactor對於我自己來說有三個目的

  1. 易閱讀
  2. 易維護
  3. 易測試

易閱讀:不管任何人來看程式碼都可以清楚明白涵意

易維護:當需要對於原本的程式碼做修改時可以快速且不影響其他功能

易測試:讓程式碼可以容易寫自動化測試

“易維護”以及“易測試”很容易理解, 因為平常在開發的時候就會深刻體會到程式碼不好新增、修改以及寫測試是多痛苦的事情

“易閱讀”說得白話一點就是看程式碼像是看一篇文章

一開始對於它的理解只局限於命名變數的時候需要注意、該抽方法的時候要注意單一職責、方法名稱要清楚表明方法做的事情

直到有一次遇到一個case讓我對於“易閱讀”以及refactor有更深刻的了解

範例

功能需求:添加廣告的時候辨識投放廣告的時間是否已經有其他廣告正在投放

收到功能需求後的思路:

  1. 一次只能放一個廣告的位置需要做檢查,其他一次可以投放多個廣告的位置不需要檢查
  2. 當新增一個廣告,需要檢查已經存在的廣告是否有佔用想要投放新廣告的位置和時段
  3. 和已存在廣告的時段、country, language條件都有交集表示此狀況下不能再新增廣告
  4. 當要更新已經存在的廣告則需要從GetExistAds排除掉目前要更新的廣告, 否則永遠都會比對到自己
If( new/updated Ad's position only can put an Ad )
{
if( the period time that the new/updated Ad display is not available &&
the exist Ad's position only can put an Ad &&
the exist Ad isn't the new/updated Ad )
{
if( new/updated Ad's country has intersection with exist Ad's country &&
new/updated Ad's language has intersection with exist Ad's language )
{
The position isn't available
}
}
}

單純從功能面下手完成的程式碼就如同圖下一樣,基本上可以refactor的部分就只有feature envy, naming的部分, 巢狀for迴圈還是沒有什麼調整空間

原始程式碼

從商業需求、目的角度思考

首先問問看看自己這些問題都瞭解了嗎

為什麼需要這個功能?
這個feature目的是什麼?

商業需求:想要盡可能賣出更多廣告版位

從商業需求重新描述這個feature:如果時段內沒有廣告被投放就可以投放其他廠商的廣告

重新描述後就很清楚程式碼應該呈現出來的樣子

If ( the position is empty )
{
put other Ad
}
Refactor結果

程式碼的易閱讀就是需要表現出商業需求

Refactor使用的相關技巧

  1. 語法糖的使用

首先在決定使用什麼語法糖前先要了解這個class或是這些method本質是什麼東西

以這次case來說本質是Helper

一般來說Helper的架構是巢狀, 導致不易閱讀

所以選擇使用extension method語法糖攤平所有過濾的方法, 增加閱讀性

Extension method

2. Select many:攤平兩層List
List<Restriction> -> List<string>Country
List<Restriction> -> List<string>Lang

Restrictions是一個List<object>
Restriction object裡的條件也是List

3. 傳進method的參數盡量使用object

在使用object當參數的時候可以多思考這麼做的優點是什麼

List<Restriction>當參數:未來如果user成為篩選條件的時候user也可變成restriction

e.g. 喜歡A類型廣告的user, 限定只能看到A類型廣告

4. 處理feature envy時什麼時機點應該推進model

推入model前先思考現在要推的東西和model是否有高內聚,當然也要避免有不必要的耦合

IsLangIntersect是restriction的條件之一,和restriction物件有高內聚特性也沒有不必要的耦合

OnlySupportOneAd這個method和AdvertismentInfo object不是高內聚而是和Position才是高內聚,Position才知道版位是不是只能投放一個廣告,這次暫時使用extension method語法糖呈現

比較好的是調整Position property的type,它的型態應該是個物件,OnlySupportOneAd就可以推入Position的物件中

OnlySupportOneAd推入Position物件
Position Object
OnlySupportOneAd推入Position model後的使用方式

總結

  1. Refactor前或實作feature前先理解method或feature的目的及價值
  2. 了解目前要做的東西本質是什麼才選擇要使用哪種語法糖
  3. 決定參數要放什麼object之前多想想有哪些好處
  4. 將method推進model之前考慮和model是否高內聚

--

--