PHP的有非常高度的隨便性,我是說自由性。
這樣的自由性,對於新手來說非常容易入手,因為怎麼寫都會動,但相對地非常容易寫出可怕的東西,導致不少PHP專案,最終都會變成可怕的樣子,難以維護。
其中有一個罪魁禍首,就是array。
php的array真的是非常方便,愛怎麼用就怎麼用,key可以是數字可以是字串,還可以任意動態增加新的key值,或是任意增加array的維數。
但是,也是這樣的方便性,當array在function間傳來傳去,常常傳到最後,根本不知道array裡面,或是array裡面該有什麼。
所以我認為,不要過於濫用array。
不要濫用 Array
舉一個取得使用者資訊的小例子:
$data = getUserData(['id' => 123]);
function getUserData($data)
{
$data['name'] = getName($data);
$data['store'] = getStore($data);
$data['storeNameForDisplay'] = getStoreNameForDisplay($data);
return $data;
}
function getName($data)
{
$name = getNameById($data['id']);
return $name;
}
function getStore($data)
{
$storeInfo = getStoreInfoByUserId($data['id']);
return [
'id' = $storeInfo['id'],
'name' = $storeInfo['name'],
];
}
function getStoreNameForDisplay($data)
{
return $data['name'].' '.$data['store']['name'];
}
如上述的例子,getUserData()
,你是無法從它的function定義看出要丟什麼東西進去的,只能一行一行看。
再來,即便知道要丟array,你也不知道要丟什麼key進去,直到你把getUserData()
裡面每一行所呼叫的function都看過了,你才知道原來$data
需要id這個key(在getName()
跟getStore()
中都有用到)。
而其中store
的這個key的value,是一個array,透過getStore()
回傳的,在下一個function getStoreNameForDisplay()
中,會用到store array的name,這也是從getStoreNameForDisplay
的介面看不出來的。
若今天有人任意把getStore
的回傳格式改了,他可能根本也不會想到,這居然會影響到getStoreNameForDisplay
這隻function吧?(莫名的耦合性)
建議的重構方向:
- 減少function間用array的形式傳遞參數
- 如果真的要用array,在進到其他function之前,盡量要拆解掉
重構結果:
$data = getUserData(123);
function getUserData($userId)
{
$userName = getUserName($userId);
$store = getStoreByUserId($userId);
$storeNameForDisplay = getStoreNameForDisplay($userName, $store['name']);
$userData = [
'name' => $userName,
'store' => $store,
'storeNameForDisplay' => $storeNameForDisplay,
];
return $userData;
}
function getUserName($userId)
{
$userName = getUserNameByUserId($userId);
return $userName;
}
function getStoreByUserId($userId)
{
$storeInfo = getStoreInfoByUserId($userId);
return [
'id' = $storeInfo['id'],
'name' = $storeInfo['name'],
];
}
function getStoreNameForDisplay($userName, $storeName)
{
return $userName.' '.$storeName;
}
明確定義getUserData($userId)
接受user id
作為參數,而不是傳一個不知所以的$data
進來。
在呼叫getStoreNameForDisplay
的時候,不直接把$srore
傳進去,而是取出$store
的name,再傳入getStoreNameForDisplay
中。
雖然這樣看起來比一開始的做法還要冗長,但每個function的介面跟回傳值,都變得更加清楚了,對於日後看程式或維護,會很有幫助。
(不過上述重構後的程式還有一些可以改善的空間就是了。)
結論
今天一個簡單的小專案,那當然快速方便為主。但是工程師不可能永遠只做小專案,系統也不可能永遠都是遞交出去就沒事了,總是會有一些後續的維護或擴充的需求。
如果到時候,看到的是,一堆莫名其妙的function,一堆array飛來飛去,裡面的key根本不知道是什麼,想必是相當頭痛的。
回歸正題,PHP array固然方便好用,但濫用的話,會造成可維護性降低,我們寧可一開始多花一點力氣,把程式寫的清楚一點,所謂長痛不如短痛,一開始的辛苦,可以降低後面的痛苦。
而我的作法,用一句話做總結就是:捨棄部分的彈性,降低不確定性。