成为程序员时,我学到了几种设计模式:单例模式,存储库,工厂,构建者,装饰者等。设计模式为我们提供了一个经过验证的解决方案,以解决现有的和重复出现的问题。我没有学到的是,类似的机制存在于更高层次上:软件架构模式。这些是用于整个应用程序或应用程序布局的模式。它们都有优点和缺点。它们都解决了具体问题。下面我们一一分析:
分层模式
分层模式可能是最着名的软件体系结构模式之一。许多开发人员在不知道名称的情况下使用它。我们的想法是将您的代码拆分为“层”,其中每个层都有一定的责任,并为更高层提供服务。
没有预定义数量的图层,但这些图层是您经常看到的图层:
Presentation(展示或UI层)
Application(应用层)
Business(业务或管理层)
Persistence(持久性或数据访问层)
Database(数据库层)
这个想法是,用户通过执行一些操作(例如点击一个按钮)来启动表示层中的一段代码。表示层然后调用底层,即应用层。然后我们进入业务层,最后,持久层将所有内容存储在数据库中。所以更高层依赖于并且调用较低层。
根据应用程序的复杂程度,您将看到相应的变体。一些应用程序可能会忽略应用程序层,而其他应用程序则会添加一个缓存层。甚至可以将两个层合并为一个。例如,ActiveRecord模式结合了业务层和持久层。
每层责任
如前所述,每一层都有自己的责任。表示层包含应用程序的图形设计,以及处理用户交互的任何代码。您不应该在此图层中添加不特定于用户界面的逻辑。
业务层是您将模型和逻辑特定于您要解决的业务问题的地方。
应用程序层位于表示层和业务层之间。一方面,它提供了一种抽象,以便表示层不需要知道业务层。理论上,您可以更改表示层的技术堆栈,而无需更改应用程序中的任何其他内容(例如,从WinForms更改为WPF)。另一方面,应用程序层提供了放置不适合业务或表示层的某些协调逻辑的位置。
最后,持久层包含访问数据库层的代码。数据库层是底层数据库技术(例如SQL Server,MongoDB)。持久层是操纵数据库的代码集合:SQL语句,连接细节等。
优点
缺点
适合场景
微内核
当您的应用程序具有一组核心职责和一组可互换部分时,微内核模式或插件模式非常有用。微内核将提供应用程序的入口点和一般流程,而不知道不同的插件正在做什么。
一个例子是任务调度器。微内核可以包含用于调度和触发任务的所有逻辑,而插件包含特定任务。只要插件遵循预定义的API,微内核就可以触发它们,而无需了解实现细节。
另一个例子是工作流程。工作流的实现包含诸如不同步骤的顺序,评估步骤结果,决定下一步是什么等概念。步骤的具体实现对于工作流的核心代码来说并不重要。
优点
缺点
适合场景
CQRS
CQRS是命令和查询责任分离(Command and Query Responsibility Segregation)的首字母缩略词。这种模式的核心概念是应用程序具有必须完全分离的读取操作和写入操作。这也意味着用于写操作(命令)的模型将与读模型(查询)不同。此外,数据将存储在不同的位置。在关系数据库中,这意味着将有用于命令模型的表格和用于读取模型的表格。一些实现甚至将不同模型存储在完全不同的数据库中,例如命令模型的SQL Server和读取模型的MongoDB。
这种模式通常与事件采购相结合,我们将在下面介绍。
它是如何工作的?当用户执行操作时,应用程序会向命令服务发送命令。命令服务从命令数据库中检索它需要的所有数据,进行必要的操作并将其存储回数据库中。然后它通知读取服务,以便可以更新读取模型。这个流程如下所示。
当应用程序需要向用户显示数据时,它可以通过调用读取服务来检索读取的模型,如下所示。
优点
缺点
适合场景
事件采购
正如我上面提到的,CQRS通常与事件采购密切相关。这是一种模式,它不会将模型的当前状态存储在数据库中,而是存储模型中发生的事件。因此,当客户名称发生变化时,您不会将该值存储在“名称”列中。你将存储一个带有新值的“NameChanged”事件(也可能是旧的)。
当您需要检索模型时,您将检索其存储的所有事件并在新对象上重新应用它们。我们称之为补水对象。
事件采购的现实类比是会计。当您添加费用时,您不会更改总额的值。在会计中,会添加一条新行,并执行操作。如果发生错误,只需添加一个新行。为了让您的生活更轻松,您可以在每次添加线路时计算总计。这个总数可以看作是读取模型。下面的例子应该更清楚。
您可以看到我们在添加发票201805时发生了错误。我们添加了两条新线,而不是更改线:首先,一条线用于取消错误线,然后是一条新的正确线。这就是事件采购的工作方式。你永远不会删除事件,因为它们在过去不可否认。为了纠正情况,我们添加了新事件。
另外,请注意我们如何拥有总值的单元格。这只是上面单元格中所有值的总和。在Excel中,它会自动更新,因此您可以说它与其他单元格同步。它是阅读模型,为用户提供了一个简单的视图。
事件采购通常与CQRS结合使用,因为重新水化对象可能会对性能产生影响,特别是当实例有很多事件时。快速阅读模式可以显着提高应用程序的响应时间。
优点
缺点
适合场景
微服务
当您将应用程序编写为一组微型服务时,实际上是在编写可以一起工作的多个应用程序。每个微服务都有自己独特的责任,团队可以独立于其他微服务开发它们。他们之间唯一的依赖是沟通。由于微服务彼此通信,因此您必须确保它们之间发送的消息保持向后兼容。这需要一些协调,特别是当不同的团队负责不同的微服务时。
一张图可以解释。
在上图中,应用程序调用一个中央API,将呼叫转发到正确的微服务。在本例中,用户配置文件,库存,订单和付款有单独的服务。你可以想象这是一个应用程序,用户可以订购一些东西。单独的微服务也可以互相调用。例如,支付服务可以在支付成功时通知订单服务。订单服务可以调用库存服务来调整库存。
目前还没有明确规定微服务的规模。在前面的示例中,用户配置文件服务可能负责数据,如用户的用户名和密码,还包括家庭地址,头像图片,收藏夹等。还可以将所有这些责任分成更小的一个选项微服务。
优点
缺点
适合: