2008-09-21 51 views
11

我尊重的一位導師認爲,簡單的bean是浪費時間 - 值對象'必須'包含一些有用的業務邏輯。Value對象包含多少業務邏輯?

另一個說這樣的代碼很難維護,所有的業務邏輯都必須外化。

我意識到這個問題是主觀的。無論如何都要問 - 想從更多的角度來了解答案。

回答

6

你最好打電話給他們Transfer ObjectsData transfer objects (DTO)

早些時候同一個J2EE模式被稱爲「值對象」,但他們改變了名字,因爲它很困惑這個

http://dddcommunity.org/discussion/messageboardarchive/ValueObjects.html

要回答你的問題,我只會把最小的邏輯,我的DTO,顯示原因需要的邏輯。更好的是,如果我們正在討論基於數據庫的Web應用程序,我會超越核心j2ee模式,並使用HibernateJava Persistence API創建一個支持延遲加載關係的域模型,並在視圖中使用它。

查看Open session in view

這樣,你沒有一組的DTO的程序,並且擁有所有可用的業務邏輯在你的意見/控制器等

2

我個人的偏好是把所有的業務邏輯放在領域模型本身,也就是在「真實」的領域對象中。所以當創建數據傳輸對象時,它們大多隻是域對象的(不可變的)狀態表示,因此不包含業務邏輯。它們可以包含用於克隆和比較的方法,但是業務邏輯代碼的肉留在域對象中。

+0

謝謝:)。你能解釋一下'true'域對象的含義嗎? – 2008-09-21 05:46:06

5

這取決於。

哎呀,我只是脫口而出一個陳詞濫調?

的基本問題,要求設計一個目標是:將管理對象的數據的邏輯是不同相同使用時/被其他物體所消耗?

如果不同的使用領域需要不同的邏輯,則將其外部化。如果不管物體到達哪裏,它都是一樣的,把它和班級放在一起。

2

什麼Korros說使用。

Value Object:一個小的簡單對象,如金錢或日期範圍,其平等不基於身份。

DTO:=在進程之間傳輸數據的對象,以減少方法調用次數。

這些是Martin Fowler提出的定義,我想推廣它們。

20

將數據和業務邏輯放在一起的想法是促進封裝,並儘可能少地向其他對象公開內部狀態。這樣,客戶可以依靠接口而不是實現。請參閱"Tell, Don't Ask"原理和Law of Demeter。封裝使得理解狀態數據可以更容易,更容易閱讀代碼,更容易分離類,並且通常更容易進行單元測試。

外化的業務邏輯(通常爲「服務」或「經理」類),使得問題,如「使用此數據在哪裏?」和「它可以在什麼狀態?」更難以回答。這也是一種程序性思維方式,被包裹在一個物體中。這可能導致anemic domain model

外化行爲並不總是不好。例如,一個service layer可能編排域對象,但不接管他們的狀態操縱職責。或者,如果您主要對數據庫進行讀取/寫入操作,以便與輸入表單很好地匹配,則可能不需要域模型 - 或者它所帶來的痛苦的對象/關係映射開銷。

傳輸對象常常用於通過提供最小狀態信息的呼叫層需求,不得暴露任何業務邏輯去耦彼此(或者從外部系統)架構層。

這可能是有用的,例如,當準備視圖的信息:只要給視圖它所需要的信息,而不是其他,這樣它可以專注於如何來顯示信息,而不是什麼要顯示的信息。例如,TO可能是多個數據源的聚合。

一個優勢是,你的意見,你的域對象是分離的。在JSP中使用您的域對象可能會使您的域更難以重構,並促使不分青紅皁白地使用getter和setter(因此破壞封裝)。

不過,也有具有大量傳輸對象,並經常有很多重複的,太相關的開銷。我一直以來一直以TO爲基礎來反映其他領域對象(我認爲這是一種反模式)。

1

我同意帕納約蒂斯:鑑於模式的開放式會話比使用DTO的要好得多。換句話說,我發現如果你從你的視圖層一直關閉你的域對象(或其某些組合),應用程序要簡單得多。

這就是說,它很難拉斷,因爲你需要使你的HttpSession重合工作持久層的單元。然後,您需要確保所有數據庫修改(即創建,更新和刪除)都是有意的。換句話說,你不希望視圖層有一個域對象,一個字段被修改,並且在沒有應用程序代碼有意保存修改的情況下修改會被持久化。另一個重要的問題是確保您的事務語義令人滿意。通常,獲取和修改一個域對象將發生在一個事務上下文中,並且使您的ORM層需要新的事務並不困難。什麼具有挑戰性的是嵌套事務,其中您想要在打開的第一個事務中包含第二個事務上下文。

如果您不介意研究非Java API如何處理這些問題,那麼值得關注Rails的Active Record,它允許Ruby服務器頁面直接與域模型一起工作並遍歷其關聯。