首页
学习
活动
专区
圈层
工具
发布

DDD &合成
EN

Software Engineering用户
提问于 2019-04-21 00:40:53
回答 1查看 1K关注 0票数 0

我有一个要构建的项目,它有以下要求:

  • 通过支付金钱来换取信贷来填补钱包;如果所使用的付款是银行转账,这也需要财务团队的批准。然后,财务小组将(在未来)开具发票。
  • 将信用从一个钱包转移到另一个钱包;不需要批准或付款。
  • 退款信用转移到另一个钱包;这也需要得到财务团队的批准。

钱包和用户逻辑生活在不同的服务中,所以上面只需要处理移动信贷的问题。

为了按照DDD方法对此进行建模,我想出了两个可能的解决方案:

  • 使用组合并构建一个具有可批准、可支付等接口的事务类。事务将成为聚合根,并在其中封装批准。我喜欢这种方法,但是我觉得审批可能需要在它自己的有限的上下文中生存。
  • 创建更细粒度的聚合根(填充、传输、退款、审批),并在自己的有限上下文中进行审批。这意味着在批准时使用组合,方法是让AR满足一个接口(审批(),Reject())。这方面的问题是循环依赖和更复杂的应用程序服务。

我想到了第三种选择,那就是使用事件。然而,我认为这种方法非常接近备选案文2,而且还需要考虑到另一层复杂性。

代码解决方案1的示例,为了清晰(伪代码)

代码语言:javascript
复制
interface IApprovable {
  approve() 
  reject()
}

interface IPayable {
  pay()
}

class Approvable implements IApprovable {
  ...
  approve() {...}
  reject() {...}
}

class NotApprovable implements IApprovable {
  ...
  approve() {...} <-- throw an error
  reject() {...} <-- throw an error
}

class Payable implements IPayable {
  ...
  pay() {...}
}

class NotPayable implements IPayable {
  ...
  pay() {...} <-- throw an error
}


class Transaction {
  private IApprovable approvable;
  private IPayable payable;

  Transaction(IApprovable approvable, IPayable payable) {
    this.approvable = approvable;
    this.payable = payable;
  }
}

public static main() {
  Transaction topup = new Transaction(new Approvable(), new Payable());
  Transaction transfer = new Transaction(new NotApprovable(), new NotPayable());
  Transaction refund = new Transaction(new Approvable(), new NotPayable());
}

是否还有其他更好的设计方法,或者,在上述三种设计中,哪一种是最好的选择?

EN

回答 1

Software Engineering用户

回答已采纳

发布于 2019-04-23 08:07:43

哎哟,看起来很乱。

工作流和规则丛书

我认为你需要的是一个工作流和一本规则手册。

随之而来的是一个TransferRequest,它包含一些源信息、目标信息和平衡。

代码语言:javascript
复制
enum AccountKind
{
    BankTransfer,
    Cashier,
    Wallet,
    ...
}

class Account
{
    AccountKind kind;
    AccountIdentifier identifier;
}

enum Currency
{
    Dollars,
    Credits
}

class Money
{
    Currency currency;
    decimal amount;
}

class Approval
{
   bool approved;
   ...
}

enum WorkflowState
{
    New,
    AwaitingMoney,
    MoneyReceived,
    AwaitingApproval,
    PayMoney,
    Done
    ...
}

class TransferRequest
{
   WorkflowState
   Account source;
   Account destination;
   Money from_source;
   Money to_destination;
   Approval approval;
}

是的,这是一个数据结构,而不是一个成熟的对象。下一个谜题是“规则书”。

代码语言:javascript
复制
class Rule
{
    Func<TransferRequest, bool> precondition;
    Func<TransferRequest, TransferRequest> transition;
}

class RuleBook
{
    private Rule[] rules;

    TransferRequest Update(TransferRequest transferRequest)
    {
        return rules.single(r -> r.precondition(transferRequest)).transition(transferRequest);
    }
}

每条规则都知道何时可以应用它,并在事务中应用它自己。其结果是将TransferRequest移动到其旅程中的下一个适当点。

现在,当一个TransferRequest出现时:

  • 使用BankTransfer的源,它的新规则将TransferRequest转换为awaitingApproval。
  • 如果它来自收银台,它将直接转换到PayMoney。
  • 如果它来自另一个钱包,它就会过渡到AwaitingMoney。

一旦转换完成并完成了与其相关的后台任务,TransferRequest就被标记为为下一个阶段做好了准备。规则手册被重新应用,将转移转移到其旅程的下一阶段。

这允许您组成一个工作流,在该工作流中,对于某些实例可以忽略某些步骤,但在其他情况下则需要某些步骤。例如,钱包之间的转移可能进入InsufficientFunds状态(在这种状态下,不可能从银行转账或出纳)。相反,银行转账需要批准,以表明收款的地方,出纳员已经处理过的资金。

票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/390691

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档