如何編寫函數(shù)----《代碼整潔之道》讀書筆記

文中代碼皆為不規(guī)范的偽代碼

程序中曾經(jīng)包含子程序和函數(shù)(可能我沒有經(jīng)歷這種年代),如今,程序中僅有函數(shù)這種方式保留下來挫望。

編程語言中的函數(shù)立润,分為內(nèi)置函數(shù)和自定義函數(shù)或類方法。內(nèi)置函數(shù)可以直接調(diào)用媳板,而自定義函數(shù)是程序員編寫的桑腮。

函數(shù)是程序的極其重要的組成部分,要寫好蛉幸,需要遵守一些原則破讨。

函數(shù)要短小。函數(shù)中不應(yīng)該容得下嵌套結(jié)構(gòu)巨缘,如if...else等添忘。在if..else、while若锁、for或foreach等嵌套結(jié)構(gòu)中搁骑,代碼不應(yīng)該超過一行,這唯一一行代碼又固,是對函數(shù)的調(diào)用仲器。請看代碼A。

function test($bool){

$age = 0;

if($bool){

$age = 5;

}else{

$age = 0;

}

return ?$age;

}

$bool = true;

echo test($bool);

上面這段代碼仰冠,函數(shù)體中包含if...else乏冀,嵌套結(jié)構(gòu),根據(jù)”函數(shù)要短小“的原則洋只,上面的代碼應(yīng)該改寫為代碼B:

function testTrue(){

$age = 5;

return $age;

}

function testFalse(){

$age = 0;

return $age;

}

$bool = true;

if($bool){

echo testTrue();

}else{

echo testFalse();

}

我喜歡用代碼B風(fēng)格的代碼辆沦。它能簡化主干代碼(抽象層次高的代碼)。實際編程中识虚,我綜合了代碼A和代碼B肢扯,因為我在代碼B的基礎(chǔ)上增加了一個函數(shù)test。請看代碼C担锤。

function testTrue(){

$age = 5;

return $age;

}

function testFalse(){

$age = 0;

return $age;

}

function test($bool){

$age = 0;

if($bool){

$age=testTrue();

}else{

$age=testFalse();

}

$bool = true;

echo test($bool);

三種風(fēng)格的代碼蔚晨,孰優(yōu)孰劣?我無法分辨肛循。編程實踐中铭腕,我選用C風(fēng)格的代碼。寫短小的函數(shù)多糠,原因是累舷,短小的函數(shù),易讀夹孔,便于調(diào)試笋粟。當然怀挠,還受制于許多程序員編程實踐中總結(jié)出的編程原則:一個函數(shù)只做一件事情。

《代碼整潔之道》用這樣的話強調(diào)這個編程原則:三十多年來害捕,無數(shù)人用無數(shù)不同的表達方式傳遞出這樣一個觀點绿淋,一個函數(shù)應(yīng)該只做一件事情;該函數(shù)應(yīng)該做好這件事情尝盼;該函數(shù)應(yīng)該做完這件事情吞滞。

掌握這項原則,必須弄明白:怎么叫一件事情盾沫?一件事情裁赠,是指這些事情都在同一個抽象層次上。舉個例子赴精,函數(shù)A把訂單數(shù)據(jù)存到數(shù)據(jù)庫佩捞,并在這個過程中創(chuàng)建券號、發(fā)送短信蕾哟。表面上看一忱,有三件事情,但由于它們都是同一個抽象層次上的事情谭确,所以帘营,實際上,只有一件事情逐哈。如果用創(chuàng)建券號中的代碼來取代創(chuàng)建券號函數(shù)芬迄,函數(shù)A就是做了兩件事情。

此外昂秃,“從上往下“讀函數(shù)(to...do)禀梳,也是區(qū)分函數(shù)是否做了一件事情的好方法。初級程序員要學(xué)會這一技巧肠骆,并不容易出皇。

看函數(shù)的區(qū)段,即一個函數(shù)能否再分拆出其他的函數(shù)哗戈,也是識別函數(shù)是否只做一件事情的方法。

我覺得荷科,根據(jù)”抽象層次“唯咬,就可以判斷函數(shù)是否只做了一件事情。

函數(shù)要區(qū)分指令和詢問畏浆。指令是指函數(shù)所做的事情胆胰,詢問是指函數(shù)回答了了什么問題。一個函數(shù)刻获,要么執(zhí)行指令蜀涨,要么回答詢問,不可同時做這兩件事,否則就違背了“一個函數(shù)應(yīng)該只做好一件事”的原則厚柳。改變類屬性的值是指令氧枣,獲取并返回用戶信息,是詢問别垮;把用戶數(shù)據(jù)存儲到數(shù)據(jù)庫是指令便监,檢測用戶A是否存在是詢問。代碼D碳想。

function isUserExists($userArray){

if $userArray exists{

return true;

}else{

save $userArray

return false;

}

}

上面的函數(shù)就把指令和詢問混合在了一起烧董。

函數(shù)要無副作用。具有副作用的函數(shù)胧奔,違背了“函數(shù)應(yīng)該只做一件事”的原則逊移,甚至還會違背“函數(shù)要區(qū)分指令和詢問”的原則,比如上面的代碼D龙填。具有副作用的函數(shù)胳泉,是隱藏的謊言。請看代碼D觅够,函數(shù)名告訴讀者胶背,它做的事情是檢測一個用戶是否存在。實際上它還在函數(shù)內(nèi)部“偷偷地”存儲了用戶數(shù)據(jù)喘先。不深入函數(shù)去看钳吟,無法知道它的真正功能。具有副作用的函數(shù)窘拯,會帶來一些預(yù)料之外的糟糕后果红且,要避免寫出有副作用的函數(shù)。

函數(shù)的參數(shù)宜少不宜多涤姊。無參數(shù)最佳暇番,一個參數(shù)還好,二個參數(shù)勉強還行思喊,三個甚至更多參數(shù)壁酬,要想辦法避免。參數(shù)代表不同概念恨课,越多舆乔,使用函數(shù)的時候越麻煩。即使有注釋剂公,可能仍然需要看函數(shù)體或其他相關(guān)資料希俩,記憶或弄清參數(shù)的順序,也不容易纲辽。兩個或兩個以上的參數(shù)颜武,測試函數(shù)的時候璃搜,這些參數(shù)會有多少個組合?需要多少測試用例才能完全覆蓋測試鳞上?(這是《代碼整潔之道》中的說法这吻,我不理解)。代碼E因块。

function getColumnValueById($id, column='*'){

$sql = 'SELECT ' . $column . ' FROM tableName WHERE id=' . $id;

$columnValue = execute($sql);

return $columnValue;

}

我可能會給這段代碼寫上注釋

/**

*@author ggh

*@purpose 根據(jù)id從tableName中獲取某個或幾個字段的值

*@return $columnValue

*/

假設(shè)tableName具有username橘原、password等字段,想通過getColumnValueById獲取username的值涡上,根據(jù)代碼并不能知道只需將$column賦值為username就可以了趾断,而是要根據(jù)注釋找到tableName,然后看存儲username的是哪個字段吩愧。將代碼E改寫為代碼F芋酌。

function getUsernameById($id){

$column='username';

$sql = 'SELECT ' . $column . ' FROM tableName WHERE id=' . $id;

$columnValue = execute($sql);

return $columnValue;

}

想查詢username的時候,直接調(diào)用getUsernameById就可以了雁佳,完全不需要去看tableName的字段脐帝。

若采用代碼F風(fēng)格,將產(chǎn)生大量的類似函數(shù)(重復(fù)代碼)糖权。目前堵腹,我是這么解決這個問題的。請看代碼G星澳。

function getColumnValueById($id, column='*'){

$sql = 'SELECT ' . $column . ' FROM tableName WHERE id=' . $id;

$columnValue = execute($sql);

return $columnValue;

}

function getUsernameById($id){

$column='username';

$username =getColumnValueById($id, column)疚顷;

return $username;

}

function getPasswordById($id){

$column='password';

$pwd=getColumnValueById($id, column);

return $pwd;

}

上面的一個簡單例子禁偎,應(yīng)該可以展示少參數(shù)函數(shù)的好處腿堤。那么如何減少函數(shù)的參數(shù)呢?無參數(shù)輸入如暖,函數(shù)的內(nèi)部代碼如何運行笆檀?工作中,我使用的一個類方法A盒至,參數(shù)有十幾個酗洒,而且還在不斷增加〖纤欤《代碼整潔之道》提供了一個方法:當一個函數(shù)需要的參數(shù)超過3個的時候樱衷,就應(yīng)該創(chuàng)建類,把需要的參數(shù)聲明為類屬性登淘。我那個函數(shù)可以用這種思路去減少參數(shù),但會增加很多類屬性封字、設(shè)置類屬性值的方法黔州。調(diào)用A的時候耍鬓,需要調(diào)用同原來A的參數(shù)個數(shù)一樣多的設(shè)置類屬性值的方法。A的參數(shù)從形式上減少了流妻,實質(zhì)仍未發(fā)生變化牲蜀,調(diào)用困難仍然存在。由于類方法A只在一處使用绅这,新增參數(shù)涣达,我只需在舊參數(shù)末尾加一個就可以。如果A被頻繁調(diào)用证薇,我每次都將不得不花一些事件詢問或看注釋這個參數(shù)應(yīng)該賦什么值度苔、那個參數(shù)應(yīng)該賦什么值。

通過創(chuàng)建類來減少函數(shù)參數(shù)的方法浑度,目前我沒有看到它的優(yōu)勢寇窑。編程中,我使用PHP中的數(shù)組來減少函數(shù)的參數(shù)箩张。代碼H甩骏。

function insertUser($username, $pwd, $age, $level){

save user

}

使用數(shù)組

$userArray = array('username'=>$username,'pwd'=>$username, 'age'=>$age,'level'=>$level);

function insertUser($userArray){

$username = $userArray['username'];

$pwd= $userArray['pwd'];

$age= $userArray['age'];

$level= $userArray['level'];

}

將許多參數(shù)放在數(shù)組里,然后將數(shù)組作為一個參數(shù)先慷,的確有效減少了參數(shù)個數(shù)饮笛,使函數(shù)看起來更美觀。僅此而已论熙,其他更多好處福青,有待發(fā)掘。

盡量避免使用輸出參數(shù)赴肚,即在函數(shù)中輸出一個變量素跺。我編程中常使用輸出參數(shù)。這樣可以消除重復(fù)代碼誉券,能使代碼更簡潔指厌。是否應(yīng)該使用輸出參數(shù),需要進一步衡量利弊踊跟。

能寫三篇《代碼整潔之道》讀書復(fù)述筆記踩验,歸功于前段時間看了幾章內(nèi)容。寫完函數(shù)這些章節(jié)商玫,若不抽時間看書箕憾,就無內(nèi)容可寫了。拋開《代碼整潔之道》看來的知識拳昌,寫作幾乎成了無米之炊袭异。可見工作以來炬藤,我掌握的知識御铃、準確地說碴里,透徹地掌握、能清楚地講出來的知識上真,非常少咬腋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市睡互,隨后出現(xiàn)的幾起案子根竿,更是在濱河造成了極大的恐慌,老刑警劉巖就珠,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寇壳,死亡現(xiàn)場離奇詭異,居然都是意外死亡嗓违,警方通過查閱死者的電腦和手機九巡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹂季,“玉大人冕广,你說我怎么就攤上這事〕ソ啵” “怎么了撒汉?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長涕滋。 經(jīng)常有香客問我睬辐,道長,這世上最難降的妖魔是什么宾肺? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任溯饵,我火速辦了婚禮,結(jié)果婚禮上锨用,老公的妹妹穿的比我還像新娘丰刊。我一直安慰自己,他們只是感情好增拥,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布啄巧。 她就那樣靜靜地躺著,像睡著了一般掌栅。 火紅的嫁衣襯著肌膚如雪秩仆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天猾封,我揣著相機與錄音澄耍,去河邊找鬼。 笑死,一個胖子當著我的面吹牛齐莲,可吹牛的內(nèi)容都是我干的卿城。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼铅搓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搀捷?” 一聲冷哼從身側(cè)響起星掰,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嫩舟,沒想到半個月后氢烘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡家厌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年播玖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饭于。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜀踏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掰吕,到底是詐尸還是另有隱情果覆,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布殖熟,位于F島的核電站局待,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏菱属。R本人自食惡果不足惜钳榨,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纽门。 院中可真熱鬧薛耻,春花似錦、人聲如沸膜毁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘟滨。三九已至候醒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杂瘸,已是汗流浹背倒淫。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留败玉,地道東北人敌土。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓镜硕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親返干。 傳聞我的和親對象是個殘疾皇子兴枯,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容