pragmaticProgrammer

Before Project - 專案啟動前

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

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

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

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

第八章: 專案啟動前

本篇文章教你如何釐清需求 如何跳脫框框思考 以及何謂敏捷開發

需求坑

所謂的達到完美 並不是指再也無法加入任何東西 而是無法拿走任何東西

許多書籍將 需求收集(requirement gathering)當作專案的早期階段 這讓人覺得需求已經在這個世界上的某個地方 只需要花時間人力去把它找到

但事實並非如此 需求很少會顯露於表面 大多數情況下 需求被埋在層層的假設 錯誤 政治之下 甚至根本不存在

沒有人確切的知道自己要什麼

需求神話

在軟體工程發展的早期 因為使用電腦成本昂貴 跑個程式碼都還要讀卡機 所以你會花很多時間在桌上規劃 再三檢查 然後再使用電腦

但這個做法在現代已經不實際了 現實世界充滿著混亂矛盾未知 你很難在寫程式之前就完全清楚自己要什麼

但這也是程式設計師用武之地 我們的工作就是了解他們想要什麼

程式設計師幫助人們了解需求

程式設計當作治療

我們把要求我們寫程式的人當作我們的客戶

典型的客戶會帶著需求來找我們 菜鳥工程師常犯的錯誤就是完全把這個需求當真 並直接實作

根據我們的經驗 最初的需求通常不是真正的需求 連客戶本身都沒有意識到這一點 我們需要去進一步探索

舉個簡單的例子 你今天在一家紙質書和電子書的公司工作 你收到一個新的請求

“所有50美金以上的訂單都要免費送貨”

現在我們來想一下

1.50美金包含稅嗎

2.50美金包含運費嗎

3.50美金是指紙質書還是電子書

4.提供什麼樣的運輸服務? 急件還是一般

5.國際訂單也是嗎

6.50美元這個數字多久會變一次

列出這些問題就是程式設計師該做的事 我們會詢問邊界狀況來惹惱別人

程式設計師: 50美金有包含本來會收取的運費嗎

客戶: 有 就是他們本來要出的錢

程式設計師: 這很好懂 但可能會有人利用這點

客戶: 怎麼說

程式設計師: 原本買一本書25元 選了最貴的overnight shipping 30元 因為選了之後超過50元 所以我們免運費 等於是這個客人花了25元 得到了25元的書加上overnight的shipping

(這時候有經驗的工程師會停下來 我們要做的就是交付事實 讓客戶做決定)

客戶: 有道理 這樣我們就虧了 讓我再好好想想

這是一個創造性的流程 你的工作是解釋客戶的話 並回饋其中的含意 為的是一個可能比你自己或是客戶單獨提出的方案更好的解決方案

需求是一個流程

Requirements Are Learned in a Feedback Loop

務實的設計師喜歡將整個專案的一切活動都視為需求收集活動 這就是為什麼我們喜歡更短的往來週期 這樣即使我們方向錯誤 損失的時間也是最少

站在客戶的立場思考

有一個方法可以深知客戶的思考模式 那就是成為客戶 花點時間了解系統要如何真正的被使用 比如說跟著客戶一起工作 這不但有助於理解需求 也可以建立信任 為未來的溝通奠定基礎

和使用者一起工作 讓您像使用者般思考

記錄需求

當我們知道怎麼真正釐清需求之後 該用什麼文件來記錄呢 你可能唯一需要的紀錄方式是可以工作的程式碼

這不代表你可以不紀錄你對需求的理解就離開 這只是代表需求檔案不是可交付的 這不該是個要給客戶簽字的東西 它只是幫忙指導實作過程的路標

過度指定規格(overspecification)

生成需求文件另一個風險就是過於具體 好的需求應該是抽象的

就需求而言 最簡單 最能準確反映業務需求的敘述就是最好的 但這不代表可以模糊

需求不是架構 需求不是設計 需求不是使用者介面 需求就是需求

維護術語表

別忘了維護一個專業術語表(project glossary) 代表這個專案中所有用到特殊術語和詞彙的地方 這樣所有專案的參與者 從最終使用者到支援人員 所以人都用術語來保持一致性

解開不可能的謎題

偶爾 你會發現自己捲入了一個專案中很艱難的問題 某些程式碼比你想像中的難寫 也許看起來根本不可能完成 這時候需要換個角度思考

想想小時候常玩的益智遊戲

Alt text

要解開這種玩具 解法通常都不是顯而易見的 你需要辨別出真實的限制 找出哪些限制是絕對條件 哪些限制只是你大腦給你先入為主的假設

自由度

要學會跳出盒子思考(Thinking outside the box) 才能幫助我們識別哪些是不適用的限制 充分理解你實際擁有的自由度 為什麼某些謎題難以破解 因為你太容易忽視潛在的解決方案

Alt text

考考你 要怎麼讓四條直線一筆畫通過所有的點呢 給你一分鐘 別忘了要跳出盒子思考









Alt text

真實限制只有

1.一筆畫 也就是線要連著

2.直線

你是不是先入為主的加入了 線不能出界的限制呢?

再問你一題 那要怎麼讓三條直線一筆畫通過所有的點呢 給你一分鐘 別忘了要跳出地球思考









Alt text

你是不是先入為主的加入了 線一定要過黑點的中心的限制呢?

再問你一題 最少可以幾條直線一筆畫通過所有的點呢 給你十秒鐘 別忘了要跳出宇宙思考









Alt text

答案是一條 你是不是先入為主的加入了 線一定要很細的限制呢?

重要的不是跳出框框思考 重要的是找到框框

敏捷的本質

敏捷(agile)是一個形容詞 他用來形容你做某件事的方式 你可以成為一個敏捷開發人員 你可以加入一個採用敏捷實作的團隊 敏捷是你的風格 不是你本人

敏捷不是一個名詞 而是你做事的方式

記住敏捷的價值觀

1.個體和個體間的互動 比流程和工具重要

2.能正常工作的軟體 勝過複雜完整的文件

3.客戶協作 勝過合約談判

4.回應變化 而不是遵循計畫

每一項而言 左邊的東西都勝於右邊的

不可能有所謂的敏捷流程

當有人跟你說 “這樣做 你就會更敏捷” 從定義上來說 這句話就是錯的

因為敏捷 指的是應對變化的能力 對你出發後的未知作出回應

團隊和個人開發人員都是如此 開發軟體時沒有單一的計畫可以遵循 四個價值中有三個價值都在告訴你要收集和回應feedback

那該怎麼做呢

敏捷開發的秘訣如下

1.找到自己目前的處境

2.朝你想要的方向邁出小但有意義的一部

3.評估現在的處境 並修復破壞的一切

有時候 即使你只是收集回饋 也會讓不起眼的決定重要起來

“我的程式碼需要獲得賬戶擁有者”

let user = accountOwner(accountID);

“恩 user這個名字聽起來沒什麼用”

let owner = accountOwner(accountID);

“嗯…感覺怪怪 我需要知道擁有者是因為我要寄email給擁有者 那我其實只要有email就可以”

let email = emailOfAccountOwner(accountID);

你可以看到這個feedback loop被套用在了非常細節的層次上 我們減少了程式碼和處理帳戶的關係耦合

這個feedback loop也可以用在專案的最高層級 當我們開始處理客戶的需求時就可以開始使用

甚至這個回饋迴圈可以用在專案之外 可以用來審查專案的流程以及工作情況 不持續試驗流程的團隊就不是敏捷團隊