物件導向系統設計經驗談
就像我在應用架構設計總結這篇blog中提到的那樣,物件導向的系統設計就好象一群人翻越一座陡峭的懸崖,只要任何乙個人沒有翻越過去,那麼就無法設計出真正的物件導向系統。
歸結一下,在你打算進行物件導向的系統之前,你一定要考慮是否已經解決或能解決以下的問題:
一、物件的持久化
物件的持久化是最容易被想到的問題,同時也是最難解決的問題。由於關係型資料庫模型和物件導向模型存在一些比較大的差異,如何將你的物件儲存和快速的查詢出來很是頭痛。雖然採用物件導向資料庫雖然可以最方便的解決這個問題,但是你會面臨更多其它的問題,比如備份,報表和實施維護人員的培訓等等。雖然有像nhibernate這樣的orm框架來幫助你做這個工作,不過你需要去多學習一門資料不全的新技術。另外,這些開源產品中有不少的bug,你必須有做好除錯別人**的準備,如果你無法完全掌握這些**的話,你會死得很慘。
如果你採用了物件導向來設計領域模型,又沒有找到將物件直接關係化到你的資料庫中的辦法的話,最好不要採用物件導向的設計。否則你會被手工的orm折磨瘋的。
比較好的選擇是用強型別的dataset,配合vs.net的資料嚮導工具,非常快。(很有道理)
二、介面顯示
由於介面無法直接的將複雜的物件顯示出來,你在介面層又必須再做一次物件的平面化操作,將物件變成各種列表和文字框控制項可以直接繫結的一維或二維資料結構。這方面目前還沒有什麼好的自動化方案,你必須手工做。所以我們的策略就是儘量減少這個轉換步驟,就是在服務端就把物件導向轉換成平面資料,然後在客戶端直接繫結到控制項上。在資料傳輸物件的選擇上,可以用自定義物件,也可以用datatable做傳輸物件,兩者區別不是很大,各有各的好處。但是考慮到datatable可以有一些繫結方面的優勢和vs.net的除錯方面的支援,我們選擇了datatable。
如果你的物件是手工持久化的話,你做到這一步會感到很沮喪。因為平面的資料被你費了老大勁從資料庫中轉為物件,還沒有怎麼體會到物件導向的好處,又要再將物件還原成平面資料交給介面去顯示,你可能會覺得非常的不值得。不如直接就把平面資料讀出來交給介面去顯示,既簡單又方便。如果你已經產生了這個念頭的話,恭喜你,你已經離全面放棄物件導向系統設計,完全退回到面向過程不遠了
。(再次暴露了orm存在的一些問題,從資料庫取回的dataset轉成object集合後,到ui又得進行轉化後與控制項繫結,特別是cs應用)
三、遠端呼叫
如果前面你還能堅持下來,到了這一步,很少人再能堅持了。物件導向對遠端訪問的問題考慮不足,使用物件導向開發系統的乙個最大的優點是建模能力強,業務模型很清晰。比如你要找某個使用者的公司名稱,你可以簡單的用user.company.name來得到該使用者所屬公司的名稱。假如你用了多層結構,那麼問題來了,你的物件是建在n層上的,而你需要在n+1層裡對物件進行操作。而且n層和n+1層是遠端呼叫。那麼,如果你傳個user過去,很明顯用user.company.name是獲取不到公司資訊的。所以,如果你打算在n+1層做業務邏輯的話,你必須把整個物件樹傳遞過去,這樣做明顯代價又太高。很多物件導向專業人士就提出了什麼vo,bo,dto,po等等五花八門的貧血物件來企**決這個問題,這樣做的結果不僅是把問題給搞複雜化,更糟糕的是,這樣一來,你當初所憧憬的物件導向系統其實已經是乙個變相的action script系統了。
所以最好的方式是你就在領域模型層把業務處理完,中間層不要採用什麼分布式系統設計。martin fowler說過:「分布式系統設計的第一原則是,不要使用分布式系統」。不知道有多少人能理解這句話的含義。
af在解決這個問題上也提供了很大的幫助,我們利用了af創造的統一程式設計模型,將邏輯盡量都放到領域層裡。從而可以讓更多的操作直接利用到領域模型的完全物件導向的業務邏輯處理的好處。
四、開發人員的物件導向思維
這一點最重要,如果開發人員無法認識到物件導向的好處,並且在思維模式上有很頑固的面向過程套路的話。在面對上述問題的時候會抱怨連連,不會盡全力的配合。如果整個的意見無法達成一致,那什麼東西都做不出來,因為團結才是最重要的。所以你要麼盡力說服你的團員,讓他們真正的明白並理解為什麼要這麼做,要麼你就趁早放棄。
最後一條建議:
要麼就完全用物件導向的概念去設計,要麼就完全用面向過程。如果當初是決定要走物件導向的道路,後來又在關鍵性問題上向面向過程做妥協。那麼就乾脆完全用面向過程的思維去解決問題比較好。否則面對乙個四不象的怪物,你會發現維護起來更加麻煩。
翻越物件導向這座大山非常艱辛,但是你如果真正能翻越過去,你會發現物件導向的世界真的是乙個很美妙的境界。
系統分層經驗談
為了將業務規則從介面和資料庫中剝離出來,通常的做法是抽象出乙個業務邏輯層出來,專門負責對業務邏輯進行處理。一般多採用三層結構,既表現層,業務層和資料層。
當開發人員在以前的兩層結構中痛苦煎熬了很長一段時間,突然看到了三層結構的解決方案的時候,一般會有終於找到了救世主的感覺。但是這種感覺往往會導致掉到另外乙個同樣恐怖的陷阱「過度設計」中。在我以前曾經供職的一家公司,以前都是把sql語句直接寫在aspx頁面的,後來在讀到了一些關於多層結構方面的資料之後,一下子又把整個系統分成了:表現層(aspx)、介面外觀層(if),業務外觀層(bf),資料訪問外觀層(daf),資料訪問層(da)和資料訪問元件(sqlhelper)。但是我並沒有吸取教訓,導致後來也犯了同樣的錯誤。
犯錯誤的原因有很多,不過主要是因為沒有乙個比較明確的如何分層的指導性原則。假如說我們分層的原則是為了抽象邏輯,分三層的原因是要讓業務邏輯和介面及資料庫解除耦合,那麼如果按照這個分層原則,我把邏輯重新歸類更加細的分為四層、五層、六層行不行呢?如果不行,那是什麼原因不行呢?在沒有正確的原則指導下,分層技巧很容易被濫用,導致分出許多沒有必要的層出來。無端的增加了開發和維護成本,以及更重要的是增加了重構的代價,降低了團隊的敏捷能力。
物件導向架構設計大師martin fowler在介紹如何設計分布式系統的時候曾說過:分布式系統的設計原則的第一條是,不要使用分布式。他的意思當然不是說要絕對禁止使用分布式設計,而是勸導人們盡量把問題簡單化。能不分布式設計的,就不要分布式設計。
我套用他的這句話提出我對分層的感受就是:多層結構系統的設計原則第一條是,不要使用多層結構
。(增加相關分層一定要有明確的作用和存在的意義)
當然我的意思也並不是說層數越少就越好,而是希望你能清醒的認識到增加層數會增加結構的複雜性,不要輕易的作出分層的決定,一定要到感覺必須要增加一層才能解決問題的時候,再來決定增加一層。
過多的層次除了會給系統帶來不必要的複雜性外,還會影響你的系統結構設計。如果你打算採用物件導向的領域模型來設計系統的話,在業務系統內的分層會給物件導向系統的設計帶來很多麻煩,會很容易走回到事務指令碼的老路上去。關於這一點,我在物件導向系統設計經驗談這篇blog裡詳細的談到過,這裡就不再贅述。
下圖是我們最終定型的應用系統結構層次:
總結一下:
建立乙個完全物件導向建模的領域模型層,讓這個層盡量處理多的業務邏輯。其它層盡可能的薄一點,把業務邏輯都轉移到領域模型層中。
ui盡可能和領域模型貼近一點,中間不要經過太多中轉,物理邊界也盡可能的少。
業務物件只能有一套,也就是領域模型。只要出了領域模型層,外面全部是零散資料,沒有物件的概念。
只有在領域模型層才可以處理物件。
如果一定要分布式。全部用簡單資料型別通過介面訪問領域模型。
這個分層結構其實是經歷了多次精簡完成的,所有的感觸都歸結為一句話:
不要過度設計,簡單就是美。
系統設計經驗談(三)
2010 12 1 1.抽象的模組劃分圖是示意圖,在系統設計中應該有配套具體的模組關係圖對其進行解釋。2.環形呼叫關係的出現有時是不可避免的。盡量不要出現。2010 12 2 1.在複雜呼叫系統中,應該明確同步阻塞關係。2.在interpreter模式中,若需要崩潰恢復,不能使用凍結指令碼虛擬機器並...
系統設計經驗談(三)
2010 12 1 1.抽象的模組劃分圖是示意圖,在系統設計中應該有配套具體的模組關係圖對其進行解釋。2.環形呼叫關係的出現有時是不可避免的。盡量不要出現。2010 12 2 1.在複雜呼叫系統中,應該明確同步阻塞關係。2.在interpreter模式中,若需要崩潰恢復,不能使用凍結指令碼虛擬機器並...
OO分析設計經驗談
1.oo分析設計不一定用於oo語言,同樣適用於vb,php 以前版本 c等 程式設計之前最好進行oo設計,然後再進行編碼,這樣的 可讀性和易重構性要強得多.2.oo設計之前,首先應具備一定的oo概念.如果從來沒有接觸過,應好好補一下.3.uml是現在做oo設計的統一語言,應好好學習,應擁有一本 4....