Linux中國

忘記技術債務 —— 教你如何創造技術財富

反思遺留代碼

關於遺留代碼最常見的定義是由 Michael Feathers 在他的著作 《高效利用遺留代碼》 Working Effectively with Legacy Code 一書中提出:遺留代碼就是沒有被測試所覆蓋的代碼。這個定義比大多數人所認為的 —— 遺留代碼僅指那些古老、陳舊的系統這個說法要妥當得多。但是 Goulet 認為這兩種定義都不夠明確。「遺留代碼與軟體的年頭兒毫無關係。一個兩年的應用程序,其代碼可能已經進入遺留狀態了,」她說。「關鍵要看軟體質量提高的難易程度。

這意味著寫得不夠清楚、缺少解釋說明的代碼,是沒有包含任何關於代碼構思和決策制定的流程的成果。單元測試就是這樣的一種成果,但它並沒有包括了寫那部分代碼的原因以及邏輯推理相關的所有文檔。如果想要提升代碼,但沒辦法搞清楚原開發者的意圖 —— 那些代碼就屬於遺留代碼了。

遺留代碼不是技術問題,而是溝通上的問題。

如果你像 Goulet 所說的那樣迷失在遺留代碼里,你會發現每一次的溝通交流過程都會變得像那條 康威定律 Conway』s Law 所描述的一樣。

Goulet 說:「這個定律認為你的代碼能反映出整個公司的組織溝通結構,如果想修復公司的遺留代碼,而沒有一個好的組織溝通方式是不可能完成的。那是很多人都沒注意到的一個重要環節。」

Goulet 和她的團隊成員更像是考古學家一樣來研究遺留系統項目。他們根據前開發者寫的代碼構件相關的線索來推斷出他們的思想意圖。然後再根據這些構件之間的關係來做出新的決策。

代碼構件最重要的什麼呢?良好的代碼結構、清晰的思想意圖、整潔的代碼。例如,如果使用通用的名稱如 「foo」 或 「bar」 來命名一個變數,半年後再返回來看這段代碼時,根本就看不出這個變數的用途是什麼。

如果代碼讀起來很困難,可以使用源代碼控制系統,這是一個非常有用的工具,因為它可以提供代碼的歷史修改信息,並允許軟體開發者寫明他們作出本次修改的原因。

Goulet 說:「我一個朋友認為提交代碼時附帶的信息,每一個概要部分的內容應該有半條推文那麼長(幾十個字),如需要的話,代碼的描述信息應該有一篇博客那麼長。你得用這個方式來為你修改的代碼寫一個合理的說明。這不會浪費太多額外的時間,並且能給後期的項目開發者提供非常多的有用信息,但是讓人驚訝的是很少有人會這麼做。我們經常能看到一些開發人員在被一段代碼激怒之後,要用 git blame 扒代碼庫找出這些垃圾是誰幹的,結果最後發現是他們自己乾的。」

使用自動化測試對於理解程序的流程非常有用。Goulet 解釋道:「很多人都比較認可 Michael Feathers 提出的關於遺留代碼的定義。測試套件對於理解開發者的意圖來說是非常有用的工具,尤其當用來與 行為驅動開發模式 Behavior Driven Development 相結合時,比如編寫測試場景。」

理由很簡單,如果你想將遺留代碼限制在一定程度下,注意到這些細節將使代碼更易於理解,便於在以後也能工作。編寫並運行一個代碼單元,接受、認可,並且集成測試。寫清楚注釋的內容,方便以後你自己或是別人來理解你寫的代碼。

儘管如此,由於很多已知的和不可意料的原因,遺留代碼仍然會出現。

在創業公司剛成立初期,公司經常會急於推出很多新的功能。開發人員在巨大的交付壓力下,測試常常半途而廢。Corgibytes 團隊就遇到過好多公司很多年都懶得對系統做詳細的測試了。

確實如此,當你急於開發出系統原型的時候,強制性地去做太多的測試也許意義不大。但是,一旦產品開發完成並投入使用後,你就需要投入時間精力來維護及完善系統了。Goulet 說:「很多人說,『別在維護上費心思,重要的是功能!』 如果真這樣,當系統規模到一定程序的時候,就很難再擴展了。同時也就失去市場競爭力了。

最後才明白過來,原來熱力學第二定律對代碼也同樣適用:你所面臨的一切將向熵增的方向發展。你需要與混亂無序的技術債務進行一場無休無止的戰鬥。隨著時間的推移,遺留代碼也逐漸變成一種債務。

她說:「我們再次拿家來做比喻。你必須堅持每天收拾餐具、打掃衛生、倒垃圾。如果你不這麼做,情況將來越來越糟糕,直到有一天你不得不向 HazMat 團隊求助。」(LCTT 譯註:HazMat 團隊,危害物質專隊)

就跟這種情況一樣,Corgibytes 團隊接到很多公司 CEO 的求助電話,比如 Features 公司的 CEO 在電話里抱怨道:「現在我們公司的開發團隊工作效率太低了,三年前只需要兩個星期就完成的工作,現在卻要花費12個星期。」

技術債務往往反映出公司運作上的問題。

很多公司的 CTO 明知會發生技術債務的問題,但是他們很難說服其它同事相信花錢來修復那些已經存在的問題是值得的。這看起來像是在走回頭路,很乏味,也不是新的產品。有些公司直到系統已經嚴重影響了日常工作效率時,才著手去處理這些技術債務方面的問題,那時付出的代價就太高了。

忘記債務,創造技術財富

如果你想把 重構技術債務 reframe your technical debt 敏捷開發講師 Declan Whelan 最近造出的一個術語 — 作為一個積累技術財富的機會,你很可能要先說服你們公司的 CEO、投資者和其它的股東接受並為之共同努力。

「我們沒必要把技術債務想像得很可怕。當產品處於開發設計初期,技術債務反而變得非常有用,」Goulet 說。「當你解決一些系統遺留的技術問題時,你會充滿成就感。例如,當你在自己家裡安裝新窗戶時,你確實會花費一筆不少的錢,但是之後你每個月就可以節省 100 美元的電費。程序代碼亦是如此。雖然暫時沒有提高工作效率,但隨時時間推移將提高生產力。」

一旦你意識到項目團隊工作不再富有成效時,就需要確認下是哪些技術債務在拖後腿了。

「我跟很多不惜一切代價招募英才的初創公司交流過,他們高薪聘請一些工程師來只為了完成更多的工作。」她說。「與此相反,他們應該找出如何讓原有的每個工程師能更高效率工作的方法。你需要去解決什麼樣的技術債務以增加額外的生產率?」

如果你改變自己的觀點並且專註於創造技術財富,你將會看到產能過剩的現象,然後重新把多餘的產能投入到修復更多的技術債務和遺留代碼的良性循環中。你們的產品將會走得更遠,發展得更好。

別把你們公司的軟體當作一個項目來看。從現在起,把它想像成一棟自己要長久居住的房子。

「這是一個極其重要的思想觀念的轉變,」Goulet 說。「這將帶你走出短淺的思維模式,並讓你比之前更加關注產品的維護工作。」

這就像對一棟房子,要實現其現代化及維護的方式有兩種:小動作,表面上的更改(「我買了一塊新的小地毯!」)和大改造,需要很多年才能償還所有債務(「我想我們應替換掉所有的管道...」)。你必須考慮好兩者,才能讓你們已有的產品和整個團隊順利地運作起來。

這還需要提前預算好 —— 否則那些較大的花銷將會是硬傷。定期維護是最基本的預期費用。讓人震驚的是,很多公司都沒把維護當成商務成本預算進來。

這就是 Goulet 提出「 軟體重構 software remodeling 」這個術語的原因。當你房子里的一些東西損壞的時候,你並不是剷除整個房子,從頭開始重建。同樣的,當你們公司出現老的、損壞的代碼時,重寫代碼通常不是最明智的選擇。

下面是 Corgibytes 公司在重構客戶代碼用到的一些方法:

  • 把大型的應用系統分解成輕量級的更易於維護的微服務。
  • 讓功能模塊彼此解耦以便於擴展。
  • 更新形象和提升用戶前端界面體驗。
  • 集合自動化測試來檢查代碼可用性。
  • 代碼庫可以讓重構或者修改更易於操作。

系統重構也進入到 DevOps 領域。比如,Corgibytes 公司經常推薦新客戶使用 Docker,以便簡單快速的部署新的開發環境。當你們團隊有 30 個工程師的時候,把初始化配置時間從 10 小時減少到 10 分鐘對完成更多的工作很有幫助。系統重構不僅僅是應用於軟體開發本身,也包括如何進行系統重構。

如果你知道做些什麼能讓你們的代碼管理起來更容易更高效,就應該把這它們寫入到每年或季度的項目規劃中。別指望它們會自動呈現出來。但是也別給自己太大的壓力來馬上實施它們。Goulets 看到很多公司從一開始就致力於 100% 測試覆蓋率而陷入困境。

具體來說,每個公司都應該把以下三種類型的重構工作規划到項目建設中來:

  • 自動測試
  • 持續交付
  • 文化提升

咱們來深入的了解下每一項內容。

自動測試

「有一位客戶即將進行第二輪融資,但是他們沒辦法在短期內招聘到足夠的人才。我們幫助他們引進了一種自動化測試框架,這讓他們的團隊在 3 個月的時間內工作效率翻了一倍,」Goulets 說。「這樣他們就可以在他們的投資人面前自豪的說,『我們一個精英團隊完成的任務比兩個普通的團隊要多。』」

自動化測試從根本上來講就是單個測試的組合,就是可以再次檢查某一行代碼的單元測試。可以使用集成測試來確保系統的不同部分都正常運行。還可以使用驗收性測試來檢驗系統的功能特性是否跟你想像的一樣。當你把這些測試寫成測試腳本後,你只需要簡單地用滑鼠點一下按鈕就可以讓系統自行檢驗了,而不用手工的去梳理並檢查每一項功能。

在產品市場尚未打開之前就來制定自動化測試機制有些言之過早。但是一旦你有一款感到滿意,並且客戶也很依賴的產品,就應該把這件事付諸實施了。

持續交付

這是與自動化交付相關的工作,過去是需要人工完成。目的是當系統部分修改完成時可以迅速進行部署,並且短期內得到反饋。這使公司在其它競爭對手面前有很大的優勢,尤其是在客戶服務行業。

「比如說你每次部署系統時環境都很複雜。熵值無法有效控制,」Goulets 說。「我們曾經見過花 12 個小時甚至更多的時間來部署一個很大的集群環境。在這種情況下,你不會願意頻繁部署了。因為太折騰人了,你還會推遲系統功能上線的時間。這樣,你將落後於其它公司並失去競爭力。」

在持續性改進的過程中常見的其它自動化任務包括:

  • 在提交完成之後檢查構建中斷部分。
  • 在出現故障時進行回滾操作。
  • 自動化審查代碼的質量。
  • 根據需求增加或減少伺服器硬體資源。
  • 讓開發、測試及生產環境配置簡單易懂。

舉一個簡單的例子,比如說一個客戶提交了一個系統 Bug 報告。開發團隊越高效解決並修復那個 Bug 越好。對於開發人員來說,修復 Bug 的挑戰根本不是個事兒,這本來也是他們的強項,主要是系統設置上不夠完善導致他們浪費太多的時間去處理 bug 以外的其它問題。

使用持續改進的方式時,你要嚴肅地決定決定哪些工作應該讓機器去做,哪些交給研發去完成更好。如果機器更擅長,那就使其自動化完成。這樣也能讓研發愉快地去解決其它有挑戰性的問題。同時客戶也會很高興地看到他們報怨的問題被快速處理了。你的待修復的未完成任務數減少了,之後你就可以把更多的時間投入到運用新的方法來提高產品的質量上了。這是創造科技財富的一種轉變。因為開發人員可以修復 bug 後立即發布新代碼,這樣他們就有時間和精力做更多事。

「你必須時刻問自己,『我應該如何為我們的客戶改善產品功能?如何做得更好?如何讓產品運行更高效?』不過還要不止於此。」Goulets 說。「一旦你回答完這些問題後,你就得詢問下自己,如何自動去完成那些需要改善的功能。」

文化提升

Corgibytes 公司每天都會看到同樣的問題:一家創業公司建立了一個對開發團隊毫無推動的文化環境。公司 CEO 抱著雙臂思考著為什麼這樣的環境對員工沒多少改變。然而事實卻是公司的企業文化對工作並不利。為了激勵工程師,你必須全面地了解他們的工作環境。

為了證明這一點,Goulet 引用了作者 Robert Henry 說過的一段話:

目的不是創造藝術,而是在最美妙的狀態下讓藝術應運而生。

「你們也要開始這樣思考一下你們的軟體,」她說。「你們的企業文件就類似那個狀態。你們的目標就是創造一個讓藝術品應運而生的環境,這件藝術品就是你們公司的代碼、一流的售後服務、充滿幸福感的開發者、良好的市場預期、盈利能力等等。這些都息息相關。」

優先考慮解決公司的技術債務和遺留代碼也是一種文化。那是真正為開發團隊清除障礙,以製造影響的方法。同時,這也會讓你將來有更多的時間精力去完成更重要的工作。如果你不從根本上改變固有的企業文化環境,你就不可能重構公司產品。改變對產品維護及現代化的投資的態度是開始實施變革的第一步,最理想情況是從公司的 CEO 開始自頂向下轉變。

以下是 Goulet 關於建立那種流態文化方面提出的建議:

  • 反對公司嘉獎那些加班到深夜的「英雄」。提倡高效率的工作方式。
  • 了解協同開發技術,比如 Woody Zuill 提出的 合作編程 Mob Programming 模式。
  • 遵從 4 個現代敏捷開發原則:用戶至上、實踐及快速學習、把安全放在首位、持續交付價值。
  • 每周為研發人員提供項目外的職業發展時間。
  • 日工作記錄作為一種驅動開發團隊主動解決問題的方式。
  • 把同情心放在第一位。Corgibytes 公司讓員工參加 Brene Brown 勇氣工廠的培訓是非常有用的。

「如果公司高管和投資者不支持這種升級方式,你得從客戶服務的角度去說服他們,」Goulet 說,「告訴他們通過這次調整後,最終產品將如何給公司的大多數客戶提高更好的體驗。這是你能做的一個很有力的論點。」

尋找最具天才的代碼重構者

整個行業都認為頂尖的工程師不願意干修復遺留代碼的工作。他們只想著去開發新的東西。大家都說把他們留在維護部門真是太浪費人才了。

其實這些都是誤解。如果你知道去哪裡和如何找工程師,並為他們提供一個愉快的工作環境,你就可以找到技術非常精湛的工程師,來幫你解決那些最棘手的技術債務問題。

「每次在會議上,我們都會問現場的同事『誰喜歡去在遺留代碼上工作?』每次只有不到 10% 的與會者會舉手。」Goulet 說。「但是我跟這些人交流後,我發現這些工程師恰好是喜歡最具挑戰性工作的人才。」

有一位客戶來尋求她的幫助,他們使用國產的資料庫,沒有任何相關文檔,也沒有一種有效的方法來弄清楚他們公司的產品架構。她稱修理這種情況的一類工程師為「修正者」。在 Corgibytes 公司,她有一支這樣的修正者團隊由她支配,熱衷於通過研究二進位代碼來解決技術問題。

那麼,如何才能找到這些技術人才呢? Goulet 嘗試過各種各樣的方法,其中有一些方法還是富有成效的。

她創辦了一個社區網站 legacycode.rocks 並且在招聘啟示上寫道:「長期招聘那些喜歡重構遺留代碼的另類開發人員...如果你以從事處理遺留代碼的工作為自豪,歡迎加入!」

「我開始收到很多人發來郵件說,『噢,天吶,我也屬於這樣的開發人員!』」她說。「只需要發布這條信息,並且告訴他們這份工作是非常有意義的,就吸引了合適的人才。」

在招聘的過程中,她也會使用持續性交付的經驗來回答那些另類開發者想知道的信息:包括詳細的工作內容以及明確的要求。「我這麼做的原因是因為我討厭重複性工作。如果我收到多封郵件來諮詢同一個問題,我會把答案發布在網上,我感覺自己更像是在寫說明文檔一樣。」

但是隨著時間的推移,她發現可以重新定義招聘流程來幫助她識別出更出色的候選人。比如說,她在應聘要求中寫道,「公司 CEO 將會重新審查你的簡歷,因此請確保求職信中致意時不用寫明性別。所有以『尊敬的先生』或『先生』開頭的信件將會被當垃圾處理掉」。這些只是她的招聘初期策略。

「我開始這麼做是因為很多申請人把我當成男性,因為我是一家軟體公司的男性 CEO,我必須是男性!?」Goulet 說。「所以,有一天我想我應該它當作應聘要求放到網上,看有多少人注意到這個問題。令我驚訝的是,這讓我過濾掉一些不太嚴謹的申請人。還突顯出了很多擅於從事遺留代碼方面工作的人。」

Goulet 想起一個應聘者發郵件給我說,「我查看了你們網站的代碼(我喜歡這個網站,這也是我的工作)。你們的網站架構很奇特,好像是用 PHP 寫的,但是你們卻運行在用 Ruby 語言寫的 Jekyll 下。我真的很好奇那是什麼呢。」

Goulet 從她的設計師那裡得知,原來,在 HTML、CSS 和 JavaScript 文件中有一個未使用的 PHP 類名,她一直想解決這個問題,但是一直沒機會。Goulet 的回復是:「你正在找工作嗎?」

另外一名候選人注意到她曾經在一篇說明文檔中使用 CTO 這個詞,但是她的團隊里並沒有這個頭銜(她的合作夥伴是 Chief Code Whisperer)。這些注重細節、充滿求知慾、積極主動的候選者更能引起她的注意。

代碼修正者不僅需要注重細節,而且這也是他們必備的品質。

讓人吃驚的是,Goulet 從來沒有為招募最優秀的代碼修正者而感到厭煩過。「大多數人都是通過我們的網站直接投遞簡歷,但是當我們想擴大招聘範圍的時候,我們會通過 PowerToFlyWeWorkRemotely 網站進行招聘。我現在確實不需要招募新人馬了。他們需要經歷一段很艱難的時期才能理解代碼修正者的意義是什麼。」

如果他們通過首輪面試,Goulet 將會讓候選者閱讀一篇 Arlo Belshee 寫的文章「 命名是一個過程 Naming is a Process 」。它講的是非常詳細的處理遺留代碼的的過程。她最經典的指導方法是:「閱讀完這段代碼並且告訴我,你是怎麼理解的。」

她將找出對問題的理解很深刻並且也願意接受文章里提出的觀點的候選者。這對於區分有深刻理解的候選者和僅僅想獲得工作的候選者來說,是極其有用的辦法。她強烈要求候選者找出一段與他操作相關的代碼,來證明他是充滿激情的、有主見的及善於分析問題的人。

最後,她會讓候選者跟公司里當前的團隊成員一起使用 Exercism.io 工具進行編程。這是一個開源項目,它允許開發者學習如何在不同的編程語言環境下使用一系列的測試驅動開發的練習進行編程。結對編程課程的第一部分允許候選者選擇其中一種語言來使用。下一個練習中,面試官可以選擇一種語言進行編程。他們總能看到那些人處理異常的方法、隨機應便的能力以及是否願意承認某些自己不了解的技術。

「當一個人真正的從執業者轉變為大師的時候,他會毫不猶豫的承認自己不知道的東西,」Goulet說。

讓他們使用自己不熟悉的編程語言來寫代碼,也能衡量其堅韌不拔的毅力。「我們想聽到某個人說,『我會深入研究這個問題直到徹底解決它。』也許第二天他們仍然會跑過來跟我們說,『我會一直留著這個問題直到我找到答案為止。』那是作為一個成功的修正者表現出來的一種氣質。」

產品開發人員在我們這個行業很受追捧,因此很多公司也想讓他們來做維護工作。這是一個誤解。最優秀的維護修正者並不是最好的產品開發工程師。

如果一個有天賦的修正者在眼前,Goulet 懂得如何讓他走向成功。下面是如何讓這種類型的開發者感到幸福及高效工作的一些方式:

  • 給他們高度的自主權。把問題解釋清楚,然後安排他們去完成,但是永不命令他們應該如何去解決問題。
  • 如果他們要求升級他們的電腦配置和相關工具,儘管去滿足他們。他們明白什麼樣的需求才能最大限度地提高工作效率。
  • 幫助他們避免分心。他們喜歡全身心投入到某一個任務直至完成。

總之,這些方法已經幫助 Corgibytes 公司培養出二十幾位對遺留代碼充滿激情的專業開發者。

穩定期沒什麼不好

大多數創業公司都都不想跳過他們的成長期。一些公司甚至認為成長期應該是永無止境的。而且,他們覺得也沒這個必要跳過成長期,即便他們已經進入到了下一個階段:穩定期。完全進入到穩定期意味著你擁有人力資源及管理方法來創造技術財富,同時根據優先權適當支出。

「在成長期和穩定期之間有個轉折點,就是維護人員必須要足夠壯大,並且相對於專註新功能的產品開發人員,你開始更公平的對待維護人員,」Goulet 說。「你們公司的產品開發完成了。現在你得讓他們更加穩定地運行。」

這就意味著要把公司更多的預算分配到產品維護及現代化方面。「你不應該把產品維護當作是一個不值得關注的項目,」她說。「這必須成為你們公司固有的一種企業文化 —— 這將幫助你們公司將來取得更大的成功。「

最終,你通過這些努力創建的技術財富,將會為你的團隊帶來一大批全新的開發者:他們就像偵查兵一樣,有充足的時間和資源去探索新的領域,挖掘新客戶資源並且給公司創造更多的機遇。當你們在新的市場領域做得更廣泛並且不斷取得進展 —— 那麼你們公司已經真正地進入到繁榮發展的狀態了。

via: http://firstround.com/review/forget-technical-debt-heres-how-to-build-technical-wealth/

作者:http://firstround.com/ 譯者:rusking 校對:jasminepeng

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國