工程師忽略的隱形成本

>>>  技術話題—商業文明的嶄新時代  >>> 簡體     傳統

  英文原文:The Hidden Costs That Engineers Ignore

  有時候我們說,實現這個功能,我只花了幾個小時。但是完成之后,我們發現每隔幾周,我們要么在修復該功能的 bug、向另一個工程師解釋,要么做客服回答問題、解釋其工作原理。維護該功能總的投入時間要遠遠超過最初開發的幾個小時。

  軟件工程特有的最嚴酷的教訓之一就是額外復雜度所帶來的隱形成本。有時候,復雜度在問題領域只是固有的。為了匹配乘客和司機,通過調整價格來平衡供求是一個復雜和痛苦的問題。因此,在擴大一個社區和維護社區質量的時候,把問題和答案疏通到喜歡回答和看問題的人們那里,也是如此。或者像是開發一個兼容所有設備的富文檔編輯器以支持實時協作。這是固有的復雜度,我們需要根據產品做出調整以取得成功。

  但是其它時候,和我們較勁的恰恰是我們自己產生的復雜度。我們用新編程語言寫代碼,很少人了解它,現在我們不得不維護它。或者我們增加了額外的基礎架構,因為我們嘗試從 Hacker News 看到的熱門新技術,但是它失敗了,這是我們當初沒有想到的。或者我們引入了一個很少人使用的功能,但是修復和 bug 報告就花掉了極不對稱的大把時間。

  額外的復雜度暴露了很多隱形成本。在開發軟件時,我們所做的決定不只是決定了我們當前的開發速度,它們還要反映出我們花在維護上的時間和努力程度。

  復雜度的隱形成本

  太多復雜度增加了認知負荷,并產生了做完事情的額外阻力。它以很多不同的方式滲入到團隊里大部分是直接滲入到代碼、系統和產品復雜度里,但是間接地滲入到了組織的復雜度里。我們逐個看看這幾種不同類型復雜度的隱形成本。

  代碼復雜度

  代碼復雜度不只是隨著代碼行數的線性函數而增長它組合式地增長。在復雜的代碼庫里,每行代碼可能與其它很多行代碼交互和影響。我們對于組合式增長難以有足夠的認識,這就是為什么我們傾向于嚴重低估完成大型軟件項目所需要的時間,這也是重寫項目有時候會大幅延期的主要原因。

  當代碼過于復雜的時候,它將變得難以擴展、難以理清其中緣由、難以修復 bug,很難理清追蹤錯誤來源的依賴和數據流向。工程師或許會積極地避免代碼庫最復雜的部分,即使它是可以做某種修改的、最有邏輯的地方,也要選擇繞彎來解決。他們或許避免把那些地方都組合起來,即使這項工作有著很大的影響。

  系統復雜度

  工程師喜歡擺弄新玩具,要么因為好奇,要么因為他們認為新技術可能為解決他們的緊迫問題提供了銀彈。當 Pinterest 在 2011 年剛開始擴容網站以應對快速增長時,他們只有 3 個工程師的后端小組卻使用了 6 種不同的存儲技術(MySQL、Cassandra、Membase、Memcache、Redis 和 MongoDB)。他們實驗每項新技術的諾言都是解決現有系統的某些限制。但是,每種新解決方案都以其自身特定方式失敗了,為了管理和維護而投入了更多時間和努力。最終,團隊明白了,增加更多機器而不是更多技術,更能簡化擴容,因此他們消除了 Cassandra 和 MongoDB 之類的系統,強化了架構的已有組件。

  把基礎架構切分為太多系統,會帶來很多隱形成本,注意力被分散到了多個系統。對于每個系統來說,更難以整合資源以開發可復用的資源庫,更難以為日常工作招聘新人,更難以理解具體的失敗模式和每個系統的性能特點。每個系統的抽象最終變得更弱,因為沒有太多的可投入時間。當工具和抽象太復雜、或太多的時候,讓團隊去理解和探索將變得困難。

  產品復雜度

  產品復雜度可以導致一個不明確的版本、或引發缺乏產品聚焦的無節制野心。它希望在很多地方是優秀的,而不只是在一個核心領域,這種欲望使其不能向新用戶明確地解釋產品的意圖。產品復雜度引發了更多的代碼和系統復雜度團隊增加更多代碼、更多基礎架構以支持新功能。當產品外圍寬泛時,增加一個新功能或修改現有功能,將需要放大很多的努力來理解和適應舊的功能。

  過于復雜的產品意味著有更多的代碼分支,更多要考慮的問題、更多的需要團隊解決的 bug 反饋。工程師和數據科學家需要分析更多的變量、做更多的一次性的報表,而不是集中于核心用戶行為的理解上。工程師需要投入更多時間來提供功能空間和提高效率。每個人最終在更多的項目中進行切換。投入在維護所有這些功能上的時間,并不是重新投入代碼、償還技術債務、加固抽象的時間。

  組織的復雜度

  代碼、系統和產品復雜度,依次產生了組織的復雜度。團隊需要雇傭更多人來處理和維護已開發的所有東西。越大的團隊意味著越多的溝通成本、越多的協調和和越低的總體效率。招聘過程本身,涉及的所有面試和匯報,消耗了團隊很大比例的時間。當然,所有新員工不得不被培訓才能上崗。

  雇傭更多人的替代方法,就是將工程師組成劃分成更小的團隊或許甚至創建了一人小組來承担較多代碼、系統和產品外圍的工作。這降低了溝通成本,但是一人小組有他們自己的成本。一旦遇到難題,就完全拖延了項目中的唯一人手,因為有更少的人來分享這些低谷期,這種體驗對于士氣是有害的。與其他人合作的機會少了,會傷害到工作場所的快樂和員工的留任。除非每個人比較自覺,而且主動詢問反饋,否則個人收到的工作反饋將更少,因為分享相同項目上下文的人更少了。減少的反饋能夠降低代碼質量、或因疏忽導致的復雜度引入到代碼庫或基礎架構里。

  如何應付復雜度

  Tony Hoare 在 1980 年圖靈獎的演講中建議,構造軟件設計有兩種方法:一種是簡單,明顯地沒有缺陷;另一種方法是使其復雜,卻沒有明顯的缺陷。提到了由于復雜度而導致的非明顯的缺陷是如何傷害我們的,以及我們該如何應對這些成本?

  下面是你能夠用到的一些策略:

  • 為簡單而優化。抵制增加更多復雜的主張。深思維護成本。要自問,為了解決 20% 的問題而引入的復雜是否值得,或者 80% 的解決方案已經足夠了。
  • 為你的團隊或產品定義一種任務說明以統一思想。在 Team Geek,Brian W. Fitzpatric 和 Ben Collins-Sussman 解釋了他們是如何輔導 Google Web Toolkit(GWT)團隊、并鼓勵他們寫下任務說明的。接下來發生的、對于任務說明的內容和形式的爭論,表明了首席工程師并不真正認同產品方向!他們被迫面對、協調不同、并最終達成了,GWT 的任務是為用戶徹底提升 web 體驗,讓開發者使用現有的 Java 工具在任意現代瀏覽器里構建高性能的 AJAX。如果他們不能盡早找出這些區別,隨之而來的努力上的分散又有多少呢?
  • 用較小的構建塊組成大型系統。Google 就是個例子,致力于構建健壯的核心抽象,然后被非常寬泛的應用程序廣為使用。他們有基礎的構建塊,像 Protocol Buffers、Google File System 和遠程程序調用的 Stubby 服務器。基于這些構建塊之上,他們還建立了其它抽象,比如 MapReduce 和 BigTable。在此之上,包括大型 web 索引、Google Analytics 站點追蹤、Google News 聚合、Google Earth 數據處理、Google Zeitgeist 數據分析在內的數以千計的應用程序,還有很多程序都是這樣構建的。
  • 清晰地定義模塊和服務之間的接口。模塊和服務的退耦,將減少能夠產生一堆代碼的組合復雜度。在 Amazon,Jeff Bezos 于 2002 年宣稱,公司將轉向面向服務的架構,所有團隊只能通過服務層級的接口彼此交流。雖然這個轉變造成了本身巨大的開發成本,但是它強制分離了代碼和服務背后的邏輯,為現在極度成功的 Amazon Web Services 的建立提供了便利。
  • 優先償還技術債務。我們總是在信息不完全的條件下開發軟件。做為條件變化的響應,代碼庫在增大,熵也在增大。增加的復雜度成為了未來開發的代價。在開發日常上預算時間可以減少這項成本。很多工程師和團隊在項目之間預算這項時間,不過召開一次性的會議會有幫助。我過去在 Quora 組織過一次 Code Purge Day(代碼消除日)活動,工程師在這一天全部關注刪除無用代碼的工作。我們在積分牌上追蹤代碼消除的進度,這使得刪除你自己的代碼更有趣味。
  • 使用數據修剪沒用的功能。在 Yammer,當工程師或產品經理發現在代碼重構時,強化或保留一個功能將花費不菲的時間時,他們將查看使用數據,以確定這項功能是否真正被使用了。如果沒有,他們將和團隊一起決定,他們是否應該只是砍掉這個功能以降低總體工作量。與簡化的代碼是怎樣減少技術債務一樣,這個策略也減少了技術債務。
  • 基于主題對進行中的項目分組。使同事彼此分享同樣的環境,更容易地參與到設計討論、代碼評審或構建可復用的資源庫。所有這些活動有助于提供檢查和平衡掉單個人或其他人所引發的問題。

  當我們為學校課程開發軟件時,我們有著世界的過于簡單的視角維護任意復雜度的成本隨著下課而消失了。但是在我們的職業生涯中,糟糕的軟件決定將產生數年負担的影響。

  不要使事情復雜化。

   END

  譯文: 《工程師忽略的隱形成本 》 臘八粥


Cnblogs 2015-08-23 08:57:36

[新一篇] 小心你的信用卡欠款! 實際年利率可能高達19.56%

[舊一篇] 庫克:微軟太守舊了 蘋果一直在顛覆過去
回頂部
寫評論


評論集


暫無評論。

稱謂:

内容:

驗證:


返回列表