一起谈.NET技术,Microsoft NLayerApp案例理论与实践 - 多层架构与应用系统设计原则

  在对NLayerApp实际项目进行讨论之前,让我们首先学习一下(或者应该说重温一下)分层/多层架构与应用系统设计原则。很多朋友会认为这些都是老掉牙的内容,只要是软件从业人员,都会对这些内容非常熟悉。然而,果真如此吗?我在这里整理这部分内容,一方面是为介绍NLayerApp打下基础,而另一方面,则是希望借此机会将这些理论性的东西做个归纳,也希望读者朋友能够认真阅读,毕竟温故知新嘛。

  需要说明的是,从本章节开始,大多数理论性的东西都源自Microsoft Spain团队针对NLayerApp所编写的《Architecture Guide Book》,事实上这本Guideline的英文版至今也还没有完成,我会从中抽出部分章节做些翻译和归纳,有兴趣的朋友请直接上microsoftnalyerapp.codeplex.com站点上下载英文版阅读。

  Layers与Tiers

  对Layers与Tiers这两个单词进行区分是非常重要的。从中文翻译看,两者都是层的意思,因此我们往往会将这两个概念弄混。Layer一词更多的是表示对系统组件或功能的逻辑区分,它并没有包含将组件分布到不同的区域、不同的服务器上的意思。而Tier则是表示系统组件和功能在服务器、网络环境以及远程位置的物理部署。尽管这两个概念同时使用者非常相近的一些术语,比如展示、服务、业务和数据等,但我们必须了解它们之间的差别。下面这幅图表明了多层(N-Layer)逻辑架构与三层(3-Tier)物理结构之间的差异:

  需要注意的是,对于具有一定复杂度的应用程序而言,采用多层(N-Layer)逻辑架构的实现方式是非常必要的,这会降低系统的复杂度,并在设计、开发、测试、部署及维护等各个环节为应用系统带来高可用性、高延展性等正面效应。然而,并非所有的应用程序必须以三层(3-Tier)/多层(N-Tier)物理结构进行部署,我们可以将多个逻辑层部署在同一台机器上,也可以根据需求,将这些逻辑层部署在网络中的不同机器上。

  逻辑分层(Layer)的设计

  在讨论DDD的分层之前,先让我们看看传统的分层方式。就像上文所述,我们应该根据项目的实际需求,将组件/功能模块合理地划分到逻辑层中。同一层中的组件,应该是高内聚的,并具有相同的抽象层次。层与层之间应该低耦合。对于以分层设计的应用程序而言,最关键的问题就是如何处理层与层之间的依赖关系。考察传统的多层架构应用,处于某层的组件,只能对同层或下层的其它组件进行访问,这样做可以有效地降低层与层之间的依赖关系。通常会有两种分层设计:严格分层与灵活分层

  1. 严格分层迫使组件只能访问同层的其它组件,或者只能访问直接下层的其它组件,于是,第N层的组件只能访问第N或N-1层的组件,而第N-1层的组件只能访问第N-1或N-2层的组件,以此类推
  2. 灵活分层允许组件访问同层的其它组件,以及所有下层的其它组件,于是,第N层的组件可以访问第N或N-1、N-2…层的组件

  使用灵活分层的架构可以提高系统性能,因为这样的结构无需引入过多的请求/反馈的传递操作,因为一个层可以直接访问位于其下的任何层;而严格分层却降低了层与层之间的耦合性,对低层的修改不会对整个系统造成广泛的影响。根据Eric Evans在其《领域驱动设计-软件核心复杂性应对之道》一书中的描述,DDD的分层选用的是灵活分层模式。

  让我们再把讨论的粒度细化,来看看层中的组件与组件之间的关系。事实上,在很多复杂的应用中,位于同一层的组件与组件虽然具有相同的抽象层次,它们也不一定是高内聚的。因此,我们可以引入模块(Module)的概念,将同一层中高内聚的组件放在同一个模块中,于是,每个层又会由一个或多个高内聚的子系统(模块)所组成,如下UML组件图所示:

  使用分层架构,有如下几点好处:

  • 提高系统的可测试性
  • 对解决方案的维护和管理变得更加简单。层内高内聚、层间低耦合的结构,使得系统实现与分层组织方式变得非常灵活方便
  • 其它外部应用程序能够非常方便地使用不同的层所提供的特定功能
  • 当系统以层的方式进行组织时,分布式开发也变得非常简单易行
  • 在某些情况下,分层系统的物理部署方式能够给系统带来延展性,当然,应该有效地评估具体的实践方式,因为这种做法有可能损伤系统性能

  应用系统基本设计原则 - SOLID

  应用系统的设计应该遵循一些基本的设计原则,这能帮助你有效地创建一个低成本、高可用、高可扩展的应用程序。在这里,我们引入一个SOLID设计原则,SOLID由如下几点构成:

  • Single Responsibility Principle(单一职责原则)
  • Open Close Principle(开-闭原则)
  • Liskov Substitution Principle(里氏替换原则)
  • Interface Segregation Principle(接口分离原则)
  • Dependency Inversion Principle(依赖反转原则)

  下面简要介绍一下这几个原则。

  • 单一职责原则:每个类应该只有一个独一无二的职责,或者说每个类只能有一个主要功能,由此派生出一个结论:每个类应该尽可能少地依赖于其它类
  • 开-闭原则:每个类,应该对扩展进行开放,而对修改进行封闭,也就是支持扩展,而不是支持修改:类中的方法可以通过继承关系进行扩展,而不会改变类本身的代码
  • 里氏替换原则:子类可以被基类型(基类或者接口)替换。应用程序依赖抽象运行,其行为不会因为具体实现的改变而更改,应用程序应该依赖于抽象(基类或者接口),而不是具体实现。接下来将要讨论到的依赖注入(Dependency Injection)就与这条原则有关
  • 接口分离原则:接口的职责也应该是单一的,接口中应该包含哪些方法,需要进行严格的评估,如果其中某些方法的职责与接口的本身定义不相符合,则应该将其分离到其它接口中。类需要根据其调用者所需要的不同接口类型,来暴露不同的接口
  • 依赖反转原则:抽象不能依赖于具体,而具体则应该依赖于抽象。类之间的直接依赖应该用抽象来取代,这样做的一个优点是,我们可以实现自上而下的设计方式:在下层的具体实现还没有确定的情况下,只要能够在抽象层面将接口确定,就能够完成上层的设计与开发,这同样给可测试性带来便捷

  除了以上所述的SOLID原则之外,还有以下几个关键的设计原则可供参考:

  • 组件设计应该是高内聚的:相信大家都很熟悉这点了,就不多说了。例如:不要将数据访问逻辑写进领域模型的业务逻辑中,这与上述单一职责原则是密切相关的
  • 将Cross-Cutting的代码从特定于应用程序的逻辑中分离开来:Cross-Cutting的代码是一些面向横面的代码,比如安全、操作管理、日志以及测量/计量系统等。将这些代码与应用系统业务逻辑混在一起会增加系统的复杂性,给将来的扩展和维护造成很大的麻烦。这与面向方面编程(Aspect-Oriented Programming,AOP)有关
  • 关注点分离(Separation of Concerns,SoC):将应用系统分成多个子部分(子系统),各个部分之间的功能尽量不要重复,其目的就是为了减少交互点,以实现高内聚和低耦合
  • Don’t Repeat Yourself(DRY):一个特定的功能只能在某个特定的组件中实现一次,同样的功能不要在多个组件中重复多次
  • 避免YAGNI(You Ain’t Gonna Need It)效应:只考虑和设计必须的功能,避免过度设计

  好了,本讲就介绍到这里,估计对大多数接触过架构的软件朋友来说,本讲的部分内容都是废话。下一讲开始,我会花部分笔墨在DDD/DDDD的分层介绍上,虽然有可能还是废话,但这对我们理解NLayerApp的解决方案组织结构会有相当的帮助。

时间: 2024-09-20 01:03:57

一起谈.NET技术,Microsoft NLayerApp案例理论与实践 - 多层架构与应用系统设计原则的相关文章

Microsoft NLa“.NET研究”yerApp案例理论与实践 - 多层架构与应用系统设计原则

在对NLayerApp实际项目进行讨论之前,让我们首先学习一下(或者应该说重温一下)分层/多层架构与应用系统设计原则.很多朋友会认为这些都是老掉牙的内容,只要是软件从业人员,都会对这些内容非常熟悉.然而,果真如此吗?我在这里整理这部分内容,一方面是为介绍NLayerApp打下基础,而另一方面,则是希望借此机会将这些理论性的东西做个归纳,也希望读者朋友能够认真阅读,毕竟温故知新嘛. 需要说明的是,从本章节开始,大多数理论性的东西都源自Microsoft Spain团队针对NLayerApp所编写的

一起谈.NET技术,Microsoft NLayerApp案例理论与实践 - 项目简介与环境搭建

项目简介 Microsoft – Spain团队有一个很不错的面向领域多层分布式项目案例:Microsoft – Domain Oriented N-Layered .NET 4.0 App Sample(在本系列文章中,我使用NLayerApp作为该项目的名称进行介绍),在codeplex上的地址是:http://microsoftnlayerapp.codeplex.com/. 它是学习领域驱动设计(DDD)的一个非常不错的案例项目.该项目采用的是经典的DDD架构,而不是CQRS架构,但我觉

Microsoft NLayerApp案例理论与实践 - 项目简“.NET研究”介与环境搭建

项目简介 Microsoft – Spain团队有一个很不错的面向领域多层分布式项目案例:Microsoft – Domain Oriented N-Layered .NET 4.0 App Sample(在本系列文章中,我使用NLayerApp作为该项目的名称进行介绍),在codeplex上的地址是:http://microsoftnlayerapp.codeplex.com/. 它是学习领域驱动设计(DDD)的一个非常不错的案例项目.该项目采用的是经典的DDD架构,而不是CQRS架构,但我觉

Microsoft NLayerApp“.NET研究”案例理论与实践 - 项目简介与环境搭建

项目简介 Microsoft – Spain团队有一个很不错的面向领域多层分布式项目案例:Microsoft – Domain Oriented N-Layered .NET 4.0 App Sample(在本系列文章中,我使用NLayerApp作为该项目的名称进行介绍),在codeplex上的地址是:http://microsoftnlayerapp.codeplex.com/. 它是学习领域驱动设计(DDD)的一个非常不错的案例项目.该项目采用的是经典的DDD架构,而不是CQRS架构,但我觉

一起谈.NET技术,我眼中的Visual Studio 2010架构工具

影响架构质量的是构建体系架构的思想.原则.实践与架构师的经验,绝不是工具.即使是最优秀的架构工具,也不可能像倚天宝剑一般--倚天一出,谁与争锋--似乎谁握住了这把利刃,就能够成为武林盟主.架构工具可以改善架构师的工作,却不能替换架构的过程.软件开发过程中,最重要的依旧是人. 我在尝鲜Visual Studio 2010架构工具[i]时,偶然看到一篇文章,用夸张的语言吹捧VS 2010架构工具,认为它是架构师最怕程序员知道的新工具.这让我有感而发,我想起数十年前甚嚣尘上的一个理论,那就是CASE工

一起谈.NET技术,从原理来看Silverlight 4的架构

简介 在前文<<初识Silverlight 4及其架构>>谈到要从多个方面来了解:Silverlight的原理,处理周期,部署,安全性,伸缩性,分布式计算能力,容错能力,等等等等.这篇从原理的角度来看Silverlight 4架构相关的一些事情. 浏览器的插件 前文已经介绍过,整个Silverlight平台中包括一个安装器.这个安装器负责将浏览器插件安装上,并在客户浏览器那里搭建起运行Silverlight程序的基础环境.初次浏览Silverlight内容的客户必须先安装一个浏览器

Java理论和实践: 安全构造技术

Java 语言提供了灵活的.看上去很简单的线程功能,使得您很容易在您的应用程序中使用多线程.然而,Java应用程序中的并发编程比看上去要复杂:在 Java 程序中,有一些微妙(也许并不是那么微妙)方式会造成数据争用(data race)以及并发问题.在这篇 Java 理论和实践中,Brian探讨了一个常见的线程方面的危险:在构造过程中,允许 this 引用逃脱(escape).这个看上去没有什么危害的做法可以在 Java 程序中造成无法可预料和不期望的结果. 测试和调试多线程程序是极其困难的,因

《OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》——6.4节点法向量和面法向量

6.4 点法向量和面法向量 OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例 本章前面几节的案例都是基于球面开发的,球面属于连续.平滑的曲面,因此面上的每个顶点都有确定的法向量.但现实世界中的物体表面并不都是连续.平滑的,此时对于面上的某些点的法向量计算就不那么直观了,图6-18说明了这个问题. 从图6-18中可以看出,顶点A位于长方体左.上.前3个面的交界处,此处是不光滑的.这种情况下顶点A的法向量有两种处理策略,具体如下所列. 在顶点A的位置放置3个不同的顶点,每个顶点看作是仅

《创业家》牛文文:少谈点模式多谈点技术

"模式"如同当年的"主义",流行于各种创业大赛.创业励志节目.论坛的"街头"式秀场 文/创业家 牛文文 "美国某某公司你知道吧?就是刚被戴尔.惠普.思科十几亿美元抢购的那家.我们的模式和它的一样,现在还没赢利,可将来起码有十几亿人民币的市值." "我开了小煤矿,但煤运不出去,上商学院之后受到启发,想搞模式创新,具体讲就是想在铁路边上搞个煤炭物流开发区,建一个大的物流和信息流平台,把分散的煤炭集中在我这个园区,这样和铁