架构模块化服务应用程序


11

我正在考虑设计一种本质上是模块化的新解决方案,并希望创建一个支持该设计的结构,以便将来轻松进行扩展,明确分离关注点,按模块进行许可等。在网络上发现的关于模块化或组合应用程序的是以UI为中心的,专注于Silverlight,WPF等。就我而言,我正在开发WCF服务应用程序,该程序将由从事各种UI项目的其他开发人员使用。

背景

我的项目的目标是创建一个集中的业务/域逻辑源,以支持我们的多个当前重复流程,规则等的业务应用程序。虽然并非可以实现模块化的所有好处,但我想抓住建立一个可以利用我们可以利用的那些部分的框架的机会。

我通过查看服务应用程序公开的API来开始设计。显然,可以按照我所考虑的模块化路线来隔离服务。例如,我将拥有FinanceService,InventoryService,PersonnelService等服务,这些服务将我的服务操作分组以在API中提供高内聚性,同时保持较低的耦合度,因此客户端仅需使用与他们的应用程序相关的服务。

对于我来说,我可以为每个服务分别拥有单独的模块,例如MyApp.Finance,MyApp.Inventory,My.Personnel等。跨领域关注点和共享类型将在MyApp共享程序集中。从这里我有点束缚。

(哦,我应该提一下,我将使用IoC容器进行依赖注入来保持应用程序的松散耦合。我不会提及哪个容器,因为我不想打开Pandora的盒子!)

在MyApp.ServiceHost中,我将创建一个与每个模块相对应的服务宿主文件(.svc),例如FinanceService.svc。服务主机需要服务的名称,该名称与配置文件中的信息相对应,该配置文件包含定义服务合同的接口。然后,将IoC配置用于映射要使用的接口的具体实现。

1.服务层应该实现API并委托给模块,还是应该使模块自包含(因为它们包含与该模块相关的所有内容,包括服务实现)?

解决该问题的一种方法是拥有一个MyApp.Services“模块”,其中包含服务合同的实现。每个服务类都简单地委派给包含该操作的域逻辑的相应模块中的另一个类。例如,MyApp.Services中的FinanceService WCF类委托给另一个接口,该接口在Finance模块中实现以执行操作。例如,这将使我能够维护精简的服务外观并将实现“插入”到服务实现中,并且无需使模块担心WCF。

另一方面,也许每个模块都是独立的,因为它具有接口和实现。服务主机引用模块中的服务合同接口,并且IoC也配置为使用模块中的适当实现。这意味着除了添加新的.svc文件和IoC配置信息外,无需更改服务层即可添加新模块。

我正在考虑如果从标准WCF切换到RESTful服务接口,或者转而使用RIA服务之类的影响。如果每个模块都包含服务合同的实现,那么如果我更改服务技术或方法,则必须在每个模块中进行更改。但是,如果外观是其自己的模块,那么我只需要换出该部分即可进行更改。然后,这些模块将必须实现一组可能在共享程序集中定义的合同(接口)的不同集合???

2.处理模块之间的资源共享和/或模块之间的依赖关系的最佳方法是什么?

以接收操作为例。乍一看,这很有意义,因为进货是库存功能,因此进入库存模块。但是,在财务方面,我们还需要生成收据并授权付款。

一方面,我希望使用某种类型的域事件/消息传递来传达操作。库存模块引发一个GoodsReceivedEvent,该事件由Financial模块处理以生成收据并启动付款过程。但是,这意味着财务模块需要了解已收到的库存项目。我可以简单地通过ID来引用它们,但是如果我需要收据的其他信息,例如名称和/或描述,单位成本等,该怎么办?每个模块都拥有自己的版本的清单项目以适应该模块的需求是否有意义?在这种情况下,财务模块在处理GoodsReceivedEvent时将必须执行自己的库存项目查找。

...

我之所以使用此示例,是因为我已经与各种ERP系统进行了大量合作,并且知道它们是采用这种类型的模块化设计的-我只是不知道如何操作。我上面也没有明确提及,但是我更喜欢遵循域驱动设计原则来设计解决方案,并相信这种类型的模块化恰好适合该领域。

非常感谢我对此有所帮助。


1
抱歉。在所有思维中都找不到问题。问题是什么?
S.Lott

1
寻找问号。在某些方面,我提供了一些选项,但没有提出解决方案,还提供了一些具体问题,以帮助指导正确的过程。
2011年

1
@SonOfPirate:对不起。我希望您能花些时间强调或强调这些问题,以便其他人可以为您提供帮助。
S.Lott

4
我同意洛特。抱歉,这不是问题,是意识流。如果将其简化为一两个重点问题,并尝试将体系结构关注点与实现细节分开,我们可以为您提供更好的帮助。
亚伦诺特,2011年

1
@SonOfPirate:“架构”是关于结构并将该结构传达给其​​他开发人员的。它从描述开始。它必须达到一定的清晰度和透明度,以使其他开发人员可以完全“获得”它并在他们所做的所有事情中遵循体系结构设计原则。
S.Lott

Answers:


2

每个模块都拥有自己的版本的清单项目以适应该模块的需求是否有意义?在这种情况下,财务模块在处理GoodsReceivedEvent时将必须执行自己的库存项目查找。我应该在模块化和共享信息之间划清界限吗?

您将始终需要权衡取舍。这就是您要回答的所有问题。将实体保存在单独的程序集中是一个好习惯,因此许多应用程序将它们保存在共享库中。但这意味着没有(物理)业务逻辑界限。执行自己的查找意味着很多冗余代码,只有在两个模块中都有特殊要求时,我才会实现这些代码。当然,从体系结构的角度来看,您的财务模块和库存模块无论如何都必须共享依赖项。财务模块很可能依赖于库存模块。如果要求允许您让一个模块依赖于另一个模块,那么我可以将实体封装在它们最属于的模块中。您' 我们需要在物理区别(共享依赖)和维护之间找到一个很好的平衡。太多的共享依赖项可能导致版本维护的噩梦。另外,对于ORM,如果要将新关系映射到现有实体或从依赖于包含实体的模块的模块扩展它们,也将遇到麻烦。

如果您不使用ORM,那么请记住,您的所有模块可能仍然共享同一数据库,通常就是这种情况。您可以将其用作共同点。

您还可以保持数据纯净(例如,以CSV /结果集的形式),并使用中央消息传递服务来向注册到其的模块通知有关新数据以及一些元信息的信息。这意味着没有真正的依赖关系,但是牺牲了类型的安全性和契约,并且格式错误的数据可能会带来麻烦。我想这就是许多大型ERP系统所做的。

简而言之,您必须确定所需的接口类型。更高的模块化导致更少的合同,反之亦然。

可能会为我的数据对象使用共享库,并使用具有发布订阅模式的中央消息传递服务,这似乎是我的最佳解决方案。


也同意这一点-dto合同的消息传递+ pub / sub和共享库(内部nuget回购)。我一直想知道与@SonOfPirate相同的问题,直到本文对我有所了解为止:msdn.microsoft.com/en-us/library/bb245678.aspx
diegohb 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.