做软件架构设计的时候,三层式体系结构是一个很常套用的分层模式。三层式体系结构中会将系统切割成为: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)关系来做设计。而「上下文关系」是另外一个有趣的议题,并且包含很多技术内容。限于篇幅的关系,这部分内容另外开主题再来讨论。
本篇文章讨论实作系统时,系统核心与系统边界之间的架构如何设计,并介绍提高内聚、减少耦合的解决方案。这些基础面向对象设计概念,阅读起来会比较无趣,并且实作时也会遇到很多的困难。但仍希望开发人员能够花点时间投资,毕竟现在很多新技术,都是靠这些面向对象的设计去堆砌出来的。
原文链接:http://www.cnblogs.com/clark159/archive/2012/07/30/2616080.html