代码改变世界

NET 应用架构指导 V2 学习笔记(八) 分层应用指导

2010-05-28 07:24  Virus-BeautyCode  阅读(2567)  评论(0编辑  收藏  举报

  本章将讨论将逻辑组件分组之后分布在不同的层,这样的一种应用。层集中关注单个逻辑和功能组件,不考虑组件的物理存放位置。逻辑层可以放在不同的物理层,也可以放在同一个物理层。本章将会交给你如何将你的应用分解为不同的逻辑层,如果选择合适的功能布局,应用如何支持多种客户端类型。

  分清楚逻辑层和物理层的区别是非常重要的,逻辑层描述的是功能逻辑和组件的分组,物理层描述的是功能和组件在不同机器上的部署分布。尽管每个都包括相同名字的层:表现层、业务层、服务层、数据访问层,但是要记住只有物理层代表物理的分离。在同一个物理层部署多个逻辑层是很常见的。

  逻辑层的设计

  不管你设计什么类型的应用,是否有用户界面,或者只是一个暴露服务(不要和应用的服务层混为一谈)的服务性应用,你都可以将应用分为不同的逻辑组。这些逻辑组就叫做层。逻辑层帮助区分组件之间的不同类型的任务,使得设计一个可重用的组件变得更加容易。

  表现层,业务逻辑层,数据访问层

  下图显示了一个简化的,这些逻辑层的高层表现,以及它们之间的关系。

  

 

  这些逻辑层可以分布在不同的物理层,也可以分布在一个物理层。如果有分开部署的需要,在设计的时候就要考虑这些问题。

  在上图中显示了常用的三层:

  •   表现层。是一些用户接口,和业务逻辑层进行通信。
  •   业务逻辑层。是系统的核心,包装了全部的业务逻辑。
  •   数据访问层。主要是对数据源的操作,对上屏蔽了数据源操作的细节。数据库源可能是数据库,也可能是文件,也可能是其他的系统提供的服务。

  服务和分层

  从高层来看,以服务为基础的解决方案要看成是有很多服务组成,例如彼此之间通过消息来通行。概念上来讲,服务也是方案中的一个组件。但是,在内部,每个服务又是由多个组件组成的。

  服务层

  如果一个应用必须为其他应用提供服务,或者是支持客户端直接实现功能,常用的方法就是使用一个服务层暴露应用的业务功能。服务层是客户端访问应用的另外一种形式。

  

  在上面的方案中,用户可以通过表现层访问应用,直接和业务层组建进行通信。同时,外部客户端和其他系统也可以通过服务层和系统进行通信。这样就允许应用更好的支持多种客户端类型。

 

  在某些情况,表现层也会通过服务层和业务逻辑层进行通信。当然,这也不是绝对的。如果应用的表现层和业务逻辑层物理部署在同一个物理层,他们就可以直接通信。

  分层架构的设计步骤:

  当开始设计应用的时候,你首先集中在高层的抽象级别上,通过将功能组分到不同的层开始。接下来要为不同的层定义通信的公共接口,这需要依赖于你正在设计的应用类型。一旦你定义了逻辑层和接口,你一定要决定应用如何部署。最后给层之间的交互选择通信协议。尽管你的结构和接口会演化多次,尤其是你使用敏捷开发,这些步骤保证你在过程的开始考虑了重要的方面。典型的步骤包括:

  1.   选择分层策略
  2.   决定你需要的层
  3.   定义如何分布层和组件
  4.   确定你是否需要折叠层
  5.   确定层之间的交互规则
  6.   确定那些需要跨层的关注点
  7.   定义层之间的交互接口
  8.   选择部署策略
  9.   选择通信协议

  1 选择你的分层策略

  分层代表将应用的逻辑按照角色和功能分为不同的组件。使用分层的方法可以提高应用的可维护性,在性能需要提高的时候很容易扩展。分组可以有很多的方式。但是,将应用分为太少或者太多的层会增加不必要的复杂性,会降低整体的性能、可维护性、灵活性。决定合适的分层粒度是分层策略的关键的第一步。

  你还需要考虑是单纯的逻辑分层,还是有潜在的物理分层存在。跨层会影响本地的性能,尤其是中间有物理层的跨越。但是,增加了应用整体的伸缩性和灵活性。另外,分层利于性能优化,可以优化单个层,而不影响相邻的层。

  在分层的情况下,部署在同一物理层上的逻辑层中间的交互和操作是在同一个进程中的,允许你使用高效的通信方式,例如:通过组建接口直接调用方法。但是,为了提高可维护性,确保将来的灵活性,你要小心维护封装和层之间的松散耦合。

  逻辑层部署在不同的物理层,相邻逻辑层之间的通信将会发生在网络环境,你要确保你的设计选择了合适的通信方式,考虑到了网络延迟和维护层之间的松散耦合。

  考虑你的应用是部署在同一个物理层,还是分离的物理层,在分层策略中也是很重要的。为了保持灵活性,通常要保持层之间的交互是松散耦合的。既保持了部署在同一物理层的时候的高性能,又在需要的时候允许你部署在不同的物理层。

  调整分层方法会增加复杂度,可能会增加预先估计的开发时间,但是如果实现的正确,将会很大的提高应用的可维护性、可扩展性、和灵活性。你一定要权衡可重用性和逻辑层之间的松散耦合,相对于带来的复杂性和性能的影响之间的利弊。很小心的考虑如何分层,层之间如何交互,确保在性能和灵活性之间有一个好的平衡。通常来说,通过分层设计,如果可以获得灵活性和可维护性,要比不分层带来的性能提升,更加重要。

  2 决定你需要的层

  分层有很多的方法。最常用的办法是将应用分为表现层、服务层、业务逻辑层、数据访问层。一些应用可能会引入报表、管理、基础架构层。

  对于增加额外的层要特别小心,如果他们对于增加可维护性、扩展性、灵活性没有帮助的话,就不要增加它们。例如:如果你的应用不需要暴露服务,单独的服务层可能就没有必要,你只需要表现层、逻辑层、数据访问层。

  3 如何分布逻辑层和组件

  你应在需要将层和组件分开部署的时候,才进行分布式部署。实现分布部署的原因通常是安全、物理环境限制、共享逻辑层、和伸缩性。

  •   在web应用中,如果你的表现组件以同步的方式访问你的业务组件,可以考虑将业务逻辑层和表现层部署在同一个物理层,以最大化性能,减少操作管理,除非安全需要在他们之间存在一个可信任的边界。
  •   在富客户端应用中,UI的处理发生在桌面应用中,出于安全原因,你需要将业务逻辑组件部署在一个单独的物理层。
  •   将业务实体和使用它们的代码部署在同一个物理层。意味着会将实体部署在多个地方。
  •   考虑将异步实体组件、工作流组件、服务部署在独立的物理层,增加性能和伸缩性。

  4 考虑你是否需要折叠层(Collapse Layers)

  在某些情况,可能需要松散的层。例如:一个应用的业务规则非常有限,或者是规则主要用来验证数据,可能在一层实现了业务逻辑和表现逻辑。一个从webservice获取数据来显示的应用,可能直接将webservice的引用写在表现层,直接消费webservice的数据。在这种情况,你的逻辑包含了数据访问和表现层。

  上面的情况还是少数的。通常的做法是分离功能到不同的层,由一个单独的层作为服务的代理,提供封装之后的数据,而不是提供一大丢功能。分离功能,在后面你可以很容易的扩展它,而不影响其他层。

  5 定义层之间的交互

  指定交互规则的主要原因是减少依赖和消除循环依赖。例如:如果两层相互依赖于对方,就是一个循环引用。可以参考下面的规则:

  Top-Down interaction。高层可以和低层进行交互,但是低层不能访问在它之上的层。这条规则可以帮助你避免循环依赖。你可以通过高层订阅低层的事件来通知高层,低层数据的改变,代替依赖。

  限制交互。每一层只能和自己相邻的低层进行交互,每一层只知道自己的下一层。好处就是,对接口的修改只会影响上面的一层。

  交互松散。高层可以绕开直接和低层进行交互。可以提高性能,但是会增加依赖。换句话说,修改低层的接口会影响到更多的高层。

  6 确定跨层的关注点

  在你定义的层之后,一定要确定一下跨层需要关注的地方。包括:日志、缓存、数据验证、用户验证、异常管理。认识这些很重要,为它们设置单独的组件进行管理。提高复用性和维护性。  

  避免将跨层关注的代码和层功能的代码混合在一起,在逻辑层中需要跨层关注点的时候,只是调用他们的代码就可以了。由于这些功能一定是跨层的,因此需要在每一层部署跨层组件。

  有很多方法可以处理跨层关注,微软的模式实践小组的类库AOP可以作为参考。

  7 定义层之间的接口

  在定义层接口的时候可以参考下面的方法:

  •   抽象接口。
  •   通用的设计类型
  •   依赖反转
  •   消息为基础。

  8 选择部署策略

  

  9 选择通信协议

  

未完待续。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

P62