簡介
團隊的開發人員撇開需求沉浸在想象中的“完美”程序中;測試人員迷茫的點擊着按鈕試圖搞明白這到底是個什麼功能;設計師造出了沒有盡頭的樓梯,更糟的是,客戶愛上了這個設計;團隊領導四處救火,力有不逮。種種跡象表明,我們得打破分工帶來的壁壘,建設全功能團隊——大多數人能完成大多數種類工作的團隊。
在一次閒聊中,女友的母親說起實習大夫必須輪崗一年纔會進行分科學習,我質疑道:“對於致力於心臟病治療的醫生來說,他豈不是在不相干的學習上浪費了一年時間麼?”,她母親笑着說:“不這麼作,你怎麼確信病人的確患有心臟病呢?”。不知道爲什麼,我眼前突然浮現出這樣的場景?測試人員在怯生生的詢問:“這是一個缺陷麼(而不是操作系統/瀏覽器的限制)?”。
亞當與大頭針工廠
亞當·斯密於1973年在描述大頭針工廠的專業化生產時提出了社會分工的好處:提高熟練程度、減少任務切換時的開銷、便於機器的應用。我們似乎可以非常自然得推導出重複設計、重複編碼、重複測試可以增加相應崗位員工技術熟練度,提升效率,並由此提升企業的盈利能力。
然而市場的不斷變化讓重複生產的美夢不在,切換任務變得越來越頻繁。IT公司不是大頭針工廠,知識工作者畢竟有別與體力勞動者,在勞動主體發生變化的過程中有兩件事情的差異被放大了:一是局部優化與整體優化的差異,二是正確的做事與做作正確的事情的差異。
有一道數學題,假設每個開發人員每天可以完成一個功能,測試人員每天可以測試2個功能,團隊由3名開發人員和1名測試人員組成,那麼一週內通過測試的功能最多爲多少個?
大多數人的第一反應是5(天)x2(功能/天)=10功能,下面的表格會告訴你,由於負載不均衡,測試人員在週一沒有功能可測,團隊其實無法在一週內交付10個功能。
週一 |
週二 |
週三 |
週四 |
週五 |
總計 |
|
開發人員 |
3功能 |
3功能 |
3功能 |
3功能 |
3功能 |
15個功能 |
測試人員 |
0功能 |
2功能 |
2功能 |
2功能 |
2功能 |
8個功能 |
(表一)
那麼我們改變一下條件,假設團隊中有4個開發人員,並且開發人員可以參與測試,結果會怎樣呢?
|
週一 |
週二 |
週三 |
週四 |
週五 |
總計 |
開發人員 |
4功能 |
4功能 |
3功能 |
2功能 |
0功能 |
13個功能 |
測試人員 |
0功能 |
0功能 |
2功能 |
4功能 |
8功能 |
14個功能 |
(表二)
我們最終能夠交付13點,產量提高了60%, 如果我們只留下三名全能人員:
|
週一 |
週二 |
週三 |
週四 |
週五 |
總計 |
開發人員 |
3功能 |
3功能 |
3功能 |
1功能 |
0功能 |
10個功能 |
測試人員 |
0功能 |
0功能 |
0功能 |
4功能 |
6功能 |
10個功能 |
(表三)
居然比3個開發人員和1個測試的人員組合還多交付兩個功能!
我們當然有理由質疑第二題的假設:“開發人員可以勝任測試人員的職位”。又或者繼續討論迭代二的數據變化。我對此的的回答是:
第一,以我的觀察來看開發人員之所以不進行測試工作,不是能力不允許,而是主觀上認爲測試工作是簡單、重複而枯燥的,不願意作。客觀上開發人員們比較貴也更難於培養,組織層面不允許這樣的“浪費”。
對測試工作的偏見客觀上促成了大量不具備技術能力的人選擇測試工程師作爲職業,而技能不足則一步導致了測試工作傾向於簡單重複。測試人員在很大程度上無法判斷什麼是正確的事情(作正確的事),從而更傾向於熟練的按照腳本進行操作(正確的做事)。
第二,我的關注點不在交付8點還是10點,我希望這個例子能夠引發大家對於均衡生產的思考。
軟件的需求和實現可以被細化,但它畢竟不是大頭針,需求和實現間往往呈現出關聯與依賴,換言之,局部效率的增加無法直接轉換爲整體效率的增加。而整體效率的優化往往依賴於均衡生產(參考表三),即消除生產的波峯(過度生產)和波谷(生產不足),避免任務時鬆時緊,鬆時生產力浪費(週一時專職測試人員),緊時加班加點,粗製濫造。
我傾向於認爲亞當·斯密對勞動分工論述的假設是:需求穩定,簡單生產。對於IT領域來講,這些假設還成立麼?
擰螺絲的卓別林
不難發現,對分工以及個體效率的迷信已經深刻的影響着IT領域。分工的端倪在招聘時就已經顯現,即便對於差異不大的畢業生們,僱主也會根據其極有限的技能,用不同的標準進行測試(Java, .Net, PHP等),並在入職後將其冠以前端工程師,後端工程師,測試工程師,支持工程師等不同的頭銜,甚至可能在其可見的職業生涯中專門負責某個文件的維護。
整體效率的優化要求IT團隊消除技能壁壘,培養多面手,根據計劃的的變動,彈性地調整任務,達到各角色和流程之間的平衡。對於IT企業來說,變化從招聘時就必須開始。找到擁有學習熱情、學習能力、學習習慣的人變成了當務之急,員工是否掌握了某種算法、語言或者工具應當從准入條件降格爲對於其學習能力和熱情的一種(不是唯一一種)證明。
整體效率的優化要求員工必須持續學習、成長,興趣無疑是成長的催化劑,然而喪失意義的工作卻在不斷扼殺人的興趣。
丹?艾瑞里在怪誕行爲學裏著述到:
勞動者與他自己的生產活動、勞動目標以及生產過程相分離。這就使工作成爲非自發性的活動,因此勞動者就無法對勞動產生認同或者領略到勞動的意義,而缺少了意義,專業人員可能覺得自己好像電影《摩登時代》中查理·卓別林扮演的角色,一切都由工廠的齒輪控制,他們根本不會有全心全意工作的願望 。
如果員工成長是必須的,那麼,幫助員工認識到工作的全貌也是必須的。角色輪換是一個很好的解決方案。在項目內部通過角色互換,不限角色的結對工作,加強不同角色,不同模塊間的知識傳遞,打破技術壁壘,幫助員工從不同視角理解項目,鍛鍊技能,進而增加團隊均衡生產的能力。
在我看來,進行角色輪換的最大阻礙在於編程能力的普遍缺乏,大多數的測試、需求分析工作(鑑於大多數團隊所處的地位,需求分析師實在言過其實,更精確的名字是需求整理師),迭代管理,簡單的客戶交流,學習曲線都非常低,任何成員都可以在師傅的帶領下迅速掌握工作要點,然而編寫程序卻是個例外,即便對於基礎良好的新人,在經驗豐富的導師帶領下,也需要2個月左右纔可能寫出比較體面的單元測試、較爲面向對象的程序。在分工的體制下,用別的角色輪換開發人員幾乎是個死局。
非常奇怪,IT領域如此的看重抽象能力和邏輯分析能力,可爲佐證的是層出不窮的建模語言,模式,領域模型,架構。然而最能訓練抽象能力和分析能力的一項活動,卻僅僅有選擇性的開展,這是不是意味着我們認爲IT項目可以在大多數人無法(也沒有能力)達成共識的情況下順利展開併成功交付呢?在我看來,編寫程序不僅僅是一項技能,一種思考方式,還承擔着構造IT團隊成員間共同經驗區,提高交流效率的目的。
一個值得從其它行業借鑑的經驗是首先展開基礎素質培養,再進入領域培養專業素養,換言之,避免過早的分工,所有新人從編程開始職業生涯,在公司的體制層面促成每個新人都能經歷力所能及的所有角色。在具有了一定的基本素質後,在員工對工作內容和自身興趣有了充分的瞭解後,根據個人意願進入領域發展專業技能,興趣將成爲員工成長的內在動力,而良好的基本素質將使員工有能力在專業崗位上施展自己的想法。
同時公司應當鼓勵員工跨界工作,《應用Selenium和Ruby進行面向領域的Web測試》的作者是擁有卓越能力的開發人員,他曾經進行了相當長時間的測試工作,在其它人抱怨自動化界面測試難於維護時,他優秀的抽象能力、分析能力已經幫他提煉出測試模式,識別出缺陷,找到了優雅高效的工作方式並誕生了這篇優秀的文章。
丹·艾瑞所言於我心有慼慼焉。
知行合一
在過去9個月間我們在團隊中進行了建設全功能團隊的初步實踐,在分享具體實踐前,我希望下面的總結性數據能幫助你獲得一些背景知識。
項目處理的是期貨交易領域,使用的技術棧是C#, ASP.NET MVC。團隊主要由八名開發人員以及兩名測試人員組成(其中一名測試人員在項目中期加入),其中4位是畢業生,3位具備工作經驗,但剛剛加入Thoughtworks,只有一位開發人員具備.Net開發經驗。
下面是全部35周的燃盡圖,黑色實線代表項目的範圍,綠色實線代表開發完成的速度,藍色實線代表測試完成的速度,每週爲一個迭代。
在這張圖的大部分區域內藍色和綠色是重疊或者非常接近的,這意味着團隊每迭代開發完成的功能恰好與測試人員的處理能力對齊。一方面,這歸功於測試人員自行實現的自動化測試框架對效率的提升,另一方面,開發人員參與測試也起到了平衡開發和測試速度的作用。
讓我們截取開發過程的一部分,觀察每個迭代的速度,在下面這樣圖中,橫軸代表第幾個迭代,縱軸代表每迭代完成的功能點數。
從項目經理的角度看,團隊的交付速度很穩定,從15周開始直到項目的結束,我們都可以放心的使用12點每週的經驗數據進行估算、計劃工作。事實上團隊在後期所處理的工作種類越來越多,包括了正常的開發任務、公式轉換、性能調優、驗收測試、支持等。在這種情況下,每個人都具備跨角色,跨模塊工作的能力才保證了可持續的交付節奏。
在這篇文章中我們一起回顧了分工歷史,對於技術團隊影響以及建設全功能團隊的必要性 ,在下一篇文章中我將詳細分享一些實踐以及經驗數據。
作者簡介
胡凱, ThoughtWorks公司的敏捷諮詢師,官方認證的Spring Framework講師,近2年一直從事持續集成工具Cruise以 及CruiseControl的設計開發工作。 創造和參與了開源測試框架junit-ext,以及用於分析CruiseControl構建的報表工具iAnalyse, 對於Web開發,敏捷實踐,開源軟件與社區活動有濃厚的興趣,可以訪問他的個人博客進行更多的瞭解。
本文出自:http://fengshen-xia.iteye.com/admin/blogs/new