工程師忽略的隱形成本
原文地址(source):http://www.theeffectiveengineer.com/blog/hidden-costs-that-engineers-ignore
有時(shí)候我們說(shuō),“實(shí)現(xiàn)這個(gè)功能,我只花了幾個(gè)小時(shí)”。但是完成之后,我們發(fā)現(xiàn)每隔幾周,我們要么在修復(fù)該功能的bug、向另一個(gè)工程師解釋,要么做客服回答問(wèn)題、以解釋其工作原理。維護(hù)該功能總的投入時(shí)間要遠(yuǎn)遠(yuǎn)超過(guò)最初開發(fā)的幾個(gè)小時(shí)。
軟件開發(fā)中內(nèi)化的最艱難教訓(xùn)之一就是額外復(fù)雜度所帶來(lái)的隱形成本。有時(shí)候,復(fù)雜度在問(wèn)題領(lǐng)域只是固有的。為了匹配乘客和司機(jī),通過(guò)調(diào)整價(jià)格來(lái)平衡供求是一個(gè)復(fù)雜和痛苦的問(wèn)題。因此,在擴(kuò)大一個(gè)社區(qū)和維護(hù)社區(qū)質(zhì)量的時(shí)候,把問(wèn)題和答案疏通到喜歡回答和看問(wèn)題的人們那里,也是如此。或者像是開發(fā)一個(gè)兼容所有設(shè)備的富文檔編輯器以支持實(shí)時(shí)協(xié)作。這是固有的復(fù)雜度,我們需要根據(jù)產(chǎn)品做出調(diào)整以取得成功。
但是其它時(shí)候,和我們較勁的復(fù)雜度恰恰是我們自己產(chǎn)生的復(fù)雜度。我們用新編程語(yǔ)言寫代碼,很少人了解它,現(xiàn)在我們不得不維護(hù)它?;蛘呶覀?cè)黾恿祟~外的基礎(chǔ)架構(gòu),因?yàn)槲覀儑L試從Hacker News看到的、熱門新技術(shù),但是它失敗了,這是我們當(dāng)初沒(méi)有想到的?;蛘呶覀円肓艘粋€(gè)很少人使用的功能,但是修復(fù)和bug報(bào)告就花掉了極不對(duì)稱的大把時(shí)間。
額外的復(fù)雜度暴露了很多隱形成本。在開發(fā)軟件時(shí),我們所做的決定不只是決定了我們當(dāng)前的開發(fā)速度。它們還要反映出我們花在維護(hù)上的時(shí)間和努力程度。
復(fù)雜度的隱形成本
太多復(fù)雜度增加了認(rèn)知負(fù)荷,并產(chǎn)生了做完事情的額外阻力。它以很多不同的方式滲入到團(tuán)隊(duì)里——大部分是直接滲入到代碼、系統(tǒng)和產(chǎn)品復(fù)雜度里,但是間接地滲入到了組織的復(fù)雜度里。我們逐個(gè)看看這幾種不同類型復(fù)雜度的隱形成本。
代碼復(fù)雜度
代碼復(fù)雜度不只是隨著代碼行數(shù)的線性函數(shù)而增長(zhǎng)——它組合式地增長(zhǎng)。在復(fù)雜的代碼庫(kù)里,每行代碼可能與其它很多行代碼交互和影響。我們對(duì)于組合式增長(zhǎng)難以有足夠的認(rèn)識(shí),這就是為什么我們傾向于嚴(yán)重低估完成大型軟件項(xiàng)目所需要的時(shí)間。這也是重寫項(xiàng)目有時(shí)候會(huì)大幅延期的主要原因。
當(dāng)代碼過(guò)于復(fù)雜的時(shí)候,它將變得難以擴(kuò)展、難以理清其中緣由、難以修復(fù)bug,很難理清追蹤錯(cuò)誤來(lái)源的依賴和數(shù)據(jù)流向。工程師或許會(huì)積極地避免代碼庫(kù)最復(fù)雜的部分,即使它是可以做某種修改的、最有邏輯的地方,也要選擇繞彎來(lái)解決。他們或許避免把那些地方都組合起來(lái),即使這項(xiàng)工作有著很大的影響。
系統(tǒng)復(fù)雜度
工程師喜歡擺弄新玩具,要么因?yàn)楹闷?,要么因?yàn)樗麄冋J(rèn)為新技術(shù)可能為解決他們的緊迫問(wèn)題提供了銀彈。當(dāng)Pinterest在2011年剛開始擴(kuò)容網(wǎng)站以應(yīng)對(duì)快速增長(zhǎng)時(shí),他們只有3個(gè)工程師的后端小組卻使用了6種不同的存儲(chǔ)技術(shù)(MySQL、Cassandra、Membase、Memcache、Redis和MongoDB)。他們實(shí)驗(yàn)每項(xiàng)新技術(shù)的諾言都是解決現(xiàn)有系統(tǒng)的某些限制。但是,每種新解決方案都以其自身特定方式失敗了,為了管理和維護(hù)而投入了更多時(shí)間和努力。最終,團(tuán)隊(duì)明白了,增加更多機(jī)器而不是更多技術(shù),更能簡(jiǎn)化擴(kuò)容,因此他們消除了Cassandra和MongoDB之類的系統(tǒng),強(qiáng)化了架構(gòu)的已有組件。
把基礎(chǔ)架構(gòu)切分為太多系統(tǒng),會(huì)帶來(lái)很多隱形成本。注意力被分散到了多個(gè)系統(tǒng)。對(duì)于每個(gè)系統(tǒng)來(lái)說(shuō),更難以整合資源以開發(fā)可復(fù)用的資源庫(kù),更難以為日常工作招聘新人,更難以理解具體的失敗模式和每個(gè)系統(tǒng)的性能特點(diǎn)。每個(gè)系統(tǒng)的抽象最終變得更弱,因?yàn)闆](méi)有可投入的太多時(shí)間。當(dāng)工具和抽象太復(fù)雜、或太多的時(shí)候,讓團(tuán)隊(duì)去理解和探索將變得困難。
產(chǎn)品復(fù)雜度
產(chǎn)品復(fù)雜度可以導(dǎo)致一個(gè)不明確的版本、或引發(fā)缺乏產(chǎn)品聚焦的無(wú)節(jié)制野心。它希望在很多地方是優(yōu)秀的,而不只是在一個(gè)核心領(lǐng)域,這種欲望使其不能向新用戶明確地解釋產(chǎn)品的意圖。產(chǎn)品復(fù)雜度引發(fā)了更多的代碼和系統(tǒng)復(fù)雜度——團(tuán)隊(duì)增加更多代碼、更多基礎(chǔ)架構(gòu)以支持新功能。當(dāng)產(chǎn)品外圍寬泛時(shí),增加一個(gè)新功能或修改現(xiàn)有功能,將需要放大很多的努力來(lái)理解和適應(yīng)舊的功能。
過(guò)于復(fù)雜的產(chǎn)品意味著有更多的代碼分支,更多要考慮的問(wèn)題、更多的需要團(tuán)隊(duì)解決的bug反饋。工程師和數(shù)據(jù)科學(xué)家需要分析更多的變量、做更多的一次性的報(bào)表,而不是集中于核心用戶行為的理解上。工程師需要投入更多時(shí)間來(lái)提供功能空間和提高效率。每個(gè)人最終在更多的項(xiàng)目中進(jìn)行切換。投入在維護(hù)所有這些功能上的時(shí)間,并不是重新投入代碼、償還技術(shù)債務(wù)、加固抽象的時(shí)間。
組織的復(fù)雜度
代碼、系統(tǒng)和產(chǎn)品復(fù)雜度,依次產(chǎn)生了組織的復(fù)雜度。團(tuán)隊(duì)需要雇傭更多人來(lái)處理和維護(hù)已開發(fā)的所有東西。越大的團(tuán)隊(duì)意味著越多的溝通成本、越多的協(xié)調(diào)和和越低的總體效率。招聘過(guò)程本身,涉及的所有面試和匯報(bào),消耗了團(tuán)隊(duì)很大比例的時(shí)間。當(dāng)然,所有新員工不得不被培訓(xùn)才能上崗。
雇傭更多人的替代方法,就是將工程師組成劃分成更小的團(tuán)隊(duì)——或許甚至創(chuàng)建了一人小組——來(lái)承擔(dān)較多代碼、系統(tǒng)和產(chǎn)品外圍的工作。這降低了溝通成本,但是一人小組有他們自己的成本。一旦遇到難題,就完全拖延了項(xiàng)目中的唯一人手,因?yàn)橛懈俚娜藖?lái)分享這些低谷期,這種體驗(yàn)對(duì)于士氣是有害的。與其他人合作的機(jī)會(huì)少了,會(huì)傷害到工作場(chǎng)所的快樂(lè)和員工的留任。除非每個(gè)人比較自覺(jué),而且主動(dòng)詢問(wèn)反饋,否則個(gè)人收到的工作反饋將更少,因?yàn)榉窒硐嗤?xiàng)目上下文的人更少了。減少的反饋能夠降低代碼質(zhì)量、或因疏忽導(dǎo)致的復(fù)雜度引入到代碼庫(kù)或基礎(chǔ)架構(gòu)里。
如何應(yīng)付復(fù)雜度
Tony Hoare在1980年圖靈獎(jiǎng)的演講中建議,“構(gòu)造軟件設(shè)計(jì)有兩種方法:一種是簡(jiǎn)單,明顯地沒(méi)有缺陷;另一種方法是使其復(fù)雜,卻沒(méi)有明顯的缺陷。”提到了由于復(fù)雜度而導(dǎo)致的非明顯的缺陷是如何傷害我們的,以及我們?cè)撊绾螒?yīng)對(duì)這些成本?
下面是你能夠用到的一些策略:
- 為簡(jiǎn)單而優(yōu)化。抵制增加更多復(fù)雜的主張。深思維護(hù)成本。要自問(wèn),為了解決20%的問(wèn)題而引入的復(fù)雜是否值得,或者80%的解決方案已經(jīng)足夠了。
- 為你的團(tuán)隊(duì)或產(chǎn)品定義一種任務(wù)說(shuō)明以統(tǒng)一思想。在Team Geek,Brian W. Fitzpatric和Ben Collins-Sussman解釋了他們是如何輔導(dǎo)Google Web Toolkit(GWT)團(tuán)隊(duì)、并鼓勵(lì)他們寫下任務(wù)說(shuō)明的。接下來(lái)發(fā)生的、對(duì)于任務(wù)說(shuō)明的內(nèi)容和形式的爭(zhēng)論,表明了***工程師并不真正認(rèn)同產(chǎn)品方向!他們被迫面對(duì)、協(xié)調(diào)不同、并最終達(dá)成了,“GWT的任務(wù)是為用戶徹底提升web體驗(yàn),讓開發(fā)者使用現(xiàn)有的Java工具在任意現(xiàn)代瀏覽器里構(gòu)建高性能的AJAX。”如果他們不能盡早找出這些區(qū)別,隨之而來(lái)的努力上的分散又有多少呢?
- 用較小的構(gòu)建塊組成大型系統(tǒng)。Google就是個(gè)例子,致力于構(gòu)建健壯的核心抽象,然后被非常寬泛的應(yīng)用程序廣為使用。他們有基礎(chǔ)的構(gòu)建塊,像Protocol Buffers、Google File System和遠(yuǎn)程程序調(diào)用的Stubby服務(wù)器。基于這些構(gòu)建塊之上,他們還建立了其它抽象,比如MapReduce和BigTable。在此之上,包括大型web索引、Google Analytics站點(diǎn)追蹤、Google News聚合、Google Earth數(shù)據(jù)處理、Google Zeitgeist數(shù)據(jù)分析在內(nèi)的數(shù)以千計(jì)的應(yīng)用程序,還有很多程序都是這樣構(gòu)建的。
- 清晰地定義模塊和服務(wù)之間的接口。模塊和服務(wù)的退耦,將減少能夠產(chǎn)生一堆代碼的組合復(fù)雜度。在Amazon,Jeff Bezos于2002年宣稱,公司將轉(zhuǎn)向面向服務(wù)的架構(gòu),所有團(tuán)隊(duì)只能通過(guò)服務(wù)層級(jí)的接口彼此交流。雖然這個(gè)轉(zhuǎn)變?cè)斐闪吮旧砭薮蟮拈_發(fā)成本,但是它強(qiáng)制分離了代碼和服務(wù)背后的邏輯,為現(xiàn)在極度成功的Amazon Web Services的建立提供了便利。
- 優(yōu)先償還技術(shù)債務(wù)。我們總是在信息不完全的條件下開發(fā)軟件。做為條件變化的響應(yīng),代碼庫(kù)在增大,熵也在增大。增加的復(fù)雜度成為了未來(lái)開發(fā)的代價(jià)。在開發(fā)日常上預(yù)算時(shí)間可以減少這項(xiàng)成本。很多工程師和團(tuán)隊(duì)在項(xiàng)目之間預(yù)算這項(xiàng)時(shí)間,不過(guò)召開一次性的會(huì)議會(huì)有幫助。我過(guò)去在Quora組織過(guò)一次Code Purge Day(代碼消除日)活動(dòng),工程師在這一天全部關(guān)注刪除無(wú)用代碼的工作。我們?cè)诜e分牌上追蹤代碼消除的進(jìn)度,這使得刪除你自己的代碼更有趣味。
- 使用數(shù)據(jù)修剪沒(méi)用的功能。在Yammer,當(dāng)工程師或產(chǎn)品經(jīng)理發(fā)現(xiàn)在代碼重構(gòu)時(shí),強(qiáng)化或保留一個(gè)功能將花費(fèi)不菲的時(shí)間時(shí),他們將查看使用數(shù)據(jù),以確定這項(xiàng)功能是否真正被使用了。如果沒(méi)有,他們將和團(tuán)隊(duì)一起決定,他們是否應(yīng)該只是砍掉這個(gè)功能以降低總體工作量。與簡(jiǎn)化的代碼是怎樣減少技術(shù)債務(wù)一樣,這個(gè)策略也減少了技術(shù)債務(wù)。
- 基于主題對(duì)進(jìn)行中的項(xiàng)目分組。使同事彼此分享同樣的環(huán)境,更容易地參與到設(shè)計(jì)討論、代碼評(píng)審或構(gòu)建可復(fù)用的資源庫(kù)。所有這些活動(dòng)有助于提供檢查和平衡掉單個(gè)人或其他人所引發(fā)的問(wèn)題。
當(dāng)我們?yōu)閷W(xué)校課程開發(fā)軟件時(shí),我們有著世界的過(guò)于簡(jiǎn)單的視角——維護(hù)任意復(fù)雜度的成本隨著下課而消失了。但是在我們的職業(yè)生涯中,糟糕的軟件決定將產(chǎn)生數(shù)年負(fù)擔(dān)的影響。
不要使事情復(fù)雜化。
原文鏈接:http://www.labazhou.net/2015/01/hidden-costs-that-engineers-ignore/