繁体   English   中英

这是否被视为过程编程(或贫血模式)?

[英]Is this considered as procedural programming (or anemic pattern)?

假设有两个类,一个是用户class,包含用户信息; 另一个是支付交易class,场景很简单,如果用户年龄>65,创建A类支付交易; 否则,创建 B 类支付交易。

做这件事有很多种方法:

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

然后有一个调用 function 的 CreateTransactionController 方法,例如:

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

我的问题是,选项 1 是否被视为过程编程,因为逻辑实际上不属于任何 object? (或贫血模式?)1 和 2 之间的区别是否只是放置逻辑的不同位置?

谢谢!

由于您将此问题标记为 DDD,我将回答由域驱动的 model 将如何实现这一点。

要回答的问题是一个Transaction是否包含在User object之内。如果包含,则意味着你总是通过用户go的记录来获取交易(并且永远不会直接访问交易)。 如果一个事务本身有一个生命周期,可以直接访问,控制域的其他部分,等等,它就不能包含在一个User中,而是一个成熟的聚合。

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

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

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

  1. API 请求会将用户的年龄作为请求的一部分发送
  2. controller 调用服务并将用户年龄传递为 integer
  3. 该服务调用一个工厂方法,该方法接受年龄为 integer、初始化并返回正确的交易类型。
  4. 到请求通过时,用户的年龄可能在后端发生了变化,或者请求可能不正确。 您可以通过一个“纠正策略”来处理这个问题,该策略在稍后创建支付交易后运行。 如果用户的年龄与选择的交易类型相匹配,那么一切都很好。 如果没有,则交易被撤销。

这通常是您处理依赖于来自多个聚合的属性的更改的方式。 你提前go,在系统中修改了聚合的state,但稍后及时查看相关的聚合数据,如果不一致则撤销修改。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM