軟體開發需求釐清

Last updated on

當接到一個新的需求或新的任務,對需求/任務的內容、牽扯到人、事、物,絕大多的情況,或許明白部份的情況,但無法全盤明確情況。

從一開始不了解需求,因為無知所產生的不安與焦慮。會隨著專案的進行,越來越來了解詳細的內容,就會變得平穩。但若中途發現有些部份的問題沒有考量到、或是誤解部份的需求,但交付期限將近,這時的感覺一定很差。

而且發生非預期的意外或誤解需求時,立即盤點影響範圍時,卻發現待解決的事項,無法在預定時程內完成,只好宣告失敗,再次爭取新的資源與時間。或是使用加班技能,交付一個自己都不滿意,但勉強可以符合需求的結果。

隨著專案的進行,從一開始不了解需求,因為無知所產生的不安與焦慮。會隨著專案的進行,越來越來了解詳細的內容,就會變得平穩。往往在專案結束後的回顧時,不禁會想到有些情況,若能提早知道,就可以避免無效的作工。

雖然,無法精確知道專案開發內,所有可能會遭遇到的難題或卡點,卻可以藉由啟動前的盤點與分析,嘗試看見全貌,提先鎖定需求或作法不明確的範圍,提早知道可能遇到的瓶頸,限定問題發生範圍。

以下分享的部份,是個人針對新專案需求的處理方式,若有更好的方式,也歡迎分享。

階段一 混沌無知的探索

以下模擬收到一個系統調整的需求的情境。

目前公司現有的倉儲系統的叫貨功能很不方便,開發一個可以把庫存不足的商品列出來,以方便叫貨。
另外,同一個商品的料件,在不同時間,不同訂單去進行叫料的動作,若分別叫貨,運費過高,目前需要手動把同個供貨商的料件彙整,才能減少運費支出。
需要一個功能,直接把相同料件欠料的資料彙整成一份清單,以便跟供貨商叫貨。

在接到需求的當下,針對現行軟體系統,需要異動到的系統範圍、注意事項、待確認項目、請求協助的範圍等等,需要處理的事項,一切都還是模糊不清的。

此時應該聚焦在需求或任務的目標本身,因為軟體開發的需求,必定為是為解決特定問題,才會被提出。

幸好現在有很多工具或方法,可以協助對焦客戶的問題,找到真正的痛點或是關鍵點。例如 Impact Mapping 就是一種好方法。

若是直接面對客戶,收到的需求,不一定是需求方真正需要解決的問題,大多的情況下,收到的需求,都是客戶想到的解決方式。若是一開始沒有確認清楚,找到客戶真正的痛點,可能最後交付給客戶的東西,雖然符合客戶需求,但收到的反應,可能會與想法不同或是不好用的回應。

但若需求是 PM/PO 開出來的,他們提出這個需求,一定要解決特定的商業問題或要達到特定的目標,若你是無法理解 PM/PO 真的想要的東西,就很有可能有很高機率,出現理解誤差,造成返工。

若這時專案又有上線的時間壓力,就會造成後期的開發、測試壓力過大,導致原本不應該發生的問題出現,或是沒有注意功能異動後,造成的隱性問題,這都是因為後期的測試不足造成的。

在詢問的時候,不要問它們想要什麼?直接問他們想要什麼,那麼很容易陷入 倖存者偏差 🔗

而是關注想要/需要解決什麼樣的問題,當開發人員對於想要解決的業務情境越了解,後期的因為需求不理解業務情境造成的返工機率就越低。同時,也比較評估現有系統在調整修改時,可能遇到什麼問題。以便提早提出疑問或問題,跟 PO/PM 同步,以便動態調整需求的規格或要求。

再者是對齊團隊的共識,不然會發生你的認知與我的認知不同(知識的詛咒 🔗) 都是會發生的。當認知偏差發生的時機點越晚,所要付出的的異動成本就越高,異動成本包含開發人力、測試人力、討論會議時間成本等。

與其這樣,到不如一開發就讓團隊,針對要開發的需求有所共識,雖然可能會比較晚切入開發進度,但確可有效減少後期的異常成本。

建立團隊共識,不可缺少的,必定建立統一的語言,以確保團隊對於特定的名詞是否認知相同,例如需求內的產品、料號、供貨商的含義是否相同,庫存不足的定義是什麼。

階段二 找出責任邊界

了解需求的細節後,接著針對需求內的每一功能,將其折分 User Story,其目的是為可以將需求細切。

接下來再進一步的分析,將每個功能的需要經過或發生的步驟或事件,將其條列出來,並依其發生前後順序,將其排列出來。此時的著眼點在於步驟的業務職責或事件的本身,所以先忽略實作的相關細節。

若出現同時發生的平行事件,也沒有關係,只有可以明確知道其相依關性即可。這時可以忽略實作或操作的細節,這時主要關注於業務面發生的事件或是狀態變動。

這個部份,使用 Event Storming 的部份技巧與元素來協助釐清業務面的需求或與基本框架。

這樣操作的目的,主要是為了可以抓出事件所屬的職責邊界(Bounded)、服務邊界、與進一步鎖定無法確定或是現有軟體系統中,模糊不清動作方式或是不了解的處理方法。

若是這時有與第三方的服務串接,就可以明確知道那邊可能是卡點,中間是否需要先使用 Mock 方式規避第三方的服務。也可以提早標注第三方服務的部份,是整個專案內需要特別注意與關心的部份。

目前公司現有的倉儲系統的叫貨功能很不方便,開發一個可以把庫存不足的商品列出來,以方便叫貨。
另外,同一個商品的料件,在不同時間,不同訂單去進行叫料的動作,若分別叫貨,運費過高,目前需要手動把同個供貨商的料件彙整,才能減少運費支出。
需要一個功能,直接把相同料件欠料的資料彙整成一份清單,以便跟供貨商叫貨。

以上方的範例為主,以業務面來看,會出現訂單叫貨單 這兩個不同的職責,那我們要如何去分析呢?

我們可以借由釐清後的業務流程,將其事件或步驟整理出來

  • 撈取庫存不足的產品 → 彙整庫存不足的產品 → 顯示報表

  • 取得待叫料的訂單 → 取得特定料件的資料 → 指定供貨商 → 產生叫貨單。

當將事件列出時,就發現某些沒有考量到,或是需求內沒有明確表示的問題。例如:

  • 庫存不足的產品的彙整方式,是要即時資料嗎? 即時有要求要多少秒內完成? 若是現行系統無法達成,可以允許的時間範圍是?

  • 已經叫貨料的訂單,若是重覆叫貨料要如何處理? 預防的機制為何?

在還沒有正式切入開發時,這個時間點,就可以提前讓許多問題其實已經浮出水面。若是還需要串接第三方服務,牽扯到更多的問題,也可以提早有所警覺。

當將上面疑惑釐清後,將釐清的資訊加入原本的流程步驟,再次調整後,就可以對需求功能的全貌更清楚。

這時我們可以簡單依據服務、職責、階段,去找出邊界(Bounded),這個邊界可能是軟體內的類別、也可能是服務與服務間的邊界。

從 High Level 的角度,已經找出該功能的骨架,所以可以看到其中較為脆弱的環結,這部份可能就是後續切入開發階段需要特別注意的部份

這階段就錯沒有完全正確也沒關係,但至少借由這個方式,對於開發的全盤有一個概括的理解,就算後續有所異動,也可以快速的找出相關的區域與範圍。

但在時,不會特別的去討論實作的細節,或是說,會刻意避免陷入因為過度討論實作細節,而忽略全局的情況。當基底未打好時,就過度追求細節,極其容易失敗與重工。

階段三 找出開發的難點

在上一個階段,找出完成需求的難點,這些難點可能是 無法控制變因過大需等待他人結果 的部份,我們需要確定這些難點所屬的邊界,特定邊界內的範圍,若有問題的難點,屬於核心功能範圍,這時,找出解決或替代的方案,就是最重要的,因為這部份無法完全,直接決定整個專案的成敗。

若是不屬於核心功能,這時可以先尋找開發時的替代方案,例如在完整的流程中,以痛點為基準點,將流程切為 N+1 段。痛點的部份可以以手動模擬或是使用 Mock 的方式替代,以確保開發中間,不會因為痛點影響開發的進度。

同時,建議在這個時間點,最好可以確認,若是因為痛點,可能會造成交付無法趕上預定時程的作法,也就是事前確認最小可交付的範圍、交付項目的迭代階段。以確定真的發生非預期的意外或開發進度不如預期時,依然可以有成果可以交付出去。

至少可以確保專案不會整個失敗,至少可以滿足客戶 70% 的需求。而來不及完成的項目,若有有其他替代作法可以達到原本的目的,也許後續客戶也不會再要求實作。若是真的很重要,這部份的需求,自然會再次出現在你們團隊面前。

個人覺得需求都可以調整的,重點在於該功能是否必要。若是必要,那就一定要實作,若非必要的,只要有替代的方案,不管是否手動介入,只可以達成目的即可。

這樣的目的,是在開發初期的時間,可以避開無法控制部份,讓專案順利進行下去。到開發中期,這時要開始進行難點的處理,需確認目前難點是否有無排除的可能性,若無法立即排除,則要提出暫時替代的方案。但需要考量難點排除後,是否可以快速替換為原本的作法。

不管何時,都要持續追蹤、關注原本難點的處理進度,直到痛點被排除。

延伸閱讀

  1. Ruddy Lee, 刻意發現 🔗
  2. 倖存者偏差(survivorship bias) 🔗
  3. 知識的詛咒(The Curse of Knowledge) 🔗