聰明的程序員使用50%-70%的時間用來思考,嘗試和權衡各類設計和實現,而用30% – 50%的時間是在忙碌着編碼,調試和測試。聰明的老闆也會讓團隊這樣作。而傻逼的老闆,苦逼的程序員會拿出來100%-150%的時間來忙着趕進度,返工,重構,fix 大量的 bug… 因此, 越差的團隊通常會越忙,並且還忙不完。程序員
在如今這個浮躁的時期,再加上敏捷諮詢師們唸的歪經,他們讓人感受上就像是軟件產品是能夠在很短的時間內高質量的完成的,這令那些管理者們很興奮,就像巴甫洛夫的條件反射實驗中的狗看到了肉就像流口水那樣興奮。他們使用 TDD,快速迭代,不斷重構,持續集成直至持續部署的方法在進行軟件開發。架構
軟件開發真是這樣的嗎?難道不須要花時間去思考嗎?對此,有些觀點在 Todd 的《「品質在於構建過程」嗎?》以及《Bob 大叔和 Jim Coplien 對 TDD 的論戰》中談到過了。我只想一想表達下面的觀點:異步
軟件的精髓在於設計,設計是一件很費大腦的事件。對於軟件來講,設計沒有完美的,它老是一件須要取捨須要權衡的事,好比:時間換空間,空間換時間,TCP 或 UDP,同步仍是異步,數據冗餘還不冗餘等等。那怕是一個小小的 observers 模式是 pull 方式仍是 push 方式都須要仔細討論。這些的東西須要時間和作前期嘗試。模塊化
TDD、快速原型和迭代可能會對軟件和團隊產生負面影響。在一開始,你須要花很大的精力來讓你的軟件從無到有(作過軟件的人都知道,從零開始寫代碼是很痛苦的事),可是由於你沒有想好,先作再說,因此,後期你會面臨更多的質量問題而讓你須要花更多的時間精力。固然,那些諮詢師會讓你用持續集成和持續部署這樣的方法。但我想告訴你,這並不解決你軟件設計的缺陷。舉個例子——TDD、迭代、原型只關注功能性需求,其不會關注非功能性需求,好比性能問題,高可用性問題,系統維護問題(模塊的耦合問題),等等。而這些問題每每均可以讓你的軟件設計從新來過。性能
重構是惡夢,重構應該越少越好。當你維護一個複雜的系統時你會知道重構是一件多麼恐怖的事情。若是一開始沒有想好,你要面臨的不僅僅是 re-design, re-architect,還要面對時間和人力成本的增長,最難的是你還要面對的是團隊士氣由於不斷的 rework 而逐漸低落併產生厭倦和懈怠情緒。測試
因此,若是你能有多一些時間去和客戶討論一下需求和將來可能的變化,去調查一下實現的技術難點和細節,去和其餘有經驗的人討論並推敲一下架構和設計,去思考設計上的缺陷,那麼,你的 coding 會變得很是地直,直到你一眼就看到盡頭,你的測試案例也會寫得很是地好,你會幾乎不須要重構,因而,你會在將來少寫不少代碼,從而你的軟件開發會愈來愈輕鬆,直到技術開始換代。優化
我如今在作的項目,花了幾乎4個月的時間來作設計,在這個過程當中,咱們反覆思考、討論和權衡若干種實現方法,並儘量地窮舉全部的場景和細節以及將來可能的變化(那怕是那些簡單的模塊),有個模塊被重寫了至少三次,每次都是寫到一半就被推翻重寫,咱們整個團隊不斷地在和其它團隊討論,並在對系統不斷地認識中對系統進行簡化和優化,併力求達到完美。如今看來,沒有貿然使用 Scrum 是明智的。編碼
這就好像咱們修路造橋同樣,咱們須要花大量的時間勘測地形地質,分析數據,思考可能出現的各類問題(各類天然災害),評估不一樣的設計方案,而不是先儘快建好再說。因此,多一些時間,不是讓你多作幾回迭代,多完成幾個模塊,而是可讓你少寫一些代碼,更快的交付一個更好的產品。設計
我相信你會有不少疑問,下面是我以爲你可能會有下面的一些觀點,讓我一條一條來回復:調試
首當其衝的必定會是項目的 deadline,或是那種你沒有活語權的項目。好比作那種「甲乙方合同式的項目」,我把這種項目統一認爲是「外包項目」,在這種項目性質下,你很難有話語權。對此,我以爲,1)做爲乙方的你仍是應該和甲方在項目計劃上爭取一下,曉之以情,動之以理。2)若是不行,只能在時間、需求範圍和質量上作一個權衡。另外,在這種狀況下你要找一個方法,把你的壓力和痛苦分擔給用戶和領導。(找到這個方法的前提須要你找到用戶和領導他們懼怕什麼,嘿嘿)
過分設計和紙上談兵。有人說會不會設計太多,形成過分設計,或是在設計上花太多的時間。這有可能。我上一家公司的一個項目團隊就花了1年多的時間來不停不停的開會和作設計,結果 release 的時候還有1000多個 bug。這個問題的緣由是,這個團隊的設計是在紙上談兵,開會是開神仙會,討論的設計都是浮雲。因此,設計並非討論和思考,還須要去嘗試,我認爲當你的設計完成的時候,你的骨幹核心代碼都基本完成了。
個人團隊成員水平太差,不會思考。首先,先恭喜你找到一堆碼農,固然,這不怪你,這是中國教育和大環境的問題,讓人不會思考。對於這樣的狀況,我有兩個建議,1)量力而行,使多大的碗就吃多少飯。2)鼓勵思考,那怕那些想法很不靠譜,由於若是不開始,那麼將永遠不會思考。
必需使用快速迭代。不少公司都在強行上敏捷,他們但願產品越快 release 越好,而沒有充分的時間思考和討論。對於這種項目,個人建議是,1)找有豐富經驗的人來作。2)迭代過程當中力求架構和程序邏輯的簡單,簡單,再簡單,力求代碼間的高內聚,低耦合。否則,重構的時候你就好玩了。
創業團隊必須要快。作得快就是作得好嗎?不少時候,不是誰快誰就能笑到最後的。這樣的例子太多了。第一個作出來的人並不必定就會佔領市場,其頗有可能會成爲先驅。
有錢的公司纔會讓團隊用更多的時間去思考。錯了,大家沒有見過有錢的公司,有錢的公司能夠招一堆幹不成活的人,能夠把事搞亂了從新來過,甚至能夠把作失敗的項目換個名字再從新立項。這些真正的有錢的公司只求快,只求人多,不怕作錯決定。像咱們這些沒錢的人,幹什麼事都是當心翼翼地,生怕作錯決定。
因此,構建一個優秀的系統,我以爲須要如下幾點:
構建一個好系統的願景。若是相關人員(經理,小組負責人,程序員)只是想混飯吃,就註定沒法構建優秀的系統。
理解業務需求。雖然不可能像業務人員同樣熟悉全部細節,但總體上應該超過業務人員。若是可能,要讓全部程序員都真正地理解業務。正如喬布斯,他基本上不會去詢問客戶的需求,由於他對「需求」的理解遠遠超過了普通大衆。惟有如此,才能建造出傑出的系統。只有真正理解了需求之後,才能在系統設計中加入將來可能須要的接口和模塊(而不是過分設計),才能在開發過程當中「抵制」客戶的不合理需求改動要求,才能避免種種業務陷阱,開發出客戶喜好的功能。
儘可能利用已有的主流軟件平臺,減小開發。在軟件開發過程當中沒有「銀彈」。即便對優秀的程序員來講,要減小BUG,也必須作大量的測試和BUG修訂。這意味着驚人的時間和成本。成熟的商業軟件系統雖然價格高昂,但其質量也遠遠高於通常公司裏IT部門開發出來的東西。本身開發的系統,複雜性一旦到達某個級別,每每會事實上不可維護。這不只僅意味着直接的維護成本,更會對公司的業務形成嚴重破壞和阻礙。應該在成熟的系統裏,經過少許二次開發來實現須要的功能。
分階段實施。不要試圖實現全部的功能,不要試圖構造完美系統。業務需求中,總有一部分相當重要。實現了這一部分,就能爲業務人員節省超過80%的時間。通常都應該迅速構造這樣一個1.0版本,並讓業務人員儘早在上面工做。等系統穩定之後,再去構造2.0版本。在系統的構造過程當中出現的絕大部分新需求或者需求改動,都應該放入下一個版本。
代碼: "輕耦合", "模塊化", "易讀"。代碼模塊相互要獨立,每一個模塊功能必須單一,並且一樣的功能不該該在不一樣的模塊中重複實現。除了上面列出的這幾條,易讀性就是最重要的。在99%的場合下,性能一類的要素都不須要考慮。合理的系統架構自己就已經解決了性能問題。合理的程序代碼(包括SQL語句)都足夠快。代碼中嵌入的註釋應該不多----優秀的代碼自己就能解釋邏輯。註釋通常應該集中在模塊的開頭部分,闡述業務邏輯,幫助程序員理解業務需求。在一個應用系統中,爲了把局部性能提升10000倍而犧牲代碼可讀性,通常是不可接受的。(除了一些極其罕見的特例)
代碼: 垃圾進,垃圾出。通常來講,對任何一個模塊,都不該該去檢測傳入參數是否合法,更不該該試圖去處理非法數據。惟一須要保證的是,合法的傳入數據將產生合法的傳出數據。這也是爲了防止"過分設計",爲了不垃圾數據,必須在源頭上卡住。避免垃圾數據進入系統。
代碼: 只有異常,才拋出異常。能夠預見的錯誤,都不該該致使異常(exception)