这被认为是程序性编程(或贫血模式)吗



假设有两个类,一个是用户类,它包含用户信息;另一个是支付交易类。如果用户的年龄>65、创建A类支付交易;否则,创建B类支付交易。

有几种方法可以做到这一点:

  1. 创建一个既不属于用户也不属于事务的方法,只需调用CreateTransaction即可。该方法的逻辑如下:
func CreateTransaction(user, transaction) {
if user.GetAge() > 65:
transaction.CreateA()
else:
transaction.CreateB()
}
  1. 另一个选项是为用户类创建一个方法:
class User {
...
func CreateTransaction(transaction) {
if user.GetAge() > 65:
transaction.CreateA()
else:
transaction.CreateB()
}
}

然后是一个CreateTransactionController方法,它调用如下函数:

func CreateTransactinController(user, transaction) {
user.CreateTransaction()
}

我的问题是,选项1是否被视为过程编程,因为逻辑实际上不属于任何对象?(还是贫血型?(1和2之间的区别只是放逻辑的不同地方吗?

谢谢!

由于您将此问题标记为DDD,我将回答由Domain驱动的模型将如何实现此问题。

要回答的问题是Transaction是否包含在User对象中。如果它是封闭的,这意味着您总是通过用户的记录来获取事务(而从不直接访问事务(。如果事务本身有生命周期,可以直接访问,控制域的其他部分,等等,那么它就不能包含在User中,而是一个完整的聚合。

transaction封装在user中意味着用户拥有与事务相关的操作,因此选项2将是正确的方法。

如果transaction是不同的聚合,则可以使用Domain Service(与选项1类似(,但这是不正确的,因为您同时处理两个聚合(usertransaction(。您最好将此功能包含在Transaction聚合中。

下一个需要解决的问题是如何决定交易类型。一种方法是:

  1. API请求会将用户年龄作为请求的一部分发送
  2. 控制器调用服务并将用户的年龄作为整数传递
  3. 该服务调用一个工厂方法,该方法接受age作为整数,初始化并返回正确类型的事务
  4. 当请求通过时,用户的年龄可能在后端发生了变化,或者请求可能不正确。您通过使用";纠正政策;其在稍后创建支付交易之后运行。如果用户的年龄与所选择的交易类型相匹配,那么一切都是好的。如果没有,则交易被撤销

这通常是处理依赖于多个聚合属性的更改的方式。您继续更改系统中聚合的状态,但在稍后的时间点检查相关聚合数据,如果不一致,则反转更改。

更好的方法是创建一个Specification,其明确任务是根据用户的年龄导出正确的支付类型。该规范包含您的业务逻辑(>65(,为年龄驱动的需求提供上下文,并充当控制逻辑的中心位置。

您可以在此处阅读有关规格的更多信息:https://martinfowler.com/apsupp/spec.pdf

相关内容

  • 没有找到相关文章

最新更新