【问题标题】:Infrastructure concerns in domain services领域服务中的基础设施问题
【发布时间】:2014-06-16 11:41:21
【问题描述】:

我有一个域服务需要应用一些影响基础设施层的规则,因为它们是域要求。简而言之:基础设施政策和战略。

public MyService : IMyService {

    private readonly RetryPolicy<ConnectionErrorDetectionStrategy> _retryPolicy;
    // there might be other strategies for other concerns
    private readonly IRepository _repository;

    public MyService(IRepository repository) {
        _repository  = repository;
        _retryPolicy = new RetryPolicy<ConnectionErrorDetectionStrategy>();
    }

    public Do() {

        _repository.CrudMagic();
        _retryPolicy.ExecuteAction(() => _repository.Commit());

    }

}

要求是确保在某些情况下(case),当应用程序连接失败时(policy ) 到数据库。然而,这感觉很尴尬,因为域不知道连接是什么(整个 DAL 甚至可能是一个模拟!)。如何确保针对此特定服务/案例应用正确的策略?

【问题讨论】:

    标签: database domain-driven-design


    【解决方案1】:

    使用代理或装饰器。

    class MyService : IMyService {...}
    class MyRetryService: IMSyService {
        private readonly IMSyService target; //inject MyService
        private readonly RetryPolicy<ConnectionErrorDetectionStrategy> _retryPolicy;
    }
    

    在单元测试时注入 mock 作为目标(IMSyService)。只需期望并验证目标的调用。如果发生故障并且重试有效,则应调用目标的次数与指定的策略一样多。

    另一种选择是 AOP(如果您的平台上有成熟的框架/lib)。测试方法是一样的。

    【讨论】:

    • "目标应该被调用多次" 你是什么意思? RetryPolicy 是一个有状态的应用层服务,它会自动重复某个动作,例如:抛出异常。如果我按照策略中指定的次数调用目标 (IMyService.Do()),我最终会在我的数据库中拥有 x 个条目(或者由于实体已经存在,甚至会出现更多异常)。
    • 另外,将所需的操作 (commit()) 与 Do() 分开并将其放在界面上也是错误的,因为我的服务不允许客户端提交。提交只是客户端操作的一部分。
    • RetryPolicy 是否旨在在出现问题时在预定义的时间内重试某些操作?如果一切正常,只执行一次操作?
    • c# 中是否有一些模拟框架可以定义和验证期望调用?如果是,请在您的测试用例中模拟存储库,在快乐路径情况下定义 repository.commit 调用一次,在失败情况下定义 repository.commit 调用 x 次(取决于您的重试配置)。
    【解决方案2】:
    猜你喜欢
    • 2021-01-08
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    相关资源
    最近更新 更多