項(xiàng)目延期半年,我被軟件外包坑慘了!
????轉(zhuǎn)自:infoQ????英文作者:Rajiv Prabhakar,翻譯:平川?多年前,年輕且天真的我決定與他人一起創(chuàng)業(yè),但同時(shí)還要兼顧我們的全職工作。我負(fù)責(zé)技術(shù)開(kāi)發(fā),另一個(gè)創(chuàng)始人負(fù)責(zé)業(yè)務(wù)。我們的 MVP 計(jì)劃是發(fā)布 iOS 和 Android App。我在后端上有開(kāi)發(fā)經(jīng)驗(yàn),但從未開(kāi)發(fā)過(guò) App。為此,我沒(méi)有選擇從頭開(kāi)始學(xué)習(xí),而是決定雇傭外部軟件開(kāi)發(fā)人員來(lái)構(gòu)建 App,而我則負(fù)責(zé)所有服務(wù)器端開(kāi)發(fā)、P/SaaS 集成和基礎(chǔ)設(shè)施。
合作始末
這不是我第一次創(chuàng)業(yè)。想起來(lái),因?yàn)橛羞^(guò)這種經(jīng)歷,所以我過(guò)度自信了。以前的創(chuàng)業(yè)中,我曾經(jīng)雇傭過(guò)一位年輕的兼職自由職業(yè)者,他來(lái)自另一個(gè)國(guó)家。他是熟人推薦的。他不僅很好完成了工作,而且每小時(shí)收費(fèi)不到 10 美元。當(dāng)時(shí),我并沒(méi)有意識(shí)到這一點(diǎn),但考慮到他的才華和責(zé)任心,他的報(bào)價(jià)非常便宜?,F(xiàn)在,他在舊金山掙六位數(shù)的工資。有點(diǎn)遺憾的是,他現(xiàn)在無(wú)法參與進(jìn)來(lái)。我的聯(lián)合創(chuàng)始人也想請(qǐng)一個(gè)更知名的組織來(lái)管理我們的前端開(kāi)發(fā)。因此,我們決定尋找開(kāi)發(fā)工作室,而非自由職業(yè)者。當(dāng)然,先要做一番調(diào)查。我們看了獨(dú)立的第三方評(píng)審報(bào)告,詢(xún)問(wèn)了評(píng)審依據(jù),并與開(kāi)發(fā)工作室之前的客戶(hù)進(jìn)行了交談,最終從多個(gè)工作室中選擇了讓我們最有信心的一家。該工作室收費(fèi)標(biāo)準(zhǔn)約為每小時(shí) 25 美元——明顯高于同類(lèi)的自由職業(yè)者。不過(guò),我們認(rèn)為,雇傭的是一個(gè)有經(jīng)驗(yàn)的專(zhuān)業(yè)組織,而非隨便一個(gè)人,這對(duì)我們來(lái)說(shuō)更合適。我的聯(lián)合創(chuàng)始人是一名律師,與他們簽訂合同時(shí),務(wù)求詳盡。眾所周知,軟件項(xiàng)目非常容易超支,所以我們協(xié)商簽訂了一份固定價(jià)格的合同,并對(duì)所有出現(xiàn)的 bug 都“保修”。花了很長(zhǎng)一段時(shí)間后,我們才敲定合同細(xì)節(jié),并在合同里詳細(xì)描述他們應(yīng)該構(gòu)建的每個(gè)功能。然后,我們支付了第一筆款項(xiàng)并啟動(dòng)項(xiàng)目。這里,我們犯下了致命錯(cuò)誤!根據(jù)合同協(xié)議,這個(gè)項(xiàng)目分為三個(gè)部分。在完成任何工作之前,我們就要預(yù)付 40% 的費(fèi)用。然后每一部分開(kāi)發(fā)完成時(shí)分別再付 30%,但是在我們收到剛完成部分的交付成果之前。因?yàn)槲覀兪莻€(gè)初創(chuàng)公司,并提前支付了 5 位數(shù)的費(fèi)用,而且在完成下一筆付款之前沒(méi)有獲得任何可交付的內(nèi)容,所以我們?cè)谡麄€(gè)項(xiàng)目期間都被鎖定了。雖然知道會(huì)發(fā)生這種事,但我們覺(jué)得沒(méi)問(wèn)題。因?yàn)樗麄冇衼?lái)自獨(dú)立第三方機(jī)構(gòu)的良好評(píng)價(jià),優(yōu)秀的客戶(hù)口碑,而我們沒(méi)有發(fā)現(xiàn)什么危險(xiǎn)信號(hào)。此外,我們知道,在一個(gè)由別人創(chuàng)建的項(xiàng)目中增加一名新的開(kāi)發(fā)人員并不不容易——所以我們計(jì)劃在整個(gè)項(xiàng)目中與他們并肩作戰(zhàn)。事后看來(lái),那是我們做出的最糟糕的技術(shù)決定,給了我們的初創(chuàng)公司一個(gè)沉重的打擊。
技術(shù)挑戰(zhàn)
按照我們的想法,這款 App 需要具備的一個(gè)關(guān)鍵功能是實(shí)時(shí)聊天。在合同談判時(shí),他們提出一些 SaaS 方面的建議來(lái)簡(jiǎn)化實(shí)時(shí)聊天功能的構(gòu)建——其中之一是 Twilio Chat。在研究了他們提出的各種不同建議后,我們覺(jué)得 Twilio 似乎是最好的選擇,于是,我倆就同意將其應(yīng)用于我們的聊天功能。遺憾的是,在開(kāi)始構(gòu)建時(shí),他們遇到難題。他們不知道如何在 React Native 中使用 Twilio Chat,盡管是他們最先推薦使用 Twilio Chat 和 React Native。更糟糕的是,他們并沒(méi)有坦白地告訴我們,他們陷入了困境,而只是簡(jiǎn)單地告訴我們“Twilio Chat 不適用于 React Native”?,F(xiàn)在,他們想讓我們切換到一個(gè)完全不同的聊天服務(wù)提供商(由一個(gè)我們從未聽(tīng)說(shuō)過(guò)的公司提供),然后重新開(kāi)始,而我們需要為此支付額外的費(fèi)用(即使這本是一個(gè)固定價(jià)格的項(xiàng)目)。最糟糕的是,他們從開(kāi)始說(shuō)的話(huà)就不是真的。Twilio Chat 用在 React Native 中完全沒(méi)有問(wèn)題——他們只是不知道怎么做。最終,作為一名沒(méi)有任何 React Native 開(kāi)發(fā)經(jīng)驗(yàn)的開(kāi)發(fā)者,我花了很多時(shí)間去研究解決方案,并教他們應(yīng)該怎么做。即使在我向他們做了演示之后,他們?nèi)匀恍枰医o他們提供文檔鏈接,并向他們解釋如何使用 Twilio API。如果我沒(méi)有和他們?cè)谝黄穑蛘邲](méi)有替他們想出辦法完成這項(xiàng)工作,那么我們可能就會(huì)采納他們的建議。我們可能會(huì)完全拋棄 Twilio,轉(zhuǎn)向一個(gè)完全不同的、低標(biāo)準(zhǔn)的服務(wù)。這個(gè)決定可能會(huì)讓項(xiàng)目推遲好幾個(gè)月,并多花一大筆錢(qián)。在安全上馬馬虎虎
我希望關(guān)于 Twilio 的問(wèn)題就此結(jié)束,但這還沒(méi)完。所有 Twilio 聊天信息都屬于一個(gè)通道,而通道可以標(biāo)記為“私有”或“公共”。顧名思義,私有通道屬于通道中的特定用戶(hù),而公共通道可以“被非會(huì)員看到和加入。此外,公共通道及其成員和消息對(duì)于給定服務(wù)中的每個(gè)客戶(hù)端端點(diǎn)都是可見(jiàn)的?!?/p>顯而易見(jiàn),所有的非公開(kāi)消息都應(yīng)該使用私有通道來(lái)實(shí)現(xiàn)。但令人驚訝的是,他們都是用的公共通道——這是我在瀏覽 Twilio 控制臺(tái)時(shí)看到的。如果我們已經(jīng)上線(xiàn)了他們的實(shí)現(xiàn),只要是有一點(diǎn)點(diǎn)開(kāi)發(fā)經(jīng)驗(yàn)的人,就能夠竊聽(tīng)每一個(gè) App 用戶(hù)的私人談話(huà)。如果我自己沒(méi)有發(fā)現(xiàn)這個(gè)問(wèn)題,開(kāi)發(fā)公司肯定不會(huì)安排任何滲透測(cè)試人員來(lái)發(fā)現(xiàn)這些安全問(wèn)題。這樣的錯(cuò)誤令人無(wú)法容忍。更令人震驚的是,他們非但沒(méi)有為自己的嚴(yán)重疏忽而道歉,還不愿意更改。顯然,使用公共通道實(shí)現(xiàn)聊天功能更簡(jiǎn)單,因此,他們更愿意保持這種方式。只有在我們多次抱怨后,他們才最終同意改變實(shí)現(xiàn)方式。Bug 無(wú)處不在
我們之所以愿意雇傭開(kāi)發(fā)工作室,而不是個(gè)人自由職業(yè)者,是因?yàn)樗麄兂兄Z給我們的其他支持。特別是 QA 團(tuán)隊(duì),他們會(huì)在向我們展示應(yīng)用前進(jìn)行詳盡的測(cè)試。任何軟件項(xiàng)目都會(huì)遇到 Bug,這是不可避免的,所以我們理解他們不能做出任何承諾。但我們相信了他們的話(huà),他們說(shuō)我們應(yīng)該只會(huì)發(fā)現(xiàn)一些極端情況下的 Bug。后來(lái)我們發(fā)現(xiàn),這完全是一派胡言。我們從他們那里收到的所有交付滿(mǎn)是 Bug。甚至最基本的功能都不能工作——我甚至懷疑,即使他們測(cè)試過(guò),他們也不是用真正的手機(jī)測(cè)試的。在整整一周的時(shí)間里,我和我的聯(lián)合創(chuàng)始人每天都要花上幾個(gè)小時(shí),煞費(fèi)苦心地測(cè)試,并記錄所有出現(xiàn)的 Bug。程序只求可運(yùn)行
舉例來(lái)說(shuō),我們發(fā)現(xiàn)的一個(gè) Bug 是,如果用戶(hù)的聯(lián)系人超過(guò) 50 個(gè),就只有前 50 個(gè)會(huì)在 App 中顯示,其他的都無(wú)法訪問(wèn)。事實(shí)是,我們的一個(gè) SaaS 集成被分頁(yè)了,開(kāi)發(fā)人員只實(shí)現(xiàn)了獲取第一頁(yè)結(jié)果的代碼。因?yàn)檫@個(gè) Bug 只有在一個(gè)用戶(hù)有 51 個(gè)聯(lián)系人時(shí)才會(huì)被觸發(fā),而且我們尚處于私人測(cè)試階段,所以我們過(guò)了一段時(shí)間才發(fā)現(xiàn)這個(gè) Bug。之后,我們向他們做了反饋,問(wèn)題很快就得到了修復(fù)。我們測(cè)試了他們的修復(fù)結(jié)果,似乎一切正常。但在審查他們的代碼變更時(shí),我發(fā)現(xiàn),他們的修復(fù)方式是多么的旁門(mén)左道。他們沒(méi)有用一個(gè) while 循環(huán)來(lái)獲取所有的結(jié)果頁(yè),而只是簡(jiǎn)單地添加了一個(gè) if 條件來(lái)獲取第二頁(yè)的內(nèi)容。一旦用戶(hù)的聯(lián)系人數(shù)量超過(guò) 100,我們就會(huì)再次遇到完全相同的錯(cuò)誤。我可以原諒第一個(gè) Bug,把它看成是無(wú)意的。但第二個(gè) Bug 就是故意失職了。他們一定知道,我們要過(guò)很長(zhǎng)時(shí)間才能觸發(fā)第二頁(yè)查詢(xún)結(jié)果,要過(guò)更長(zhǎng)的時(shí)間才能觸發(fā)第三頁(yè)。他們清楚地知道自己在做什么,知道“修復(fù)”的局限性,但他們還是那樣做了。如果沒(méi)有人仔細(xì)檢查他們的代碼,這個(gè) Bug 就會(huì)進(jìn)入生產(chǎn)環(huán)境。沒(méi)有版本歷史
作為一名開(kāi)發(fā)人員,我親身體會(huì)到版本控制歷史是多么有用。它可以幫助未來(lái)的開(kāi)發(fā)人員了解為什么要做出某些設(shè)計(jì)決策,特定的功能是如何構(gòu)建的,以及如何構(gòu)建其他類(lèi)似的特性。出于這個(gè)原因,在合同談判中,我特別堅(jiān)持最后的交付物應(yīng)該是一個(gè) Git 存儲(chǔ)庫(kù)。他們欣然同意,并說(shuō)他們內(nèi)部也普遍使用 Git。遺憾的是,在交付源代碼的時(shí)候,他們只給我們發(fā)送了一個(gè)壓縮文件,其中包含所有源代碼和生成的文件。我提醒他們,根據(jù)合同,他們應(yīng)該給我們一個(gè) Git 存儲(chǔ)庫(kù)。事實(shí)上,在他們發(fā)送的壓縮文件中,我甚至看到了一個(gè)“.git”目錄——表明他們?cè)陂_(kāi)發(fā)時(shí)確實(shí)在用 Git。第二天,他們很快就給我們發(fā)送了一個(gè) Git 存儲(chǔ)庫(kù),其中只有一次提交,而里面的文件與前一天發(fā)送給我們的 zip 文件完全相同。我抑制著自己的挫敗感告訴他們,我們想要整個(gè)版本歷史,而不只是一次提交,而且還是提交的同一個(gè) zip 文件。他們回答說(shuō),他們的 Git 存儲(chǔ)庫(kù)中有一些“敏感信息”,不方便向外人提供。因此,他們不能分享給我們。“合同只規(guī)定交付 Git 存儲(chǔ)庫(kù)。但并沒(méi)有說(shuō)存儲(chǔ)庫(kù)中應(yīng)該包含所有的開(kāi)發(fā)提交和歷史“。隨意改變規(guī)則
在談判過(guò)程中,我們多次提到服務(wù)器端 API 還沒(méi)有完全實(shí)現(xiàn),我們希望后端開(kāi)發(fā)和前端開(kāi)發(fā)同時(shí)進(jìn)行。在項(xiàng)目開(kāi)始時(shí),我會(huì)把所有 API 端點(diǎn)提供給他們,其中一些會(huì)完全實(shí)現(xiàn)。這樣,他們就可以使用這幾個(gè)端點(diǎn)立即開(kāi)始開(kāi)發(fā)比較簡(jiǎn)單的特性。當(dāng)他們完成這些功能時(shí),用于下一批特性的 API 也就完成了。我們的目標(biāo)是避免延期,同時(shí)開(kāi)展這兩項(xiàng)工作,可以更快地推出我們的 App。這是我們預(yù)先明確并反復(fù)申明的內(nèi)容。我們總是被告知,沒(méi)有問(wèn)題。遺憾的是,付完錢(qián)之后,我們開(kāi)始聽(tīng)到一些完全不同的聲音。他們直截了當(dāng)?shù)鼐芙^開(kāi)始任何工作,直到整個(gè)項(xiàng)目中每一個(gè)特性用到的后端都 100% 完成開(kāi)發(fā)并最終確定。所幸,我們?cè)诤贤勁泻驮O(shè)計(jì)工作上花費(fèi)了大量時(shí)間,我?guī)缀跻呀?jīng)完成了后端開(kāi)發(fā)。所以這并沒(méi)有成為一個(gè)問(wèn)題。但令人震驚和痛心的是,他們沒(méi)有履行銷(xiāo)售人員早些時(shí)候做出的承諾。唯我獨(dú)尊
當(dāng)我們把他們當(dāng)作潛在客戶(hù)來(lái)交談的時(shí)候,他們?yōu)槲覀冧侀_(kāi)了紅地毯。但一談到實(shí)質(zhì)問(wèn)題,他們就堅(jiān)持要按他們的方式來(lái)做。例如,在研究了各種選項(xiàng)之后,我決定用 Swagger 來(lái)記錄所有 API 端點(diǎn)、它們的輸入、模式、描述和行為。這樣,文檔就嵌入到了代碼中,能夠自動(dòng)生成,并保持更新。Swagger GUI 還提供了一種非常友好的方式讓我們可以瀏覽所有 API 文檔,甚至可以直接從 GUI 進(jìn)行 API 調(diào)用來(lái)做測(cè)試。遺憾的是,這不是他們的做事方式。因此,他們拒絕使用 Swagger 作為文檔源。取而代之,他們堅(jiān)持讓我們用電子郵件給他們發(fā)送一個(gè) Word 文檔,包含所有在 Swagger 中能找到的內(nèi)容,但要按照他們指定的格式填寫(xiě)。我們花了好幾天討論這個(gè)問(wèn)題,最后他們讓步了。但在整個(gè)開(kāi)發(fā)過(guò)程中,他們的態(tài)度一直沒(méi)有改變。我們雇傭他們,是為了讓他們使用我們的后端 API 來(lái)創(chuàng)建移動(dòng)應(yīng)用。但他們卻對(duì) API 的實(shí)現(xiàn)方式提出要求。每當(dāng)在 API 設(shè)計(jì)上出現(xiàn)意見(jiàn)分歧時(shí),我們就不得不花好幾天討論,還要忍受他們的抱怨。這種爭(zhēng)論可能是源于他們對(duì) API 最佳實(shí)踐的熱情,但我懷疑,他們主要是想讓自己的工作盡可能簡(jiǎn)單。而且,他們經(jīng)常弄不清楚如何利用現(xiàn)有的 API 實(shí)現(xiàn)所需的功能。缺少直接溝通
項(xiàng)目開(kāi)始后還有一個(gè)很大的意外,就是缺乏溝通。在我以前所有的工程項(xiàng)目中,在跨團(tuán)隊(duì)合作時(shí),為了更好地了解和解決出現(xiàn)的問(wèn)題,我們都會(huì)直接與工程師交談。令我驚訝的是,這是他們明確禁止的事情。按照他們的規(guī)定,我們只能與一個(gè)非技術(shù)的項(xiàng)目經(jīng)理單點(diǎn)聯(lián)系。盡管我們提了要求,但他們拒絕讓我們與實(shí)際從事項(xiàng)目開(kāi)發(fā)工作的開(kāi)發(fā)人員聯(lián)系。此外,他們的項(xiàng)目經(jīng)理也拒絕通過(guò)實(shí)時(shí)聊天工具交流。他們堅(jiān)持一切都通過(guò)電子郵件進(jìn)行。隨著時(shí)間的推移,這帶來(lái)了很大的溝通問(wèn)題。每當(dāng)開(kāi)發(fā)人員遇到問(wèn)題,或者有什么想不明白,他們就會(huì)把問(wèn)題發(fā)給項(xiàng)目經(jīng)理。然后,她會(huì)把所有的問(wèn)題匯總起來(lái),在一天工作結(jié)束時(shí)給我發(fā)一封大郵件。即使我很快回復(fù)了郵件,他們還是要到下一個(gè)工作日才能看到。因此,即使是一個(gè)簡(jiǎn)單的問(wèn)答也需要 24 個(gè)小時(shí)的時(shí)間,比較復(fù)雜的討論則需要好幾天,而不是聊 30 分鐘,然后問(wèn)題就解決了。值得慶幸的是,在項(xiàng)目后期,他們終于意識(shí)到這個(gè)過(guò)程是多么低效,并允許我們與他們的開(kāi)發(fā)人員直接聯(lián)系。遺憾的是,到那時(shí)候,一切都太晚了。在項(xiàng)目剛開(kāi)始時(shí),我們就知道這會(huì)成為一個(gè)大問(wèn)題。但他們向我們保證,這不成問(wèn)題??梢钥隙ǖ氖牵覀兊膿?dān)憂(yōu)變成了現(xiàn)實(shí)。事實(shí)證明,當(dāng)你每天只能通過(guò)一封電子郵件進(jìn)行溝通時(shí),很難做到敏捷。嚴(yán)重延期
很遺憾,上述所有問(wèn)題體現(xiàn)到了項(xiàng)目時(shí)間表上。原本應(yīng)該是一個(gè)為期 2 個(gè)月的項(xiàng)目,最后卻用了 7 個(gè)月。對(duì)我們來(lái)說(shuō),這是一個(gè)重大挫折,因?yàn)槲覀冨e(cuò)過(guò)了許多潛在的用戶(hù),他們決定不再等我們的 App 發(fā)布。現(xiàn)在回想起來(lái),這些延誤一點(diǎn)也不奇怪,因?yàn)樗麄內(nèi)鄙偌夹g(shù)專(zhuān)家,堅(jiān)持采用瀑布式方法,并拒絕通過(guò)聊天或電話(huà)直接溝通。但我懷疑,這還不是問(wèn)題的全部。我懷疑,在不同時(shí)段,他們有其他覺(jué)得更有利可圖的項(xiàng)目,并因此降低了我們項(xiàng)目的開(kāi)發(fā)優(yōu)先級(jí)。這也是其開(kāi)發(fā)團(tuán)隊(duì)在項(xiàng)目中途出現(xiàn)重大人事變動(dòng)的原因。推卸責(zé)任
在他們所有的失敗中,要說(shuō)有什么東西不變的話(huà),那就是他們完全拒絕為任何事情負(fù)責(zé)。在執(zhí)行任何任務(wù)之前,他們都會(huì)對(duì)自己的能力表現(xiàn)出百分之百的信心,并承諾結(jié)果不會(huì)有任何差錯(cuò)。而當(dāng)他們沒(méi)能兌現(xiàn)自己的承諾時(shí),總是把責(zé)任推給其他人。- 你們搞不清楚如何使用 twilio SDK?
- 在 React Native 中無(wú)法使用 Twilio 聊天軟件
- 你們的聊天實(shí)現(xiàn)會(huì)暴露所有的私人對(duì)話(huà)?
- 替代方案太復(fù)雜了
- 為什么某個(gè)屏幕要花 30 秒來(lái)加載?
- 我們必須進(jìn)行 5 次 API 調(diào)用,這使它變慢了。
經(jīng)驗(yàn)教訓(xùn)
面對(duì)上面出現(xiàn)的所有問(wèn)題,我很想說(shuō):"離岸開(kāi)發(fā)者很糟糕。"但是,這樣的結(jié)論既狹隘也過(guò)于局限。我與來(lái)自其他國(guó)家的優(yōu)秀工程師合作過(guò),認(rèn)為優(yōu)秀的開(kāi)發(fā)人員只存在于美國(guó),是非常愚蠢的。我也很想說(shuō),永遠(yuǎn)不要把開(kāi)發(fā)工作外包。如果你的公司像谷歌一樣成熟,或者是由風(fēng)險(xiǎn)投資公司資助的初創(chuàng)公司,那么一切都要自己構(gòu)建,并且使用工資六位數(shù)的開(kāi)發(fā)人員。但是,對(duì)于一個(gè)創(chuàng)始團(tuán)隊(duì)規(guī)模不大的自給自足的初創(chuàng)公司來(lái)說(shuō),使用一些便宜的雇傭兵來(lái)幫助你完成 MVP 是有意義的。這是一個(gè)可以成功應(yīng)用于其他場(chǎng)合的方法。我們不禁會(huì)想,既然看到了上面出現(xiàn)的所有問(wèn)題,那么應(yīng)該可以通過(guò)談判達(dá)成具體的合同條款來(lái)預(yù)防。這種做法注定要失敗。有太多的未知因素和太多的主觀性,不可能把所有東西都囊括在一個(gè)法律文件中。更不用說(shuō)通過(guò)訴訟依法執(zhí)行合同,這本身就是一個(gè)巨大的工程。歸根結(jié)底,當(dāng)你雇用自由職業(yè)者或開(kāi)發(fā)工作室時(shí),重要事的只有一件,那就是:如果他們做得不好,你有能力離開(kāi)他們。我們遇到的所有問(wèn)題,都是因?yàn)槲覀內(nèi)鄙僦坪馐侄?。因?yàn)槲覀冾A(yù)付了很多錢(qián),所以我們沒(méi)有能力離開(kāi)并雇傭其他人,即使事情變得非常糟糕。一種更好的方法
合同一結(jié)束,我們就與他們斷了聯(lián)系,并大大地松了一口氣。我真得感到卸下了一個(gè)大包袱。從此之后,我們從根本上改變了與外部開(kāi)發(fā)人員的合作方式:- 針對(duì)我們想要構(gòu)建的功能,擬定一個(gè)順序列表。
- 找?guī)酌_(kāi)發(fā)人員,最好是獨(dú)立的自由職業(yè)者,但如果同意以下流程,開(kāi)發(fā)工作室也沒(méi)問(wèn)題。
- 對(duì)于每名開(kāi)發(fā)人員,挑選列表中最重要的功能,與他們討論功能需求、預(yù)算和成本。讓他們實(shí)現(xiàn)那個(gè)特性并測(cè)試。
- 讓一名內(nèi)部人員審核他們的 PR,測(cè)試升級(jí)后的 App,并標(biāo)出有問(wèn)題的地方。
- 符合要求后,合并并部署該特性,這樣,所有創(chuàng)始人 / 用戶(hù)就可以繼續(xù)審核該 App,并提供反饋或者根據(jù)需要調(diào)整。
- 如果我們對(duì)他們所做的工作感到滿(mǎn)意,就挑選下一個(gè)我們希望他們實(shí)現(xiàn)的功能,然后再次重復(fù)這個(gè)過(guò)程。
- 如果我們對(duì)他們的工作不滿(mǎn)意,就解雇他們,并尋找替代者。
- 客戶(hù)合作勝于合同談判
- 個(gè)體和互動(dòng)勝于流程
- 可運(yùn)行的軟件勝于詳細(xì)的文檔
- 響應(yīng)變化勝于遵循計(jì)劃