閒侃Domain Logic Patterns

napoleonn發表於2004-10-29
最近總是在思考Domain Logic Patterns的幾種形式,這也讓我不得不從先哲們的書中探尋答案。看了下martin 的Patterns of Enterprise Application Architecture,感覺略微明白了點事情。

在Domain Logic Patterns這個問題上面,martin歸結了三種主要形式。Transaction Script、Domain Model、Table Module。

java裡面的名詞真是很多,讓人摸不著頭腦。簡單說吧,domain logic pattern是關於構建什麼樣的domain model並操作他們來完成business logic的幾種模式。

我也不打算重複martin對這個問題的精闢解釋了,具體的可以看看他的那個書,國內也有好多朋友早就關注過這個問題了,可以看看透明思考的blog。我只想形象化的來說說這個問題。於是我寫了下面這個假象的情景。

老闆讓我辦一個全由機器人作為演員的戲劇。這些機器人是有自己執行狀態的比如在舞臺什麼位置,要說些什麼臺詞;不僅如此,這些機器人還可以定義和別的機器人存在的複雜關係,比如有個機器人是自己的妻子,還有一群機器人是自己的孩子。

=======================================
martin : 從oo角度看,你這戲劇就相當於一組要完成的business logic了。這些機器人就相當於domain model。機器人的屬性就相當於domain model裡面的屬性了。機器人和別的機器人的關係就相當於entity 的relationship
=======================================

老闆還發話了,這戲劇得全自動錄影,要把機器人走到什麼位置,做了什麼動作,說了什麼臺詞都記錄下來。幸好機器人外面提供了一個叫DAO的介面可以把機器人內部狀態儲存起來,可是這DAO介面可是什麼事情也不做的,我們得自己按照這個介面的規範自己把功能實現了!據機器人制造商說是為了方便,你可以自己來用不同方法儲存機器人狀態,比如儲存在檔案裡面啦,儲存在資料庫裡面啦,等等。製造商說了,這個介面不僅機器人自己可以呼叫,控制機器的人也可以呼叫!是非常強大和透明的!我自己嘀咕著:廢話,你啥事情都沒做當然強大了,還不得我自己完成那。

=======================================
martin: 恩,製造商的做法還是相當不錯的,提供了個介面,那樣也方便了使用者的擴充套件,機器人內部或者操縱的人使用起來也比較透明化。我們就把它叫做DAO層吧
=======================================

我感覺最適合的是採用一個資料庫來記錄這些資訊,不過老闆只提供我一個關係型的資料庫,我認識到問題的嚴重了,把物件式的資料儲存到關係型的資料庫可有點麻煩,我還是比較懶的,工夫不負有心人,終於讓我發現了一個叫hibernate的元件,這東西居然十分好使,只要幾下就把DAO那個介面給實現了。

======================================
martin: 你就別驚訝了,DAO對hibernate也只是個瘦包裝罷了,如果你不用考慮擴充套件的話,你可以直接把hibernate做在機器人裡面,不過這樣還是有點不那麼優雅。
======================================

為了讓這些機器人自動演出戲劇,沒有指令碼怎麼行!於是我就為了劇情開始寫指令碼。這些機器人還是很笨的,從A點走到B點這樣的行動都得我親自在指令碼里面說明,我指令碼里面從A點到B點這個行動我這麼寫的
A點出發-方位45度行走3米-方位30度行走5米-到達B點。
我每次都要在指令碼里面重覆上面的東西是多麼讓人痛苦的事情!我夢想:要是隻給機器人從A-B的指令,他自己能走過去是多麼的棒!!!那樣我的指令碼只要這麼寫了
從A走到B。
那把這樣的A到B走路的功能做個指令碼放到機器人裡面,我委託機器人完成不就可以了?於是我找來製造商的技術支援mm,我給她敘述了我的需求,她說我們公司是有這樣可程式設計的機器人的,可是你們公司採購的都是不可程式設計的機器人。

我的天啊!把所有應該機器人內部處理的功能都讓我在指令碼里面處理!會死人的呀!我懷著萬般無奈,還是把一份冗長的指令碼做完了。不過雖然冗長,但是還是比較簡單直觀的,我也不用去考慮機器人內部有些什麼預置的功能,反正一步步按我指令碼走就是了。

=======================================
martin: 我真是很瞭解你的痛苦,其實你的痛苦就是現在很流行的Transaction Script做法,這種做法把屬於domian model固有的方法剝離了,放到script裡面了。這樣造成的就是我說的貧血的domain model,而在你看來就是這樣的沒有程式設計功能的木頭機器人。這是我們極力應該避免的。
=======================================

由於演出還算成功,在第二次表演的時候,我極力要求老闆全部換成可程式設計的機器人,並且威脅他說,不換我就走人。老闆鑑於先前的機器人話劇取得了很大成功,還是滿足了我的要求,於是我樂呵呵的到機器人公司mm那裡訂購了一批可程式設計機器人。

可是帶來的問題是我該給這些機器人內部做些什麼功能呢?哪些功能的確是屬於機器人固有的,哪些功能是我需要在指令碼里面說明的,這問題思考起來真是頭痛。

=======================================
martin: 這就是domain model這種模式的難點了,構建一個優美緊湊的domain model可不是一件容易的事情啊。不過你還是要為你的行動感到自豪,你現在在賦予木頭人思維,讓他真正成為一個機器人,所以還是堅持下去吧,雖然有時候你會發現自己的機器人功能會很龐大,但是不要擔心,我們總是有辦法來使這個模型變的更好,孩子你還是去看看這本書吧《Domain-Driven Design》
=======================================

由於我最終構建了一個非常好的模型,所以我的指令碼寫起來相當簡單而靈活,而且一旦需要演別的話劇,這些機器人內部的有些方法是可以複用的,為我做新的指令碼減輕很多負擔,我覺得使用這樣一種機器人確實是非常好的。

=======================================
martin: 孩子,你終於得到回報了,其實你以前使用的Transaction Script模式是程式導向的而不是物件導向的,從表象上看,你確實擁有很多model,但是這些model僅僅是domain data struct,而不是domain object,因為按照object的定義,object需要有資料和操作的。我們長久以來為之奮鬥的物件導向的概念,在Transaction Script這裡遭受了重創。我們確實該回到domain model這種形式,讓我們把本該屬於domain model的方法從service layer剝離出來,按回原位。其實存在這樣一種refactor方法,讓你從Transaction Script回到domain model。這個就自己去尋找吧。
=======================================

寫這個文章我參考了幾份文件
Patterns of Enterprise Application Architecture
By Martin Fowler, David Rice, Matthew Foemmel, Edward Hieatt, Robert Mee, Randy Stafford

AnemicDomainModel
http://martinfowler.com/bliki/AnemicDomainModel.html

透明思考Blog中關於這個的討論
http://gigix.blogdriver.com/gigix/166013.html

在此做個廣告,我也常在自己的blog裡面有些胡思亂想的東西,歡迎大家批評指正。
我的blog才建不久,http://napoleon.blogdriver.com/napoleon/index.html
新手看看也許會更適合,因為我自己也剛入門不久,所以可能有些問題會有相同的困惑。可以探討探討。

也可以透過電子郵件與我聯絡 napoleonn@21cn.com

相關文章