pragmaticProgrammer

Pragmatic Projects - 務實的專案

千呼萬喚 終於等到Pragmatic Programmer 20週年紀念版 如果沒聽過這本書 你大概也聽過程序員修煉之道︰從小工到專家這本暢銷了20年的書 終於等到了再版

在再版裡面 刪掉了比較過時的內容和範例 收集了20年來收到的feedback 在讓這本書的內容也可以適用於2020年的程序員 但在我細細品嚐後發現 其實很多人生的哲學並不是只適用於程序員 各行各業看了都可以有所收穫

因為每個篇章的篇幅都不長 所以筆記也用條列式紀錄

本篇的圖片以及程式碼來自於原書內容

第九章: 務實的專案

隨著專案的進行 我們需要從個人的哲學問題轉移到更大規模的專案問題

一旦做專案的團隊不只一個人 你就需要建立一些基本規則 並相應的分配工作量 我們會在務實的團隊提到如何兼顧實用主義

軟體發展方法論的目的是幫人們一起工作 我們會在不要只學表面形式討論如合為你的團隊找到最合適的交付頻率

然後 我們會在務實的上手工具討論版本控制 測試 以及自動化

最後我們會在取悅您的客戶中向你展示如何取悅每個專案的出資者

傲慢與偏見中 我們會告訴你本書的最後一個 成為務實工程師的技巧

務實的團隊

本章節主要會以團隊的角度來重新定義前面多個小節的內容

不允許破窗

品質是一個團隊問題 即使你把一個最勤奮的人員擺在一個沒人在乎品質的團隊中 他們會因為一直在修東西而失去熱情 如果團隊本身還不鼓勵在修復問題上花時間 那問題會更嚴重

團隊作為一個整體 不應該容許破掉的窗戶 也就是沒有人想去修的小缺陷

一個團隊不該去指派一個品質官來保證品質 而是團隊中的每個人都必須要保證產品的品質

煮青蛙

在專案的時間壓力下 你很容易會太專注於專案本身而失去了對整個環境的關注 就像溫水裡的青蛙被煮熟

請你試著鼓勵團隊中的每個人去積極監控團隊的變化

保持清醒 意識到專案範圍的擴大 時間尺度的縮短 額外的功能 新的環境等等

不要身處熱水中還不知情

調整您的知識組合

我們說過你應該要投資你個人的知識 這對團隊來說也一樣 如果你的團隊認真看待改進和創新 那就應該把它排入工作中

找空檔做的意思就是永遠不會做

團隊的工作不僅僅是開發新功能 還有以下的事情

1.舊系統維護: 安排時間去維護舊系統

2.處理回應和改良: 你需要花時間去找處系統內哪些是有效的 哪些是不正確的 然後做出改變 持續的改進才會發生 太多的團隊忙於把水排出去 以致於沒有時間修補漏洞 你需要安排修復工作到你的專案時程中

3.新技術實驗: 不要因為 “每個人都在這麼做” 或是你在某會議或某網站上看到一個好技術就直接採用這個技術 框架 或函式庫 請謹慎的使用原型去審查所有的候選技術 一樣 把嘗試新事物的任務排在專案時程裡

4.學習技術加強: 比起一個人獨立學習 很多技能在團隊內傳播更為有效

Don’t Repeat Yourself

如果團隊缺乏良好的溝通 那就可能會導致重複的工作 這會降低團隊效率

良好的溝通意味著立即無摩擦 如果你每次有個想法都必須要等一個禮拜的某個會議才能提出來 那很可能你需要改變團隊的溝通方式

自動化

確保一致性和準確性的好方法是將團隊所做的一切自動化 自動化是每個專案團隊的基本組成 請確保團隊有工具建構的技能 以及能部署自動化專案和生產部署的工具的技能

知道何時收手

記住團隊是由個人所組成的 賦予每個成員以他們自己的方式發光的能力 給他們足夠的支援 並確保專案交付價值 別忘了我們的哲學 - 夠好的軟體 你要抵抗住想一直加東西的誘惑

不要只學表面形式

我們常看到一些聲稱自己在用Scrum的團隊 仔細看才發現他們一個禮拜才有一次的standup 四個禮拜的週期變成八個禮拜 他們認為他們在套用流行的“敏捷”排程工具

環境問題

你問問自己以及團隊 為什麼你們要用這種特殊的開發方法? 這種framework? 或是這種測試技術? 他真的適合手上的工作嗎? 對您有用嗎? 還是只是因為他很流行所以你也用?

目前的趨勢是採用成功公司的政策以及流程 比如Spotify/Netflix/Stripe/GitLab 等等 每個成功公司都對於軟體發展和管理有著獨特理解 你必須考慮你的環境 你是不是在相同的市場 是不是有著相同的限制以及機會 是不是有著相同的專業知識以及組織規模

只仿效特定表面結構/策略/流程/方法是不夠的

用有效的開發方法 不要用流行的開發方法

真正的目的

軟體開發的目的 不是”使用Scrum” “使用敏捷”等等的開發方法 而是 能夠交付可工作的軟體 這些軟體能在短時間內為使用者提供一些新的功能 注意不是幾週 幾個月或幾年的時間交付 而是當下交付

Alt text

如果你的交付週期是幾年 請試著把交付週期縮短到幾個月 再試著把交付週期所短到幾週 從四週的sprint開始 再變成兩週 再縮短成一週 再縮短成一天 最後是依照需求進行交付

注意 依照需求進行交付不代表每天每分鐘要交付 而是只有使用者需要時 以及這麼做在業務上有意義時 才交付產品

當使用者有需求時交付

請你和你的團隊調查並嘗試這些方法 但也不要做過頭 過度投資某一個方法會對其他方法視而不見

務實的上手工具

這個章節我們會討論每個專案的三個關鍵支柱

1.版本控制

2.回歸測試

3.完全自動化

版本控制

如果我們在版本控制中所說 建議您將一個專案需要的一切 都至於版本控制之下

使用版本控制去Drive Builds, Drive Tests And Drive Releases

也就是說 建構 測試 和部署的動作 都是透過提交或推送到版本控制來觸發的 這樣可以讓專案中重要的細節變成不需要開發者特別去注意的一部份 而達到真正的持續交付

無情且持續的迴歸測試

找bug有點像用網捕魚 我們用精細的小網(unit test)捕捉小魚 用大的粗漁網(integration test)抓大魚 當有魚逃脫時 我們修補任何我們找到的洞

早期測試 更常測試 自動的測試

大多時候 測試的程式碼會比主要程式碼要來得多 而且在你通過所有測試之後 你才可以放心的說 這段程式碼已經完成 以下簡略性的描述各種類型的測試

單元測試 unit test

單元測試是對一個模組執行的測試程式碼 畢竟如果一個模組不能單獨的工作 那他們就不能很好的一起工作

一旦所有相關模組都通過了各自的單元測試 就可以進入下一個階段

整合測試 integration test

整合測試是用於表明組成專案的主要子系統工作良好 而且彼此配合良好

如果有良好的合約 和良好的測試 任何的整合問題都可以容易的被檢測出來 整合測試實際上只是從單元測試擴展出來的 你在測試整個系統如何履行他們的合約

確認和驗證 Validation and Verification

雖然使用者告訴了你他們需要什麼 但這真的就是他們需要的嗎?

這東西是否真的能滿足系統的需求呢 針對錯誤問題所做的系統 縱使沒有bug也是無用的

效能測試 Performance Testing

軟體是否滿足了現實世界條件下的效能要求 預期的每秒使用數 連接數 交易次數 這些能力是有彈性的嗎

對於某些應用程式 你可能還需要真實的模擬負載

測試測試程式 Testing the Tests

我們要比寫主要程式還認真的去寫測試程式 因為測試程式沒有測試

在你寫了一個測試程式檢測特定的bug之後 請故意製造bug 並確保測試程式成功回報

以刻意破壞來測試你的測試

徹底測試

我們通常會用一些工具來知道測試的覆蓋率有多少 但即使覆蓋率是100% 也不代表全部都測試到了 重要的是你的程式可能有多少狀態

舉個例子

int test(int a, int b) { 
  return a / (a + b);
}

我們可以只寫一個測試

assertEquals(test(3, 0), 1);

那測試覆蓋工具就會告訴你 test這個函數已經100%被測試了 但其實並沒有 你並沒有測a + b = 0 的情況

知道有執行到這行保證測試通過了所有可能狀態 的差距天高地遠 而通常測試所有可能狀態是非常困難的

請測試狀態覆蓋率 而不是程式碼覆蓋率

基於屬性的測試

參考以屬性為基礎的測試

收網

如果現有的測試網子漏抓了一個bug 那麼下一次你需要添加一個測試來抓住它

不讓同樣的bug出現第二次

一旦開發人員找到了一個bug 他要保證這是出現這個bug的最後一次

完全自動化

不要讓你的測試包含手動的流程

人類的可重復性沒有像電腦那樣優秀 人類很笨 請把重複的繁雜的事交給電腦

當你有了版本控制 無情的測試以及完全自動化三個支柱之後 你就可以將精力集中在取悅使用者了

取悅您的客戶

當人們開始喜歡你的服務時 你的目標不是從他們身上賺錢或讓他們做你想做的事 而是要讓他們快樂

作為開發人員 我們的目的就是取悅使用者 你的使用者需要的不是程式碼 他也不在乎你交付的頻率 他們需要的是透過跟你合作來在預算之內解決他們的業務問題

他們的期望也和軟體無關 他們無法給你一個完整的規格 他們的需求也會不斷變化 那身為工程師要怎麼挖掘他們的期望呢 就問他們一個簡單的問題

“你要怎麼知道一個專案完成一個月(或是一年或是任意時間)後 我們算是成功了呢”

這個問題的答案 才是對客戶真正重要的東西 軟體只是達成目的的手段

當你知道了客戶的期望之後 你應該要依循以下原則

1.確保團隊中的每個人都清楚這些期望

2.做決定的時候 想一想哪條路更接近這些期望

3.根據期望來分析使用者需求 因為大多數時候使用者並不知道自己的需求是什麼 如果你能證明某些事可以讓專案更接近期望 就不要害怕提出改變需求的建議

4.在執行專案的過程中 繼續思考這些期望

請你取悅使用者 而不是發布程式碼

即使你名片上的頭銜是軟體開發人員 或是程式設計師 但你實際的職稱其實是問題解決者 這是我們的工作 也是一個務實的程式設計師的本質


我們解決問題


傲慢與偏見

務實的設計師不會逃避責任 我們樂於接受挑戰 並讓自己的專案廣為人知 如果我們負責一個設計 或一個程式碼 我們會讓自己為自己的工作感到自豪

在你的產品上簽上自己的名字

然而 專案團隊通常是由多人組成的 程式碼擁有權的想法偶爾會導致合作問題 人們可能會變得狹隘 可能導致你對別人的程式碼有偏見 但這不是我們想要的

你不該反對自己的程式被其他人干涉 同理你也該尊重別人的程式碼

如果在大型專案中存在匿名性 那就會衍生粗心 錯誤 懶惰和糟糕的程式碼 人們只把自己視為車輪上的小小齒輪 在無止盡的狀態報表中想鱉腳藉口

我們想看到你自豪地宣告所有權 “這是我寫的程式碼 我為我的工作品質做擔保”

你的簽名應該被視為品質的標誌 人們應該在一段程式碼中看到你的名字時 覺得他是可靠的 覺得是由一位專業人士完成的一份專業工作

這就是務實的程式設計師