应用程序框架实战七:分层架构的选择

  创建应用程序框架,首先要考虑的问题是,你准备采用哪一种分层架构,而后根据应用程序框架的逻辑层次来肯定须要建立的VS解决方案和程序集。程序员

  若是项目很小,需求很简单,时间异常紧迫,且你手上没有任何积累,那么,单层架构将是首选,最简单的单层架构以下图所示(为了集中你的注意力,我把不相关的文件都删除了)。数据库

 

  单层架构的主要优点是代码火力集中,干活直截了当,不像多层架构那样拐弯抹角,每一个操做都须要层层传递。对于上图的User.aspx,全部相关代码都直接写到aspx页面或后置代码中,包括界面上的控件操做,业务操做和数据库操做。编程

  另外,单层架构比较符合初学者的习惯,初学者对编程语法和.Net 基本API尚且不熟,哪会过多考虑代码结构上的问题。c#

  使用单层架构,主要依赖于.Net强大的控件体系,拖控件,配属性,写事件处理函数,是单层架构下编程的真实写照,这也是.Net程序员在外人眼里一直保持的印象。架构

  对于主要包含CRUD操做的小项目,单层架构能够工做得很好,但若是项目有一些比较复杂的业务逻辑,好比订单流程 ,会发现代码很快会变成一团烂泥,失去方向。业务逻辑与表现层代码混杂在一块儿,其结果是界面上的任何修改均可能致使业务逻辑失败。框架

  为了提高代码复用能力,能够把每一个页面都须要处理的操做,好比权限检查,日志跟踪,全局错误处理等,提取到一个PageBase的基类中,放到Base文件夹,另外能够建立一个Helpers文件夹来放置公共操做类。函数

  单层架构为下一个相似项目所做出的积累微乎其微,业务上大部分代码会被抛弃,有多是技术的变化,好比以前使用Web Form,如今须要使用Win Form, 因为业务代码和表现层代码高度耦合,很明显没法再使用以前的代码。哪怕技术没有变化,要在以前开发的烂泥中新增和修改功能,将是举步维艰。有些逻辑上看似很是简单的需求,当你实际动手时,发现并非这么简单,修改一处会牵动更多地方,所谓牵一发而动全身。学习

  对于技术上的积累,主要经过复制文件的方式供下一个项目使用。一个更好的办法是把技术积累单独提取到一个.Net类库中,以下图所示。spa

 

  这样就实现了业务与技术的分离,当下一个项目到来时,只须要把Util.dll引入便可。设计

  为了挖掘单层架构的极限能力,须要开发一套强大的自定义控件,把数据库操做、验证操做、权限操做等内容所有封装进去,在控件上设置数据库列名,不须要通过DataTable或实体对象,直接生成Sql发送到数据库。若是配上代码生成器,开发简单项目的速度惊人。

  对于单层架构,不论你怎么想尽办法,它对复杂项目都无能为力,使用单层架构来开发业务逻辑复杂的项目,最终获得的就是一团乱麻。提高代码质量能够在必定程度上缓解这些问题,但要从根本上解决,还必须向多层架构靠拢。

  从上面分析能够看到,单层架构不能胜任复杂业务领域,并且复用能力十分有限。因为应用程序框架的目标在于提高技术和业务两方面的代码复用,因此单层架构不是一个合适的选择。

  信息系统从根本上来讲,是对数据库的操做,而且须要提供一套操做界面。若是按相关职责划分到不一样的层中,会有助于项目的管理和代码清晰度的提高。分层架构是SRP(单一职责原则)的一个应用,把高度相关的东西汇集在一块儿,把各个层用接口链接起来,这样就能获得一个高内聚、低耦合的设计。

  目前.Net程序员广泛使用的分层架构是传统三层架构,架构示意图以下。

 

  传统三层架构的核心在业务逻辑层,表现层会把数据放到实体中,做为参数传递给业务逻辑层,业务逻辑层会使用过程式的代码来处理业务,若是须要访问数据库,则调用数据访问层。

  传统三层架构把表现、业务和数据访问分离到不一样的层中,当切换表现层技术,或更换数据库时,只须要替换相关的组件便可,不需所有重写。

  天下没有白吃的午饭,在得到清晰度、重用性,扩展性等好处的同时,也带来了一些问题,主要是直观性下降,复杂度提高,工做量增大。在单层架构下实现一个功能,可能只须要一个方法就能彻底搞定,理解起来也比较容易,进入三层架构之后,每一个操做都被分离打散到不一样的层里,每一个层有一部分代码,须要在几个层里来回跳动,才能窥其全貌,因此直观性有所下降。另外,任何一个操做,须要在多个地方编写,工做量倍增。

  若是严格按照三层架构的要求来编写代码,表现层尽可能不要有业务操做,更不能有数据操做,业务层只管逻辑,这样能够得到比较高的可维护性。可是不少初学者对架构职责没有认识,他们会随便找个地方放置代码,这个地方多半是表现层,这样一来,不只代码质量不好,架构还很复杂,就得不偿失了。

  传统三层架构特别具备争议的地方是Model实体层。这些实体从表面上看,好像是业务对象,好比客户Customer,仔细观察这个类,发现里面全是属性,没有方法,它用来充当数据容器,在各层之间传递数据。

  有些人一直认为本身是在进行面向对象开发,毕竟c#是个面向对象的语言,又使用了三层架构,还建立了实体,不就是面向对象开发吗?实际上传统三层架构仍是面向过程的,只是披上了面向对象的外衣。还有些人对是否面向对象开发不屑一顾,“管它这些理论干啥,咱只搞实际的”,没错,通常程序员确实能够无论这些道理,但若是要追求更高的封装性、复用性,可维护性,就必须向面向对象深刻。

  面向对象的核心是根据概念建模,好比客户,虽然传统三层架构在Model层中确实建立了一个Customer类,可是Model层在三层架构中属于辅助地位,是一个无关紧要的东西,若是把Customer类换成DataTable也同样可行。

  Model中的实体之因此用处不大,是由于违反了对象的特征,真正的对象是数据与操做的集合。有人把单纯的数据对象称为贫血模型,把具备数据和丰富操做的对象称为充血模型,意指只有属性的数据对象先天不足,养分不良,智商低,只会吃饭(数据),不会干活。

  为什么对象必定要把数据和操做放到一块儿,才能发挥威力?由于这些数据与数据上的操做老是息息相关,且同时变化。把数据和操做封装到一块儿,能够为操做提供惟一访问点,主要好处是对操做集中管理,消除代码冗余。当数据发生变化时,相关操做多半须要同时修改,因为代码没有冗余副本,且在对象内部完成修改,对外界甚至不产生影响,可维护性大大提高。

  把业务对象的数据和操做分离之后,第一个影响是业务逻辑散乱,难以管理。因为操做没有一个统一的位置,因此没有人知道这些操做究竟位于何处?可能在业务层,也可能在表现层,还有可能在存储过程里。哪怕严格按照三层架构职责编写代码,全部业务逻辑都在业务层中,但可能不少个类都使用了这个实体,究竟某个操做在哪一个类里?特别是在团队做战时,这个问题更加明显,若是他不能很容易找到他要的方法,那么他就会本身添加一个,从而致使冗余。第二个影响就是致使明显的代码冗余,而代码冗余是可维护性的天敌。每当数据发生变化或发现Bug,须要找到全部操做代码的副本进行修改,若是有遗漏就会埋下地雷。

  固然,CRUD简单操做不在以上讨论范围,上面主要指业务逻辑受数据的影响程度。

  能够看到,三层架构相比单层架构来讲,已经有至关进步,但它还有一些缺陷能够改进,若是把Model实体层和BLL业务逻辑层合并,就能够获得面向对象模型,在《企业应用架构模式》中称为领域模型。不过Eric Evans在《领域驱动设计》中以更具体的方式指导如何使用面向对象进行开发。

  应该采用充血模型(面向对象)、仍是贫血模型(面向过程)?要不要使用ORM,要不要使用DDD(领域驱动设计)?这些问题老是争论不休。不过个人建议是,若是你还准备在.Net界多混几年,不如提前进行,由于这是大势所趋,就好像单层架构最终被三层架构所取代。另外,领域驱动设计若是用得很差,充其量也就和三层架构差很少,因此你不须要有任何顾忌。

  本系列文章将采用Entity Framework和DDD分层架构演示应用程序框架的建设,因此本文暂不对DDD进行介绍。

  本文对分层架构的演化过程进行了简单介绍,为你选择适合本身的架构提供了一些参考,最后的结论是,不管你是否愿意,因为软件行业的发展,特别是微软技术的推进,你始终会走上面向对象之路,与其被动挨打,不如主动学习。

  有些朋友发现这个实战系列名不符实,全是废话,一句代码都没有,还有些朋友喜欢四处搜集源码,坐等干货。我想说的是,这个实战系列毕竟是介绍架构和框架的,若是你只拿到几行代码,没有真正搞懂如何为你的项目创建应用程序框架,代码没法造成一个体系结构,仍是一团乱麻,那又有什么用。另外,我所提供的代码也是四处搜集整理,没有什么特别,你若是须要源码,直接百度就会多如牛毛,但我但愿你能搞懂每一个细节, 这样更有帮助。

  .Net应用程序框架交流QQ群: 386092459,欢迎有兴趣的朋友加入讨论

相关文章
相关标签/搜索