如果值对象创建逻辑涉及访问外部API(域驱动设计),我应该把它放在哪里



我有一个实体,假设它是UserAccount。UserAccount有一个值对象,它是MembershipID。MembershipID之所以成为值对象,是因为它内部有一些业务逻辑,而不仅仅是一个字符串。但这里有一个棘手的情况。

要生成成员身份ID,我需要使用一个随机字符串和创建用户帐户的时间戳。然后,这两个值被发送到外部REST API,其成功响应将包含MembershipID。

这种价值对象的创建逻辑涉及到外部API调用,它属于基础设施层。Factory和Repository首先出现在我的脑海中,作为放置这种创建逻辑的地方,但这两个是针对实体的,而不是价值对象。那么,在不违反DDD的情况下,我应该把这个价值对象的创建逻辑放在哪里呢?

基本思想:应用程序(而不是域模型(负责从模型之外的世界获取数据。

要生成成员身份ID,我需要使用一个随机字符串和创建用户帐户的时间戳。然后,这两个值被发送到外部REST API,其成功响应将包含MembershipID。

实际上,您有一个看起来像函数的东西,它以随机种子和时间戳作为参数,并返回MembershipId。

该功能将由知道如何使用REST、外部api所在位置等的应用程序组件实现

该函数将被调用,通常是两种方式之一。要么应用程序要完成工作,然后将值传递给域模型。。。

m = membershipId(domainModel.randomSeed, domainModel.createdTime)
domainModel.assignMembershipId(m)

或者,我们将把能力传递到域模型中,并让模型决定是否调用它:

DomainModel::doIt(membershipId) {
this.membershipId = membershipId(this.randomSeed, this.createdTime)
}

这两种方法的区别主要在于如何处理失败。在第一种方法中,所有错误处理代码都位于域模型之外,域模型只在值可用时接收值。第二个答案适用于更过程化的风格——你只需要随时使用应用层提供的回调——但当你在"域"代码中工作时,你必须更加注意错误处理。

我发现前一种风格——与外部API可能在我们需要时不可用这一事实相关的所有复杂性——更符合DDD方法,即将域代码与管道分离。实际上,域模型变成了一个简单的内存状态机,用于记账,应用程序与所有管道问题进行接口。

现在我将外部API访问逻辑放入域服务中

使用上层样式,您将在应用程序服务中实现访问逻辑,而不是在domain服务。从"其他地方"获取数据不是一个领域建模问题,而是一个管道问题。

第二种风格,我们将功能传递到要调用的域模型中,类似于使用域服务。你会在很多例子中看到这种风格,因为人们倾向于应用模式来匹配他们通常做的事情,而不是调整他们的风格来匹配新的模式。

相关内容

  • 没有找到相关文章

最新更新