開發人員守則:避免無謂的隱形成本(上)
開發人員要實現一個軟件功能,可能只花了幾個小時,但是完成之後,測試、debug、漏洞修補、向另一個工程師解釋,回答客戶問題、解釋工作原理……。維護單一功能所需的時間往往超過最初開發的幾個小時,人手成本難以預計。
固有複雜度
軟件開發的複雜程度帶來很大的隱形成本,有時候,複雜度是固有的,通過調整價格來平衡供求是一個複雜和痛苦的問題。因此,擴大軟件功能和維護品質的時候,這是固有的複雜度,我們需要根據產品進行調整以取得成功。
撇除固有的複雜度,開發人員仍然受自己產生的複雜度所困擾,例如:
- 用新程式語言寫代碼,對新語言的瞭解不足,而維護上便需花上額外的時間;
- 又或者從網絡看到新興熱門技術,躍躍欲試而增加了額外的基礎架構,但嘗試後便發現失敗了;
- 開發時引入了一個很少人使用的功能,但是修復和 debug 報告就花掉了極不對稱的時間。
額外的複雜度造成了很多隱形成本,開發前期我們所做的決定不只決定了目前的開發速度,還埋下了後期維護的時間和人力資源的消耗。複雜度以很多不同的方式滲入到團隊裡,大部分是直接滲入到代碼、系統和產品複雜度裡,亦有間接地滲入到企業裡。我們逐個看看這幾種不同類型複雜度的隱形成本。
代碼複雜度
代碼複雜度不是隨著代碼行數增加而線性增長,絕大部份情況是複式增長。在複雜的代碼庫裡,每行代碼可能與其它很多行代碼互相影響。我們對於複式增長難以控制,這就是為什麼團隊容易低估大型軟件專案所需要的時間,這也是重寫項目有時候會大幅延期的主要原因。
當代碼過於複雜的時候,它將變得難以擴展、難以釐清其中緣由、難以修復 bug、難以追蹤錯誤來源和資料流程。工程師或許會積極地避免代碼庫最複雜的部分,即使可以做某種修改、最有邏輯的地方也要選擇一些「硬揼」來解決。即使這項工作有著很大的影響,他們或許也會避免把那些地方組合起來。
系統複雜度
工程師喜歡擺弄新玩具,可能是因為好奇,因為新技術可解決他們的緊迫問題。當 Pinterest 在 2011 年剛開始擴充網站以應對快速增長時,他們只有 3 個工程師的小組卻使用了 6 種不同的存儲技術(MySQL、Cassandra、Membase、Memcache、Redis 和 MongoDB),實驗每項新技術的目的都是為了解決現有系統的某些限制。但是;最終,團隊明白了,增加更多機器而不是更多技術,更能簡化擴充,因此他們消除了 Cassandra 和 MongoDB 之類的系統,強化了架構的已有元件。
把基礎架構切分為太多系統,會帶來很多隱形成本。注意力被分散到了多個系統。對於每個系統來說,更難以整合資源以開發可重用的資源庫,更難以為日常工作招聘新人,更難以理解具體的失敗模式和每個系統的性能特點。每個系統的抽象最終變得更弱,因為沒有可能投入太多時間。當工具和抽象太複雜、或太多的時候,讓團隊去理解和探索將變得困難。
產品複雜度
產品複雜度可以導致一個不明朗的目標,無節制的野心會令產品缺乏清晰定位。開發人員或投資者總希望不只是在單方面做出優越的成績,而是要在很多地方都有出色表現。這種欲望使其不能向使用者明確地解釋產品的意圖,產品複雜度引發了更多的代碼和系統複雜度,團隊增加更多代碼、更多基礎架構以支持新功能。當產品要增加一個新功能或修改現有功能,將需要很多努力來理解和適應。
過於複雜的產品意味著有更多的代碼分支,更多要考慮的問題、更多的需要團隊解決的 bug。工程師和數據分析師需要分析更多的變數、做更多的報表,而不是集中於核心用戶行為。工程師需要投入更多時間來提供功能空間和提高效率。每個人最終在更多的項目中進行切換。投入在維護所有這些功能上的時間,並不是重新投入代碼、技術、加固抽象的時間。
<待續>
相關文章: