当我成为程序员的时候,我学习了几种设计模式:单例模式、存储库、工厂、构建器、装饰器等,设计模式为我们提供了经过验证的解决方案一个现有的和反复出现的问题。我没有学到的是更高层次上存在类似的机制:软件架构模式。这些是用于整个应用程序或应用程序布局的模式。它们都有优点和缺点。他们都解决特定的问题。让我们一一分析:分层模式分层模式可能是最著名的软件架构模式之一。许多开发人员在不知道名称的情况下使用它。这个想法是将您的代码分成“层”,其中每一层都有一定的职责并为更高层提供服务。没有预定义的层数,但这些是您最常看到的层数:Presentation(表示层或UI层)Application(应用层)Business(业务层或管理层)Persistence(持久层或数据访问层)Database(数据库层))这个想法是用户通过执行某些操作(例如单击按钮)来启动表示层中的一段代码。然后表示层调用底层,即应用层。然后我们到业务层,***,持久层把所有的东西都存到数据库里。所以高层依赖并调用底层。根据您的应用程序的复杂性,您会看到相应的变体。一些应用程序可能会省略应用程序层,而另一些应用程序会添加一个缓存层。甚至可以将两层合并为一层。例如,ActiveRecord模式结合了业务层和持久层。每一层的职责如前所述,每一层都有自己的职责。表示层包含应用程序的图形设计,以及处理用户交互的任何代码。您不应在此层中添加不特定于UI的逻辑。业务层是您针对要解决的业务问题创建模型和逻辑的地方。应用层位于表示层和业务层之间。一方面,它提供了一种抽象,使表示层不需要了解业务层。理论上,您可以在不更改应用程序中的任何其他内容的情况下更改表示层的技术堆栈(例如,从WinForms更改为WPF)。另一方面,应用层提供了放置一些不适用于业务或表示层的协调逻辑的地方。***,持久层包含访问数据库层的代码。数据库层是底层的数据库技术(如SQLServer、MongoDB)。持久层是操作数据库的代码集合:SQL语句、连接细节等。优点大多数开发人员都熟悉这种模式。它提供了一种简单的方法来编写组织良好、可测试的应用程序。缺点它往往会导致应用程序单体化,以后很难分离。开发人员经常发现自己编写了大量代码来遍历不同的层,而没有在这些层中添加任何值。如果您所做的只是编写一个简单的CRUD应用程序,那么分层模式对您来说可能有点过头了。适用场景标准业务线应用程序,而不仅仅是CRUD(写入-读取-修改-删除)操作微内核当您的应用程序具有一组核心职责和一组可互换部分时,微内核模式或插件模式很有用。微内核将在不知道不同插件在做什么的情况下提供应用程序的入口点和一般流程。一个例子是任务调度程序。微内核可以包含调度和触发任务的所有逻辑,而插件包含特定任务。只要插件遵循预定义的API,微内核就可以在不知道实现细节的情况下触发它们。另一个例子是工作流。工作流的实现包含不同步骤的顺序、评估步骤结果、决定下一步是什么等概念。步骤的具体实现对于工作流的核心代码并不重要。优势这种模式提供了极大的灵活性和可扩展性。一些实现允许在应用程序运行时添加插件。微内核和插件可以由不同的团队开发。缺点决定什么是微内核是什么不是微内核是很困难的。预定义的API可能不适合未来的插件。适用场景从不同来源获取数据、转换数据并将其写入不同目的地的应用程序工作流应用程序任务和作业调度应用程序CQRSCQRS是命令和查询责任分离缩写的首字母缩写词。该模式的核心概念是应用程序具有必须完全分离的读取和写入操作。这也意味着用于写操作(命令)的模型将不同于读模型(查询)。此外,数据将存储在不同的位置。在关系数据库中,这意味着将有用于命令模型的表和用于读取模型的表。一些实现甚至将不同的模型存储在完全不同的数据库中,例如命令模型使用SQLServer,读取模型使用MongoDB。这种模式通常与我们在下面描述的事件溯源相结合。它是如何工作的?当用户执行操作时,应用程序将命令发送到命令服务。命令服务从命令数据库中检索它需要的所有数据,执行必要的操作并将其存储回数据库中。然后它会通知读取服务,以便可以更新读取模型。流程如下。当应用程序需要向用户显示数据时,可以通过调用读取服务来检索读取模型,如下所示。优点命令模型可以专注于业务逻辑和验证,而读取模型可以针对特定场景进行裁剪。您可以避免复杂的查询(例如,SQL中的连接),从而提高读取效率。缺点保持命令和读取模型同步会变得很复杂。适合场景需要大量读取的应用程序具有复杂域的应用程序的事件溯源正如我上面提到的,CQRS通常与事件溯源密切相关。这种模式不将模型的当前状态存储在数据库中,而是存储模型中发生的事件。因此,当客户的姓名更改时,您不会将该值存储在“姓名”列中。您将存储一个具有新值(也可能是旧值)的“NameChanged”事件。当您需要检索模型时,您检索它存储的所有事件并将它们重新应用于新对象。我们称它们为水合对象。事件溯源的一个现实类比是会计。添加费用时,不会更改总计的值。在会计中,添加了一个新行,并执行了操作。如果发生错误,只需添加一个新行。为了让您的生活更轻松,您可以在每次添加一行时计算总计。这个总数可以看作是读取模型。下面的例子应该更清楚。您可以看到我们在添加发票201805时出错。我们没有更改行,而是添加了两行:首先是取消错误行的行,然后是新的正确行。这就是事件溯源的工作原理。您永远不会删除事件,因为它们在过去是不可否认的。为了纠正这种情况,我们添加了新事件。另外,请注意我们如何为总值设置单元格。这只是上面单元格中所有值的总和。在Excel中,它会自动更新,因此您可以说它与其他单元格同步。它是阅读模型,为用户提供了一个简单的视图。事件溯源通常与CQRS结合使用,因为重新水化对象会对性能产生影响,尤其是当实例具有许多事件时。快速阅读模式可以显着提高应用程序的响应时间。优点这种软件架构模式提供开箱即用的审计日志记录。每个事件代表在某个时间点对数据的操作。缺点这需要一些纪律,因为您不能通过在数据库中进行简单的编辑来修复坏数据。改变事件结构不是一件容易的事。例如,如果您添加一个属性,数据库仍然包含没有该数据的事件。您的代码需要慷慨地处理这些缺失的数据。适用场景需要向外部系统发布事件会用CQRS构建需要更改数据审计日志微服务当你把一个应用程序写成一组微服务时,你实际上是在写多个可以协同工作的应用程序。每个微服务都有自己独特的职责,团队可以独立于其他微服务开发它们。他们之间唯一的依赖就是沟通。由于微服务相互通信,您必须确保它们之间发送的消息保持向后兼容。这需要一些协调,尤其是当不同的团队负责不同的微服务时。一张图可以说明。在上图中,应用程序调用一个中央API,它将调用转发到正确的微服务。在此示例中,用户配置文件、库存、订单和付款有单独的服务。您可以将其想象成一个用户可以在其中订购东西的应用程序。各个微服务也可以相互调用。例如,支付服务可以在支付成功时通知订单服务。订单服务可以调用库存服务来调整库存。微服务的规模还没有明确规定。在前面的示例中,用户配置文件服务可能负责用户的用户名和密码等数据,还有家庭住址、头像图片、收藏夹等。还有一个选项可以将所有这些职责拆分为更小的微服务。优点您可以单独编写、维护和部署每个微服务。微服务架构应该更容易扩展,因为您只能扩展需要扩展的微服务。无需扩展应用程序中不常用的部分。重写应用程序的某些部分更容易,因为它们更小并且与其他部分的耦合度更低。缺点与您的预期相反,开始编写结构良好的宏并在以后将它们分解为微服务实际上更容易。随着微服务的出现,许多额外的问题开始发挥作用:通信、协调、向后兼容性、日志记录等等。错过编写结构良好的宏所需技能的团队可能难以编写一组好的微服务。单个用户操作可以通过多个微服务。失败的点比较多,当出现问题时,可能需要更多的时间来定位问题。适用于:应用程序的某些部分将被密集使用,需要扩展为多个其他应用程序提供功能的服务如果组合为一个整体,应用程序可能会变得非常复杂应用程序可以定义定义明确的有界上下文总结以上内容专栏识别软件开发中的几种软件架构模式,以及它们的优缺点。但是还有比这里列出的更多的模式。组合其中几种模式也很常见。它们并不总是相互排斥的。例如,您可以有多个微服务,其中一些使用分层模式,而另一些使用CQRS和事件源。要记住的重要一点是,没有一种解决方案适用于所有地方。当我们问应用程序使用哪种模式的问题时,旧的答案仍然适用:“这取决于您的项目需要!”。您应该权衡解决方案的利弊并做出明智的决定。
