[Architecture] 系統邊界設計

摘要:[Architecture] 系統邊界設計

做軟體架構設計的時候,三層式架構是一個很常套用的分層模式。三層式架構中會將系統切割成為:PL(Presentation Layer)、BLL(Business Logic Layer)、DAL(Data Access Layer)。在這其中BLL是整個系統的系統核心,而DAL則是資料物件進出系統的系統邊界。本篇文章討論實作系統時,系統核心與系統邊界之間的架構如何設計,才能提高內聚、減少耦合。

 

 

我們先假設系統設計時,將BLL、DAL各自獨立為一個DLL。而BLL裡有Control物件操作Object物件、ObjectReposository物件用來提供功能給PL使用、DAL裡則有ObjectReposository物件來封裝Object物件進出系統邊界的職責。這樣的系統架構下,會發現Object物件,同時被BLL及DAL所使用。這個共用的Object物件,在系統裡該如何存在是一件很有趣的問題。

 

 

思考Object物件在系統裡該如何存在這件事,以最直覺方式來思考的話,會認為BLL層是「使用」Object物件,而DAL只是讓Object物件「通過」。那Object物件歸類進BLL裡,應該是可以接受的設計。

 

實作上卻會發現,BLL裡的Control物件要操作ObjectReposository物件,所以BLL層相依DAL層。而將Object物件歸類進BLL裡,ObjectReposository物件要操作Object物件,又必須DAL相依BLL。這兩個相依,造成了設計上的循環相依。

 

 

 

Object物件放進BLL會有循環相依的問題,那將Object物件放進DAL也是會有同樣的問題發生。那乾脆就將Object物件封裝成一個獨立DLL,這樣的設計避免BLL、DAL之間的循環相依,也提供了彈性讓DAL、Object物件的組合可以重用。

 

實作上這個設計可以正常工作,但這是架構在「Object物件為貧血物件」這個前提上。假設Object物件不是貧血物件實作了部分系統功能,而BLL實作其他系統功能,當Object物件要重用BLL的系統功能時,就會造成循環相依的問題。而Object物件如果實作了所有系統功能,那BLL的存在就顯得多餘。

 

 

 

在網路上或設計架構書籍裡可以看到,將BLL要使用的邊界物件設計為介面封裝成一個獨立DLL,並且BLL相依於這個介面、DAL實作這個介面。這樣的設計避免BLL、DAL之間的循環相依,也提供了彈性讓BLL可以抽換DAL實作。

 

實作上這個設計可以正常工作,但還是架構在「Object物件為貧血物件」這個前提上,無法解決這個前提造成的種種問題。

 

 

 

問題的解決方案其實沒那麼困難,回到最直覺的設計,將Object物件歸類進BLL裡,並且在BLL與DAL之間套用IoC,反轉Control物件與ObjectReposository物件之間的相依性。這樣的設計避免BLL、DAL之間的循環相依、提供了彈性讓BLL可以抽換DAL實作,並且加強了BLL的內聚、減少BLL的耦合、……。。

 

但是這樣的設計在遇到重用Object物件的情景,例如:使用WCF來傳遞Object物件時,則必須要去考慮不同上下文(Context)關係來做設計。而「上下文關係」是另外一個有趣的議題,並且包含很多技術內容。限於篇幅的關係,這部分內容另外開主題再來討論。

 

 

 

本篇文章討論實作系統時,系統核心與系統邊界之間的架構如何設計,並介紹提高內聚、減少耦合的解決方案。這些基礎物件導向設計概念,閱讀起來會比較無趣,並且實作時也會遇到很多的困難。但仍希望開發人員能夠花點時間投資,畢竟現在很多新技術,都是靠這些物件導向的設計去堆砌出來的。

 

 

期許自己
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。