高效程序員的十個習慣

高效程序員的十個習慣

來源於“高效程序員的45個習慣-敏捷開發修煉之道”中的部分習慣的摘抄與個人部分讀後感,目的:注重於培養軟件開發者的態度、原則、操守、價值觀,交付高質量的軟件

敏捷概述

迭代開發,價值優先分解任務,真實進度
站立會議,交流暢通用戶參與,調整方向
結對編程,代碼質量測試驅動,安全可靠
持續集成,儘早反饋自動部署,一鍵安裝

1.對事不對人

對方案設計的討論失控變成了情緒化的指責——做決定是基於誰提出了這個觀點,而不是權衡觀點本身的利弊。一個團隊能夠很公正地討論一些方案的優點和缺點,你不會因爲拒絕了有太多缺陷的方案而傷害別人,也不會因爲採納了某個不甚完美(但是更好的)解決方案而被人忌恨。

如果你準備提出一個想法,卻擔心有可能被嘲笑,或者你要提出一個建議,卻擔心自己丟面子,那麼你就不會主動提出自己的建議了。然而,好的軟件開發作品和好的軟件設計,都需要大量的創造力和洞察力。分享並融合各種不同的想法和觀點,遠遠勝於單個想法爲項目帶來的價值。
負面的評論和態度扼殺了創新,你必須把重點放在解決問題上,而不是去極力證明誰的主意更好。在團隊中智商高是沒有用的,如果他還很頑固並且拒絕合作,那就更糟糕。在這樣的團隊中,生產率和創新都會頻臨滅亡的邊緣。
我們每個人都會有好的想法,也會有不對的想法,團隊中的每個人都需要自由地表達觀點。即使你的建議不被全盤接受,也能對終解決問題有所幫助。不要害怕受到批評。記住,任何一個專家都是從這裏開始的。“你不需要很出色才能起步,但是你必須起步才能變得很出色。”
集體決策確實非常有效,但也有一些最好的創新源於很有見地的個人的獨立思考。如果你是一個有遠見的人,就一定要特別尊重別人的意見。你是一個掌舵者,一定要把握方向,深思熟慮,吸取各方的意見。另一個極端是缺乏生氣的委員會,每個設計方案都需要全票通過。這樣的委員會總是小題大作,如果讓他們造一匹木馬,很可能最後造出的是駱駝。並不是建議你限制會議決策,只是你不應該成爲一意孤行的首席架構師的傀儡。這裏建議你牢記亞里士多德的一句格言:“能容納自己並不接受的想法,表明你的頭腦足夠有學識”

有效方式
設定終期限:如果你正在參加設計方案討論會,或者是尋找解決方案時遇到問題,請設定一個明確的終期限,例如午飯時間或者一天的結束。這樣的時間限制可以防止人們陷入無休止的理論爭辯之中,保證團隊工作的順利進行。同時應現實一些:沒有最好的答案,只有更合適的方案。設定期限能夠幫你在爲難的時候果斷做出決策,讓工作可以繼續進行。
逆向思維:團隊中的每個成員都應該意識到權衡的必要性。一種客觀對待問題的辦法是:先是積極地看到它的正面,然後再努力地從反面去認識它。目的是要找出優點多缺點少的那個方案,而這個好辦法可以儘可能地發現其優缺點,這也有助於少帶個人感情。
設立仲裁人:在會議的開始,選擇一個仲裁人作爲本次會議的決策者。每個人都要有機會針對問題暢所欲言。仲裁人的責任就是確保每個人都有發言的機會,並維持會議的正常進行。仲裁人可以防止明星員工操縱會議,並及時打斷假大空式發言。如果你自己沒有積極參與這次討論活動,那麼你好退一步做會議的監督者。仲裁人應該專注於調停,而不是發表自己的觀點(理想情況下不應在整個項目中有既得利益)。當然,這項任務不需要嚴格的技術技能,需要的是和他人打交道的能力。
支持已經做出的決定:一旦方案被確定了(不管是什麼樣的方案),每個團隊成員都必須通力合作,努力實現這個方案。每個人都要時刻記住,我們的目標是讓項目成功
滿足用戶需求:客戶並不關心這是誰的主意——他們關心的是,這個軟件是否可以工作,並且是否符合他們的期望。
結果重要:設計充滿了妥協,成功屬於意識到這一點的團隊。工作中不感情用事是需要剋制力的,而你若能展現出成熟大度來,大家一定不會視而不見。這需要有人帶頭,身體力行,去感染另一部分人。

對事不對人:讓我們驕傲的應該是解決了問題,而不是比較出誰的主意更好。

平衡的藝術
1.盡力貢獻自己的好想法,如果你的想法沒有被採納也無需生氣。不要因爲只是想體現自己的想法而對擬定的好思路畫蛇添足。
2. 脫離實際的反方觀點會使爭論變味。若對一個想法有成見,你很容易提出一堆不太可能發生或不太實際的情形去批駁它。這時,請先捫心自問:類似問題以前發生過嗎?是否經常發生?
3. “我們不能採用這個方案,因爲數據庫廠商可能會倒閉”或者:用戶絕對不會接受那個方案。你必須要評判那些場景發生的可能性有多大。想要支持或者反駁一個觀點,有時候你必須先做一個原型或者調查出它有多少的同意者或者反對者。
4. 在開始尋找
好的解決方案之前,大家對“最好”的含義要先達成共識。在開發者眼中的 好,不一定就是用戶認爲 好的,反之亦然。
5. 只有更好,沒有最好,只有在某個特定條件下更好的實踐。
6. 不帶個人情緒並不是要盲目地接受所有的觀點。用合適的詞和理由去解釋爲什麼你不贊同這個觀點或方案,並提出明確的問題。

2.跟蹤變化

軟件技術的變化如此之快,繼續用你熟悉的語言做你的老本行,你不可能跟上技術變化的腳步。

跟上技術變化的步伐的建議
迭代和增量式的學習:每天計劃用一段時間來學習新技術,它不需要很長時間,但需要經常進行。記下那些你想學習的東西——當你聽到一些不熟悉的術語或者短語時,簡要地把它記錄下來。然後在計劃的時間中深入研究它。
瞭解新行情:互聯網上有大量關於學習新技術的資源。閱讀社區討論和郵件列表,可以瞭解其他人遇到的問題,以及他們發現的很酷的解決方案。選擇一些公認的優秀技
術博客,經常去讀一讀,以瞭解那些頂尖的博客作者們正在關注什麼
參加本地的用戶組活動,聽講座,參加研討會議: 各種技術在很多地區都會有用戶組,加入微信羣或者QQ羣。聽IT先進公司的公開課程。
如飢似渴地閱讀:找一些關於軟件開發和非技術主題的好書(我們很樂意爲你推薦),也可以是一些專業的期刊和商業雜誌,甚至是一些大衆媒體新聞(有趣的是在那裏常常能看到老技術被吹捧爲
新潮流)。
跟蹤技術變化: 你不需要精通所有技術,但需要清楚知道行業的動向,從而規劃你的項目和職業生涯。

平衡的藝術
1.許多新想法從未變得羽翼豐滿,成爲有用的技術。即使是大型、熱門和資金充裕的項目也會有同樣的下場。你要正確把握自己投入的精力。
2.你不可能精通每一項技術,沒有必要去做這樣的嘗試。只要你在某些方面成爲專家,就能使用同樣的方法,很容易地成爲新領域的專家。
3.你要明白爲什麼需要這項新技術——它試圖解決什麼樣的問題?它可以被用在什麼地方?
4.避免在一時衝動的情況下,只是因爲想學習而將應用切換到新的技術、框架或開發語言。在做決策之前,你必須評估新技術的優勢。開發一個小的原型系統,是對付技術狂熱者的一劑良藥。

3.讓設計指導而不是操縱開發

好的設計應該是正確的,而不是精確的。也就是說,它描述的一切必須是正確的,不應該涉及不確定或者可能會發生變化的細節。好設計是一張地圖,它也會進化。設計指引你向正確的方向前進,它不應該標識具體的路線,是目標,不是具體的處方。你不要被設計(或者設計師)操縱。

“設計”是軟件開發過程不可缺少的步驟。它幫助你理解系統的細節,理解部件和子系統之間的關係,並且指導你的實現。一些成熟的方法論很強調設計,例如,統一過程(Unified Process,UP)十分重視和產品相關的文檔。項目管理者和企業主常常爲開發細節困擾,他們希望在開始編碼之前,先有完整的設計和文檔。畢竟那也是你如何管理橋樑或建築項目的。
另一方面,敏捷方法建議你早在開發初期就開始編碼,但不就意味着沒有設計,好的設計仍然十分重要。畫關鍵工作圖(例如,用UML)是必不可少的,因爲要使用類及其交互關係來描繪系統是如何組織的。在做設計的時候,你需要花時間去思考(討論)各種不同選擇的缺陷和益處,以及如何做權衡。然後下一步才考慮是否需要開始編碼。如果你在前期沒有考慮清楚這些問題,就草草地開始編碼,很可能會被很多意料之外的問題搞暈。
但是,即使之前已經提交了設計文檔,也還會有一些意料之外的情況出現。時刻謹記,此階段提出的設計只是基於你目前對需求的理解而已。一旦開始了編碼,一切都會改變。設計及其代碼實現會不停地發展和變化。
一些項目領導和經理認爲設計應該儘可能地詳細,這樣就可以簡單地交付給“代碼工人們”。他們認爲代碼工人不需要做任何決定,只要簡單地把設計轉化成代碼就可以了,沒有一個願意在這樣的團隊中做純粹的打字員。
如果系統和已有代碼的現狀表明接收到的設計不夠理想,那該怎麼辦?太糟糕了!時間已經花費在設計上,沒有工夫回頭重新設計了。團隊會死撐下去,用代碼實現了明明知道是錯誤的設計。這聽起來是不是很愚蠢?是夠愚蠢的,但是有一些公司真的就是這樣做的。嚴格的需求—設計—代碼—測試開發流程源於理想化的瀑布式開發方法,它導致在前面進行了過度的設計。這樣在項目的生命週期中,更新和維護這些詳細的設計文檔變成了主要工作,需要時間和資源方面的巨大投資,卻只有很少的回報。我們本可以做得更好。
設計可以分爲兩層:戰略和戰術,前期的設計屬於戰略,通常只有在沒有深入理解需求的時候需要這樣的設計。更確切地說,它應該只描述總體戰略,不應深入到具體的細節。戰略級別的設計不應該具體說明程序方法、參數、字段和對象交互精確順序的細節。那應該留到戰術設計階段,它應該在項目開發的時候再具體展開。不要一開始就進行戰術設計,它的重點是集中在單個的方法或數據類型上。這時,更適合討論如何設計類的職責。因爲這仍然是一個高層次、面向目標的設計。事實上,CRC(類—職責—協作)卡片的設計方法就是用來做這個事情的。每個類術語描述。類名。職責:它應該做什麼?協作者:要完成工作它要與其他什麼對象一起工作?
如何知道一個設計是好的設計,或者正合適?代碼很自然地爲設計的好壞提供了好的反饋。如果需求有了小的變化,它仍然容易去實現,那麼它就是好的設計。而如果小的需求變化就帶來一大批基礎代碼的破壞,那麼設計就需要改進。

平衡的藝術
“不要在前期做大量的設計”並不是說不要設計。只是說在沒有經過真正的代碼驗證之前,不要陷入太多的設計任務。當對設計一無所知的時候,投入編碼也是一件危險的事。如果深入編碼只是爲了學習或創造原型,只要你隨後能把這些代碼扔掉,那也是一個不錯的辦法。
即使初始的設計到後面不再管用,你仍需設計:設計行爲是無價的。正如美國總統艾森豪威爾所說:“計劃是沒有價值的,但計劃的過程是必不可少的” 在設計過程中學習是有價值的,但設計本身也許沒有太大的用處。 白板、草圖、便利貼都是非常好的設計工具。複雜的建模工具只會讓你分散精力,而不是啓發你的工作。

4.提早實現自動化部署

系統的安裝或者部署應該簡單、可靠及可重複。一切都很自然。

系統能在開發者,測試人員,用戶的機器上,生產環境中部署運行當然很好,但是這就意味着,你要能用一種可重複和可靠的方式,在目標機器上部署你的應用。不幸的是,大部分開發者只會在項目的尾期纔開始考慮部署問題。結果經常出現部署失敗,要麼是少了依賴的組件,要麼是少了一些圖片,要麼就是目錄結構有誤。
如果開發者改變了應用的目錄結構,或者是在不同的應用之間創建和共享圖片目錄,很可能會導致安裝過程失敗。當這些變化在人們印象中還很深的時候,你可以快速地找到各種問題。但是幾周或者幾個月之後查找它們,特別是在給客戶演示的時候,可就不是一件鬧着玩的事情了。
如果還是手工安裝應用,那麼後把應用部署到生產環境時會發生什麼呢?就算公司給你加班費,你也不願意爲不同用戶的機器或不同地點的服務器上一遍又一遍地安裝應用。 有了自動化部署系統後,在項目開發的整個過程中,會更容易適應互相依賴的變化。很可能你在安裝系統的時候,會忘記添加需要的庫或組件——在任意一臺機器上運行自動化安裝程序,你很快就會知道什麼丟失了。如果因爲缺少了一些組件,從第一天起就開始交付一開始就進行全面部署,而不是等到項目的後期,這會有很多好處。事實上,有些項目在正式開發之前,就設置好了所有的安裝環境。要求大家爲預期客戶實現一個簡單的功能演示——驗證一個概念的可行性。即使項目還沒有正式開始,我們就有了單元測試、持續集成和基於窗口的安裝程序。這樣,我們就可以更容易更簡單地給用戶交付這個演示系統:用戶所要做的工作,就是從我們的網站上點擊一個鏈接,然後就可以自己在各種不同的機器上安裝這個演示系統了。
在簽約之前,就能提供出如此強大的演示,這無疑證明了我們非常專業,具有強大的開發能力。一開始就實現自動化部署應用。使用部署系統安裝你的應用,在不同的機器上用不同的配置文件測試依賴的問題。質量保證人員要像測試應用一樣測試部署。
平衡的藝術
1.一般產品在安裝的時候,都需要有相應的軟、硬件環境。比如,Java或Ruby 的某個版本、外部數據庫或者操作系統,檢查依賴關係,也是安裝過程的一部分。
2. 在沒有詢問並徵得用戶的同意之前,安裝程序絕對不能刪除用戶的數據。提早實現自動化部署
3. 部署一個緊急修復的bug應該很簡單,特別是在生產服務器的環境中。但是在凌晨3點半,你還在手工部署系統。
4. 用戶應該可以安全並且完整地卸載安裝程序,特別是在質量保證人員的機器環境中。
5. 如果維護安裝腳本變得很困難,那很可能是一個早期警告,預示着——很高的維護成本(或者不好的設計決策)。

5.度量真實的進度

清楚項目的真實進度,是一項強大的技術。度量剩下的工作量。不要用不恰當的度量來欺騙自己或者團隊。要評估那些需要完成的待辦事項。使用待辦事項及個人與項目管理工具的列表的更多信息,用自己的時間表報告工作進度,用它做項目計劃。不用管那些實際的工作時間,每週填滿40小時就可以了。

時間的消逝(通常很快)可以證明:判斷工作進度 好是看實際花費的時間而不是估計的時間。你說早已經用時間表進行了追蹤。不幸的是,幾乎所有公司的時間表都是爲工資會計準備的,不是用來度量軟件項目的開發進度的。例如,如果你工作了60 個小時,也許你的老闆會讓你在時間表上只填寫40個小時,這是公司會計想看到的。所以,時間表很難真實地反映工作完成狀況,因此它不可以用來進行項目計劃、評估或表現評估。即使沒有時間表,一些開發人員還是很難面對現實了,專注於你的方向解自己的真實進度。你曾經聽到開發人員報告一個任務完成了80%嗎?然而過了一天又一天,一週又一 Focus on where 周,那個任務仍然是完成了80%?隨意用一個比率進行度量是沒有意義的,這就好比是說80%是對的(除非你是政客,否則對和錯應該是布爾條件)。所以,我們不應該去計算工作量完成的百分比,而應該測定還剩下多少工作量沒有完成。如果你
初估計這個任務需要40個小時,在開發了35
個小時之後,你認爲還需要另外30個小時的工作。那就得到了很重要的度量結果(這裏誠實非常重要,隱瞞真相毫無意義)。
在你後真正完成一項任務時,要清楚知道完成這個任務真正花費的時間。奇怪的是,它花費的時間很可能要比 初估計時間長。沒有關係,我們希望這能作爲下一次的參考。在爲下一個任務估計工作量時,可以根據這次經驗調整評估。如果你低估了一個任務,評估是2天,它後花費了6天,那麼係數就是3。除非是異常情況,否則你應該對下次估計乘以係數3。你的評估會波動一段時間,有時候過低估計,有時候過高估計。但隨着時間的推移,你的評估會與事實接近,你也會對任務所花費的時間有更清楚的認識。

度量真實的進度,如果能一直讓下一步工作是可見的,會有助於進度度量。 好的做法就是使用待辦事項(backlog)。待辦事項就是等待完成的任務列表。當一個任務被完成了,它就會從列表中移除(邏輯上的,而物理上就是把它從列表中劃掉,或者標識它是完成的狀態)。當添加新任務的時候,先排列它們的優先級,然後加入到待辦事項中。你也可以有個人的待辦事項、當前迭代的待辦事項或者整個項目的待辦事項。通過代辦事項,就可以隨時知道下一步 重要的任務是什麼。同時,你的評估技巧也在不停地改進,你也會越來越清楚完成一項任務要花費的時間。

Scrum方法中的sprint
在Scrum(迭代增量開發方法),每個迭代被稱作sprint,通常爲30天時間。sprint 的待辦事項列表是當前迭代任務列表,它會評估剩下的工作量,顯示每個任務還需要多少小時可以完成。每個工作日,每個團隊成員會重新評估完成一個任務還需要多少小時。不管怎麼樣,只要所有任務的評估總和超過了一個迭代剩餘的時間,那麼任務就必須移到下一個迭代中開發。如果每月還有一些剩餘的時間,你還可以添加新的任務。這樣做,客戶一定會非常喜歡並且你會覺得很舒服,因爲你很清楚哪些任務已經完成,哪些是沒有完成的,以及它們的優先級。

平衡的藝術

  1. 6分鐘作爲一個時間單位,它的粒度實在太細了,這不是敏捷的做法。一週或者一個月的時間單元,它的粒度太粗了,這也不是敏捷的做法。需要關注功能,而不是日程表。
  2. 如果你在一個項目中花費了很多時間來了解你所花費的時間,而沒有足夠的時間進行工作,那麼你在瞭解你所花費的時間上花費的時間就太多了。
  3. 一週工作40個小時,不是說你就有40個小時的編碼時間。你需要減去會議、電話、電子郵件以及其他相關活動的時間。

6.用代碼溝通

註釋就像是可以幫助你的好朋友,可以先閱讀註釋,然後快速瀏覽代碼,從而完全理解它做了什麼,以及爲什麼這樣做。建立代碼文檔無外乎兩種方式:利用代碼本身;利用註釋來溝通代碼之外的問題。用註釋溝通。使用細心選擇的、有意義的命名。用註釋描述代碼意圖和約束。註釋不能替代優秀的代碼。

“如果代碼太雜亂以至於無法閱讀,就應該使用註釋來說明。精確地解釋代碼做了什麼,每行代碼都要加註釋。不用管爲什麼要這樣編碼,只要告訴我們到底是怎麼做的就好了。”通常程序員都很討厭寫文檔。這是因爲大部分文檔都與代碼沒有關係,並且越來越難以保證其符合目前的新狀況。這不只違反了DRY原則(不要重複你自己,
Don’t Repeat Yourself),還會產生使人誤解的文檔,這還不如沒有文檔。
如果必須通讀一個方法的代碼才能瞭解它做了什麼,那麼開發人員先要投入大量的時間和精力不要用註釋來包裹你的代碼 。反過來講,只需短短几行註釋說明方法行爲,就可以讓生活變得輕鬆許多。開發人員可以很快了解到它的意圖、它的期待結果,以及應該注意之處這可省了你不少勁兒。應該文檔化你所有的代碼嗎?在某種程度上說,是的。但這並不意味着要註釋絕大部分代碼,特別是在方法體內部。源代碼可以被讀懂,不是因爲其中的註釋,而應該是由於它本身優雅而清晰——變量名運用正確、空格使用得當、邏輯分離清晰,以及表達式非常簡潔。
如何命名很重要。程序元素的命名是代碼讀者必讀的部分。通過使用細心挑選的名稱,可以向閱讀者傳遞大量的意圖和信息。反過來講,使用人造的命名範式會讓代碼難以閱讀和理解。這些範式中包括的底層數據類型信息,會硬編碼在變量名和方法名中,形成脆弱、僵化的。知道一件事物的真實名稱可以讓。
使用細心挑選的名稱和清晰的執行路徑,代碼幾乎不需要註釋。許多註釋沒有傳遞任何有意義的信息,這種註釋只會分散注意力,而且很容易失去時效性。
註釋可用來爲讀者指定一條正確的代碼訪問路線圖。爲代碼中的每個類或模塊添加一個短小的描述,說明其目的以及是否有任何特別需求。對於類中的每個方法,可能要說明下列信息。
1.目的:爲什麼需要這個方法?
2.需求(前置條件):方法需要什麼樣的輸入,對象必須處於何種狀態,才能讓這個方法工作?
3.承諾(後置條件):方法成功執行後,對象現在處於什麼狀態,有哪些返回值?
4.異常:可能會發生什麼樣的問題?會拋出什麼樣的異常?

文檔不只是爲團隊或組織之外的人準備的。假定你要修改幾個月之前所寫的代碼,如果只要看一下方法頭上的註釋,就知道需要了解的重要細節,那麼修改起來是不是會方便很多。

平衡的藝術
1.花時間去寫簡明扼要的註釋吧,代碼可以傳遞意圖的地方不要使用註釋
2.解釋代碼做了什麼的註釋用處不那麼大。相反,註釋要說明爲什麼會這樣寫代碼。
3.當重寫方法時,保留描述原有方法意圖和約束的註釋。

7.編寫內聚的代碼

編寫新的代碼,首先要決定的就是把這些代碼放在什麼地方。如果所有的代碼都在一個類或組件裏面,要找起來是很方便的。內聚性用來評估一個組件(包、模塊或配件)中成員的功能相關性。內聚程度高,表明各個成員共同完成了一個功能特性或是一組功能特性。內聚程度低的話,表明各個成員提供的功能是互不相干的。每個類或組件只做一件事,而且做得很好。bug 很容易跟蹤,代碼也易於修改,因爲類和組件的責任都很清晰。

如何組織一個組件中的代碼,會對開發人員的生產力和全部代碼的可維護性產生重要影響。在決定創建一個類的時候,問問自己,這個類的功能是不是與組件中其他某個類的功能類似,而且功能緊密相關。這就是組件級的內聚性。類也要遵循內聚性。如果一個類的方法和屬性共同完成了一個功能(或是一系列緊密相關的功能),這個類就是內聚的。

假定要對數據庫的表結構進行一次微調。這個微小的變化會導致應用中所有的頁面發生變化,而且每個頁面中都會有多處改變——這個應用很快就變成了一場災難。如果應用使用了中間層對象(比如一個COM組件)來訪問數據庫,數據庫表結構變更所造成的影響就可以控制在一定的範圍之內,代碼也更容易維護。
低內聚性的代碼會造成很嚴重的後果。假設有這樣一個類,實現了五種完全不相干的功能。如果這5個功能的需求或細節發生了變化,這個類也必須跟着改變。如果一個類(或者一個組件)變化得過於頻繁,這樣的改變會對整個系統形成“漣漪效應”,並導致更多的維護和成本的發生。考慮另一個只實現了一種功能的類,這個類變化的頻度就沒有那麼高。類似地,一個更具內聚性的組件不會有太多導致其變化的原因,也因此而更加穩定。根據單一職責原則一個模塊應該只有一個發生變化的原因。
一些設計技巧可以起到幫助作用。舉例來說,我們常常使用模型—視圖—控制器(MVC)模式來分離展示層邏輯、控制器和模型。這個模式非常有效,因爲它可以讓開發人員獲得更高的內聚性。模型中的類包含一種功能,在控制器中的類包含另外的功能,而視圖中的類則只關心UI。內聚性會影響一個組件的可重用性。組件粒度是在設計時要考慮的一個重要因素。根據重用發佈等價原則:重用的粒度與發佈的粒度相同。這就是說,程序庫用戶所需要的,是完整的程序庫,而不只是其中的一部分。如果不能遵循這個原則,組件用戶就會被強迫只能使用所發佈組件的一部分。很不幸的是,他們仍然會被不關心的那一部分的更新所影響。軟件包越大,可重用性就越差。 讓類的功能儘量集中,讓組件儘量小。要避免創建很大的類或組件,也不要創建無所不包的大雜燴類。

平衡的藝術
1.有可能會把一些東西拆分成很多微小的部分,而使其失去了實用價值。當你需要一隻襪子的時候,一盒棉線不能帶給你任何幫助。
2.具有良好內聚性的代碼,可能會根據需求的變化,而成比例地進行變更。考慮一下,實現一個簡單的功能變化需要變更多少代碼。

8.根據契約進行替換

保持系統靈活性的關鍵方式,是當新代碼取代原有代碼之後,其他已有的代碼不會意識到任何差別。深層次的繼承是很棒的。如果你需要其他類的函數,直接繼承它們就好了!不要擔心你創建的新類會造成破壞,你的調用者可以改變他們的代碼。這是他們的問題,而不是你的問題。

某個開發人員可能想爲通信的底層架構添加一種新的加密方式,或者使用同樣的接口實現更好的搜索算法。只要接口保持不變,開發人員就可以隨意修改實現代碼,而不影響其他任何現有代碼。然而,說起來容易,做起來難。所以需要一點指導來幫助我們正確地實現。
Liskov替換原則告訴我們:任何繼承後得到的派生類對象,必須可以替換任何被使用的基類對象,而且使用者不必知道任何差異。換句話說,某段代碼如果使用了基類中的方法,就必須能夠使用派生類的對象,並且自己不必進行任何修改。要遵守Liskov替換原則,相對基類的對應方法,派生類服務(方法)應該不要求更多,不承諾更少;要可以進行自由的替換。在設計類的繼承層次時,這是一個非常重要的考慮因素。繼承是OO建模和編程中被濫用多的概念之一。如果違反了Liskov替換原則,繼承層次可能仍然可以提供代碼的可重用性,但是將會失去可擴展性。類繼承關係的使用者現在必須要檢查給定對象的類型,以確定如何針對其進行處理。當引入了新的類之後,調用代碼必須經常重新評估並修正,這不是敏捷的方式。但是可以借用一些幫助。

當使用繼承時,要想想派生類是否可以替換基類。如果答案是不能,就要問問自己爲什麼要使用繼承。如果答案是希望在編寫新類的時候,還要重用基類中的代碼,也許要考慮轉而使用聚合。聚合是指在類中包含一個對象,並且該對象是其他類的實例,開發人員將責任委託給所包含的對象來完成。
那麼繼承和聚合分別在什麼時候使用呢?
1.如果新類可以替換已有的類,並且它們之間的關係可以通過is-a來描述,就要使用繼承。
2. 如果新類只是使用已有的類,並且兩者之間的關係可以描述爲has-a或是uses-a,就使用聚合吧。
開發人員可能會爭辯說,在使用聚合時,必須要寫很多小方法,來將方法調用指向所包含的對象。在繼承中,不需要這樣做,因爲基類中的公共方法在派生類中就已經是可用的了。僅憑這一點,並不能構成使用繼承足夠好的理由。通過替換代碼來擴展系統。通過替換遵循接口契約的類,來添加並改進功能特性。要多使用委託而不是繼承。

平衡的藝術

  1. 相對繼承來說,聚合更加靈活,適應力也更強。
  2. 繼承不是魔鬼,只是長久以來被大家誤解了。
  3. 如果你不確定一個接口做出了什麼樣的承諾,或是有什麼樣的需求,那就很難提供一個對其有意義的實現了。

9.報告所有的異常

不要讓程序的調用者看到那些奇怪的異常。處理它們是你的責任。把你調用的一切都包起來,然後發送自己定義的異常或者乾脆自己解決掉。代碼剛剛完成時,是尋找問題的佳時機。如果放任不管,它也不會變得更好。

從事任何編程工作,都要考慮事物正常狀況下是如何運作的。不過更應該想一想,當出現問題——也就是事情沒有按計劃進行時,會發生什麼。在調用別人的代碼時,它也許會拋異常,這時我們可以試着對其處理,並從失敗中恢復。當然要是在用戶沒有意識到的情況下,可以恢復並繼續正常處理流程,這就好不過了。要是不能恢復,應該讓調用代碼的用戶知道,到底是哪裏出現了問題。不過也不盡然。

平衡的藝術

  1. 決定由誰來負責處理異常是設計工作的一部分。
  2. 不是所有的問題都應該拋出異常。
  3. 報告的異常應該在代碼的上下文中有實際意義。比如拋出一個
    NullPointerException起不到任何幫助作用。
  4. 如果代碼中會記錄運行時調試日誌,當捕獲或是拋出異常時,都要記錄日誌信息;這樣做對以後的跟蹤工作很有幫助。
  5. 檢查異常處理起來很麻煩。沒人願意調用拋出31種不同檢查異常的方法。這是設計上的問題:要把它解決掉,而不是隨便打個補丁就算了。
  6. 要傳播不能處理的異常。

10.做代碼複查

要尋找深藏不露的程序bug,正式地進行代碼檢查,其效果是任何已知形式測試的兩倍,而且是移除80%缺陷的唯一已知方法。——Capers Jones的《估算軟件成本》
代碼複查或許是找到並解決問題的佳方式。然而,有時很難說服管理層和開發人員使用它來完成開發工作。管理層擔心進行代碼複查所耗費的時間。他們不希望團隊停止編碼,而去參加長時間的代碼複查會議。開發人員對代碼複查感到擔心,允許別人看他們的代碼,會讓他們有受威脅的感覺。這影響了他們的自尊心。他們擔心在情感上受到打擊,代碼複查不只針對初級開發者編寫的代碼——團隊中每個開發人員的代碼都應該進行復查,無論其經驗豐富與否。代碼複查隨着開發活動持續進行,而且每次針對的代碼量相對較少。感覺複查活動就像是項目正在進行的一部分,而不是一種令人畏懼的事情。

如何進行代碼複查基本方案
1.撿拾遊戲。當某些代碼編寫完成、通過編譯、完成測試,“提交複查”是一種快速而非正式的方式,保證代碼在提交之前是可以被接受的。爲了消除行爲上的慣性,要在開發人員之間進行輪換。比如,如果A的代碼上次是由B複查的,這次不妨讓C來複查。這是一種很有效的技術。
2.結對編程。在極限編程中,不存在一個人獨立進行編碼的情況。編程總是成對進行的:一個人在鍵盤旁邊(擔任司機的角色),另一個人坐在後面擔任導航員。他們會不時變換角色。有第二雙眼睛在旁邊盯着,就像是在進行持續的代碼複查活動,也就不必安排單獨的特定複查時間了。

在代碼複查中要看什麼呢?
你可能會制訂出要檢查的一些特定問題列表(所有的異常處理程序不允許空,所有的數據庫調用都要在包的事務中進行等等),不過這裏是一個可供啓動的基本的檢查列表。

  1. 代碼能否被讀懂和理解?
  2. 是否有任何明顯的錯誤?
  3. 代碼是否會對應用的其他部分產生不良影響?
  4. 是否存在重複的代碼(在複查的這部分代碼中,或是在系統的其他部分代碼)?
  5. 是否存在可以改進或重構的部分?

複查所有的代碼。對於提升代碼質量和降低錯誤率來說,代碼複查是無價之寶。如果以正確的方式進行,複查可以產生非常實用而高效的成果。
要讓不同的開發人員在每個任務完成後複查代碼。

平衡的藝術

  1. 不進行思考、類似於橡皮圖章一樣的代碼複查沒有任何價值。
  2. 代碼複查需要積極評估代碼的設計和清晰程度,而不只是考量變量名和代碼格式是否符合組織的標準。
  3. 同樣的功能,不同開發人員的代碼實現可能不同。差異並不意味着不好。除非你可以讓某段代碼明確變得更好,否則不要隨意批評別人的代碼。
  4. 如果不及時跟進討論中給出的建議,代碼複查是沒有實際價值的。可以安排跟進會議,或者使用代碼標記系統,來標識需要完成的工作,跟蹤已經處理完的部分。
  5. 要確保代碼複查參與人員得到每次複查活動的反饋。作爲結果,要讓每個人知道複查完成後所採取的行動。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章