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

简介:   在对NLayerApp实际项目进行讨论之前,让我们首先学习一下(或者应该说重温一下)分层/多层架构与应用系统设计原则。很多朋友会认为这些都是老掉牙的内容,只要是软件从业人员,都会对这些内容非常熟悉。

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

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

  Layers与Tiers

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

image

  需要注意的是,对于具有一定复杂度的应用程序而言,采用多层(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组件图所示:

image

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

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

  应用系统基本设计原则 - 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的解决方案组织结构会有相当的帮助。

目录
相关文章
|
16天前
|
设计模式 安全 Java
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
20 0
|
4天前
|
Kubernetes 安全 Java
构建高效微服务架构:从理论到实践
【4月更文挑战第9天】 在当今快速迭代与竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性及容错性,成为众多企业转型的首选。本文将深入探讨如何从零开始构建一个高效的微服务系统,覆盖从概念理解、设计原则、技术选型到部署维护的各个阶段。通过实际案例分析与最佳实践分享,旨在为后端工程师提供一套全面的微服务构建指南,帮助读者在面对复杂系统设计时能够做出明智的决策,并提升系统的可靠性与维护效率。
|
1天前
|
Linux 数据安全/隐私保护
Linux基础与服务器架构综合小实践
【4月更文挑战第9天】Linux基础与服务器架构综合小实践
12 6
|
12天前
|
消息中间件 安全 API
构建高效微服务架构:策略与实践
【4月更文挑战第1天】在数字化转型的浪潮中,微服务架构已成为企业追求敏捷、可扩展和灵活部署的重要技术手段。本文将深入探讨如何通过合理的设计原则和先进的技术栈,构建一个高效的微服务系统。我们将剖析微服务设计的核心要点,包括服务的划分、通信机制、数据一致性以及安全性问题,并结合案例分析,展示如何在现实世界中应用这些策略以提升系统的可靠性和性能。
|
13天前
|
设计模式 API 持续交付
构建高效微服务架构:从理论到实践
在当今快速迭代和部署的软件开发环境中,微服务架构已成为一种流行的设计模式,它允许开发团队以模块化的方式构建、维护和扩展应用程序。本文将深入探讨微服务的核心概念,包括其定义、优势、挑战以及如何在实际项目中实施。我们将通过一个实际案例来展示如何将传统的单体应用拆分成一系列独立、松耦合的服务,并通过容器化、服务发现、API网关和持续集成/持续部署(CI/CD)等技术手段来管理这些服务。
|
16天前
|
存储 监控 安全
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
15 0
|
16天前
|
存储 Java 应用服务中间件
【分布式技术专题】「架构实践于案例分析」盘点互联网应用服务中常用分布式事务(刚性事务和柔性事务)的原理和方案
【分布式技术专题】「架构实践于案例分析」盘点互联网应用服务中常用分布式事务(刚性事务和柔性事务)的原理和方案
40 0
|
6天前
|
API 数据库 开发者
构建高效可靠的微服务架构:后端开发的新范式
【4月更文挑战第8天】 随着现代软件开发的复杂性日益增加,传统的单体应用架构面临着可扩展性、维护性和敏捷性的挑战。为了解决这些问题,微服务架构应运而生,并迅速成为后端开发领域的一股清流。本文将深入探讨微服务架构的设计原则、实施策略及其带来的优势与挑战,为后端开发者提供一种全新视角,以实现更加灵活、高效和稳定的系统构建。
13 0
|
20天前
|
负载均衡 测试技术 持续交付
高效后端开发实践:构建可扩展的微服务架构
在当今快速发展的互联网时代,后端开发扮演着至关重要的角色。本文将重点探讨如何构建可扩展的微服务架构,以及在后端开发中提高效率的一些实践方法。通过合理的架构设计和技术选型,我们可以更好地应对日益复杂的业务需求,实现高效可靠的后端系统。
|
20天前
|
监控 持续交付 API
构建高效可扩展的微服务架构
在当今快速迭代和竞争激烈的软件市场中,构建一个高效、可扩展且易于维护的后端系统变得尤为重要。微服务架构作为一种流行的分布式系统设计方式,允许开发者将应用程序划分为一系列小型、自治的服务,每个服务负责执行特定的业务功能。本文将探讨如何利用现代技术栈搭建一个符合这些要求的微服务架构,并讨论其潜在的挑战与解决方案。我们将涵盖服务划分策略、容器化、服务发现、API网关、持续集成/持续部署(CI/CD)以及监控和日志管理等关键主题,以帮助读者构建出既可靠又灵活的后端系统。