2013年6月29日 星期六

OO的"沉重",DDD (1)

Domain Driven Design提示了我許多以前沒看過的議題,如何讓設計者更加專心地在OO上面

Domain model是一種Ubiquitous lanuage

  • 現實以及模型做綁定,這是很簡單的規則,但是往往愈到專案後期,分析的模型愈是和實際的程式碼相差愈大
  • Domain Model不是單純的圖形,他是一種語言,也就是包含了上下文(context)
  • Domain Model因為有語言的特色,大家需要看得懂,聽得懂
  • Domain Model必須不斷的精練,也就是隨著專案成長以及精簡

為何不如XP之類的agile process採用user story之類的技巧呢?主要的問題在於各個user story以及design存在於設計師的心中,是一種隱性的資料(implicit data),其次agile process,往往產出的主要成果是code,code是一種完美的實現(implemetation)的呈現,然則是太細節,如果將專案的整個class diagram畫在黑板上鐵定很壯觀,但是恐怕解釋要花上很久

而如同agile process一樣,必須發展適當的、共通的語言,將設計精簡的呈現出來,且DDD和agile process一樣相信,feedback是很重要的,設計過程必須和使用者溝通,也就是"語言"主要的用途

如何從問題/需求過渡到設計,DDD的方式採用了類似DB Table design(這是一個很不好的比喻,但是退化/極簡的domain model幾乎就是這種模式),跟著利用design pattern作為指引,可以簡單地使用下面的圖形作為依據


設計工作主要圍繞著serviceentityvalue object之間的設計

  • entity含有唯一ID,且生命週期間狀態的轉換是有意義的,如身分證
  • value object則是臨時的狀態,通常是依附於entity上面
  • service則是一種類似於基礎建設的存在,往往處於領域的邊界,如DNS service

而entity以及value object中間往往有關係,在設計上,希望關係(關係在設計圖上用連線表示)愈簡單愈好,避免太過複雜的關係,簡化關係的方式有三

  • 限定travel方向
  • 限定關聯方式
  • 減少關聯


另外一種"打包"關係的方式就是使用aggregation,將物件打包成一個entity,所有內部資料必須透過root處理,且參考到的物件,往往只是value object,也就是並不會影響到實際物件內部物件的狀態

同樣的,如果需要生成狀態的抽象畫,可以使用factory pattern。而repository pattern則適用於查詢相似物件的應用或者封裝travel/filter的行為,比方說,從persistence裝置找到所有大於65歲的老年人口,如果要從某個根物件訪問到所有符合條件的物件太過費時、複雜且沒效率。

DDD有兩個特色,全都形而上,幾乎不涉及persistence,也不涉及class定義等等的部分(GoF多少有class定義)。DDD提示我們如何專注在OOAD上面,而非過去的設計模式(procedure or others)

這裡有些anti-pattern,可供參考,是否是使用舊的方式在設計
  • 每個entity就是對應一個table或者一個record
  • 關係非常複雜,很多關係是雙向的
  • 所有物件的persistence是由一個巨大的facade對應到DB或者檔案
從DDD我也體悟到了J2EE為何會被批評為太過heavy,J2EE每每需要綁訂多個責任,因為J2EE這個architecture管理了persistence以及object的life-time,造成了物件往往有過多的責任,這是一種負擔

經過這些基本考量之後,跟著在每個iteration,如何繼續改善domain model,是一個重要的工作,而且沒有固定的方法

OO的"沉重",architecture design(架構設計)

初步建立
從需求捕捉=>分析=>設計=>code,由OOAD到OOP是一件不簡單的工作,從UP來說,可能的流程是這樣的
Use cases=>analysis model=>design model=>code

如果簡單的說,就是找出需求,分析的時候分離出名詞跟動詞,將其組合成物件,跟著抽象化倒出analysis model,借用design pattern設計出模型,最後寫出程式碼

中間過程
似乎很簡單,但是中間很多空隙(gap)需要填充,比方說UP推崇architecture centric的思維,那麼如何找出architecture?這是一個很困難的工作

為了設計architecture,UP擴展了許多東西,首先他們在use cases內部添加了一些constraints,表達non-functional features,比方fault tolerance、performance ...,這些非功能性的限制,跟著引入了controller、boundary object以及entity組成的collaboration diagram

利用sub system interface做切割,填補design以及requirement之間的縫隙,並且完成其中的對應(tractability在CMMI很重要!)

建構架構
UP中architecture centric的設計方式有賴經驗,而且要take care的重點很多,很難一概而論,同時要考慮user centric、functional features跟non-functional features,導致作法多樣,同時為了抽象表示的不足,在UP才引入collaboration diagram

在設計architecture的時候可以考慮Matrin Folwer的建議,使用domain model,可以使用DDD (domain driven design)模式,DDD一口氣跳過分析方式,直接由需求到設計,而DDD面臨的兩個議題是,模型的描述語言以及分析的方式

在DDD的部分,使用domain model是很好的選擇,跟UP的collaboration diagram很像,然則也不是那麼容易。主要一個議題是,如何符合iterative建構?如果要辨識出所有的需求再來考慮architecture,整體就變得類似waterfall的設計方式

模型的描述語言DDD使用類似class diagram的模型,並且加上類似use case的補充來描述,客戶專家以及程式設計師,必須懂得同樣的terms,DDD模型大多時候不考慮operations,連attributes也很少紀錄,畢竟是一種抽象思考。

另外一個議題是分析的方式,DDD利用design pattern填補分析方式的不足,DDD相信大家都可經由消化知識,抽象畫原本的議題,進而達成共識(領域專家未必能接受這種語言),其次這裡的design pattern也與GoF不大一樣,主要注重抽象的層級

另外一種architecture的設計方式類似DDD,首先確立業務目標(白雲,參考writin effective use case 一書),接著確立範圍以及特色(風箏跟海平面),同時利用類似use case的上下文(context)來分割出architecture的輪廓,本質上跟DDD很類似,但是只是比較方法論去形塑domain model

不管DDD或者是使用UP的cooperation diagram,重點必須找出重要的(考慮各種non-functional feature)、主要的(risk)、使用者最關心的(user centric),來做為architecture model,如果單純依照UP提示的,找出涵蓋整個系統,一寸深的architecture,我想只有非常資深的設計師才能做到,且有太多不必要的考量因素

還缺了甚麼?
architecture相當程度是為了演繹一些系統重要的部分,形成重要的骨幹,然則與DDD/Domain model有點不大一致,Domain model主要是要表達整體的概念,而DDD則是以Domain model為依歸衍生設計
可以說architecture是Domain model的主要部分,用以檢驗是否滿足各種需求(functional and non-functional)

2013年6月26日 星期三

CMMI簡介(1)

說到CMMI,一般就是拜讀CMMI: Guidelines for process Integration and Product Imporovement這一本書

  • CMMI由眾多的process組成,通過特定process之後可以達到某個Level,但是主要又以objective為主
  • 每個process分成許多的objective,如果只跟該process有關的為specific goal (SG),跟整個level有關的objective列為generic goal (GG)
  • 每個SG或者GG有許多practice ,分別是SP跟GP,往往跟產出的work product有關,也就是要有相關的描述
  • 然則CMMI告訴大家What to do,但是沒有告訴大家How to do,所以以軟體來說,軟體工程/軟體流程/PMP是很好具體實踐的手法
  • CMMI涉及組織流程的以及process的推行,這部分倒是軟體工程較少著墨,軟體流程幾乎從缺的地方

軟體測試...筆記(1)

因為教科書上面已經寫了很多,撇開測試的定義以及目的不談,單以軟體流程來說(也就是不涉及組織行為),最容易一窺全貌的是最著名的V-model或者W-model
但是從W-model來說,由於太過抽象,一般在requirement test跟functional test變得很模糊
比方說,requirement test可以執行幾樣工作的檢查
  • Visible ?
  • Clear? (unambiguous)
  • Complete?
  • Consistent? (conflicting requirements must be prioritized)
  • Reasonable? (achievable)
  • Measurable? (quantifiable)
  • Modifiable? (will it change or is it stable?)
  • Traceable? (the source is known)
  • Dependent requirements identified?
  • Testable? (given current environment, resources, skills)
或許可以使用specification by example的作法,再來檢驗這件事情會比較容易,也比較全面,以specification by example為骨幹,檢驗這幾個因素為分支,這樣就顯得較為明顯。

至於其他V model內建議的unit test, integrated test, system test, acceptance test比較工程化,也比較容易理解

以工程化的測試來說
依照測試特性可以分成
  • 白箱測試
  • 灰箱測試
  • 黑箱測試

依照開發過程可以分成
  • unit test
  • integrated test
  • system test
  • acceptance test
  • regression test

依照需求分類可以分成
  • smoke test
  • sanity test
  • benchmark test

依照性質分類可以分成
  • functional test
  1. equivalance class test
  2. boundary test
  3. random test
  4. state transition test
  • nonfunctional test
  1. install/uninstall test
  2. usability test
  3. negative test
  4. recovery test
  5. security test
  6. compatibility test
  7. performance test
  8. stress test/load test
  9. volume test
  10. ad hoc test


在CMMI Level 3中可以對應到Verfication and Validation (V&V) KPA這個項目

Verfication : Are we building the thing right?
Validation : Are we building the right thing?
主要任務是
  • 可追蹤性分析
  • 評估
  • 介面分析
  • 關鍵性分析
  • 測試
  • 危害性分析
  • 風險分析
  • 其他