从Active Record转换为Domain Object模式方法

时间:2016-01-18 14:06:21

标签: c# activerecord domain-driven-design

以下是该方案:

我加入了一个团队,他们开始开发一个相当大的金融系统,并且据称是针对具有丰富的行为领域模型的DDD。但是,我可以在项目的当前区域看到很多气味,这些气味指向Active Record:单个" Save"应用服务中的方法;一组相当贫乏的域对象,它们有一个很大的" Validate"方法等等。所有非常类似CRUD,并且变得越来越难以管理。

我正在开发的用户故事大致转换为"当直接付款从特定状态转换到另一个(未预算编入预算)时,为顾问创建一个任务项目,以便工作在" 。有各种规则决定什么"没有预算" "预算编号"的意思。

目前DirectDebit类没有" state"的概念。总之,它是一个相当大的DTO(有几个子对象 - 再次,所有DTO),有大约1000行验证逻辑,试图确定它应该是什么形状。业务有"清除"直接借记可以处于不同状态的概念,我相信该域足够丰富,可以保证域模型。

DirectDebit应用程序服务有一个" Save"传入更新的直接借记(来自UI)的方法。该方法从存储库中获取现有的DirectDebit,完全忽略它,运行"验证"在更新的直接借记对象上,并将其保存到仓库。然后,该方法审核旧的和新的直接借记对象之间的变化。

我试图摆脱那些在这里开始发展的类似CRUD的怪物,并向团队展示他们如何开始重构这一点。

理想情况下,我想开始重构域对象以使用状态模式,使用良好的封装并且可能使用域事件来冒泡状态已经改变的事实。 Application层将有一个名为" CreateTaskWhenBudgeted"的域事件处理程序。或类似的东西来解耦逻辑。

我的问题是大型的#34; Save"直接借记方法,源自UI。

有没有分解/重构这种方法的策略?由于没有明确的命令发生,因此没有简单的方法可以告诉他们发生了什么变化。#34; s" s" s" s"或者,我应该继续加入混乱并忽略我认为是一个问题....?

这是应用服务的缩减版本:

public void SaveDirectDebit(DirectDebit directDebit)
{
    directDebit.Validate(false);

    var beforeDirectDebit = _directDebitRepository.FetchDirectDebit(directDebit.ExpenditureId.Id);

    _directDebitRepository.SaveDirectDebit(directDebit);

    var afterDirectDebit = _directDebitRepository.FetchDirectDebit(directDebit.ExpenditureId.Id);

    var accountAuditLog = CreateDirectDebitAudit(beforeDirectDebit, afterDirectDebit);

    _auditLogRepository.CreateAudit(accountAuditLog);
}

1 个答案:

答案 0 :(得分:1)

当然没有一种方法可以做到(与其他方式相比),你有多个参数(时间,复杂性......)。

内向外

免责声明:遗留代码越大,这种方法似乎越难以实现(对我来说成功的条件是:你不应该是唯一一个关心这种重构的人)。

- >保存到数据库是一个技术性的东西。您必须首先引入一些无处不在的语言来使隐式显式,并能够引入概念并进行设计(创建边界和单独的上下文)。

另一种方式

另一种方式是我在评论中开始描述的内容,对我来说,当你被遗留系统包围时,它与Eric Evans所说的“泡沫上下文”有关,从一个干净的小有界上下文开始就更容易了。这种隔离将帮助您应用比现有系统更好(不同)的设计。