我正在开发一个3层应用程序(不是3层!),其中一个层(物理群集)上运行的客户端应用程序与另一个服务应用程序层和另一层上的数据库服务器。应用程序有很多业务规则,流程逻辑等,我相信应该可以在应用程序层和服务层上使用,以改善用户体验,减少对服务的调用并消除冗余编码。.NET中的分布式DDD:与客户端共享域对象
让我们用这个例子:在我的领域层,我有一个Document对象。该对象包含AllowPublish属性,该属性检查对象的内部状态,如果状态允许发布文档,则返回true/false。该对象还具有一个Publish方法,该方法通过将IsPublished标志设置为true并引发已发布的域事件来修改对象的内部状态,以反映它正在发布的事实。
我有一个单独的AuthorizationService,它确定是否允许当前用户发布以及将该对象持久化到数据库的DocumentRepository。
在我的服务应用程序中,我的DocumentService有一个PublishDocument方法,它接受文档ID,使用ID从存储库中检索文档,检查AllowPublish属性,如果为true,则调用Publish然后使用存储库持久更新的对象。
我在客户端上的行为稍有不同。在这种情况下,我使用AllowPublish属性来启用/禁用命令按钮。启用并单击后,我会调用一个服务代理,该服务代理公开一个接受文档ID的PublishDocument方法。代理将该调用传递到具有相同名称的服务应用程序的DocumentService方法。为了消除重复的代码,共享业务逻辑,验证规则等,我将域对象放置在一个单独的程序集中,由客户端应用程序和服务应用程序共享。这意味着客户端应用程序现在可以访问我的Document类的Publish方法,尽管它只与我的服务应用程序有关,并且只应该被我的服务应用程序使用。这让我重新考虑了我正在采取的整个方法。
虽然我了解使用DTO在客户端和服务器之间传递状态,但我使用.NET 3.5,据我所知,共享程序集是共享业务和验证规则的唯一方法。客户端应用。我有一些想法,我可以去的其他方向,但希望得到一些建议,然后开始一条新的道路。
另一方面,我目前对客户的实施采取了我认为是一种全面的授权方法,可能只是一个指标,表明不同的模式会更好。就像我在我的服务器端服务应用程序中有一个DocumentService用来执行授权的AuthorizationService,我有一个类似的代理,我的客户端代码使用它。这意味着我需要在我的客户端代码中使用另一个间接层来支持授权,可能是Controller或ViewModel。如果用例是有效的,那很好。
EDIT
我可能需要澄清的是,AllowPublish属性是动态的文档正在被编辑时。当第一次检索时,它可能是错误的,但随着业务规则的满足会变成真。通过在客户端应用程序中运行业务规则,我们可以提供更丰富的用户体验。
这可能是调查CQRS的好时机。这不是一小步,而是根据你所描述的,这可能是一个很好的选择。这个想法是为写入(命令)和读取(查询)分别建立模型。这样,您的文档对象(又名DDD实体或Agregate)将成为写模型的一部分,在读模型中,您将拥有一个简单的DTO,其中包含所有已经计算好的属性 - DocumentDTO的AllowPublish将成为一个简单的布尔字段每当Document实体发生更改时都会更新。如果您需要我可以提供更多信息,但我认为谷歌应该足够了。 – 2011-05-02 14:18:12
事实上,我的精神实施CQRS。例如,检索文档列表的查询方法实际上会返回包含简单只读属性(不过是DTO)的DocumentInfo对象。这些DTO仍然由具有逻辑的实际域对象生成,以确定像AllowPublish这样的布尔属性将包含哪些值。虽然我喜欢CQRS背后的概念,但我并不喜欢实现,因为我发现它超出了平均开发人员的理解范围。所以,我尝试用R/O DTOs来简化读取和写入域对象。 – SonOfPirate 2011-05-02 15:34:13
我应该澄清:CQRS因为它是一个交易存储而失去了我 - 这意味着我们正在存储交易,而不是状态。这对许多应用程序来说都很好,但对于我的努力,我还没有遇到过这样的情况,因为它非常适合。我不想通过一系列交易来检索我的当前状态,并且实施服务对于汇总数据的额外开销等等太多。我喜欢分离职责的想法,实际上已经实现了一个版本,其中查询是针对CUBE而不是实际的数据存储执行的。这跟我来的时间差不多。 – SonOfPirate 2011-05-02 17:11:00