[Architecture Design] 系统边界设计

做软件架构设计的时候,三层式体系结构是一个很常套用的分层模式。三层式体系结构中会将系统切割成为: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)关系来做设计。而「上下文关系」是另外一个有趣的议题,并且包含很多技术内容。限于篇幅的关系,这部分内容另外开主题再来讨论。



本篇文章讨论实作系统时,系统核心与系统边界之间的架构如何设计,并介绍提高内聚、减少耦合的解决方案。这些基础面向对象设计概念,阅读起来会比较无趣,并且实作时也会遇到很多的困难。但仍希望开发人员能够花点时间投资,毕竟现在很多新技术,都是靠这些面向对象的设计去堆砌出来的。


posted @   Clark159  阅读(2418)  评论(4编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示