Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从活动记录移动到域对象模式方法_C#_Activerecord_Domain Driven Design - Fatal编程技术网

C# 从活动记录移动到域对象模式方法

C# 从活动记录移动到域对象模式方法,c#,activerecord,domain-driven-design,C#,Activerecord,Domain Driven Design,以下是场景: 我已经加入了一个团队,他们正在开始开发一个相当大的金融系统,并且应该以DDD为目标,拥有丰富的行为领域模型。然而,在项目的当前区域中,我可以看到许多指向活动记录的气味:应用程序服务中的单个“保存”方法;一组相当贫乏的域对象,它们有一个大的“验证”方法等。所有这些都非常粗糙,并且变得越来越难以管理 我正在开发的用户故事大致可以翻译为“当直接借记从特定状态转换到另一个状态(未编入预算到编入预算)时,创建一个任务项供顾问处理”。有各种规则确定“未编入预算”和“编入预算”的含义 目前,Di

以下是场景:

我已经加入了一个团队,他们正在开始开发一个相当大的金融系统,并且应该以DDD为目标,拥有丰富的行为领域模型。然而,在项目的当前区域中,我可以看到许多指向活动记录的气味:应用程序服务中的单个“保存”方法;一组相当贫乏的域对象,它们有一个大的“验证”方法等。所有这些都非常粗糙,并且变得越来越难以管理

我正在开发的用户故事大致可以翻译为“当直接借记从特定状态转换到另一个状态(未编入预算到编入预算)时,创建一个任务项供顾问处理”。有各种规则确定“未编入预算”和“编入预算”的含义

目前,DirectDebit类根本没有“状态”的概念,它是一个相当大的DTO(有几个子对象——同样是所有DTO),有大约1000行验证逻辑,试图确定它应该是什么形状。业务部门对直接借记可能处于的不同状态有“清晰”的概念,我相信该领域足够丰富,可以保证一个领域模型

DirectDebit应用程序服务有一个“Save”方法,用于传入更新的DirectDebit(从UI)。该方法从存储库中获取现有的DirectDebit,完全忽略它,对更新的DirectDebit对象运行“Validate”,并将其保存到repo。然后,该方法审核新旧直接借记对象之间的更改

我试图摆脱这里开始发展的积垢般的怪物,并向团队演示如何开始重构它

理想情况下,我希望开始重构域对象以使用状态模式,使用良好的封装,或者使用域事件来冒泡状态已更改的事实。应用层将有一个名为“CreateTaskWhenBudget”或类似的域事件处理程序来解耦逻辑

我的问题是大型“保存”直接借记方法,它起源于UI

有什么策略可以分解/重构这种方法吗?没有简单的方法来判断“改变”了什么,因为没有一个明确的命令正在发生。或者,我是否应该继续增加混乱,忽略我认为是问题的东西

下面是应用程序服务的精简版本:

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);
}

当然,没有一种方法可以做到这一点(好方法与其他方法相比),您有多个参数(时间、复杂性…)

由内而外的方式

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

->保存到数据库是一项技术工作。您必须首先引入一些普遍存在的语言,以使隐式显式,并能够引入概念和进行设计(创建边界和单独的上下文)

另一种方式


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

当您正在开发一个新的用户故事并且您知道触发因素时,为什么不公开不同的方法?在第一次你可能会重复代码…这是一个公平的点-我可以公开第二个方法,但我可能会保存到数据库两次。我希望有一种从内到外的重构方法。