if else
程式上每個判斷條件對程式的維護、擴充、修改都是種風險,尤其是面對很多的if else時,程式的複雜性就提高很多。 一但程式需求有所變更,是個高風險、高成本的工作。
範例
輸入縣市能查詢出是電話開頭。
<?php class phone { public function findPrefix($county) { if ($county === '台北市') { return '02'; } else if ($county === '桃園縣') { return '03'; } else if ($county === '苗栗縣') { return '037'; } else if ($county === '台中市') { return '04'; } else { return '查無資訊'; } } }
當有縣市要新增時,我們可能會這樣寫。
<?php class phone { public function findPrefix($county) { if ($county === '台北市') { return '02'; } else if ($county === '桃園縣') { return '03'; } else if ($county === '苗栗縣') { return '037'; } else if ($county === '台中市') { return '04'; } else if ($county === '基隆市') { return '02'; } else { return '查無資料'; } } }
之後另外一個人接手,稍微優化程式。
<?php class phone { public function findPrefix($county) { if (in_array($county, array('台北市', '基隆市'))) { return '02'; } else if ($county === '桃園縣') { return '03'; } else if ($county === '苗栗縣') { return '037'; } else if ($county === '台中市') { return '04'; } else { return '查無資料'; } } }
又有新縣市,又換另外一個人寫。
<?php class phone { public function findPrefix($county) { if (in_array($county, array('台北市', '基隆市'))) { return '02'; } else if ($county === '桃園縣') { return '03'; } else if ($county === '苗栗縣') { return '037'; } else if ($county === '台中市' || $county === '彰化縣') { return '04'; } else { return '查無資料'; } } }
說明
以程式需求上來講,這樣寫沒錯,但程式風格卻不大相同,每一次的修改或者新增,都需要閱讀大量程式碼來確保結果的正確性,以及修改大量的程式碼。
另外每一個if else相關邏輯在單元測試中都必須進行一次測試,才能確保邏輯的正確性。
- 在多人持續對這程式碼做編輯中,程式碼邏輯將變得無法控制。
- 在單元測試中,邏輯區塊必須進行測試,否則無法確保其正確性。
- 邏輯程式碼越少,邏輯複雜度就越少;邏輯程式碼越多,邏輯複雜度就越高。
解決方法
要避免以上的問題,就是將邏輯跟資料分離開來。
<?php class phone { public function findPrefix($county) { $countPhone = array( '台北市' => '02', '基隆市' => '02', '桃園縣' => '03', '苗栗縣' => '037', '台中市' => '04', '彰化縣' => '04', ); return $this->handle($countPhone, $county); } private function handle($countPhone, $county) { if (array_key_exists($county, $countPhone)) { return $countPhone[$county]; } return "查無資料"; } }
這種寫法的好處在
- 邏輯與資料區分一目了然。
- 資料表可以替放,如機率換成視訊,單元測試可以注入其他資料內容,這代表資料來源的靈活性,可以隨時轉換資料。
- 在單元測試中邏輯必須測試,資料則無需測試。
結論
- 修改邏輯成本大,修改資料成本小。
- 修改邏輯風險大,修改資料風險小。
- 資料來源更靈活,資料改變更靈活。
重構的原理與物件導向的開放封閉相似。