軟件項(xiàng)目失敗的20個(gè)原因
每一個(gè)軟件項(xiàng)目都是從遠(yuǎn)大的夢想和宏偉的愿景開始的。或許在另一個(gè)世界的某個(gè)地方,的確會有一個(gè)項(xiàng)目可以實(shí)現(xiàn)每一個(gè)人的夢想,但是在我們的世界中,軟件項(xiàng)目總是跌跌撞撞地走向終點(diǎn)線,有時(shí)甚至?xí)竭^它。
當(dāng)然,根據(jù)定義,軟件項(xiàng)目的失敗并不總是非此即彼的事情。你可能會得到運(yùn)行良好但沒人使用的代碼?;蛘吣憧赡軙玫讲荒芫幾g的代碼。有時(shí)你可以從燃燒的殘骸中搶救出一些有用的東西,但最好在它爆炸前逃跑。
當(dāng)悶熱的爛攤子冷卻下來,分析就開始了,因?yàn)槿藗兿胫朗鞘裁吹胤匠隽藛栴}。以下是最常見的罪魁禍?zhǔn)住?/p>
過少的團(tuán)隊(duì)成員
用太少的程序員做太多的事情是一個(gè)常見的問題。開發(fā)人員在耗盡精力之前只能編寫這么多的代碼。我曾經(jīng)在一個(gè)團(tuán)隊(duì)工作過,在這個(gè)團(tuán)隊(duì)中,經(jīng)理認(rèn)為從敏捷團(tuán)隊(duì)中擠出更多工作的正確方法是安排每個(gè)“sprint”,讓它在前一個(gè)sprint之后就立即開始。沒有深思熟慮的停頓來找出什么是有效的,什么是無效的。Sprint 42于周三下午1:59結(jié)束,Sprint 43就于周三下午2:00開始了。回顧性分析會議通常被安排在下一個(gè)sprint開始之后。一些聰明的家伙建議他們將其改名為“馬拉松”,但很快就投入了另一份工作。
當(dāng)然,很難知道究竟有多少程序員才是足夠的。有時(shí)路障和問題會阻礙我們前進(jìn)。工作量翻倍也許不是經(jīng)理的錯(cuò),但如果你沒有足夠的人手,你的項(xiàng)目就注定要失敗。
團(tuán)隊(duì)成員太多
如果太少的程序員可能是不好的,那么太多就可能會更糟,因?yàn)榫W(wǎng)絡(luò)效應(yīng)也可能會毀滅一個(gè)軟件項(xiàng)目。更多的人意味著需要更多的協(xié)調(diào),也就意味著更多的會議,它將占用原本編寫代碼的時(shí)間。但是如果你召開的會議不夠多,你很快就會發(fā)現(xiàn)團(tuán)隊(duì)A的API不能與團(tuán)隊(duì)B的微服務(wù)進(jìn)行銜接。
如果我們可以通過給項(xiàng)目配備過多的人員來砸錢解決問題,那當(dāng)然很好,但你不能這樣做。
太多的溝通
編寫軟件是一門孤獨(dú)的藝術(shù)。人類可以一起工作,但只能在有限的時(shí)間內(nèi)。許多開發(fā)人員討厭開會,因?yàn)樗麄冃枰獙⒆约旱乃季S從沉浸式的邏輯思維轉(zhuǎn)向更開放、更社會化的模式。這需要時(shí)間。一些團(tuán)隊(duì)領(lǐng)導(dǎo)試圖通過召開更多的會議來使每個(gè)人保持同步以對抗失敗。這是一個(gè)崇高的努力,但你依舊可以聽到齒輪的磨擦聲。團(tuán)隊(duì)需要分享足夠的信息來保持同步,但太多的信息只會浪費(fèi)大腦周期。
基本功能的變化
理論上,開發(fā)人員喜歡認(rèn)為自己是敏捷的。這就是他們擁抱這個(gè)詞的原因。但有時(shí)敏捷會讓人失去平衡。這一切取決于這種轉(zhuǎn)變是否需要對基礎(chǔ)框架進(jìn)行根本性的改變。當(dāng)只是移動按鈕或改變顏色時(shí),很容易變得敏捷。但是,當(dāng)涉及到需要重新編寫數(shù)據(jù)庫模式或處理分片和復(fù)制時(shí),就沒有一種簡單的方法可以優(yōu)雅地進(jìn)行調(diào)整了。
為工作選擇了錯(cuò)誤的技術(shù)
即使你仔細(xì)計(jì)劃并制定了正確的特性列表,如果使用了錯(cuò)誤的技術(shù),事情也可能會失敗。例如,數(shù)據(jù)庫被設(shè)計(jì)為通用和靈活的,但是存在架構(gòu)上的限制。推動他們?nèi)プ鲆恍┧麄儾幌胱龅氖虑椋?dāng)他們被要求擴(kuò)展時(shí),他們就會放慢速度,甚至是停止。或者,你可能會開始使用NoSQL數(shù)據(jù)庫,因?yàn)樗鼈兟犉饋砗芸幔髞戆l(fā)現(xiàn)你確實(shí)需要ACID級別的事務(wù)來保持一致性,而數(shù)據(jù)庫卻不提供這些事務(wù)。
缺乏優(yōu)先級
好的規(guī)劃者會列出一個(gè)特性列表,并對它們進(jìn)行優(yōu)先排序。但有時(shí)優(yōu)先事項(xiàng)與實(shí)施它們的現(xiàn)實(shí)并不一致。在最糟糕的情況下,可能最重要的特性是最難創(chuàng)建的。
你的開發(fā)者該怎么做?如果他們專注于最重要的特性,他們將無法取得任何進(jìn)展,并且可能最終無法交付任何功能。但是如果他們開始完成那些簡單的特性,他們就可能會得到一些毫無價(jià)值的東西。
好的計(jì)劃所需要的不僅僅是一張清單。對遠(yuǎn)景的架構(gòu)必須考慮到需求和交付它們的成本。
市場窗口的關(guān)閉
有時(shí)候這不是程序員的錯(cuò)。我曾經(jīng)的一個(gè)項(xiàng)目是把一本最暢銷的參考書變成一個(gè)應(yīng)用程序。在互聯(lián)網(wǎng)出現(xiàn)之前的幾年里,這本書非常暢銷。該公司計(jì)劃利用這一需求,制作一個(gè)交互式的版本,讓人們可以對數(shù)據(jù)進(jìn)行排序和搜索。編程團(tuán)隊(duì)交付的軟件包含了書中的所有內(nèi)容,但比書本身更快、更漂亮、更輕。但是沒有人想要它了。因?yàn)橐呀?jīng)有足夠多的其他來源了,沒有人需要另一個(gè)應(yīng)用程序來做幾乎和新聞網(wǎng)站一樣的事情。
有時(shí)候一個(gè)想法看起來很不錯(cuò),但市場已經(jīng)改變了。
糟糕的架構(gòu)決策
在一個(gè)項(xiàng)目中,我的任務(wù)是更改數(shù)據(jù)庫中某一行中的一個(gè)數(shù)字。當(dāng)用戶完成注冊后,我要將用戶的id號添加到最新的訂單中。聽起來很簡單,對吧?但是系統(tǒng)是建立在微服務(wù)架構(gòu)上的,我不能通過編寫一行代碼來告訴數(shù)據(jù)庫更新該列來解決這個(gè)問題。不行。架構(gòu)的計(jì)劃是在現(xiàn)有堆棧中添加一個(gè)新的微服務(wù)調(diào)用,即使這樣做也很困難,因?yàn)槲业牡谝粋€(gè)微服務(wù)調(diào)用需要觸發(fā)另一個(gè)微服務(wù)調(diào)用等等。
最后,創(chuàng)建這個(gè)微服務(wù)網(wǎng)絡(luò)的架構(gòu)奇才告訴我,這一切都非常簡單,并勾勒出了一條貫穿整個(gè)體系結(jié)構(gòu)五層的蜿蜒路徑。我的工作是向5個(gè)不同的微服務(wù)添加5個(gè)新的API調(diào)用,這也意味著需要為每個(gè)層添加5組自動化測試。這些年來,每個(gè)API都是由不同的團(tuán)隊(duì)開發(fā)的,這就要求我理解和模仿五種不同的編碼風(fēng)格。所有的一切就是為了改變一個(gè)數(shù)字。
架構(gòu)決策可能會持續(xù)一生--尤其是當(dāng)你的自我意識已經(jīng)完全投入其中而你無法改變它的時(shí)候。項(xiàng)目經(jīng)理必須時(shí)刻注意主架構(gòu)何時(shí)會不起作用,并做出重大決策。
政治沖突
將技術(shù)故障歸咎于政治因素似乎有些含糊其辭,但事實(shí)已經(jīng)越來越真實(shí)了。隨著項(xiàng)目的擴(kuò)大和跨越多個(gè)組織,出現(xiàn)派系和團(tuán)隊(duì)來爭奪控制權(quán)、資源和最終權(quán)力也就不足為奇了。
政治派系不同于真正的技術(shù)差異。通常有一些技術(shù)標(biāo)準(zhǔn)或代碼庫會以不同的方式做同樣的事情。以XML和JSON為例。我能感覺到這兩種技術(shù)的粉絲都急于解釋為什么它們不一樣,以及為什么他們最喜歡的選擇是正確的。但是當(dāng)一個(gè)團(tuán)隊(duì)的一部分喜歡一個(gè)選擇,而另一部分則最尊重有競爭關(guān)系的另一方時(shí),摩擦就會把他們分開。
隨著架構(gòu)師將應(yīng)用程序拆分為多個(gè)更小的服務(wù)和API,這種情況將變得更加常見。不同的團(tuán)體最終會控制這些,但他們不會總是和睦相處。如果A組喜歡JSON,而B組喜歡XML,那么你的團(tuán)隊(duì)要么需要同時(shí)實(shí)現(xiàn)它們,要么更改其中一個(gè)。所有這三種情況,對于必須同時(shí)與A組和B組合作的團(tuán)隊(duì)來說都是一種痛苦。
押注于還沒有準(zhǔn)備好投入生產(chǎn)的技術(shù)
程序員喜歡最新的工具和框架。他們愿意相信,新方法將掃除上一代人遺留下來的所有糟粕。
但通常情況下,下一代的技術(shù)可能還沒有準(zhǔn)備好投入生產(chǎn)。新功能或許看起來很完美,但通常會有一些不太明顯的缺陷。有時(shí)代碼只支持少數(shù)的文件類型,或者只支持幾個(gè)數(shù)據(jù)庫的接口。他們向你保證,其他產(chǎn)品很快就會推出,但是你的項(xiàng)目需要在這個(gè)月就發(fā)布,而“很快”則可能意味著需要6個(gè)月或更多的時(shí)間才能完成所需的特性。
押注于即將過時(shí)的技術(shù)
根據(jù)我的經(jīng)驗(yàn),舊的技術(shù)通常更可靠,更經(jīng)得起考驗(yàn),但這并不意味著舊技術(shù)是完美的。即使軟件項(xiàng)目已經(jīng)投入使用,也可能會缺少對軟件項(xiàng)目至關(guān)重要的特性。更糟糕的是,押注于老技術(shù)可能會讓你錯(cuò)過未來可能出現(xiàn)的變化。新的思想、協(xié)議和文件格式出現(xiàn)了,但它們可能還無法實(shí)現(xiàn)。如果競爭團(tuán)隊(duì)的某個(gè)人堅(jiān)持認(rèn)為你應(yīng)該支持某種新協(xié)議,那么舊的技術(shù)將會帶來傷害。
不切實(shí)際的截止日期
截止日期是棘手的。許多項(xiàng)目需要在特定的季節(jié)或事件之前進(jìn)入市場。然而,當(dāng)?shù)谝淮螌懴陆刂谷掌跁r(shí),開發(fā)人員可能還沒有發(fā)現(xiàn)他們前進(jìn)道路上的障礙。然后,如果項(xiàng)目失敗,并且沒有啟動軟件,事件就過去了,那么整個(gè)項(xiàng)目就會被視為失敗,即使代碼已經(jīng)準(zhǔn)備好順利運(yùn)行。截止日期可以幫助每個(gè)人集中精力,齊心協(xié)力,但也可能會讓人產(chǎn)生不切實(shí)際的期望。
無法預(yù)見的競爭
一個(gè)好的產(chǎn)品經(jīng)理在進(jìn)入市場之前會調(diào)查競爭情況,但是沒有人能預(yù)測什么樣的競爭會突然出現(xiàn)。如果新的競爭對手引入了你必須復(fù)制的新特性,請參閱上面關(guān)于特性更改和優(yōu)先級不匹配的部分。
匆忙的流程
許多軟件項(xiàng)目都是從想要修復(fù)某些東西的個(gè)人或團(tuán)隊(duì)的愿景開始的。他們可能會想出“Snapchat for Y”或“Uber for Y”這樣的短語,然后就期望產(chǎn)品團(tuán)隊(duì)能像Snapchat或Uber一樣反應(yīng)迅速。問題在于,確定項(xiàng)目的范圍、描繪數(shù)據(jù)流和設(shè)想U(xiǎn)I的工作量通常是編寫代碼的十倍。而幻想家們想要馬上將想法變成代碼。
線框圖、數(shù)據(jù)庫模式和用戶描述不是一蹴而就的,而是工作中必不可少的一部分。但大多數(shù)人認(rèn)為軟件項(xiàng)目只是編寫代碼來實(shí)現(xiàn)一個(gè)想法而已。
錯(cuò)誤地相信軟件的力量
夢想家常常對軟件改變世界的力量抱有不切實(shí)際的信念。很多人以為社交媒體會把我們團(tuán)結(jié)在一起,但不知為何,它只是暴露了一直以來都很明顯的斷層線。軟件項(xiàng)目通常是以幻燈片開始的,這些幻燈片承諾將徹底改變世界的某個(gè)角落。然后,當(dāng)向數(shù)據(jù)庫中塞入數(shù)據(jù)并不能改變?nèi)魏稳藭r(shí),人們就會感到憤怒、無聊、困惑甚至更糟。他們說,這個(gè)軟件被破壞了,因?yàn)樗茨軐?shí)現(xiàn)大家所期待的神奇轉(zhuǎn)變。
許多軟件項(xiàng)目可以編譯、通過QA、發(fā)布,甚至獲得不錯(cuò)的評審,但卻最終未能實(shí)現(xiàn)幻燈片上的任何承諾,因?yàn)槟切└淖兪澜绲某兄Z是不可能的。
邪惡的分包商
我們喜歡那些提供庫和工具的廠商,這些庫和工具使得我們只需要使用幾行代碼就能創(chuàng)造奇跡。但是偶爾,他們會聽到自己的力量,并利用它來摧毀一個(gè)項(xiàng)目。版本1.0的預(yù)算表非常好,以至于管理層會毫不猶豫地批準(zhǔn)版本2.0。然后供應(yīng)商就可能會通過三倍或五倍的價(jià)格來擠壓我們。
即使供應(yīng)商不是故意這樣做的,也可以感受到這種影響。免費(fèi)的庫可以讓一個(gè)項(xiàng)目看起來非常便宜。然后,當(dāng)需求飆升,第二個(gè)版本擴(kuò)大了需求時(shí),實(shí)際價(jià)格就會開始上升了。
翻天覆地的巨變
在大流行和抗議的一年里,沒有什么比時(shí)代精神改變得更快了。該項(xiàng)目是否將強(qiáng)大的隱私保護(hù)作為了一個(gè)核心特征?唉。大流行使得每個(gè)人都對追蹤接觸者感興趣了。有人想專注于商務(wù)旅行嗎?唉。酒店業(yè)已經(jīng)崩潰了。需要一年或更長時(shí)間的大型軟件項(xiàng)目可能有被災(zāi)難性事件中斷的風(fēng)險(xiǎn)。一開始看起來似乎是個(gè)很不錯(cuò)的想法,但到了要付諸實(shí)踐的時(shí)候,就可能會變得毫無希望、毫無意義。
技術(shù)遷移
不僅僅是世界的變化??萍冀绲某绷髯兓矔a(chǎn)生同樣的效果。NoSQL曾經(jīng)是一個(gè)天才的想法,它能夠?qū)⑽覀儚年P(guān)系模式中解放出來。然后又有人意識到文件的膨脹是因?yàn)槊總€(gè)記錄都帶有一個(gè)本地模式。雖然一個(gè)好的敏捷開發(fā)團(tuán)隊(duì)可以在技術(shù)的巨大變化改變領(lǐng)導(dǎo)層和客戶的態(tài)度時(shí)進(jìn)行調(diào)整。但是即使是最敏捷的團(tuán)隊(duì)也不能處理那些會把他們的架構(gòu)計(jì)劃全部搞垮的重大變化。這個(gè)系統(tǒng)是建立在假設(shè)X是一個(gè)好主意的前提下的,而在突然之間X變成了一個(gè)垃圾?;蛟S有時(shí)候最好的選擇是把它炸掉,然后再重新開始。
太多附庸
一些軟件項(xiàng)目的起步很好,甚至被成功地發(fā)布了。然后就會有人添加了一到三個(gè)額外的特性,將新代碼移植到現(xiàn)有的版本上,使代碼繼續(xù)蹣跚前行。英勇的開發(fā)人員可能會多次實(shí)現(xiàn)這個(gè)目標(biāo),特別是在最初的架構(gòu)師計(jì)劃良好的情況下。但是在某個(gè)時(shí)候,基礎(chǔ)就崩潰了??赡苁菙?shù)據(jù)庫無法處理負(fù)載??赡苁切枰噙B接來滿足各種查詢。好的軟件可能會變得過于臃腫,有時(shí)只是因?yàn)橐恍┬⌒〉母倪M(jìn)把它推到了邊緣。
目標(biāo)的改變
最初的計(jì)劃是建立一個(gè)數(shù)據(jù)庫來跟蹤客戶支出,以幫助制定營銷計(jì)劃。后來,一些天才又增加了一個(gè)功能,試圖利用人工智能來將消費(fèi)與天氣預(yù)報(bào)聯(lián)系起來?;蛘哂腥讼胱屵@個(gè)軟件自動為搜索引擎廣告出價(jià)。改變目標(biāo)也可能會顛覆一個(gè)項(xiàng)目。
很少有變化會自己毀掉一切。但是新的目標(biāo)可能會揭示弱點(diǎn)并觸發(fā)失敗的模式。也許是這個(gè)團(tuán)隊(duì)現(xiàn)在太小了,無法成功地完成這個(gè)項(xiàng)目。也許是其技術(shù)基礎(chǔ)對于新方法來說非常低效??傊?,當(dāng)決定改變目標(biāo)時(shí),每個(gè)人都會很難預(yù)料到這些煩躁的組合。