我正在尝试设计一个具有复杂业务域和支持REST API(严格来说不是REST,而是面向资源)的应用程序。我想出一种以面向资源的方式公开域模型的方法时遇到一些麻烦。
在DDD中,域模型的客户端需要通过过程“应用程序服务”层来访问由实体和域服务实现的任何业务功能。例如,有一个具有两种方法来更新User实体的应用程序服务:
userService.ChangeName(name);
userService.ChangeEmail(email);
此应用程序服务的API公开命令(动词,过程),而不是状态。
但是,如果我们还需要为同一应用程序提供RESTful API,则有一个用户资源模型,如下所示:
{
name:"name",
email:"email@mail.com"
}
面向资源的API公开状态,而不是命令。这引起了以下问题:
根据REST API上的每个属性,每个针对REST API的更新操作都可以映射到一个或多个Application Service过程调用。
对于REST API客户端,每个更新操作看起来都是原子操作,但是并不是那样实现的。每个应用程序服务调用被设计为一个单独的事务。在资源模型上更新一个字段可能会更改其他字段的验证规则。因此,我们需要一起验证所有资源模型字段,以确保所有潜在的应用程序服务调用在开始创建之前都是有效的。一次验证一组命令要比一次执行简单得多。我们如何在甚至不知道存在单个命令的客户端上执行此操作?
以不同的顺序调用Application Service方法可能会产生不同的效果,而REST API看起来没有什么区别(在一个资源内)
我可以想出更多类似的问题,但是基本上它们都是由同一件事引起的。每次调用应用程序服务后,系统状态都会更改。什么是有效更改的规则,即实体可以执行下一个更改的一组操作。面向资源的API试图使它们看起来都像原子操作。但是跨越这个鸿沟的复杂性一定要到某个地方,而且看起来是巨大的。
另外,如果UI更加面向命令(通常是这种情况),那么我们将不得不在客户端的命令和资源之间进行映射,然后再在API端进行映射。
问题:
- 所有这些复杂性是否应该仅由(厚)REST到AppService映射层处理?
- 还是我对DDD / REST的理解缺少什么?
- REST是否对于在一定程度(相当低)的复杂度下公开域模型功能不可行?