飛機飛得再高,畢竟要落地。你準(zhǔn)備好了嗎?
實效的敏捷,第四屆敏捷大會熱鬧非凡,上千元的票價抵不了龐大的支出,更阻擋不了人們的好奇和求知的欲望。說實話,我沒有聽到新的東西,不管是美麗的故事還是悲慘的故事,還是困惑的故事,我聽得太多了。但是卻并不阻礙我的興趣,聽這些故事,我沒有打算找到答案。雖然我也問了很多問題,也被問了很多問題。但是對于絕大部分問題,我知道那沒有答案。雖然我做出一副掙扎的樣子,其實我的內(nèi)心早就屈服了。
Brooks不是早就說了嗎?——沒有銀彈。
比如,如何衡量績效?敏捷了就很難衡量績效了。很多人這樣想,可是“Comparing With What”(Kent Beck)跟什么對比呢。當(dāng)然是CMMx!那CMMx是怎么衡量的呢?代碼行數(shù)?靠譜嗎?測試覆蓋率?圈復(fù)雜度?敏捷了就不能用了嗎?這個世界上真的有衡量開發(fā)人員績效的好辦法嗎?有嗎?CMMx的時候容易嗎?問一問自己的內(nèi)心,如果你是一名經(jīng)理,你是不是現(xiàn)在內(nèi)心打個分?jǐn)?shù)然后再去計算每個人的分?jǐn)?shù)呢?如果你是一個開發(fā)人員,你真的認(rèn)為代碼行數(shù)能反映一個人的水平嗎?還是你的主觀判斷更靠譜?如果你是一個測試人員,你是否厭倦了以發(fā)現(xiàn)Bug的數(shù)量來衡量績效的辦法(順便表達(dá)一下對使用這種績效評估的領(lǐng)導(dǎo)的鄭重的鄙視)。今年的D應(yīng)該輪在誰的頭上,還是那個新來的嗎?別跟我說,你當(dāng)新兵的時候沒"被"得過D。如果你的工作就是績效評估,你的內(nèi)心是否掙扎過,到底應(yīng)該以什么樣的指標(biāo)來衡量?你是否在內(nèi)心確信你定義的指標(biāo)足夠“公平”合理?你是否確信你看到的數(shù)據(jù)不是“做”出來的?順便諸位項目經(jīng)理哪位沒有“做”過數(shù)據(jù)?為了測試覆蓋率跑跑那些從來不用的測試?為了追趕發(fā)布期,警告測試部門盡量手下留情合并缺陷?為了圈復(fù)雜度拆分函數(shù)而沒有同時分析提取函數(shù)是否恰當(dāng)?難道是我“恰好”碰到了這些極端的例子?怎么辦?敏捷來了,難道還沒有辦法嗎?我不知道。你要問問自己,我到底要干什么?我為什么去衡量?我能不能做得更符合我的目標(biāo)一些?僅此而已,你永遠(yuǎn)做不到公平,在軟件行業(yè)尤其如此。總的來說,軟件行業(yè)還是工匠式的行業(yè),開發(fā)還是一門手藝。你要任何一個容易指標(biāo)都很容易導(dǎo)致“局部優(yōu)化”,任何一個真正有價值的指標(biāo)都不那么容易量化。在敏捷開發(fā)中常見的量化衡量團隊開發(fā)能力的指標(biāo)是Velocity,但是這個看上去量化的指標(biāo)只能用來衡量一個團隊自身的進(jìn)步,不具有任何橫向?qū)Ρ鹊囊饬x。要去提高Velocity,最簡單的辦法就是將每個故事的點數(shù)乘以2。你要換算成人日數(shù)嗎?你會得到非常有趣的比較,那就是A團隊平均每個人每周完成的工作量是5個人日,這個碰巧跟B團隊的平均值相等。(這跟某次世界杯上,總進(jìn)球數(shù)和總失球數(shù)恰好相等非常類似。)
所以,我們的建議是,這些指標(biāo)只能被度量,不能被管理,而且這種度量是以反饋為目的的,而絕不是以績效為目的的。在敏捷團隊中我們有很多指標(biāo),很多衡量手段。比如簽入代碼行數(shù)、測試覆蓋率、圈復(fù)雜度,我們用這些指標(biāo)來幫助我們分析團隊的狀況。比如,測試覆蓋率下降了,我們要看看,為什么下降了,是不是單元測試無法覆蓋某些場景,我們是不是需要增強集成測試和系統(tǒng)測試來保障系統(tǒng)的質(zhì)量;再比如,圈復(fù)雜度提高了,我們會去考慮是不是最近重構(gòu)做得不夠頻繁了,需不需要專門留出時間來做一些重構(gòu)。當(dāng)這些指標(biāo)成了反饋手段,我們不需要“做”任何數(shù)據(jù),CI的紅燈和綠燈都是我們的朋友。(這些想法都屬于“基于信任”的管理方式,關(guān)于對于這種方式的質(zhì)疑與回應(yīng)參考光磊的文章)。
====隨便分個段,因為跳躍性太大==
下午的TDD情景坊來了一個做SQA(記不清了)的同學(xué),指出我們是在誤人子弟。我們的方法命名不符合Java的某個“規(guī)范”,測試命名不符合工具“要求”,沒有注釋??傊凰?。我能看出他的好意,但實在沒有給別人解釋的機會,就開始演示他的TDD了。我試圖跟他解釋我們?yōu)楹畏椒ㄟ@樣命名、為何測試類不能對應(yīng)被測的類、為何我們“基本上是反對注釋”的。但結(jié)局是“完敗”。
要實踐敏捷,開放的心態(tài)是非常重要的。今天正好在看Git的源代碼,發(fā)現(xiàn)Linus竟然是在用“Ruby的命名規(guī)范”來命名C的函數(shù)(如int diff_tree_stdin(char *line))。我很后悔沒能把Linus抓過來跟那個同學(xué)過過招:)
下午跟某公司的同學(xué)聊到測試分層的問題,另一個同學(xué)插話說他們的測試很難定義邊界值。我跟他說這個問題和測試分層是正交的。也就是說,無論采用什么樣的分層方式,問題總是存在的。這里說正交其實并不嚴(yán)格。我們可能會通過某種測試分層方案來緩解這樣的問題。比如,邊界值也許會在較低層的測試上容易確定。但是,從根本上說,原來的問題還是存在。但是,這個問題是不是就是一個測試問題,卻又是另一個話題。也許是一個設(shè)計問題——Kent Beck響應(yīng)式設(shè)計。
軟件開發(fā)中有很多問題并不是依靠一個實踐就能解決的,而且還有一些問題并非現(xiàn)有的每個實踐能解決的。這個時候追蹤背后的問題是非常重要的。我見過一些團隊,單獨一個團隊不能交付任何特性,甚至自己的代碼編譯都不能通過,必須與其他團隊協(xié)作才能編譯、驗證。遇到這樣的問題怎么辦呢?
這可能是一個組織問題,也可能是一個設(shè)計問題,但是我們見到很多團隊選擇從哪些角度去解決它呢?配置管理,測試框架,流程管理。我一一介紹一下:
配置管理:既然你必須跟別人在一起才能編譯,不然把你們放到一個分支上,互相能訪問對方的代碼。
測試框架:既然你自己不能編譯,我能不將你的依賴Mock掉或者Stub掉?這樣你就可以針對某個Mock框架或者一些Stub代碼進(jìn)行編譯驗證了。
流程管理:我們也可以規(guī)定A團隊必須在幾點幾分提交,然后你再編譯。
這些方法好不好?作為一個“響應(yīng)式改進(jìn)”(向“響應(yīng)式設(shè)計”致敬)的倡導(dǎo)者,我不會說好還是不好。我只想讓你問問自己:這種選擇是不是符合你內(nèi)心的“真北原則”(參考《成功人士的7個習(xí)慣》)。你有沒有分析從設(shè)計或者組織的角度去做改進(jìn)的成本和收益?你的選擇是不是考慮和長期收益和短期收益的平衡?如果你全面的分析了各個原因之后,仍然選擇用上面的這些“間接方法”去做改良,那你的選擇就沒有問題。
溫伯格說:不要把解決問題的方案當(dāng)作要解決的問題本身。
即使我們選擇了上面的方法去解決我們的問題,我們在內(nèi)心要始終記著我們要解決的是什么問題,并且在任何下一次再采用同樣的方法去解決這個問題的時候,要問一下自己“現(xiàn)在的背景是不是跟我們上一次做決定的時候是一樣的”。再做一次符合內(nèi)心“真北原則”的選擇,而不是直接就選擇先前的那個方案。
====再分割一下====
昨天中午有幸跟Kent Beck一起吃中午飯,我問他響應(yīng)式設(shè)計是不是從XP風(fēng)格設(shè)計的一種回歸?;蛘哒f響應(yīng)式設(shè)計是不是介于傳統(tǒng)設(shè)計和極限編程風(fēng)格的設(shè)計(比如TDD)之間的一種形式或者思想?(原話:Is responsive design a step back from XP style design? I mean on the road that we transform from traditional design to xp style design。Is responsive design somewhere between the two styles of design?)。
本來沒有期望太驚人的答案,因為我確實覺得傳統(tǒng)設(shè)計太“保守”極限編程太“激進(jìn)”,而響應(yīng)式設(shè)計正是某種形式的折中或者回歸。但Kent Beck思考了一會兒卻說,不是回退,而是更進(jìn)一步。極限編程提倡把設(shè)計的決策推遲到實現(xiàn)特性的時刻,而響應(yīng)式編程則更推遲了,你要判斷上下文決定是否設(shè)計或者作出何種設(shè)計。(僅根據(jù)我的理解整理,不確認(rèn)這是Kent Beck的本意。)
===想起Dave的Broken Window理論,明天繼續(xù)寫。