系列第十八天。技術總監(於老大)對代碼品質要求嚴格,透過代碼審查引導小帥帥運用重構技法改善設計。
LinklistCharListHandle::exec() 原始碼包含三層巢狀 foreach,於老大一眼指出結構混亂,要求重構。
小帥帥將內層邏輯提煉為 propertiesTransferCharlist() 與 addCores() 兩個方法:
class LinklistCharListHandle extends CharListHandle {
public function exec() {
$sql = "select word from category_linklist where cid='{$this->selectorItem->cid}'";
$linklist = DB::makeArray($sql);
foreach ($linklist as $strWords) {
$words = explode(",", $strWords);
$this->propertiesTransferCharlist($words);
}
}
public function propertiesTransferCharlist($linkWords) {
$properties = $this->selectorItem->getProperties();
foreach ($properties as $property) {
$this->charlist->addCore($property->value);
if (in_array($property->value, $linkWords)) {
$this->addCores($linkWords);
}
}
}
public function addCores($words) {
foreach ($words as $char) {
$this->charlist->addCore($char);
}
}
}
代碼可讀性提升,但於老大提出兩個關鍵問題:
propertiesTransferCharlist 為何需要傳參數?addCores 屬於哪個類別的職責?小帥帥將 addCores 搬移至 CharList 類別,符合「資料與操作資料的方法應在一起」的高內聚原則:
class CharList {
private $core = [];
private $blacklist = [];
public function addCore($char) {
if (!in_array($char, $this->core)) $this->core[] = $char;
}
public function addCores($words) {
foreach ($words as $char) $this->addCore($char);
}
public function getCore() { return $this->core; }
public function addBlacklist($char) { /* ... */ }
public function getBlacklist() { return $this->blacklist; }
}
於老大引入靜態快取、單一職責、封裝查詢邏輯,最終版本:
class LinklistCharListHandle extends CharListHandle {
private static $linklist = [];
public function exec() {
$this->propertiesTransferCharlist();
}
public static function linklist($cid) {
if (!isset(self::$linklist[$cid])) {
$sql = "select word from category_linklist where cid='$cid'";
self::$linklist[$cid] = DB::makeArray($sql);
}
return self::$linklist[$cid];
}
public function propertiesTransferCharlist() {
$properties = $this->selectorItem->getProperties();
foreach ($properties as $property) {
$this->charlist->addCore($property->value);
$this->extendCharlist($property->value);
}
}
public function extendCharlist($char) {
$linklist = self::linklist($this->selectorItem->cid);
foreach ($linklist as $strWords) {
$words = explode(",", $strWords);
if (in_array($char, $words)) {
$this->charlist->addCores($words);
}
}
}
}
| 重構手法 | 應用場景 | 效益 |
|---|---|---|
| Extract Method | 過長函數、重複邏輯、嵌套過深 | 提升可讀性、可複用、可測試 |
| Move Method | 方法更常使用另一類別的資料/行為 | 高內聚、低耦合、職責清晰 |
| Replace Parameter with Query | 參數可由接收者自行查詢 | 簡化介面、減少耦合 |
| Introduce Caching | 重複昂貴查詢 | 效能提升、資源節省 |
「代碼隨便改變下,區別這麼大,以前為啥從來沒有這感覺。」—— 小帥帥
重構不是重寫,而是在保持行為不變前提下,通過微小步驟持續改善設計。技術總監的價值不在於寫多少代碼,而在於建立標準、引導團隊產出可維護的高品質代碼。