2017年最后一周,我按計劃把《The Clean Coder》讀完了,大約100頁左右。
第6章?練習
這一章的內容是專業人士如何刻意練習。Bob大叔提到40年來他使用的電腦綜合性能(內存硬盤容量和速度,顯示分辨率的提升;提及能耗價格等的縮減)提升了10的22次方倍,但是實際上計算機程序的本質并沒有變化,是可以通過一些基礎程序的練習來不斷提升自己的技能的。為了讓22次方更形象,Bob大叔用了一個喬布斯經常用的技巧,把它轉換成人可以理解的其他東西:是從這里到半人馬座阿爾法星的距離(以埃為單位),是1美元硬幣里的電子數,是地球質量與個人質量的比例。
今天,編譯不再需要程序員等待。現在仍然有些程序員必須等待構建,這是悲劇,也是不夠仔細的征兆。如今,構建時間應該用秒來衡量,而不是分鐘,更不是小時。
構建時間這么細節的問題體現了專業性,比如前段時間大家關注解決的flex編譯時間的問題,只是通過申請更好的機器就把整個項目的編譯時間從90分鐘縮減到20分鐘,這應該是最便宜的投資了。不過還沒達到Bob大叔說的秒級構建的水平,這里還有進一步提升的空間,但是也需要有專業人士的投入才行,需要學習和嘗試下flex的增量編譯框架fcsh和flex編譯支持maven的工具flexmojos,也許會有幫助。
對于練習方式,作者給出了幾種形式,一些練習套路,可以嘗試在公司里設計相關的課程。
卡塔
在武術里,卡塔是一套設計好的、用來模擬搏斗一方的招式。與之類似,編程卡塔也是一整套敲擊鍵盤和鼠標的動作,用來模擬編程問題的解決過程。聯系著不是在解決真正的問題,因為你已經知道了解決方案。相反,你是在練習解決這個問題所需要的動作和決策。
編程卡塔的最終目標,也是逐步練習以達到純熟。反復的練習會訓練大腦和手指如何動作和反應。在不斷練習當眾,你或許會發現動作的細微進步,或者解決問題效率的小幅提升。
要學習熱鍵和導航操作,以及測試驅動開發、持續集成之類的方法,找整套的卡塔來練習都是相當有效的。
Bob大叔給出了一些卡塔,參考網站http://codekata.pragprog.com,其中包括在《ASD》中給出的保齡球計分程序。今年后備教練訓練營的TDD作業,我做的就是這個BowlingGame的程序。
真正的挑戰是把一個卡塔練習到爐火純青,你可以窺見其中的韻律。要做到這一點可不容易。
瓦薩
瓦薩基本可以說是兩個人的卡塔。其中的招式需要精確地記憶,反復演練。一個人負責攻,另一個人負責守。攻守雙方互換時,各種動作要一而再、再而三地反復。
程序員可以用一種叫“乒乓”的游戲來進行類似的練習:兩個人選擇一個卡塔,或者一個簡單問題,一個人寫單元測試,另一個人寫程序通過單元測試,然后交換角色。
自由練習
自由練習就是不限制形式的搏擊。模擬搏斗與編程并不是特別貼合。不過,很多編程練習場中都會玩一種叫做“自由練習”的游戲。它很像由兩個參與者解決問題的瓦薩,只是自由練習是有很多人參與的,而且規則是可以延續的。在自由練習中,屏幕被投影到墻上,一個人寫測試,然后坐下來,另一個人寫程序通過測試,再寫下一個測試。桌子邊的人一個個輪流接下去,或者有興趣的人可以自己排隊參加。無論怎么安排,都是非常有趣的。
上面這三種方式,無一不是以TDD的方式進行,和上一章的內容吻合。另外還有在業余時間參與開源社區,也是推薦的練習方法,總之,專業人士需要不斷的練習。
無論如何,專業人士都需要練習。他們這么做,是因為它們關心自己能做到的最好結果。更重要的是,他們用自己的時間練習,因為它們知道保持自己的技能不落伍是自己的責任,而不是雇主的責任。練習的時候你是賺不到錢的,但是練習之后,你會獲得回報,而且是豐厚的回報。
第7章? 驗收測試
Bob大叔舉了一個和業務人員一起以不斷探索的方式寫應用程序的例子,并總結了一些經驗。其實是再一次闡述了敏捷的一些原則,強調變化是一定會有的,過早精細化是不必要的,業務方自己很可能并不知道自己要什么。應對方式是推遲精細化,用驗收測試驅動開發。驗收測試要自動化。幾年前測試團隊做過相關的嘗試,當時覺得在驗收自動化測試上投入有點高,沒有繼續進行下去,2018年是不是可以再嘗試一下,改變一下PO和BA的工作方法?
驗收測試和單元測試
驗收測試是寫給業務方看的,單元測試是寫個程序員的,它們并不重復。它們的主要功能其實不是測試,測試只是附屬功能。它們首先是文檔,其次才是測試。
圖形界面的測試
這里提到了增加ID和分層測試服務兩種方式,都是以前曾經嘗試過的,關鍵是要找到項目真實的落地。
持續集成
這里重點提到的是持續集成的紀律,集成失敗必須立即修復,這是優先級最高的事情。實際做起來是需要全員意識上的改變的。
第8章?測試策略
“QA應該找不到任何錯誤”,這是對專業人士的要求。QA的主要職責不是發現程序員的錯誤,保證程序沒有錯誤是程序員自己的職責。那QA做什么?
QA在團隊中要扮演的是需求規約定義者(specifier)和特性描述者(characterizer)。
需求規約定義者:QA的任務是和業務人員一起創建自動化驗收測試,作為系統真正的需求規約文檔。
特性描述者:QA的另一項任務是遵循探索式測試的原則,描述系統運行中的真實情況,將之反饋給開發人員和業務人員。在這項任務中,QA并沒有解析需求,而是在鑒別系統的真實情況。
自動化測試金字塔
專業開發人員遵循測試驅動開發的要求來創建單元測試。專業開發團隊使用驗收測試定義系統需求,使用持續集成保證質量穩步提升;同時,這些測試又屬于全局測試體系。擁有一套單元測試和驗收測試的同時,還需要有更高層次的測試,這樣QA才找不出任何錯誤。
Bob大叔給出了五層的自動化測試金字塔,和我們經常看到的三層的金字塔不太一樣,從下到上依次是:單元測試、組件測試、集成測試、系統測試、人工探索式測試。
單元測試是程序員自己編寫自己使用,并且要做到接近100%的覆蓋率,通常在90%以上,并且是真實的覆蓋率,而不是那種雖然能通過但并不關心運行結果的錯誤的單元測試。
組件測試和集成測試都是針對API進行的測試。組件測試針對單個組件,集成測試針對多個組件。組件測試由QA和業務人員編寫,開發人員提供輔助。常用的工具是FitNesse, JBehave, Cucumber。針對GUI的是Selenium或Watir等工具。組件測試要覆蓋差不多系統的一半,主要是成功路徑。異常路徑是要靠單元測試來覆蓋的。集成測試主要針對大型系統,是編排性測試,主要不是測試業務規則,而是測試組件裝配在一起時是否協調。集成測試一般由系統架構師或主設計師來編寫,用于確認系統架構層面的結構是否正確無誤。集成測試時間運行比較長,一般不會作為持續集成的一部分。
系統測試大約占測試的10%,由系統架構師和技術負責人編寫,一般是在GUI層次。
人工探索性測試不是自動化測試,它需要使用人類的創新能力,對系統進行深入研究和探索。預先編寫測試計劃反而會削弱這類測試的效果。可以考慮一些全員“抓蟲”行動。覆蓋率不是探索性測試的目標。
結論
TDD、驗收測試這些組合起來,最終目標還是讓QA找不到任何錯誤。
第9章?時間管理
會議
關于會議,有兩條真理:
(1)會議是必需的;
(2)會議浪費了大量時間。
通常,兩條真理同時適用于同一場會議。有些與會者認為這兩條總結得非常好,有些則認為它們是正確的廢話。
你需要為自己的時間負責,所以你需要選擇哪些會議參加哪些會議不參加。Bob大叔提到Scrum的四會的問題,相關內容應該可以參考Scrum相關書籍。
爭論/反對
Kent Beck曾告訴我一個深刻的道理:“凡事不能在5分鐘內解決的爭論,都不能靠辯論解決。”
如果爭論必須解決,就應當要求爭論各方在5分鐘時間內向大家擺明問題,然后大家投票。這樣,整個會議花的時間不會超過15分鐘。
注意力點數
現在是個爭搶注意力的時代,每個人最稀缺的資源就是注意力,誰搶到更多的注意力就能賺錢。如何保持注意力?
首先需要保證睡眠。Bob大叔每晚需要睡7小時。年初有幾個月我曾經每晚睡5小時,想多爭取些時間工作和學習,靠每天早晨的咖啡來支撐,后來發現自己有點扛不住,就盡量往7小時睡眠靠了。前陣子聽樊登講《睡眠革命》,一個睡眠周期時間是1.5小時,如果在睡眠周期中間被鬧醒,則整天都會受影響,所以睡眠時間最好是1.5小時的整數倍,一周累積睡到35個周期就沒問題。正在嘗試中,貌似挺有道理。
肌肉注意力。體力活動需要肌肉注意力,編程需要心智注意力,兩者的要求不相同。不過定期訓練肌肉注意力可以提升心智注意力的上限。Bob大叔的做法是騎自行車1-2小時,大約30-50km,騎車的時候可以聽播客或者音樂。我自己挺喜歡慢跑的,周六的早上慢跑聽書是一種享受,也是一種放松。不過進入冬天霧霾重了就沒怎么跑了。不過在家里做些俯臥撐也挺有好處。
時間拆分和番茄工作法
番茄工作法我用過一段時間,有時經常被打斷或者自己內心沒法靜下來;有時又覺得25分鐘時間好像有點短,專注的做一件事情時剛進入狀態,番茄就結束了。看到有的文章說番茄時間設置成1小時比較好。不過按照Bob大叔前面的說法,其實進入心流狀態并不是很好。也許25分鐘的番茄鐘就是很科學的。
要避免的行為是優先級錯亂,或者不按優先級順序來處理,這個事情在我身上也經常發生,明明知道有個事情是重要的,但總是拖到最后一刻才做,把自己逼到死角,搞得很忙亂。
番茄時間也需要回顧,感覺番茄工作法就是一個人的Scrum。我對自己的回顧就是對于每項事情的預估時間還是經常偏樂觀,也許是因為自己有完美主義的傾向。這個和敏捷的思路并不太匹配,造成自己效率不高,需要調整。
死胡同和泥潭
死胡同:比如選擇了走不通的技術道路,越是堅持浪費的時間越多。要記得,任何時候都有選擇。
坑法則:如果你掉進了坑里,別挖。
比死胡同更糟糕的是泥潭。泥潭會減慢速度,但不會讓你徹底停下來。但如果你使盡全力,你仍然可以取得進展。
之所以說泥潭比死胡同更麻煩,是因為在泥潭中,你仍然可以看到前進的道路,而且看起來總是比回頭路要短(雖然實際不是這樣)。
這兩個道理一看就懂,可以如何分辨哪些是死胡同,哪些是泥潭,哪些是需要堅持挺過去的呢?感覺需要大智慧才行啊。
第10章?預估
預估是軟件開發人員面對的最簡單、也是最可怕的活動之一了。
承諾和預估
承諾是確定性的,必須要完成,其他人會依據你的承諾制定計劃。不能兌現的承諾是一種欺騙。
預估是一種猜測,預估錯誤無關聲譽。
我記得Steve McConnell的《快速軟件開發》中有過描述,預估總是會給出兩個值,要么是一個區間范圍,要么是一個值和概率,而承諾就只有一個值。糟糕的是我們給出的大部分預估都會被管理者當成承諾,因為我們在預估時往往只給出一個值。
特別提一點,按照我們完成任務的時長繪制出直方圖,大致上是符合韋伯分布的,而不是正態分布。從我司的度量數據可以看出這一點。如果出現明顯不符合韋伯分布的曲線,要么說明任務粒度差異比較大,要么說明這里存在明顯的異常,需要關注一下。
常用的預估方法,都是PMBOK中的知識:三點法、DELPHI法等。計劃撲克就是一種DEPLHI法。
關于軟件估算,McConnell專門寫了一本書,可惜沒投入時間仔細讀過。從經驗來看,多人一起拍腦袋做類比估算是比較靠譜的,在PMBOK中叫做專家判斷。目前業界的趨勢應該是使用功能點方法或快速功能點方法,感覺其本質也是類比估算,不過是基于大數據的類比估算,最核心的東西是其積累的成千上萬的項目數據信息。
第11章?壓力
即使有壓力,專業開發人員也會冷靜果斷。盡管壓力不斷增大,他仍然會堅守所受的訓練和紀律,他知道這些是他賴以戰勝由最后期限和承諾鎖帶來的壓力感的最好方法。
本章前面講述了Bob大叔自己承擔壓力以及他的應對方法。確實在他40年的軟件生涯中,什么都遇到過了。有興趣就閱讀原書吧。
保持整潔
快速前進確保最后期限的方法,便是保持整潔。專業人士不會為了快點前進而亂來。他們明白“快而臟”是自相矛盾的說法。臟亂只會導致緩慢!
根據經驗和我自己的理解,如果工作總是在交接中,可以找到下一位“接盤俠”,那么大家在工作中保持專業性的可能性就會大大降低。以前我維護的程序,我知道出了問題都要自己去解決,沒有其他人可以依靠,所以為了讓自己維護和理解程序的負擔輕一些,所以我會把所有已知的問題都花時間消除掉,這樣在遇到問題時我就不會分心去考慮這些已知的問題。已知的問題包括編譯器檢查出的所有告警,要么通過修改代碼消除掉隱患,要么自己要確信理解了編譯器告警的原因,并且明確這是無害的。事實證明這個確實有效,我很為我以前維護過的程序的穩定性和代碼質量自豪。
是的,那時我還不知道Clean Code和TDD,不然我一定也在自己維護的代碼中進行實踐。
危機中的紀律
觀察自己在危機時刻中的反應,就可以了解自己的信念。如果在危機中依然遵循著你守持的紀律,就說明你確實相信那些紀律。反過來說,如果在危機中改變行為,就說明你并不真正相信常規行為中的原則。
如果在非危機時刻你會遵循測試驅動開發的紀律,但是在危機時刻你放棄了這種做法,就說明你并不真正相信TDD是有幫助的。如果在平常時候你會注意保持代碼整潔,但在危機時刻你卻會產出混亂的代碼,就說明你并不真正相信混亂會導致速度下降。如果在危機時刻你會結對工作,但平時卻不結對,就說明你相信結對工作比不結對更有效率。
Bob大叔已經說得很清晰了,我完全贊同。意識不到混亂會導致速度下降,也許是因為還沒有合適的度量方式讓大家意識到這一點。想起CMMI顧問魏老師曾經給過的一個建議:如果公司不為修復程序故障支付報酬,或者只支付固定比例的報酬,也許對我們的交付質量提升會有比較大的促進作用。
應對壓力
1:不要驚慌失措;2:溝通;3:依靠你的紀律原則;4:尋求幫助。
第12章?協作
程序員正是因為不善于和人打交道,喜歡和機器打交道才選擇了這個職業。Bob大叔從程序員與雇主,程序員與程序員兩個方面討論了協作的問題,并且又是用自己親身經歷來說法。曾經他做過獨行俠,忽略了雇主和公司利益,慘遭解雇的故事。這部分簡單易懂,但很有警醒作用,值得讀一下。
第13章?團隊與項目
有凝聚力的團隊
形成團隊需要時間。團隊成員需要首先建立關系。他們需要學習如何互相協作,需要了解彼此的癖好、強項、弱項,最終,才能凝聚成團隊。
有凝聚力的團隊確實有些神奇之處。他們能夠一起創造奇跡。
有凝聚力的團隊通常有大約12名成員。由12個人組成的理想團隊,人員配備情況是這樣的:7名程序員、2名測試人員、2名分析師和1名項目經理。
這個團隊規模不符合5-9人的原則,不過可能平常我們是認為分析師(BA)和項目經理(PM)是團隊外的人員,算起來也差不多。這個規模差不多也是我們以前一個科室的規模,確實感覺很不錯。記得團隊在解散的時候科室同事在公司論壇上留下一個帖子:“鋼七連要解散了,實名留念”。我被別人叫做“七連長”(參考《士兵突擊》),感覺這是我十幾年工作生涯中得到過的最高褒獎。
團隊和項目,何者為先?
試圖圍繞項目來構建團隊是一種愚蠢的做法。按照這種做法,團隊永遠都不可能形成凝聚力。
專業的開發組織會把項目分配給已形成凝聚力的團隊,而不會圍繞著項目來組建團隊。一個有凝聚力的團隊能夠同時承接多個項目,根據成員各自的意愿、技能和能力來分配工作,會順利完成項目。
結論
團隊比項目更難構建。因此,組建穩健的團隊,讓團隊在一個又一個項目中整體移動共同工作是較好的做法。并且,團隊也可以同時承接多個項目。在組建團隊時,要給予團隊充足的時間,讓他們形成凝聚力,一直共同工作,成為不斷交付項目的強大引擎。
第14章?輔導、學徒期與技藝
這是全書的最后一章(不算附錄,附錄說的是工具,和人無關),Bob大叔用自己的成長經歷做了個總結,表達了對學校科班教學的失望,認為學校的教育并沒能教會學生編程,真正的編程是在工作中學習和錘煉出來的。這個確實是現狀,可能在中國和美國都是類似的情況,我自認自己只是個中級水平的程序員,這個能力水平也是在工作之后讀了一些書做了一些實踐之后獲得的,剛畢業的時候確實很渣。
Bob大叔是雪鳥會議的發起者,某種意義上說可以認為是敏捷宣言之父,他同時也是軟件工藝運動的推動者,他用這本小書向我們闡述了何為專業人士,以及如何成為專業人士,為他的專業精神所折服,推薦程序員都讀一讀,然后不再自稱“碼農”。
很高興自己在兩周內讀完了一本書,并且這也是唯一一本我寫完了讀后感的書,感謝Bob大叔的言簡意賅。
對了,其實還有最后的附錄工具沒有寫,里面提到了配置管理工具svn/git,代碼編輯器IDE,持續集成工具,問題跟蹤工具,自動化測試工具等,提供的都是最優秀的選項,值得學習和參考。
我是有底線的