over 1 year ago

今天來談一點比較軟的東西,算是有感而發吧!昨天職棒的總冠軍賽落幕,自己支持的球隊很可惜無法板平賽事,將戰線延到第七戰,不過從整個球季到季後賽可以看到一些有趣的東西,這次季後賽的兩支隊伍很有意思,簡短看一下兩支球隊:

一支球隊在開季前透過交易自由球員的方式得到王牌級的打者,並透過外籍打擊教練的調整讓整體的打擊獲得成長,因此在上半季很快就快得到季後賽門票,但魔術數字點亮後卻沒有如一開始那麼迅速確實拿下上半季冠軍,雖然最終還是拿下,但下半季的狀況卻是跌跌撞撞;另一支球隊,有相當平均的戰力,投手、打擊和守備都很優秀,但上半季戰績卻始終無法超越首位,甚至上半季後段的連敗,讓東家決定要出售球隊,下半季則是調整戰力,緩緩地成為首位,到最後剩餘的幾場賽事,才拿下下半季冠軍,最終拿下總冠軍。

這兩支球隊與軟體開發有什麼關係?雖然我沒有參與球隊的決策,但從球迷的角度來看,支持的球隊為了「上半季冠軍」這個短期目標,忽略戰力的調整,即使牛棚有快撐不住的跡象,仍靠著球員的意志力撐下去,拿到上半季冠軍後,理論上下半季的賽事應該為總冠軍賽調整優先,戰績次之,但又為了下一個「全年度戰績第一」短期目標,整個調度又亂掉,然後又是靠意志力撐過去。

意志力很重要沒錯,特別是像總冠軍這種高強度的短期賽事,球員打了一整季的比賽,體力、傷勢等不利條件上身,真的需要有堅強的意志力,但意志力不是萬能,意志力無法彌補投手戰力的消耗,意志力無法像自來水那樣想要就有,更何況,參與總冠軍賽的兩支球隊,雙方意志力都很強,最終,還是看團隊的整體戰力而不是意志力。

看完有沒有覺得好像在軟體開發的職場也很像?為了業務的短期目標,工程師靠著意志力加班,勉強達成目標,但大家都知道,這段期間不只完成目標也累積龐大的技術債,本來承諾短期目標達成後,會有時間調整,像是整理技術債,或是讓菜鳥工程師能獲得技術訓練,但想也知道,馬上又會有下個短期目標,工程師為了技術債已經焦頭爛額時,又為了新需求發動意志力 (或是燃燒小宇宙),有達成目標可能還好,也許還能得到獎金,平撫受傷的意志力,但沒達成目標呢?就像支持的球隊,在九局上半救援投手崩盤沒撐過去呢?

在軟體開發的職場上崩盤會是什麼情況呢?工程師的離職是最常見的,特別是王牌級的工程師會最先離開,因為王牌級的工程師不乏其他工作機會,王牌級工程師離職後,本來的工作量由其他工程師承擔,其他工程師只好繼續燃燒小宇宙,留下更多技術債,更難達到目標,然後又有新的短期目標,專案整個嚴重 delay,看到這,我想應該有很多人都會心有戚戚焉。

在戰力有限的情況下,怎樣可以不這麼依賴意志力呢?簡言之,就是讓團隊有好的體質,方法不外乎幾點:

  • 有好的基礎建設
  • 專注做真正該做的事
  • 保持靈活的彈性

好的基礎建設,像是版控系統幾乎是最基本的,我蠻難想像沒有版控該怎麼開發大型的軟體,但只有版控系統是不夠的,雖然需要額外的開發時間,但與其用無法重複使用的人力測試,我個人比較相信能不斷重複執行的單元測試,在修改程式時,單元測試還能幫忙測試有沒有改壞什麼東西,甚至透過構思「如何測試?」以寫出容易維護與好設計的程式。

單元測試加上持續整合,能發揮更好的效果,每次簽入程式碼,若是需要編譯的程式語言,除了確保簽入的程式不會造成編譯失敗,還能在短時間內執行大量的單元測試與整合測試,能儘早發現問題,減低之後修復的成本。由於現在的系統越來越龐大,部署變成是一件很複雜的事,若只依賴人工部署,龐大的配置 (configuration) 很容易出錯,所以更進一步是最好能自動部署,讓容易出錯的部分減到最小。

專注做真正該做的事,如果將團隊的開發能力當成分母,要開發的需求作為分子,在開發團隊的能力無法快速提升的情況下,要讓產品更快完成,就是讓分子變小,這不是指減少開發的項目,而是避免讓不必要的項目加到分子中,有人可能會說,在沒上市前誰會知道哪些項目是不需要的,但這句本身就是個盲點,既然不知道是不是不需要的,同樣也表示他可能不是需要的,其實不須急在這個版本中釋出,我相信「能決定開發項目的優先順序以讓產品成功」是好的產品經理或 product owner 最重要的能力之一。

保持靈活的彈性,簡單說就是擺脫過去 waterfall 開發方式的思維,不論是用 scrum、kanban 或其他敏捷開發法,在一個較短的週期裡,馬上能有一定的產出,能檢視過去做錯的部分,不管是開發中遇到的技術問題或是需求的問題,能在短的週期裡立即作出調整,當產品有一定的程度,其實就可以投入市場接受考驗,不要思考說做到完美才上,因為就如同剛說的,未上市前不會知道什麼是完美的,甚至花了一堆時間做的完美,對使用者來說卻毫無意義,那時間都是浪費掉的。

至於新創團隊要不要寫單元測試?是要跑 scrum 還是跑 kanban?先談單元測試,有一種說法是新創團隊不寫測試是因為開發的東西還不知道有沒有市場,花時間寫測試不划算,因為需求隨時都可能改掉。我覺得這完全是兩回事,單元測試是用來驗證開發的程式是否如設計般正確,不是驗證是否有市場,與其用寶貴的人力做設計的驗證,我還是覺得單元測試比較好,但這決策只能由新創團隊自己決定。至於要跑哪種開發法,我倒覺得重點是彈性,而不是死守這些方法的規範,當然,前提是真的了解為什麼要有這些規範後,才能知道哪些規範也許現在不適用。

用棒球賽類比軟體開發或許不夠精確,畢竟季後賽打完,整個賽季也就結束了,新的賽季開始,整個戰績全部重來,每支球隊都從零勝零敗開始,這就是比賽。但軟體開發則不是,可能這一仗打輸了,市場沒了,整個公司就結束了,所以每一次釋出都像是在打季後賽,意志力是有必要的。可是,當公司已經在市場上,透過不斷地釋出添加新功能,反而像是例行賽,是一場長時間的考驗,若沒有好的團隊體質,光靠意志力是不夠的。而這兩者間其實沒有那麼明確的一條線,當跨過那條線之後就是例行賽,沒跨過前每場都像季後賽。即使有那麼一條明確的線,良好的團隊體質是需要時間培養的,跨過那條線才開始培養有點太晚了。

最後,我想起《瘋狂改變世界:我就是這樣創立Twitter的!》書中的一段,Biz Stone 提到即使在有信用卡卡債的情況下,只要稍微有一點點餘力,還是會捐款給有需要的組織,因為總有比他們更需要這筆錢的人。也許,為了短期目標已經快沒有餘力了,可是即使只有一點點,一丁點一丁點的投資,都比不投資要好,這些投資最終會打造出好的團隊體質。

系列索引
上一篇《閒談軟體架構:內部函式庫
下一篇《閒談軟體架構:意志力不是萬能藥

← 閒談軟體架構:內部函式庫 閒談軟體架構:例外處理 →