軟件開發(fā)項(xiàng)目由于各種項(xiàng)目管理和技術(shù)因素而偏離正軌或以失敗告終——從過高的期望到基本的功能變化。
所有的軟件項(xiàng)目都始于夢(mèng)想和宏偉的愿景。在平行宇宙的某個(gè)地方,有一個(gè)能夠?qū)崿F(xiàn)所有夢(mèng)想項(xiàng)目,但是在我們的宇宙中,軟件項(xiàng)目往往踉踉蹌蹌地走到終點(diǎn)線,有時(shí)甚至?xí)邕^它。
分析師也許喜歡隨機(jī)推算出一些評(píng)估軟件項(xiàng)目失敗的百分比,但這些數(shù)字必然是十分不準(zhǔn)確的,因?yàn)槭〔⒉皇欠谴思幢说氖挛?。你最終可能會(huì)得到運(yùn)行順利但無人使用的代碼?;蛘吣闵踔?xí)玫讲荒芫幾g的代碼。有時(shí)你可以從熊熊燃燒的殘骸中找到有用的東西,有時(shí)最好在爆炸發(fā)生前逃跑。
當(dāng)余火燃盡的現(xiàn)場(chǎng)冷卻時(shí),尸體解剖隨之開始,人們開始尋找事發(fā)原因。以下列出了軟件項(xiàng)目失敗的最常見原因。
團(tuán)隊(duì)成員太少
用很少的程序員做很多的事情,這種效應(yīng)不難理解。一年只有52周,人們?cè)诶劭逯澳軗v鼓出來的代碼就只有那么一點(diǎn)。我曾經(jīng)在一個(gè)團(tuán)隊(duì)中工作過,該團(tuán)隊(duì)中的管理者認(rèn)為從敏捷團(tuán)隊(duì)中擠出更多成果的正確方法是安排好每一場(chǎng)“沖刺”,以便在前一個(gè)沖刺之后立即接力。不留喘息的余地。也無從弄清楚什么在起作用,什么失敗了。Sprint 42周三下午1點(diǎn)59分結(jié)束,Sprint 43周三下午2點(diǎn)結(jié)束。他們甚至計(jì)劃在下一次沖刺開始后進(jìn)行回顧性分析會(huì)議。有些聰明人建議將其改名為“馬拉松”,并很快跳槽了。
當(dāng)然,到底需要多少程序員,這很難估算。有時(shí)計(jì)劃完成了,估算也是準(zhǔn)確的。有時(shí)候障礙和問題會(huì)擋道。工作量翻倍可不一定是管理者的錯(cuò),但是如果你人手不足,你的項(xiàng)目很可能會(huì)失敗。
團(tuán)隊(duì)成員太多
如果程序員太少是一件壞事,那么程序員太多情況則更糟糕。同一個(gè)使一些社交媒體平臺(tái)顯得不可或缺的網(wǎng)絡(luò)效應(yīng)也可能導(dǎo)致軟件項(xiàng)目失敗。人越多,協(xié)調(diào)工作就越復(fù)雜,開會(huì)也更頻繁,寫代碼的時(shí)間也遭到了剝奪。你可以試著取消會(huì)議,讓程序員有更多的創(chuàng)建時(shí)間,但是如果你沒有開足夠的會(huì)議,你很快就會(huì)發(fā)現(xiàn)甲隊(duì)的API無法對(duì)接乙隊(duì)的微服務(wù)。
如果程序員過多,他們可能會(huì)相互消耗精力,使項(xiàng)目掉進(jìn)五指山。如果我們破財(cái)消災(zāi),在項(xiàng)目上搞人海戰(zhàn)術(shù),這也不錯(cuò),但是你不能這么做。
基本功能變更
理論上,開發(fā)人員往往自命敏捷。這就是他們接受這個(gè)詞的原因。但有時(shí)敏捷會(huì)讓所有人亂了方寸。這一切都取決于這種轉(zhuǎn)變是否需要對(duì)基礎(chǔ)框架進(jìn)行根本的變更。在移動(dòng)按鈕或更改顏色時(shí)很容易做到敏捷。但是涉及到重新構(gòu)建數(shù)據(jù)庫模式或者使用切片和復(fù)制時(shí),想優(yōu)雅地轉(zhuǎn)變,談何容易。
選錯(cuò)了技術(shù)
即使你認(rèn)真規(guī)劃并為項(xiàng)目擬定了正確的功能列表,如果你在構(gòu)建功能集時(shí)用錯(cuò)了技術(shù),這也可能會(huì)導(dǎo)致失敗。例如,數(shù)據(jù)庫的目的就是盡可能通用和靈活,但是它們受限于架構(gòu)。如果你試圖促使它們實(shí)施超出設(shè)計(jì)范圍的事情,那么當(dāng)它們擴(kuò)展時(shí),你可能會(huì)眼睜睜地看著它們慢得幾乎停下來?;蛘吣憧梢詮腘oSQL數(shù)據(jù)庫開始,因?yàn)樗鼈兟犉饋砗芸?,可是后來卻發(fā)現(xiàn)你確實(shí)需要ACID級(jí)別的事務(wù)(transaction)來保持事物的一致性,而數(shù)據(jù)庫不提供這樣的事務(wù)。天哪!
沒設(shè)置好優(yōu)先級(jí)
優(yōu)秀的規(guī)劃人員會(huì)繪制一個(gè)功能列表并分清輕重緩急。但有時(shí)候,現(xiàn)實(shí)并不符合實(shí)施這些優(yōu)先事項(xiàng)的條件。在最壞的情況下,最重要的功能也是最難創(chuàng)建的。
你的開發(fā)人員要做什么呢?如果他們專注于最重要的功能,他們將無法取得進(jìn)展,最終可能什么功能都實(shí)現(xiàn)不了。但是,如果他們解決了簡(jiǎn)單的功能,那么他們最終可能只實(shí)現(xiàn)了毫無價(jià)值的功能。
良好的規(guī)劃需要的不僅僅是清單。架構(gòu)層面的愿景必須考慮到交付這些架構(gòu)的需求和成本。
市場(chǎng)窗口關(guān)閉
有時(shí)候這不是程序員的錯(cuò)。我其中一個(gè)項(xiàng)目是將最暢銷的參考書做成應(yīng)用。該書在互聯(lián)網(wǎng)出現(xiàn)之前就已經(jīng)很暢銷。這個(gè)計(jì)劃就是要挖掘這一需求并制作一個(gè)交互式版本,使人們可以對(duì)數(shù)據(jù)進(jìn)行分類和搜索。編程團(tuán)隊(duì)交付了包含書中所有內(nèi)容的軟件,但它比紙質(zhì)版更快,更漂亮且更輕。但沒有人想要它。我們幾乎送都送不出去。但這不是開發(fā)商的錯(cuò)。市場(chǎng)恰恰不再需要這些數(shù)據(jù)。資料來源越來越豐富,沒有人需要一個(gè)與新聞網(wǎng)站做同樣事情的多余的應(yīng)用。
軟件項(xiàng)目無法補(bǔ)救編程團(tuán)隊(duì)或管理團(tuán)隊(duì)的錯(cuò)誤。有時(shí)候,一個(gè)想法看似不錯(cuò),但市場(chǎng)是不會(huì)刻舟求劍的。
糟糕的架構(gòu)決策
在一個(gè)項(xiàng)目中,我授命在數(shù)據(jù)庫中更改一個(gè)數(shù)字。在用戶完成注冊(cè)時(shí),我要將用戶的ID號(hào)添加到最新的訂單中。這看起來很簡(jiǎn)單,對(duì)吧?但是這個(gè)系統(tǒng)是建立在一個(gè)微服務(wù)架構(gòu)上的,光寫一行命令數(shù)據(jù)庫更新該列的代碼是不能解決這個(gè)問題的。想都別想。架構(gòu)規(guī)劃是為現(xiàn)有棧添加一個(gè)新的微服務(wù)調(diào)用命令,就這也已經(jīng)很難了,因?yàn)槲业牡谝粋€(gè)微服務(wù)調(diào)用命令需要觸發(fā)另一個(gè)微服務(wù)調(diào)用命令,以此類推。
最后,創(chuàng)建這個(gè)微服務(wù)網(wǎng)絡(luò)的架構(gòu)專家告訴我,這一切都非常簡(jiǎn)單,然后他通過微服務(wù)架構(gòu)的五個(gè)不同層次概述了一條蛇形路徑。所以我的工作是向五個(gè)不同的微服務(wù)應(yīng)用程序添加五個(gè)新的API調(diào)用命令。這些命令都是完全獨(dú)立的,這意味著每一層都要添加五組自動(dòng)化測(cè)試。各個(gè)微服務(wù)API歷來都由不同的團(tuán)隊(duì)開發(fā),這些微服務(wù)要求我理解和模擬五種不同風(fēng)格的編碼。一切只為更改一個(gè)數(shù)字。
諸如此類的簡(jiǎn)單要求使團(tuán)隊(duì)不斷變慢。在我離開時(shí),五個(gè)新的API調(diào)用命令已經(jīng)寫好了,它們正好一致通過測(cè)試。但我從未看到它們得到部署。
架構(gòu)決策可以持續(xù)整個(gè)生命周期——如果你全身心投入,而你無法改變他們,情況尤其如此。在主要的架構(gòu)計(jì)劃不起作用時(shí),項(xiàng)目管理者必須時(shí)刻留意到,以便做出重大決策。當(dāng)規(guī)劃出了亂子而管理層又沒有注意到,工作在一線的編碼人員要不斷努力,在不良架構(gòu)模型造成的不良后果中迎難而上。
勾心斗角
將技術(shù)上的失敗歸咎于權(quán)術(shù)之爭(zhēng),這看似一種逃避,而不是坦然地承認(rèn)這是自己的錯(cuò)誤,但這種現(xiàn)象越來越現(xiàn)實(shí)。隨著項(xiàng)目日漸變大,跨越多個(gè)組織和層級(jí),派系出現(xiàn),小組爭(zhēng)奪控制權(quán)、資源和權(quán)力,這應(yīng)該不會(huì)讓人感到意外。
派系和真正的技術(shù)差異是兩碼事。人們往往有技術(shù)標(biāo)準(zhǔn)或代碼庫,它們以不同的方式完成同樣的事情。以XML和JSON為例。既然我已經(jīng)輸入了這樣的內(nèi)容,我可以感覺到粉絲們急于解釋為什么它們不一樣,他們喜歡哪個(gè),哪個(gè)就是正確的選擇。他們也許是對(duì)的,但是當(dāng)一個(gè)團(tuán)隊(duì)中的一部分人選擇了技術(shù)而另外一部分人卻十分看重?cái)硨?duì)派系,那么沖突就會(huì)使他們分裂。
當(dāng)架構(gòu)師將應(yīng)用程序分成多個(gè)更小的服務(wù)和API時(shí),這種情況變得更加普遍。不同小組會(huì)得到對(duì)它們的控制權(quán),但他們并不總能和睦相處。如果甲組喜歡用JSON,乙組堅(jiān)持用XML,那么你的團(tuán)隊(duì)要么兩者都實(shí)現(xiàn),要么對(duì)其中一個(gè)進(jìn)行變更。對(duì)于所有必須與甲組和乙組一起工作的團(tuán)隊(duì)而言,這三種情況(兩種技術(shù)加派系之爭(zhēng))都是令人煩惱的。
押寶尚未準(zhǔn)備好投入生產(chǎn)的技術(shù)
程序員都喜歡用最新的工具和框架。他們寧愿相信,新方法將掃除所有停滯于上一代的殘余物。他們確信,新的抽象和例程將統(tǒng)一,擴(kuò)展和簡(jiǎn)化代碼應(yīng)該做的所有事情。
但下一代工具和框架往往還沒有準(zhǔn)備好用于生產(chǎn)。新功能也許閃閃發(fā)亮,看似完美,但是差距往往很難在頃刻間體會(huì)到。有時(shí)代碼僅支持少數(shù)幾種文件類型,或者僅能與少數(shù)幾個(gè)數(shù)據(jù)庫進(jìn)行交互。他們向你保證,其它的代碼即將推出,但你的項(xiàng)目需要在本月交付,“即將”可能意味著要六個(gè)月或更長(zhǎng)時(shí)間才能完成你需要的功能。
諸如此類的問題可能注定會(huì)使軟件項(xiàng)目失敗。團(tuán)隊(duì)押寶一項(xiàng)新技術(shù)是因?yàn)樗坪踅鉀Q了許多重大問題,而且確實(shí)經(jīng)常能解決問題。但是在某個(gè)階段,通常在沖刺階段,程序員發(fā)現(xiàn)新技術(shù)缺失了某些部分。而這些缺失有時(shí)甚至沒有記錄。該代碼的開發(fā)人員卻要著手處理,結(jié)果可想而知。
押寶即將過時(shí)的技術(shù)
人們會(huì)忍不住像金鳳花姑娘(Goldilocks)一樣思考,對(duì)太舊的技術(shù)的指責(zé)絲毫不亞于對(duì)太新的技術(shù)的指責(zé)。根據(jù)我的經(jīng)驗(yàn),舊的東西往往更可靠,更經(jīng)得住考驗(yàn),這比完整的功能集更有價(jià)值。但這并不意味著舊技術(shù)是完美的。一旦軟件上線,對(duì)你的軟件項(xiàng)目來說很重要的功能可能會(huì)缺失。但更糟糕的是,押寶舊技術(shù)可能會(huì)使你錯(cuò)失先機(jī),因?yàn)樗鼈儠?huì)根據(jù)線路的變化而發(fā)生變化。新的想法、協(xié)議和文件格式會(huì)誕生,而它們也許未能得到實(shí)施。如果競(jìng)爭(zhēng)團(tuán)隊(duì)的人一定要你支持某種新協(xié)議,那么舊技術(shù)將會(huì)受損。
不切實(shí)際的期限
專家說,找出需要多長(zhǎng)時(shí)間然后加倍。就好像已然成為笑柄的專家能在有生之年中真正完成一個(gè)項(xiàng)目似的。他們總提意見卻不寫代碼。
截止日期是個(gè)很棘手的問題。很多項(xiàng)目要在特定季節(jié)或活動(dòng)中推向市場(chǎng)。然而,最初寫下截止日期時(shí),開發(fā)人員還沒有發(fā)現(xiàn)過程中可能出現(xiàn)的障礙。然后,如果項(xiàng)目延期并且活動(dòng)在沒有啟動(dòng)軟件的情況下遭到了忽略,那么即使代碼能流暢運(yùn)行,整個(gè)項(xiàng)目也無異于失敗。截止日期可以幫助所有人集中注意力,使他們齊心協(xié)力,但他們也會(huì)產(chǎn)生不切實(shí)際的期望。
不可預(yù)見的競(jìng)爭(zhēng)
優(yōu)秀的產(chǎn)品經(jīng)理在參與競(jìng)爭(zhēng)前會(huì)對(duì)其進(jìn)行調(diào)查,但沒有人能預(yù)測(cè)什么樣的競(jìng)爭(zhēng)會(huì)突然出現(xiàn)。如果新的競(jìng)爭(zhēng)對(duì)手引入了你必須復(fù)制的新功能,那么請(qǐng)參閱上述關(guān)于功能變更和優(yōu)先級(jí)不匹配的部分。
急于求成
很多軟件項(xiàng)目都是以想要解決問題的人或團(tuán)隊(duì)的愿景開始的。他們想出了“乙的色布拉”或“乙的優(yōu)步”這樣的短語,然后期望產(chǎn)品團(tuán)隊(duì)能夠像色布拉(Snapchat)或優(yōu)步(Uber)一樣迅速響應(yīng)。問題是,確定項(xiàng)目范圍,勾畫數(shù)據(jù)流和設(shè)想用戶界面(UI)的工作量往往是寫代碼的十倍之多。但是構(gòu)想者卻想立即將想法變成代碼。(為什么呢?你可能要責(zé)怪那些演示新框架,數(shù)據(jù)庫或無服務(wù)器等玩意兒,同時(shí)承諾你用幾行代碼就能寫成應(yīng)用程序的開發(fā)人員。)
線框、數(shù)據(jù)庫模式和用戶故事可不是虛張聲勢(shì)的東西,而是工作的重要組成部分。但大多數(shù)人想當(dāng)然地認(rèn)為,軟件項(xiàng)目只是編寫代碼來實(shí)施一個(gè)想法。
誤信軟件的力量
有時(shí)候,夢(mèng)想家對(duì)軟件改變世界的力量有著不切實(shí)際的信念。很多人認(rèn)為社交媒體會(huì)把我們所有人聯(lián)合起來,但這總是莫名其妙地暴露出明顯的斷裂帶。很多軟件項(xiàng)目都是一系列以藍(lán)天白云為背景的幻燈片開始的,這些幻燈片有望破壞某些東西并革新世界的某個(gè)角落。當(dāng)在數(shù)據(jù)庫中插入一些位并不能拯救或改變?nèi)魏稳藭r(shí),那么,有人會(huì)生氣,無聊,困惑或者變得更糟。然后他們會(huì)說軟件壞了,并接著做別的事情。至于數(shù)據(jù)庫是否運(yùn)行順暢,應(yīng)用程序是否將這些位存儲(chǔ)在正確的位置,這些都不重要了。這樣的軟件無法實(shí)現(xiàn)人人都期望的魔法般的轉(zhuǎn)變。
很多軟件項(xiàng)目都可以編譯,通過質(zhì)量保證,出貨甚至獲得好評(píng),但最終卻無法實(shí)現(xiàn)藍(lán)天白云般的幻燈片中所承諾的一切,因?yàn)檫@些改變世界的承諾是不可能兌現(xiàn)的。