2008年4月22日 星期二

物件模型的觀念與誤解

前一篇post說明了OOA與OOD兩種物件模型的差別。本篇不再刻意強調兩者區別,而一般性地討論物件塑模的方法。也就是說,要怎麼摸索或"設計"出一個好的物件模型。它可以用在分析與設計。

首先指出幾個常見的誤解:

  1. [錯誤]用UML來設計,就是在做object model。[正解]其實UML是一種符號或語言,但不是一種方法。你的模型可以用UML記錄下來,但是問題在於怎麼樣才能設計出好模型。UML只是語言不是方法。就好像Java是語言, TDD是開發方法。
  2. [錯誤]用UML,才是object model。[正解]物件模型可以用UML或其他記號法來表示。Analysis Patterns整本書寫於UML誕生前,但它仍是Object Model的經典名著。
  3. [錯誤]做物件模型的方法,就是把需求用use cases記錄下來。然後將use cases畫成sequence diagram,完成後物件模型就出來了。也就是說把use case裏的"名詞"抽出來,作為sequence diagram上方的objects,use cases的"動詞"抽出來,畫成橫向箭頭,定義出物件的methods。[正解]這樣跟傳統SA相比,沒有實質上的進步,除了呈現方法改用UML以外。它不會鼓勵你善用繼承與多型。而且一次只對一個use cases思考,容易導致重用度低。單靠本能做模型,可能粗糙又不實用,常常被use case文字描述的方式影響。後面會更詳細說明。
  4. [錯誤]做物件模型需要配合Rational Rose之類的軟體工具。在工具上做模型,完成後還可以轉換成程式碼的外框,非常方便。[正解]事實上,"分析設計"與"code generation"是有牴觸的。要做到code generation需要確定每個method的所有的輸入輸出的參數。分析設計階段不應該將心力用在這些細節,這反而讓人分心。這階段最重要的應該是專注在模型而不是實做細節。進一步說,一份好的分析設計文件,必需要隱藏不必要的細節,呈現該文件要表達的關鍵部份。知道如何拿捏詳細程度,才是功力所在。鉅細靡遺地定義所有的細節,倒不如直接去跟原始碼打交道。
也許讀者會覺得很奇怪,一個類別就是要有properties跟methods。如果照前一點所說的,物件模型的階段不要定義出所有的methods,那要怎麼規範每個類別呢?

比methods更根本的是,每個類別的"責任"(responsibility)。物件模型階段,只要決定每個類別的責任,以及類別間互動的關鍵的methods就夠了。好的模型,每個物件的責任都可以用一兩個短句子描述。

了解OOA的人都知道,一組use case,可以有多種的不同物件模型去解釋它。例如前面的Post"OOA範例:組織架構的樣式"中,我們可以看到一個簡單的組織架構問題,就有多種不同的模型可供選擇。所以,好的modeling方法,要符合兩個條件:
  1. 能夠輕易地讓開發者建立各種不同的模型。
  2. 能夠讓這些不同的模型有系統地競爭淘汰,挑選出最適合的模型。
最著名的方法就是Kent Back跟Ward Cunningham提出的CRC Cards。以下的步驟基本上是Alistair Cockburn的版本
  1. 選一組use cases。不是只針對單一的use case做模型,挑一組相關,看起來有共同的底層的use cases來model。
  2. 每個物件用一張卡片來表示。將有動作的物件卡片放在桌上。
  3. 走過各個use cases,將卡片取名,決定每個卡片的責任。標示在卡片上。完成以後一組這樣的卡片就是一個物件模型。
  4. 要測試這個模型好不好的方法是,改變一下use case的情景(假想需求變更),看這組卡片是不是仍能完成這個情景,或是需要小調整一些責任,或是需要增加新的卡片,或是要做更大的更動才能完成。最好的模型會最簡單,而又在最小的調整下應付最多的需求變更。
  5. 把這組卡片推到一邊(先不要丟掉,可能隨時要拿出來參考。),試著找出不同的模型。讓這個設計不斷演化,不要忘了用前一步的方法測試新設計。
  6. 把最後找出最好的模型記錄下來。你喜歡的話,可以用Rose將它畫好。但我個人最愛用的方法是用數位相機拍下來,用圖檔保留。
在Rose之類的工具上直接做模型,往往一個模型就用掉半天一天,不可能有時間做微調、測試以及更新設計。由於太早標出細節,也會造成設計變更或需求變更的困難度。我們可以看到,CRC Cards不浪費力氣在畫UML以及追逐細節,反而是很快地找出各種不同的模型,有系統地挑出最好的。CRC Cards才是真正的一種塑模方法。

2 則留言:

匿名 提到...

在物件模型的階段,物件的抽象化應該也是重點之一,一邊對物件找尋賦予它的責任,一邊對具有類似責任的物件來做歸納與抽象,不知道我這樣的說法是否正確呢?

EC 提到...

您說的有點像是設計原理。做這些歸納與抽象化,可以算是對既有模型的改進。

本文的重點在於,可以試著用各種方法多做出不同的模型,再檢驗哪一個模型既簡單又能應付未來的變更。