領域建模(domain modeling)


        想像一下,如果您的團隊中的每個人都在說不同種類的語言。假設你說德語,你的同事說法語,別的同事在說希伯來語。每次有人發言,其他人都“收獲了什么東西”,然后點點頭,貌似他們已經完全理解了。其實他們走進了一個完全錯誤的解釋,這不是發言者真正想表達的話。在幾乎所有IT項目中,溝通不暢的問題都很“猖獗”,但是人們卻很少注意到,因為每個人都認為他們使用相同的“語言”,其實根本不是。比如:一個人說“書評”(book review”),有些人將其解釋為“編輯評論”(”editorial review“由編輯小組撰寫的評論),而其他人可能將其解釋為“客戶評論”(“customer review”由客戶撰寫的評論,並發布到現場)。結果經常是災難性的,因為系統在開發的過程中,每個人都會以不同的方式解釋需求和設計。

領域模型是一個靈活的,協作的”工做組件“。它對整個項目進行了細化和更新,從而反映了目前對“問題空間(或需求空間)”的理解。在本文中,我們將介紹領域建模,其目的是通過建立映射問題空間的常用詞匯來解決項目溝通不暢的問題。

萬尺視圖:

域建模是構建項目詞匯表或項目中使用的詞典的任務。項目的領域模型定義了范圍,並形成了構建用例的基礎。域模型還提供了一個常見的詞匯表,以便能夠在項目團隊成員之間進行明確的溝通。所以即使這本書是關於用例驅動的開發,我們必須從一開始就開始使用域建模。

什么是領域模型?如前所述,域模型本質上是項目詞匯表:項目中使用的所有術語的“實時”字典。但領域模型比項目詞匯表更好,因為它以圖形方式顯示了所有這些不同的術語如何相互關聯。實際上,它是一個簡化的類圖,在不同的類(領域對象)之間使用線條進行描繪,以顯示它們如何相互關聯。領域模型顯示領域類之間的聚合和泛化關系(has-a和is-a關系),下圖是一個領域模型的例子。

為什么開始使用域模型而不是用例?

 

你會發現,如果您在項目開始時快速構建出了領域模型,那么它真的有幫助。當你從項目一開始就使用用例的時候,很容易使它們變得抽象,高級(high-level),模糊(vague)和雙關(ambiguous.)。事實上,有些“大牛”甚至建議你用這種方式寫你的用例(只有他們稱之為“抽象的”,“必要的”,“無技術的”等等)。我們的建議恰恰相反:您的用例文本應基於現實,它應該非常接近您將要設計的系統。換句話說,用例應該寫在對象模型的上下文中(即用例文本需要通過名稱引用域對象)。通過這樣做,您將能夠將模型的靜態和動態部分結合在一起,如果您希望根據用例推動您的分析和設計工作,這是至關重要的。因此,在編寫用例之前,您需要先對領域模型進行一次嘗試。領域模型構成了您的模型的靜態部分的基礎,而用例是動態部分的基礎。靜態部分描述結構;動態部分描述行為。

(分析層面上,術語“對象”和“類”有時可互換使用(一個對象是類的運行時實例)。然而,當我們得到更接近的設計水平時,這個區別對象和類之間變得更加重要。)

十大領域建模指南:

10.關注現實世界(問題領域)對象。

9.使用泛化(is-a)和聚合(has-a)關系來顯示對象如何相互關聯。

8.將您的初始域建模工作限制在幾個小時。

7.圍繞問題領域的“關鍵抽象”來組織您的類。

6.不要將您的領域模型誤認為數據模型。

5.不要將一個對象(代表單個實例)與數據庫表(其中包含事物的集合)混淆。

4.使用領域模型作為項目詞匯表。

3.在您編寫用例之前,先做一些初始域模型,以避免使用名稱歧義。

2.不要指望您的最終類圖精確匹配您的領域模型,但他們之間應該有一些相似之處。

1.不要在您的域模型上放置屏幕(screens)和其他GUI特定的類。

10. Focus on Real-World Objects

創建領域模型時,請確保將問題領域與實際對象集中在一起。 嘗試着圍繞現實世界來組織您的軟件架構。 現實世界往往比軟件需求變化要小。下圖顯示了兩種不同類型的類符號。在完整的詳細類圖上,您將使用左側的版本,其屬性和操作。然而,在初始領域建模過程中,分配類的這些部分為時尚早。最好使用右邊所示的簡單符號。此版本僅顯示領域類的名稱。

9. Use Generalization (Is-a) and Aggregation (Has-a) Relationships

 

隨着時間的推移,您將會使用新的領域類別來識別您的領域模型。您還會注意到他們之間的聯系(或關聯) - 例如,書評屬於書,采購訂單(purchase order)和信用卡(credit card)是兩種,因為它們都是付款類型。
第一個關系(書評屬於一本書)被稱為聚合(has-a,因為一本書都會有一書評)。第二個關系(采購訂單和信用卡都是付款類型)被稱為泛化(is-a,因為采購訂單是付款類型)。圖2-3顯示了這些概念的說明。

這些所謂的一般關系是您的領域模型中最重要的關系。您可以使用聚合和泛化關系建模您的模型的類關系中的百分之九十五。盡可能不要使用“關聯”,使領域模型從左到右和從上到下閱讀,就像普通文本一樣。 這將提高您的圖表的可讀性(這句話可以不用在乎)。

8. Limit Your Initial Domain Modeling Efforts to a Couple of Hours

我們建議您做一個時間預算來構建您的初始領域模型,可能需要幾個小時,你不會使它完美無缺,所以做得很快,並希望在項目進行中不斷修復它。您應該保持警惕,對您的分析級別類模型進行必要的調整,以響應在魯棒性分析和整個項目期間發現的發現(You should be vigilant about making necessary adjustments to your analysis-level class model in response to discoveries made during robustness analysis and throughout the project)。

當您使用用例和魯棒性圖表時,您會發現缺少的對象。用例驅動的過程會假定領域模型不完整,並提供了發現遺漏的機制。
一開始您做的領域建模可能是您在項目上花費的最重要的兩個小時! 在這兩小時的頭腦爆發期間,您可能會發現80%的域名類。如果您可以將80%的領域名詞匯消除歧義,那么花費兩個小時。


7. Organize Your Classes Around Key Abstractions in the Problem Domain

圍繞在領域問題中的的”關鍵抽象“ 組織您的類通常是一個很好的做法。請記住,領域模型是一個先進的類圖,成為您的軟件架構的基礎。這使得模型面對變化更有彈性。圍繞現實世界的抽象組織架構使得模型在面對不斷變化的需求方面更有彈性,因為需求通常會比現實世界更頻繁地變化。

6. Don’t Mistake Your Domain Model for a Data Model(選看)

即使這些圖可能相似,但請記住,數據模型的良好做法在類圖上可能不是良好的做法(反之亦然)。 類很小,表比較大。關系數據庫中的表通常涉及許多事情。相反,如果它是一個相對較小的數據和行為(方法)包,則用類去設計會更好。

在類圖中,您可能會有一個管理數據庫表的類,您可能會顯示一些聚合常規域類的TableManager類。這TableManager類型類的目的是從代碼庫的其余部分隱藏數據庫管理系統(DBMS)的詳細信息。

(In a class diagram, it’s likely that you’ll have a class that manages a database table, and you might show some sort of TableManager class aggregating a regular domain class. The purpose of these TableManager-type classes is to hide the details of the database management system (DBMS) from the rest of the code base.)

5. Don’t Confuse an Object with a Database Table

一個對象代表一個單一的東西。數據庫表表示事物的集合。您不必像企業JavaBeans(EJB)世界中的文字一樣,實體bean通常表示表中的單個行。領域類是相似的。如果你調用一個領域類圖書,那么並不意味着書表(數據庫里面沒),而是是一本書。數據庫表中的列通常映射到類上的屬性。
但是,數據庫表通常包含比包含屬性更多的列(表通常具有外鍵作為一個示例),因此表行和對象之間可能沒有直接的1:1映射。

4. Use the Domain Model As a Project Glossary

如果模糊的要求(二義性)成為了你的敵人,那么領域模式就是第一道防線。“項目領域主題專家”對名稱的二義性命名和使用是非常普遍但卻是非常有害的(對同一個詞匯有不同的叫法)。領域模型應作為項目詞匯表,有助於在描述問題空間時確保術語的一致使用。使用領域模型作為項目詞匯表是消除模型歧義的第一步。在Doug教授的每一個Jumpstart教學中,他發現至少有兩到三個領域名類,其中學生使用不明確的名稱(例如“購物車shopping cart,””,“購物籃shopping basket”或“購物車shopping trolley”)。

3. Do Your Domain Model Before You Write Your Use Cases

由於您使用域模型來消除問題領域的抽象,因此使用不明確的術語編寫用例來描述域類是很愚蠢的。因此,在編寫用例之前,請花兩個小時在領域模型上工作。編寫沒有域模型的用例將所有內容綁定在一起存儲很多問題以供以后使用

2. Don’t Expect Your Final Class Diagrams to Precisely Match Your Domain Model

隨着設計的進行,類圖將比域模型更加詳細;域名模式故意保持相當簡單。在設計(使用序列圖)時,詳細的設計構造(如GUI幫助器,工廠類和基礎架構類)將添加到類圖中,領域模型圖幾乎可以分解成幾個詳細的類圖。然而,仍然可以將大多數類追溯到等效的領域類。

1. Don’t Put Screens and Other GUI-Specific Classes on Your Domain Model

這樣做會打開潘多拉的盒子,並導致一個擁擠的領域模型,其中包含許多實現特定的細節。性能優化類,助手類等也應該保留在域模型之外。領域模型應該只關注問題領域。

 

Extracting the First-Pass Domain Model from High-Level Requirements

當您創建領域模型的時候,一個良好的領域類包括很多高級要求-通常(但不總是)是以”系統應該這樣做“的形式編寫要求,或者是”系統不應該這樣做“。掃描這些要求,提取名詞和名詞短語,然后,您可以定義這些名詞或者短語來創建出事領域模型。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM