小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

代碼質(zhì)量隨想錄(一):可讀是王道

 rookie 2012-06-21

  一直以來(lái)想寫(xiě)點(diǎn)關(guān)于代碼質(zhì)量的心得,礙于自身的懶惰。今天終究找到一個(gè)提前忙完工作的午后,可以先讓自己的思路開(kāi)動(dòng)起來(lái)了。

  最終促使我開(kāi)始整理自己對(duì)于代碼質(zhì)量的看法,還多虧了前陣子認(rèn)識(shí)的Long小朋友,他及時(shí)地向我推薦了《The Art of Readable Code》這本書(shū)(下文簡(jiǎn)稱(chēng)ARC)。在看過(guò)了馬叔叔的《Clean Code》和《Clean Coder》之后,這本書(shū)徹底讓我沉迷于代碼質(zhì)量之中了。

  我就將每天讀書(shū)所做的筆記和自己的想法綜合起來(lái),再加上原來(lái)歷次項(xiàng)目之中的研究心得,陸續(xù)寫(xiě)出來(lái),與大家分享。也歡迎更多的代碼潔癖者一起交流。

  可讀性一直是代碼質(zhì)量管控所追求的目標(biāo)之一。沒(méi)有這個(gè),后面的可維護(hù)和可修改都不太容易達(dá)成。可讀性怎么強(qiáng)調(diào)都不為過(guò),ARC一書(shū)的作者對(duì)具備可讀性的代碼給出說(shuō)法是:

花最少的時(shí)間就能理解的代碼。

  私以為這個(gè)定義是我暫時(shí)能找到的比較合理的解釋了。可讀性的研究應(yīng)該從橫向與縱向兩個(gè)層面展開(kāi)。

  橫向地說(shuō),團(tuán)隊(duì)內(nèi)部,尤其是開(kāi)源項(xiàng)目,更是要維護(hù)個(gè)成員之間對(duì)代碼的理解度。封裝與理解并不矛盾,封裝是為了更好的讓客戶代碼理解其結(jié)構(gòu)與功能,更為恰當(dāng)?shù)厥褂眠@個(gè)模塊。僥幸將自己搞不清爽的代碼以封裝的名義塞到某個(gè)莫名其妙的類(lèi)中,終歸會(huì)導(dǎo)致那部分代碼的缺陷通過(guò)接口或頻繁使用暴露出來(lái)。這一點(diǎn)是個(gè)大問(wèn)題,以后專(zhuān)文再述。

  在同一個(gè)項(xiàng)目或者同一個(gè)模塊工作的開(kāi)發(fā)者之間一定要彼此理解對(duì)方所寫(xiě)的代碼。這就是我為何一再?gòu)?qiáng)調(diào)“交叉代碼評(píng)審” 的原因。為了減少橫向溝通的時(shí)間,提高合作效率,大家最好是在一份理解的比較透徹的代碼庫(kù)上進(jìn)行協(xié)作。如果發(fā)現(xiàn)某段代碼出現(xiàn)難于理解的情況,立即自我檢 查、并于其他同事討論,大家一起拿出來(lái)個(gè)所有人都易于理解的辦法來(lái)。切勿打出“時(shí)間緊,以后再說(shuō)”(一旦說(shuō)出這種話,我還沒(méi)見(jiàn)過(guò)以后還有人會(huì)主動(dòng)回過(guò)頭來(lái) 整理代碼)的擋箭牌或者“勿要過(guò)分偏執(zhí)于代碼質(zhì)量”這樣的理由。

  實(shí)際上,很多工作中的溝通不暢都是源于對(duì)產(chǎn)品代碼、設(shè)計(jì)、架構(gòu)的理解不到位。對(duì)于這個(gè)問(wèn)題,我提倡采用極限編程或與其等效的協(xié)同式結(jié)對(duì)或組團(tuán)工作法,同時(shí)縮短代碼評(píng)審周期。所有一線程序員一定要經(jīng)常舉行20-25分鐘左右(番茄法)的技術(shù)討論對(duì)話。

  縱向地說(shuō),代碼的理解實(shí)際上也是對(duì)程序員本人業(yè)務(wù)能力的一種拓展訓(xùn)練。在沒(méi)有系統(tǒng)地學(xué)習(xí)敏捷開(kāi)發(fā)等代碼管控技術(shù)之前,我經(jīng)常對(duì)自己幾個(gè)月前、幾 周前甚至三天前所寫(xiě)的代碼一頭霧水,根本不清楚當(dāng)時(shí)是在何種情境下寫(xiě)出那些代碼的。協(xié)同工作時(shí)更為嚴(yán)重,我們不僅要理解自己很久以前寫(xiě)過(guò)的代碼,還要理解 其他同事甚至離職人員的遺留代碼。如果不及時(shí)進(jìn)行品質(zhì)管控,整個(gè)項(xiàng)目就無(wú)法繼續(xù)健康的運(yùn)作下去,因?yàn)閷?duì)當(dāng)前模塊的編寫(xiě)勢(shì)必要引入原來(lái)的既有模塊,而且為了 應(yīng)對(duì)復(fù)雜多變的需求,必須經(jīng)常把原來(lái)的代碼拿出來(lái)曬太陽(yáng),以便理順?biāo)悸?,盡速應(yīng)對(duì)需求。長(zhǎng)時(shí)間進(jìn)行有意識(shí)的質(zhì)量訓(xùn)練,就可以在工作中積累大量的代碼范式和可復(fù)用模塊,并且在遇到新工作的新需求時(shí)及時(shí)從腦中呼出原有的高品質(zhì)解決方案。

  在談到對(duì)“理解”的判定標(biāo)準(zhǔn)時(shí),ARC的作者提出的標(biāo)準(zhǔn)也比較有參考性。他們認(rèn)為,代碼閱讀者能夠?qū)ζ渥鞒鲂薷?、能夠指出其中的Bug、能夠理解它與其余部分代碼是如何進(jìn)行溝通的。做到了上述這些,才算“完全理解了代碼”。小翔我雅以為是。在進(jìn)行上述我提到的橫向和縱向溝通時(shí),都必須以“徹底”理解為溝通目標(biāo),不要蒙混過(guò)去。

  除了橫向和縱向的溝通問(wèn)題之外,還有一個(gè)問(wèn)題就是如何處理代碼質(zhì)量與其他工程要素之間的關(guān)系,例如代碼執(zhí)行效率、軟件設(shè)計(jì)與架構(gòu)、代碼是否易于測(cè)試等等。很多反對(duì)花時(shí)間提升代碼質(zhì)量的人都拿這些來(lái)做文章。不過(guò)依我在實(shí)際工作中的感覺(jué)是,如果因?yàn)榇a品質(zhì)得不到保證而導(dǎo)致溝通不暢,那么相應(yīng)的效率、架構(gòu)、易測(cè)試性都可能隨之出現(xiàn)問(wèn)題,因?yàn)樗鼈冏罱K都要落實(shí)到具體代碼與具體開(kāi)發(fā)者身上,一個(gè)尊崇易讀性的編碼環(huán)境才能催生執(zhí)行高效、架構(gòu)合理、易于測(cè)試的代碼。

  原來(lái)我之所以沒(méi)有及時(shí)將代碼質(zhì)量的相關(guān)心得與想法總結(jié)起來(lái),很重要的一個(gè)原因是代碼質(zhì)量所涉及的知識(shí)點(diǎn)太多、太散,而且和其他話題聯(lián)系頗多。在 開(kāi)始讀ARC這本書(shū)之后,我決定依照可讀性為主線,把我這個(gè)有代碼潔癖者的所思所想整理成系列文章,這樣更方便按照主題去閱讀、研究。

  說(shuō)到到可讀性的具體判定標(biāo)準(zhǔn),這則是要靠每個(gè)人在學(xué)習(xí)、工作中不斷總結(jié)出來(lái)的。很多教材整本書(shū)所講的就是如何依據(jù)一系列的經(jīng)驗(yàn)法則來(lái)指導(dǎo)編程,比如《Clean Code》。我以為不妨按照代碼層級(jí),將可讀性的研究分為“零散代碼改觀”、“簡(jiǎn)化邏輯與循環(huán)”、“宏觀結(jié)構(gòu)重整”三 個(gè)部分。零散代碼改觀涉及函數(shù)或方法內(nèi)部的命名與注釋等僅涵蓋數(shù)行代碼的初階問(wèn)題。而邏輯與循環(huán)則是函數(shù)或方法代碼中的核心部分,它們通常以代碼塊或數(shù)行 與流程相關(guān)的代碼組成。針對(duì)此部分的品質(zhì)提升,主要表現(xiàn)在梳理控制流、簡(jiǎn)化表達(dá)式、考究循環(huán)控制變量等問(wèn)題。結(jié)構(gòu)重整就是在更為宏觀的函數(shù)、類(lèi)、包等級(jí)別 上進(jìn)行質(zhì)量管控。

  為了說(shuō)明代碼質(zhì)量不是隨心所欲能決定的,我就翻炒一下ARC中的幾個(gè)小例子(小栗子)。

  跟著感覺(jué)走,有時(shí)不可靠。

Node node = list.head;
if (node == null)
  return;
while (node.next != null) {
  print(node.data);
  node = node.next;
}
if (node != null)
  print(node.data);

  這段代碼當(dāng)然不如下面這段簡(jiǎn)潔,這大家憑感覺(jué)就能看出來(lái):

for (Node node = list.head; node != null; node = node.next)
  print(node.data);

  然而

return exponent >=0? mantissa *(1<< exponent): mantissa /(1<<-exponent);

  與

if (exponent >= 0) {
return mantissa * (1 << exponent);
} else {
return mantissa / (1 << -exponent);
}

  誰(shuí)好誰(shuí)壞就難說(shuō)了。第一個(gè)更簡(jiǎn)潔,第二個(gè)更具親和力。

  短代碼未必不好

assert((!(bucket = findBucket(key)))||!bucket.isOccupied());

  上一段代碼的可讀性不如下一段:

bucket = findBucket(key);
if(bucket !=null)assert(!bucket.isOccupied());

  多寫(xiě)點(diǎn)注釋也好

// 更快地執(zhí)行"
hash = (65599 * hash) + c"hash =(hash <<6)+(hash <<16)- hash + c;

  上面這段代碼多虧了這個(gè)注釋?zhuān)駝t立刻滑入雜技代碼的深淵。

  下幾篇系列文章將講述如何選取易讀的標(biāo)識(shí)符名稱(chēng)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多