<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          重寫軟件的 6 大風(fēng)險

          共 5920字,需瀏覽 12分鐘

           ·

          2020-09-18 13:28

          作者 | Ben Northrop
          策劃 | 萬佳
          盡管重寫必然會給團隊帶來風(fēng)險,但我們經(jīng)常還是不顧一切地踏上重寫的旅程。


          重寫帶有一種欺騙性的誘惑,其邏輯看上去是這樣:

          這個系統(tǒng)已經(jīng)應(yīng)用于生產(chǎn)環(huán)境,我們顯然知道它是如何工作的,因此只要將其移植到一個更好的平臺,一旦我們完成這項工作,事情就會變得更簡單。

          我們在本文將批判這種基于直覺的認(rèn)識。你會看到,重寫絕非易事。盡管我們不受新應(yīng)用程序部分挑戰(zhàn)的影響,但也會碰到前所未有的全新挑戰(zhàn)。為成功地完成重寫,我們必須應(yīng)對這些挑戰(zhàn),因此提前了解有什么風(fēng)險很有必要。

          在冒險重寫前,讓我們講述一個快速的起源故事,看看我們是怎么走到這一步的?

          ? ? 開始? ??

          這一切都始于綠地開發(fā)( Greenfield Development )階段。在這個階段,我們萌生一個想法,開始構(gòu)建一款功能強大的應(yīng)用程序。經(jīng)過數(shù)周或幾個月的不懈努力,我們最終向市場發(fā)布了一款產(chǎn)品。當(dāng)然,這個“市場”既可能是真正的付費用戶,也可能是一組內(nèi)部業(yè)務(wù)用戶等等。

          如果應(yīng)用程序很受歡迎,在一段時間內(nèi),它會處于增強( Enhancement )階段,添加新功能,解決缺陷。這是個平衡階段,每個人都是快樂的。最終, 技術(shù)債務(wù)會不斷累積,我們開始發(fā)現(xiàn),努力工作的回報在遞減——在過去,一周的開發(fā)足以添加一個完整的新功能,但現(xiàn)在,可能都不夠改變按鈕的顏色。


          這時,我們可能就會產(chǎn)生疑問:投入時間和金錢去做一件注定失敗的事,這樣做是否值得。此外,自應(yīng)用程序首次發(fā)布以來,可能出現(xiàn)了一些令人興奮的新技術(shù),我們可能對如何利用這些技術(shù)讓應(yīng)用程序更具彈性、更易使用和更高效等有一些宏偉愿景。所以,我們開始制定一個重寫計劃。其思想是將現(xiàn)有系統(tǒng)的開發(fā)短時間凍結(jié),然后將資源轉(zhuǎn)移到替代系統(tǒng)上。我們會先打基礎(chǔ)(使用更現(xiàn)代的模式、工具、語言等等),然后將現(xiàn)有的功能遷移過去。用戶只需要安然度過“暫?!保床猾@得任何新的更新),但是當(dāng)重寫的系統(tǒng)就位時,工作效率應(yīng)該是以前的兩倍(或者更多!) 。

          雖然這個“直接遷移(lift and shift)”計劃看起來直截了當(dāng),但它掩蓋了一些關(guān)鍵風(fēng)險——技術(shù)、組織和心理方面的因素都會使這個重寫階段極不穩(wěn)定。此外,這個階段拖得越久,我們成功(即交付替換品)的機會就越低。因此,讓我們看看其中隱含的一些危險。

          第一個風(fēng)險:雙倍的工作量

          在這段旅程中,我們常常面對的第一個風(fēng)險是重寫基本上是雙倍的工作量。當(dāng)然,在技術(shù)上,我們希望自己可以暫停以往的開發(fā),只專注于在新平臺上編寫代碼,但現(xiàn)實(準(zhǔn)確地說是業(yè)務(wù))很難遵守這一原則。

          或許是為了贏得(或留住)一個重要客戶,業(yè)務(wù)人員要求我們現(xiàn)在就在已有系統(tǒng)中添加一些新特性?;蛘叩谌较到y(tǒng)改變了其 API,而我們需要重構(gòu),或者出現(xiàn)了 sev-1 缺陷,或者新的政府法規(guī)發(fā)布。

          關(guān)鍵是, 生產(chǎn)系統(tǒng)幾乎不可能長時間處于靜止?fàn)顟B(tài) ,甚至在重寫期間也是如此。對舊系統(tǒng)進行維護是不可避免的,而這意味著并行開發(fā)。

          這樣,第一個問題是并行開發(fā)違反了我們作為開發(fā)人員最神圣的原則:不要重復(fù)自己。對遺留系統(tǒng)的任何更改都需要移植到新系統(tǒng)中。例如,如果我們在舊棧中添加特性 X,我們必須在新棧中再次添加 X(但這次是用新的語言或框架編寫的)。這種重復(fù)工作也適用于 X 的測試、項目管理、構(gòu)建和部署。本質(zhì)上,無論對遺留系統(tǒng)進行更改需要花費多少時間或資源,在重寫階段,成本很容易翻倍。

          而且,根據(jù)重寫工作的進度,更改(如功能、缺陷修復(fù)等等)可能發(fā)生在源代碼中尚未重寫的部分,所以團隊必須記住,到那里的時候要把重寫的時間線后推?;蛘咴谙喾辞闆r下,更改發(fā)生在應(yīng)用程序中已經(jīng)重寫的部分,因此,團隊必須返回并更新剛剛遷移過的代碼(然后重新測試等等)。

          無論哪一種方式,重寫過程中的并行開發(fā)都可能讓人覺得,團隊在地面上構(gòu)建替代品的同時還要保證飛機的正常飛行。為了乘客的安全,那架飛機必須留在空中,但如果我們花太多的精力去維護它,我們就永遠(yuǎn)無法讓新飛機起飛。當(dāng)然,負(fù)責(zé)這兩駕“飛機”的團隊通常是同一個,這就引出了下一個問題。

          第二個風(fēng)險:團隊分裂

          假設(shè)需要做一些必要的工作來支持現(xiàn)有系統(tǒng),那么問題是:誰對此負(fù)責(zé)?通常,團隊會采用兩種方法來管理并行工作。一種選擇是,讓更多的初級開發(fā)人員留在維護模式中,從而解放高級開發(fā)人員來開發(fā)新系統(tǒng)。這是有道理的,因為完成重寫通常需要更高層次的技術(shù)“無畏派”——掌握各種新技術(shù)并整合應(yīng)用、配置環(huán)境、建立模式和約定等等,這些都是棘手的任務(wù),可能會讓新晉開發(fā)人員深陷泥潭。因此,團隊可能會決定進行這種類型的分裂,初級開發(fā)人員維護,高級開發(fā)人員繼續(xù)前進。但這可能只是短時間有效, 不用多久,高級開發(fā)人員還是會被拉回來幫助解決需要全員參與的關(guān)鍵問題或討論一些變化的影響。

          多年來,他們對舊系統(tǒng)的了解,以及他們與業(yè)務(wù)利益相關(guān)者、運維人員和其他人的關(guān)系,讓他們不可替代。他們不得不參與其中。即使這種“抽離”每周只占用幾個小時,但上下文切換仍然會阻礙工作效率。當(dāng)開發(fā)人員在舊系統(tǒng)和新系統(tǒng)之間來回切換時,重寫的時間線就會被推后。

          為避免這種情況,團隊可以采取另一種方法:組建一個新團隊,這樣更容易專注于重寫。這個“重寫團隊”的開發(fā)人員與現(xiàn)有系統(tǒng)的聯(lián)系可以忽略不計(也許他們是顧問、新雇員等等),因此他們能更好地將自己隔離開來,并在新工作中保持高效。

          問題解決了?沒有。第一個問題是根據(jù)定義,這些開發(fā)人員不太熟悉代碼庫,不具備領(lǐng)域知識,不知道事物是如何運轉(zhuǎn)的,也不知道為什么要這樣運轉(zhuǎn)。當(dāng)然,他們有原始代碼作為文檔,但這就像通過查看源代碼來學(xué)習(xí)編程語言一樣。這都是事實,不是講故事。因此,這個新團隊要么會在理解現(xiàn)有系統(tǒng)的錯綜復(fù)雜之處時步履維艱,要么會為了繼續(xù)前進而做出錯誤的假設(shè),要么最終不得不拉攏原來的團隊。這些都不是富有成效的結(jié)果。

          此外,這種“組建新團隊”的方法也會疏遠(yuǎn)那些留下來負(fù)責(zé)支持遺留系統(tǒng)的資深開發(fā)人員,使他們感到好像自己因為忠誠度和經(jīng)驗受到了懲罰。新團隊使用現(xiàn)代化的技術(shù)開始全新工作,而他們還在毫無生氣的做著維護。這一點也不酷。因此,不出所料,這樣很快就會導(dǎo)致開發(fā)人員不滿,稍后是人才流失。我們需要設(shè)計一個團隊結(jié)構(gòu),既能支持舊系統(tǒng),又能正確高效地構(gòu)建新系統(tǒng),讓每個人都滿意。但即使你讓合適的人上了合適的車,還是會有意外發(fā)生。

          第三個風(fēng)險:意外之事

          現(xiàn)在,即使重寫的團隊配備了經(jīng)驗豐富的開發(fā)人員(即那些幫助編寫遺留系統(tǒng)或至少有一些經(jīng)驗的開發(fā)人員),在將現(xiàn)有的源代碼遷移到新平臺時,總還是會有意外。對于此類意外事件,Donald Rumsfeld 提出了比較中肯的見解:

          有報道說 ,我們總是對沒有發(fā)生的事情感興趣,因為據(jù)我們所知 ,有已知的已知 ;有些事情我們知道我們已經(jīng)知道。我們也知道有已知的未知;也就是說,我們知道有些事情是我們不知道的。但也有未知的未知——那些我們不知道自己不知道的。縱觀我們國家和其他自由國家的歷史,后一類往往是最困難的一類。

          通常,當(dāng)開始重寫過程時,我們會設(shè)法估計需要付出多少努力。從這里開始,我們會編目前兩類工作。當(dāng)然,有一些代碼庫我們有直接的經(jīng)驗,因此,我們可以更快(更準(zhǔn)確)地做出估計。這些是已知的已知。但是,系統(tǒng)中也有一些地方,我們知道自己沒有直接的經(jīng)驗,所以我們增加了一些緩沖。

          比如,Joe 編寫了注冊流程,但是他去年辭職,所以遷移可能需要更長的時間。

          這些就是已知的未知。我們按計劃繼續(xù)進行,評估這兩種類型的工作,并為已知的未知留出額外時間,直到就整個時間線達成一致。

          然而,直到我們深入研究并開始遷移代碼時,我們才偶然發(fā)現(xiàn)第三種也是最有害的工作類別,即未知的未知。它可能是我們從來不知道其存在的 1000 行令人費解的業(yè)務(wù)邏輯,或者是我們不知道何人使用的一組報告,又或者是一些我們不知道的將整個系統(tǒng)集成在一起的“膠帶”。不管是什么,我們最初的重寫計劃都從來沒有考慮到它,但我們此時已經(jīng)走出太遠(yuǎn),無法回頭。

          結(jié)果是,我們要分析這個(以前)未知的未知,看看“它到底做了什么?”,然后進行處理(“我們需要把它遷移過來,還是可以拋在一邊?”)。這些額外的分析、討論和努力只會推遲最初計劃好的時間,降低業(yè)務(wù)發(fā)起人和客戶的耐心。

          雖然其中一些未知的未知可以被消化吸收,但太多的話可能會使整個重寫工作陷入危的境地。通過更好的計劃和分解(稍后詳細(xì)討論),可以盡量減少這種未知的未知,但是要完全避免還是很困難的。不管怎樣,我們還會給自己造成另一種危險。

          第四個風(fēng)險:第二系統(tǒng)效應(yīng)

          通常,我們長期忍受現(xiàn)有系統(tǒng)的缺陷,以至于當(dāng)有機會重新來過時,我們?nèi)滩蛔∠胱屢磺凶兊酶?,或者更完美?br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">

          幾十年前, Fred Brooks 將這種趨勢稱為第二系統(tǒng)效應(yīng)( Second System Effect)。在《 人月神話》中,Brooks 談到了系統(tǒng)架構(gòu)師,根據(jù)他的觀察:

          在設(shè)計第一個項目時,他會不斷地修飾和潤色功能。這些功能會被存起來,用于“下一個”項目。早晚有一天,第一個項目結(jié)束了,架構(gòu)師對這類系統(tǒng)充滿信心,他相信自己已精通這一級別的系統(tǒng),并時刻準(zhǔn)備著開發(fā)第二個系統(tǒng)。

          第二個系統(tǒng)是架構(gòu)師們所設(shè)計的最危險的系統(tǒng)。當(dāng)他著手第三個或第四個系統(tǒng)時,先前的經(jīng)驗會相互驗證,他們就可以判斷出此類系統(tǒng)的通用特性,而系統(tǒng)之間的差異會幫助他識別出經(jīng)驗中不具普遍性的部分。

          這種影響可以通過幾種方式表現(xiàn)出來。首先,我們傾向于把重寫看作是一個消除我們在過去的系統(tǒng)中所積累的全部技術(shù)債務(wù)的機會。我們希望分解 God 類,修復(fù)不一致的變量命名,改寫和重組數(shù)據(jù)結(jié)構(gòu)等等。基本上,我們認(rèn)為這是解決遺留代碼中所有小問題的機會,因為將債務(wù)移植到新代碼庫中感覺不太合適。

          此外,我們還很容易產(chǎn)生這樣的想法,不僅將重寫看作是對架構(gòu)中有缺陷或缺少支持的的某些部分進行現(xiàn)代化的機會,而且還將其看作是一躍跨到技術(shù)最前沿的工具 。也許 UI 仍然是陳舊的 AngularJS,并不能為移動 Web 用戶提供很好的渲染,所以移植到一個更現(xiàn)代的 Web 框架似乎是合理的。但是,當(dāng)完成這項工作后,我們又將后端分解為微服務(wù),并使用 Go 編寫它們!從本質(zhì)上說,重寫就像一項法案——它可能只是一項減少槍支暴力的簡單法案,但當(dāng)它通過并成為法律時,西弗吉尼亞州已經(jīng)有了五座新橋梁,俄勒岡州的農(nóng)民也得到了種植大豆的補貼。

          第二系統(tǒng)效應(yīng)不僅存在于開發(fā)者中間。通常,業(yè)務(wù)涉眾也會采取同樣的策略,但是有他們自己的優(yōu)先級。“我們還不如把這個用戶渴望已久的功能在重寫時添加,因為無論如何我們都會修改代碼?!本拖窦夹g(shù)上的改進和潤色一樣,范圍變得越來越大,重寫的發(fā)布日期也被推得越來越晚。

          最后,初始系統(tǒng)的開發(fā)口號是“快速上線運行!”,而重寫時變成了“我們以后再也沒有機會做 X、Y 和 Z 了!”

          第五個風(fēng)險:重蹈覆轍

          人們常說,將軍在和平時期會為最后一場戰(zhàn)爭做準(zhǔn)備。他們會回顧和反思過去作戰(zhàn)計劃中的缺陷和錯誤,并發(fā)誓絕不讓這些錯誤再次發(fā)生。然后下一場戰(zhàn)爭就來了,和上次完全不同。他們的準(zhǔn)備是徒勞的。重寫也會發(fā)生同樣的情況。我們非常清楚自己在第一個系統(tǒng)上的失誤,所以當(dāng)設(shè)計第二個系統(tǒng)時,我們首先要確保自己不會重蹈覆轍。但人們很容易忽略,事情已經(jīng)發(fā)生了變化。在我們重寫的時候,那些過去的錯誤可能不是問題,所以沒有必要去預(yù)防它們。與此同時,在重寫中使用的現(xiàn)代化技術(shù)引入了一整套我們還無法預(yù)見到的新問題。

          在從事咨詢工作的早期,我?guī)椭粋€客戶建立了一個大型網(wǎng)絡(luò)應(yīng)用程序,服務(wù)于幾千名內(nèi)部用戶。這個應(yīng)用程序是成功的,換言之,我們在預(yù)算范圍內(nèi)按時交付了功能,但是,我們不知不覺把“馬”套在了錯誤的馬車上。那是單頁應(yīng)用出現(xiàn)的早期,所以我們使用了一個名為 Google Web Toolkit 的剛起步的框架,在當(dāng)時,它非???。遺憾的是,在這個應(yīng)用發(fā)布一年左右之后,谷歌從 GWT 轉(zhuǎn)向了更好的技術(shù)(Angular),讓所有人(包括這個客戶)都困在了這種基本上不受支持的技術(shù)上。這種糟糕的情況,我們是很難預(yù)測和預(yù)防的。

          幾年后,我有機會與一些仍然在那里的開發(fā)者重新取得聯(lián)系,他們告訴我,他們別無選擇,只能重寫這個應(yīng)用程序。但當(dāng)我問他們選了哪些技術(shù)時,我感到很驚訝。他們不想再被單頁面應(yīng)用技術(shù)或一個曇花一現(xiàn)的框架所傷害,于是他們選擇了一項非常非常成熟且有十年之久的服務(wù)器端頁面渲染技術(shù),盡管此時,單頁框架已經(jīng)非??煽?,每個人都在使用,而他們那有著豐富用戶交互的應(yīng)用程序本可以從那個模型受益。換句話說,他們重寫的核心驅(qū)動力是避免第一個系統(tǒng)的錯誤,但在這個過程中,他們錯過了現(xiàn)代 Web 框架的許多優(yōu)勢。他們在打最后一場戰(zhàn)爭。

          第六個風(fēng)險:全有或全無

          重寫的最后一個大風(fēng)險是可以避免的,但通常還是無法避免。雖然我們現(xiàn)在認(rèn)可了迭代開發(fā)的智慧和最小可行產(chǎn)品的概念,但通過重寫,很難找到一種方法來一次性交付所有的東西。例如,如果客戶一直在使用一個擁有 100 個功能的遺留系統(tǒng),如果我們希望他們(愉快地)轉(zhuǎn)換,我們交付的新系統(tǒng)怎么能夠少于 100 個功能呢?基本上,重寫的系統(tǒng)需要能夠完成舊系統(tǒng)所做的一切,因此,在回到迭代開發(fā)之前,我們似乎必須首先部署整個替代系統(tǒng)。這不僅取決于現(xiàn)有系統(tǒng)的大小,可能需要付出相當(dāng)?shù)呐Α?br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">

          此外,這種“全有或全無”的需求與業(yè)務(wù)人員持續(xù)不斷的需求相結(jié)合,會給團隊帶來難以置信的壓力。如果團隊在重寫全部完成之前不能交付任何東西,那么他們就不能顯示任何有形的價值,直到替代產(chǎn)品推出。在某種意義上,業(yè)務(wù)被重寫工作俘虜了,他們要保持耐心,相信他們的開發(fā)團隊可以完成這項工作。這并非易事。如果客戶特別要求,或者團隊經(jīng)常遇到意想不到的延遲和問題(例如,未知的未知等),將重寫的發(fā)布日期推后,業(yè)務(wù)可能就會覺得必須施加壓力(這會迫使團隊走捷徑),或者干脆放棄。

          ? ? 總結(jié)? ??

          最后,希望你已經(jīng)了解了重寫階段可能存在的風(fēng)險。雖然綠地開發(fā)階段肯定也有它的風(fēng)險,但重寫也不是在公園里散步。即使最有能力的團隊,也很容易被并行開發(fā)、團隊組織、特性和技術(shù)鍍金以及“大爆炸式”部署的挑戰(zhàn)拖垮。因此,我們必須對大規(guī)模重寫有充分的理解。

          ?延伸閱讀

          http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-2-the-risks-of-rewrites.php


          瀏覽 30
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  777精品久无码人妻蜜桃 | 乱伦婷婷五月天 | 伊人五月丁香婷婷大香蕉 | 亚洲成人免费无码视频 | 久久久夜色 |