|
英文原文:Software Development Lessons Learned from Poker
(作者:Jay Fields,譯者:李劍)
2008年5月19日
我以前不是做軟件開發的。在加入ThoughtWorks兩年之前,我主要靠玩撲克為生。當然,如果你曾跟我打聽過我前臂上的紋身,那你肯定已然聽過我的故事了。要是還沒有,等下次我們一起喝一杯時,我可以講給你聽。
我從未因為花這么長時間玩牌而感到過遺憾,從中我學到了一些放之四海而皆準的知識。開發軟件的時間愈久,我就愈加確信這二者之間具有令人難以置信的相似性。
學習
我學習打撲克和學習軟件開發的方式是一樣的:盡可能多讀書。我用兩年的時間,讀完了所能找到的每一本有關撲克的書。最后竟至39本之多。編程亦如是。此刻,我面前仍然擺著接下來要讀的5本書;而在過去三年ThoughtWorks的工作中,我翻爛的書亦不在少數。
我認為,無論編程還是玩牌,閱讀書籍、博客與雜志都是要想有所成就的必備條件;而若要以二者為謀生之業,僅靠讀書卻是遠遠不夠的。也許你可以把書本上的一切知識都裝入腦中,但知道在何時應用何種規則,這才是真正高手的標志。
誠然,開卷有益。但總要走過萬里路,方能對應用特定技術的具體環境爛熟于心。書本不可能把所有情況都囊括一空,只有通過親身體會得來的經驗,才能讓你在某些狀況下為自己或是雇主做出快速而正確的決策,而這些決策可能價值幾千乃至數百萬美元。
經驗之寶貴,世間無物可代。
藝術的巔峰
你可以設計出擊敗普通撲克玩家的計算機程序。遵守一些基本規則,自然就可獲勝。但迄今為止,還沒有任何程序可以擊敗最好的撲克玩家。因為撲克技能達到巔峰時,也就成了一門藝術。軟件開發亦如是。要想成為一個還行的開發者,只要遵循一系列最佳實踐即可。如果按照經典參考指南一類的書籍行事,開發出還不錯的應用程序應該不成問題,而且效果會勝過其他最常見的做法。有了這么多失敗的項目作為前車之鑒,我相信,還不錯的應用就足以令大多數管理層甘心掏腰包了。
當然,有些經理有更高的標準。在銀行、創業公司、醫療系統等領域,標準則更為嚴苛。“還不錯”自是遠遠不夠。那些經理會很樂意為最佳選擇買單,他們期待的是遠超常人的技能。但問題在于,專家級程序員的技能與普通程序員不同。普通程序員知道做事的方式;專家知道做事的目的。普通程序員會僵化跟隨模式書籍中的指示,就如遵守參考指南一般;專家則明白對模式的創新可能會帶來指數級的性能改善。
他們看到的絕非同一個世界,所以普通程序員很難跟專家對面交流。做藝術評論家易,做優秀的藝術評論家難。
決策技能
在撲克和編程中有一條絕對真理:幾乎沒人能像他自我感覺的那么良好。有自知之明是不錯的開始,但人們依然很難知道自己與專家之間的差距。程序員接觸專家的機會并不多,也就無法公正評判自己的技能。在牌桌上,每個人都是為了錦標而來,可大多數人都會過高評價自己的牌技,這總是讓我驚訝不已。
程序員之間亦是如此,而且大多數人可以獲得的信息更少得可憐。一個從不參加任何大會的技術領導人,只能跟自己的團隊成員一比高下。當然,他可能已經很優秀了,否則也不會成為技術領導。但如果與整個行業中最出類拔萃的人相比,他又處于什么位置?如果覺得在自己的圈子里已經一覽眾山小了,那碰到不同意見時,他又會作何反應?有些人會視之為學習的契機并為此感到興奮,但絕大多數都會對不同意見嗤之以鼻。
團隊協作
乍看上去,撲克是一種彼此對抗的游戲。但事實很少如是。即使在賭注最小的牌桌上,通常也至少會有幾個人常打交道。他們不會達成條件一致對付牌桌上的其他人——他們也不必如此。大家都明白一條道理:你不是要去跟牌玩得好的人對著干,贏他們的錢,而是要從水平低的人身上賺錢。專業牌手甚至會像一個團隊一樣協同工作。有些人彼此利益相關,故而一人得利則眾人均有收益。他們不僅互相了解,而且認識很多人。如果出現一局精彩牌局,樓層經理會跟他們打招呼;侍者會為他們的對手調制酒精度高的飲品;和手(即發牌者)會故意“犯錯”以影響某人心情(很少有人在心情不好的時候能夠打好牌)。每個人都在協同工作,確保大家都能掙到錢。
頗為有趣的是,程序員的情況也與之相似。很多人都坐在格子里,完全依賴自己解決問題。他們往往工作在代碼個人獨有制模式之下。我曾親眼目睹,在這種程序員交付的應用中,集成問題一直都是大家的心病。而更為不幸的是,集成之痛還只是最小的問題。假設IT部門把業務需求鎖定為500頁的需求文檔。如果公司決定改變業務方向,隨之而來的系統變更需求將令人痛不欲生。數以百萬計的金錢付諸東流,因為程序員開發的特性已不再具備業務價值,而IT部門還沒有找到更好的方式來應對業務變化。
當然,情況并非總是如此。專家懂得協作。他們會跟其他專家協作,但也不排斥與經理、客戶、業務部門、分析師、質保人員,以及所有可以為成功貢獻力量的人協作。他們胸懷大局:只有協作,才能讓每個人有所收獲。
度量
雄心勃勃的牌手常常討論他們贏了多少手牌,又輸了多少手。他們討論最多的還是本該贏但卻輸掉的那幾手牌。有時人們會犯錯誤輸錢,但他們一般都不會記得這幾手是怎么輸掉的。相反的是,如果有些牌局只是因為手氣不好而輸掉,他們就會記得那一局中的每一處細節,他們還會在故事中透露對手必然獲勝的幾率,來證明自己根本沒有勝出的機會。真正的牌手知道他們輸掉過多少手牌,以及失敗的大概幾率。他們懂得度量。而且專業牌手會專注于重要的度量標準。你贏了多少手,輸了多少手,這無關緊要;重要的是你贏了多少錢,輸了多少錢。而且,為你的狗屎運(譯者注:bad beat,即開局時輸家比贏家牌好,贏的幾率更大,但關鍵時刻贏家卻來了更好的牌。碰到狗屎運——take a bad beat——用來形容輸家,來了狗屎運——lay a bad beat——用來形容贏家)苦惱實際上等于替你對手的牌運犯愁。既然你的收入來自于對手的錯誤,那你就是在抱怨為什么對手把錢給了你。
有度量標準是好事,不過專業人士懂得哪些標準重要,哪些只會分散注意力,哪些介于二者之間。
軟件開發也有很多度量標準,而且有很多標準身上的光環已經遠遠超出了它們所應有的范圍。例如,知道代碼行數幾乎不能帶來任何價值。復雜應用需要相當多的代碼,但這個“相當”到底是多少?它得依賴于語言、工具及其他因素。
修復的bug數量也是個很有趣的話題,只是略遜于前一個。為什么人們會在乎修復了多少個bug?Bug數量也許有其價值,但是修復的bug數目并不能為我們帶來多少有用信息。
特性完成率是我自己最喜歡把玩的一個標準。除非我們使用特性來評估工作量,否則知道完成了多少特性又有何用?而且,如果已經對工作量做出了評估,那為什么不把剩余工作與已完成工作相比較,從而得到工作進度呢?我很難從特性完成率中看到價值所在。
代碼覆蓋率讓我想起了記錄狗屎運。這項度量是有意義的,但很多人都沒抓住重點。代碼覆蓋率低意味著可能有問題存在,但是代碼覆蓋率高只能表示你有一個很大的代碼覆蓋率數值。高代碼覆蓋率與高質量之間沒有必然聯系。
注意人,而不是邏輯
如果看過有玩牌鏡頭出現的電影,你大概聽過這樣一句話:你不是在與撲克玩,而是與人玩。此言極是。牌手無疑都是心理學家。有時你確實需要某些牌,但拿一手好牌只是賺錢的一部分而已。一旦有了好牌,你就需要知道怎樣利用好它們。你是應該加注,還是先讓牌然后加注,還是徹底讓牌,還是跟進?這些做法依賴于很多因素,但關鍵還是要了解牌桌上的對手。當你得到一手好牌,首要目標就是盡可能多地從對手那里贏錢,而達到這種目的的唯一方式則是想辦法讓對手給你更多的錢。了解邏輯可以幫助你贏得幾手牌,了解人則可以幫助你贏錢。
在交付軟件時,人處于同樣重要的地位。如果軟件只是讓一切工作起來,那只要把它變成自動化的工作,事情就容易得多了。但軟件卻遠非功能組合這么簡單。在一場高爾夫球比賽中,人們會賣出軟件包;在全家到迪斯尼免費旅游時,人們會簽下軟件服務合同;為了避免法律糾紛,人們會履行合同去構建已經毫無用處的軟件;為了超越競爭對手,人們會使用軟件來加快業務響應速度。
人們使用軟件、開發軟件、維護軟件,或是在某種程度上依賴軟件。軟件開發與這個世界有著千絲萬縷的聯系,要把洋洋灑灑的變量組合成簡單方程,生產出高質量的軟件,又與登天何異?但是,軟件開發高手需要考慮每個人引入的所有已知與未知的變量,做出他們力所能及的推測。知道應該做什么會讓你受益,而知道必須做什么所帶來的價值卻是難以衡量。了解邏輯可以幫助你交付應用,了解人則可以幫助你交付價值。
在殘缺的信息下工作
有關這點,剛開始打牌的人處理的非常好:打好每一手牌,老老實實押注,從不虛張聲勢。這便是了,新手就應該只做該做的事情,除非你的錢多得沒地方花了。難點在于如何從初學者的水平提升。大量信息霎那間紛至沓來,你需要注意牌桌上每個人的每一處細節:他們怎樣交流,你從前跟他們每個人打過什么交道,他們所鐘愛的玩牌方式,誰在贏,誰在輸,凡此種種不一而足。而且,你也不可能知道對手手里的牌是什么,下一張牌又是什么。你所擁有的信息已超出所能處理的極限,而且這遠非全部。
編程亦如是。領域專家無所不知,但把一切都向你傾囊相授卻毫無意義。何況,你也不一定需要所有的領域知識。你需要熟悉團隊,但同事總有些事情是你永遠無法知曉,或者不能完全理解的。不過,編程高手能夠把必要的領域知識融會貫通,掌握團隊的動態,并始終提供技術上的真知灼見。他們知道他們永遠無法成為百曉生,他們知道什么事情值得思考,哪些應該置之不理。縱使面前洶涌澎湃的信息仍是殘缺不全,他們也總能做出正確的決定。
即時反饋
普通牌手在反饋信息少的游戲中表現最好。因為牌手是根據信息而贏錢的。在5張牌梭哈中只有一輪押注的機會。各位玩家只有一次機會來分析你給出的信息,而你也只有一次機會犯錯。專家級牌手更喜歡多輪的游戲。游戲中的回合數越多,他們就有越多機會從低水平的對手身上撈到好處。他們喜歡即時反饋,并根據反饋做出調整。在有多個回合的游戲中,每一個回合都可以得到反饋,專業玩家就會根據當前局勢調整打法。
編程高手同樣喜歡即時反饋。從業務人員即時反饋回來的信息,可以避免你在構建業務應用時走上彎路。從另一個程序員即時反饋回來的信息,可以在軟件產品化之前發現bug。持續集成服務器可以提供即時的集成反饋,從而避免集成之痛。喜歡敏捷的人能馬上說出迭代是一個有著顯著成效的實踐,因為它可以讓程序員和業務人員得到即時反饋。不過,作為一個編程高手,縱使他不喜歡敏捷,他也能夠意識到即時反饋的價值;即使在非敏捷的環境中,他也會爭取得到更多的反饋,從而避免浪費時間精力。即時反饋可以讓你了解前行的方向正確與否,每一個專家都會珍視這些信息。
上下文為王
無論撲克還是編程,沒有絕對正確或是絕對錯誤的選擇。如果你有一對K,那么在翻牌之前你該不跟么?也許吧。這要看你是在打比賽還是賭錢、有上限還是沒上限、你坐在哪個位置上、你是否已經不跟過一次還是已經封頂了等等。我在撲克中學到了一點,那就是在給出答案之前,一定要綜合考慮所有的因素。
在編程中沉浸的時間愈久,同樣的體會在我心里就愈加深刻。Java在有些時候是不錯的選擇,但它并非萬能。所有的編程語言均如此。工具亦然。Hibernate很不錯,但它不適用的地方還有IBatis,當IBatis也不適用的地方還會出現或自己創造新的解決方案。幾乎沒有一款解決方案能夠絕對有效,它只有在恰當的形勢下才會發揮應有的作用。在錯誤的環境中,它也許會成為毒藥。
所以,面對一門新的語言或者工具,無論是你是打算棄若敝履,或是愛不釋手推而廣之,不妨先想想它的適用環境,盡量做到對癥下藥,量體裁衣。
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。