Skip to main content

Ch10: 不要害怕新增程式碼

觀念

為何會害怕新增程式碼?

  • 第九章提到: 新增程式碼會增加成本
  • 追求完美的代碼,導致不敢下手

10.1 接受不確定性: 進入危險

  • 直面最不確定的部分,勇敢挺進是scrum五大精神之一
  • Google發現可以預測團隊生產力的關鍵指標
    • 團隊成員是否互相信任,並且在面對風險時有安全感
  • 克服恐懼就要面對恐懼
    • 換到新地方要部署第一行Code很可怕
    • 逼迫自己第一天就一定要推Code,可以消除恐懼,並且知道如何在團隊中創造價值

10.2 使用 Spikes 來克服建造錯誤事物的恐懼

  • 第九章提到的Spike: 一個短暫的、實驗性的研究階段,旨在評估新技術或解決方案的可行性。
  • 透過Spike為團隊帶來第一版本,以及接下來實作跟設計的信心
  • Spike的Code不能直接作為生產環境使用
  • 引入Spike的困難
    • Stakeholders: 要能同意花時間實作但是不能馬上作為生產環境用的Code
    • Developers: 直接使用的誘惑

10.3 固定的時間分配非功能性需求

  • 有部分人對寫Code的恐懼可以觀察他圍繞著工具和流程的建設比實際生產代碼花更多時間
    • 打造完善的CICD流程但是沒有任何Code進版
    • 80/20法則(IT Revolution Press, 2016)
      • 80%時間給功能性需求
      • 20%時間給非功能性需求

10.4 通過擁抱逐步改進來克服對不完美的恐懼

  • 冒名頂替症候群(Imposter syndrome)
  • 接受不完美的代碼,應專注於哪裡要投資成本讓他完美,哪裡要接受不完美
    • 高效的Code,需要技巧與分析
    • 好用的Code,需要測試與驗證
    • 擴展性佳的Code,需要重構與遠見
    • 穩定的Code,需要測試
  • 衡量完美的指標很多無法都關注,好的建議 -> 關注開發者的生活
    • 盡可能縮短獲得任務到任務交付的時間
    • 短的反饋循環,可以增加迭代次數,藉此增加質量,因為反饋會帶來改善
  • 尖峰與穩定模式(Dan North): 關注開發者的生活,僅花時間在有意義的事物上
    • 我們將一個任務視為尖峰
      • 生成代碼時不考慮指標
    • 在代碼中添加監測,在六週後查看代碼是否被使用
      • 如果沒有使用,我們刪除它
      • 否則,我們在監測所得到的反饋指導下重構它

10.5 Copy and Paste對變更速度的影響

  • 添加代碼的最基本方式之一:複製代碼
  • 單一調用點
    • Pros
      • 全局改變行為很容易,代碼可維護性高
    • Cons
      • 耦合增加Coupling
      • 調整時容易影響到使用該代碼的所有位置
  • Copy and Paste
    • Spike的期間建議可以都用Copy and Paste
    • Deliver之前要重新評估是否需要重構,要思考單一調用點是否有意義
    • Pros
      • 每個地方都Decouple,修改單一節點邏輯成本很低
      • 可以很好進行邏輯實驗與修改
    • Cons
      • 維護性很差

10.6 通過可擴展性進行新增修改

  • 如果我們知道某些代碼容易接受變更,我們可以使其可擴展
    • 變化點使我們的代碼變得更複雜
    • 所有東西都可擴展會是浪費
  • 本質複雜性: 領域本身就很複雜
  • 偶然複雜性: 技術選擇或設計錯誤導致複雜性提升
  • 要減少偶然複雜性,可以依循下列三步驟
    • 複製代碼
    • 使用並適應它
    • 如果這樣做有意義,則調整為單一調用點
  • 擴展-合約模式
    • 在擴展階段,我們添加新功能。兩個相同行為的副本需要維護。
    • 進行遷移,慢慢將調用者移動到新功能。
    • 一旦所有調用者都被移動,我們執行合約階段,在這裡我們刪除原來版本的行為。
  • 兩種使代碼更具可擴展性的重要方式
    • 用Class替換條件判斷
      • 通過添加另一個Class來簡單地修改行為
    • Strategy Pattern
      • 通過添加新策略動態地添加新副本

10.7 實現向後兼容

  • 我們對代碼進行版本控制時,我們提供給調用者選擇繼續使用熟悉版本的選項,而不用擔心我們可能會更改它
  • 為調用者提供最大可能的安全性,我們的代碼應該在其整個生命周期內保持向後兼容
  • 增加新功能時要保證新舊兼容,但是維護既有邏輯會增加偶然複雜性
    • 應該努力廢棄舊版本
    • 調整教程材料以使用新版本
    • 大聲宣布更改來促使人們轉向新版本
    • 監控顯示原始版本沒有被使用,我們就可以安全地移除它
info

微軟對向後兼容的承諾

  • Windows 95的代碼如何仍在Windows 10中運行
  • 不能在Windows中命名一個文件為CON
  • Windows 10系統中找到Windows 3.1的文件選擇提示

10.8 通過Feature Toggle進行新增修改

  • 讓代碼存在Source Code,而不讓它運行,最簡單方法是將其放在if (false)中
  • From Zero to Hero
    • 簡單的boolean判斷
    • 環境變量
    • 專業工具
  • 有兩份相同的代碼在運行,if語句增加了實際的複雜性
    • 在代碼中添加監測,在六週後查看代碼是否被使用
      • 如果沒有使用,我們刪除它
      • 否則,我們在監測所得到的反饋指導下重構它
  • 風險: Toggle trouble at Knight
    • 不小心同時roll out兩個版本
    • 導致交易失控

10.9 通過抽象分支進行新增修改

  • Feature Toggle 是否違反了不要使用if與else的規則?
    • if是單一的且臨時的
    • 抽象分支: 有多點要進行版本控制
      • 用Class替換If判斷
        • 不是返回true或false
        • 而是返回NewA或OldA

Summary

  • 將Spikes 納入我們的工作流程可以幫助我們克服建造錯誤事物的恐懼。
  • 接受一定程度的浪費是必要的,這樣我們可以將大部分時間用於為利益相關者創造價值。
  • 以開發者生活為目標最大化練習和生產力。
  • 複製代碼鼓勵實驗,而共享代碼則增加了脆弱性。
  • 擁有更多的代碼可以揭露更多的基礎結構,為我們的重構提供更清晰的方向。
  • 重構旨在減少偶然複雜性。本質複雜性是對潛在領域進行有意義建模所必需的。
  • 通過添加進行修改支持向後兼容性,從而降低風險。
  • 功能切換支持代碼集成,從而降低風險。
  • 抽象分支有助於管理複雜的功能切換。