2013年4月7日星期日

限制搜尋空間 加速設計

在2月份Barcamp中跟Steven Mak一起做了一場演講,題目是「少文件、大設計、快開發」,講述以少量文件開始計劃,並以設計技巧加速開發的心德分享。因為涉獵的範圍太廣,當初就題目的決定可真費煞思良。實踐果然是最佳的驗証法,收到不少的意見,其中有段的反應不錯,所以決定獨立成文跟大家分享。

關於限制

限制總是令人討厭,有時會聽到說要是當初沒有這個限制就能好了~事情一定更美滿之類的說辭。

可是細心思考,失去所有限制真的是好事嗎?

試想像突然間要你寫一篇作文,題目不限,你會寫什麼?結果是飛快把文章寫出來,還是遲遲動不了筆?

<<人月神話>>的作者Frederick. P Brooks,在他的新書<<設計的設計>>中提到:
「限制或許是負擔,但也可能是好事。限制可以縮減設計師的搜尋空間,有所限制,比較容易聚焦並加速設計。
……
讀國中的時候,我們很多人都不喜歡「自訂題目的作文」,我們發現有些事是真的;把限制統統拿掉,會使「設計」作文的工作更加困難,而不是更簡單。

……

人為限制對設計工作來說,好處是可自由放寛限制,理想情況下,它可以把設計師推向設計空間中未經探索的角落,從而激發出創意。」

限制並非創意的制肘、相反詞,好的限制反而可以激發出創意,問題是一些誤解、過時甚至矛盾的限制,例如下圖……


要平?要好?又要快?去你的。


需求不清

沒有限制的作文令人猶疑不決;需求不清的軟件開發則舉步為艱,二者的情況其實很相似。

有些人明確地認知到,有些人潛意識地知道,完全的自由並不存在,沒有說明限制不代表沒有限制,通常在交付時才知道。故總是恐懼著做出少於隱藏限制的工作,又害怕做出多於要求的事浪費氣力,結果精力都消耗在摸索那條不可視的界線。

所以一份清楚的需求可以幫助導論出明確的限制,但不幸的是需求不清下開發已經變成了業內的常態,雖然不支持卻只能照著辦。
設計不足的困境 
常見於菜鳥或技能狹窄的團隊,以不變的舊方法挑戰新問題,缺乏對應問題的設計,又因解決方案的涵蓋範圍不足,結果問題多多最終難尾收場。這種團隊的常見特質是把High Risk的東西都放到最後。 
過度設計的抓狂 
另一種極端是過度設計,為了應付不清淅、未知的需求多想多設計不是壞事,但往往會無止盡地思考、搜尋可能性,不自覺地做出過於複雜的架構,拉長了開發時間,而更糟的是有可能做出超出能力的設計,直接出局。
有點相當之有趣,就是設計不足的團隊往往比過度設計的團隊成功,因為前者最少能做出讓客戶收貨的第一個版本,雖然會因為需求修改、又或者結構太爛導至technical debt的債台高築,令開發的時間及成本不斷上昇。

但最少能快速地做到第一個版本,投資者願意付錢,又能發佈出去令士氣得以維持,正付合MVP的精神;總好過因為不肯定是否需要的問題而拖長開發時間,所以Extreme Programming有所謂"You aren't gonna need it" (YAGNI)的原則,需求修改則以TDD及Refactoring應對。

明確的時限是一種避免過度設計的限制


把想法歸成四類的分析法


有次跟某開發團隊會面,討論他們的設計,期間提出了許多試探性的問題,例如做不做得到一項不在規格內的功能?為什麼要用/不用這方法?這個問題發生時該怎麼辦?

大部份問題都是無理,甚至是愚蠢的,持續發問是為了考驗他們對自身設計的掌握,但結果工程師的回答速度越來越慢,漸漸失去自信。

這不能怪責他們,因為需求本身就處於不清淅的狀態,在無限制的設計中,搜尋(回答)的速度必然下降。

為了讓設計得到限制,我們做了一個嘗試。

就會議中提出的所有點子、Story,不論是問題、原則、想法、猜測,只要認為重要的,請寫下並歸類成以下四種狀況:
Requirement 
明確地由客戶、老闆提出的需求,那是一種proven fact,無用質疑的Story都歸類在這裹。

在那次會議中可以被歸類為Requirement的想法遠比其他種類少,正是問題的所在。

Constraint 
在項目管理中,Constraint指應被檢查、限制、禁止的資源及要避免的行為,同時又包括為此而採取的行動,用途是為專案所覆蓋的範圍定出明確的界線。你可以理解為完成需求而應該及不應該做的事。

Assumption
也可以稱之為Educated Guess,沒有實質的証據支持,但憑籍經驗進行猜度的各種想法。

Uncertainty 
專案中的大敵,混沌的根源,理應盡早排除,但若因此過份賣力,卻會陷入過度設計的地獄。最糟的其實不是項目存在不確定、不清淅的地方,而是自己都不知道不清楚什麼,所以把Uncertainty記錄下來是有幫助整理思考的作用。
參考

若Requirement及Uncertainty處於二個極端,那麼Constraint及Assumption就是彌補二者之間的空缺,在進行軟件分析及設計時會在腦中跑出許多的點子,對這些點子過早進行批判是無益的,一來在大藍圖清淅前欠缺足夠理據下決定,二來為每個點子進行深度分析是很費時的,需要的僅是記錄及歸類。



完全不明白、猜不透的想法
Uncertainty
我覺得專案需要...吧...?
Assumption
我們要做或不要做個
Constraint
原來文件有寫的
Requirement

這個歸類是很簡單的,建議可以先自行準備,然後拿出來給團隊一起研究,他們可以幫助確認想法的正確性,例如把不對的Assumption拿掉、跟客戶老闆談Uncertainly,最後變成Requirement或者Constraint等等。

故此這個分析表的內容會隨著時間而改變,理應越來越準確,在這個前提下第一版與最後版本必定有很大的出入,所以起草人不妨「大膽假設」,而非慢慢分析,寧可快點拿出起討論,反正有錯是正常的。

限制搜尋空間的設計


並非所有編程師都有規劃的能力,按部就班編程還可,規劃整個軟件卻無能為力或者費時日久,這與經驗有關,也與思考方法有關,試想像同時把數十至數百項要求同時放進腦部思考有多困難?

能同時處理、思考的數目多寡主要由天資及思維決定,不過可以用方法補救,就是利用之前寫下的分析列表,以檢核表法(Checklist Method)方式輔助思考。

在未有一個大藍圖之前,先由Requirement著手,就每個單獨的要求做一個設計:

  1. 只針對這個要求做設計,不考慮其他。(除非你認為行有餘力)
  2. 內容可以是Use-case diagram、Class Diagram、Activity Diagram、Sequence Diagram、Deployment Diagram、Collobration Diagram,建議採用圖像化方式,但Pseudo Code及point form也可
    1. 如果做的是Class Diagram,不用把需求外的Class列入,比起一張overall的Class diagram,針對use-case所繪的class diagram更容易令人理解.
  3. 建議手繪,因為快,易加入注解,在設計成形後才轉用數碼方法


註:如果之前已經有重覆的設計,可以考慮修改而非做一個新設計

檢核表法驗証


為一個單獨的需求做的設計可以很快很簡單,但驗証卻要難得多,會無止盡地思考擔心是否足夠呢?

這時候就該把之前的分析成果拿出來用。

首先把剛完成的設計跟過往的設計比較:

  1. 有衝突的地方嗎? => 有則一起修改,尋求一致性
  2. 有重覆的地方嗎? => 抽出來變成模組




然後跟分析結論再做比較:

  1. 有未完成的條件嗎?
    1. 再設計 or
    2. 列入Uncertainty (其實可能是不需要的做的,先記下來再討論吧!)
  2. 有分析文件中沒有的功能嗎?
    1. 再設計、刪除 or
    2. 列入Assumption (憑我的經驗推斷,這功能是需要的)




結論

以上嘗試提出的是一種系統性的分析及設計方法,檢核表法的作用是限制搜尋的空間,放棄無止盡地去思考,而是與過去的設計及分析結果逐一對比,若沒有修改就代表初部設計完成,定出一個明確的完成條件.

對於經驗豐富的架構師來說,大概用途不大,因為他們已經有自己一套的分析及設計論,最大的作用是用來培育仍不得要領的新手,在有限制的時間內讓他們累積設計經驗.

事實上當我們完成了以上的分析後,工程師們回答問題的速度明顯地提昇了許多,另外發現到設計出現問題的原因多數在於Assumption出錯或Constraints不足,基本上只要協助澄清這些需求及分析結果,他們就能自行修正設計。菜鳥的話則加多把勁吧。

這方法其實是把分析及設計放在一起進行,在設計完成時分析的內容或會因此改變,這跟傳統的SDLC的先分析再設計有一定的分別,但若果說這其實更接近Winston Royce(提出Waterfall model的人)原來的想法,而且他本人就不相信Waterfall model,你會相信呢?

好比如這篇文章的主旨「利用限制加速」一樣,有時候有些固有的觀念並不一定通用,不妨用更靈活的方式去思考問題吧。這是一個初步提出的想法,歡迎大家一起討論。

沒有留言:

Creative Commons License
本網誌Ben Lau製作,以共享創意署名-非商業性-相同方式共享 3.0 香港 授權條款釋出。