最好的方法是什么?为什么?
V1:
try
{
var service = IoC.Resolve<IMyBLService>();
service.Do();
}
catch(BLException ex)
{
//Handle Exception
}
V2
var service = IoC.Resolve<IMyBLService>();
var result = service.Do();
if (!result.Success)
{
//Handle exception
}
答案 0 :(得分:5)
在我看来,例外情况更好。我认为DDD代码首先是优秀的面向对象代码。关于在OO语言中使用异常与返回代码的争论大多已经结束。在DDD上下文中,我看到了使用异常的以下好处:
他们强制调用代码来处理它们。异常不要让客户端代码忘记错误。调用代码可能会忘记检查result.Success
。
我认为投掷和处理代码更具可读性,自然性和简洁性。没有'ifs',没有多重退货声明。无需将您的域服务弯曲为“操作”。
我认为DDD就是使用简单的OO语言来表达特定的业务问题并尽可能地保留基础设施。创建'OperationResult'类似乎太基础设施和通用,特别是当语言已经支持异常时。
域对象无论如何都会抛出异常,即使它仅用于检查参数。因此,对域服务使用相同的机制似乎很自然。
也许值得看一下设计本身,也许有一种方法可以不首先进入错误状态?例如,可以使用Value Objects而不是原始字符串和整数来消除整个“验证”错误条件。
DDD是一种方法,一套指导方针,因此没有“正确”的方法。 book从未直接提及此问题,但代码段和示例项目中的代码使用例外。
答案 1 :(得分:4)
首先,IoC.Resolve<IMyBLService>()
实际上是IoC容器的一个非常糟糕的用法,你应该注入你的依赖,而不是解决它们。我知道这不是问题的关键,但值得一提。
至于异常vs方法结果,它取决于。处理此问题的标准方法是使用Exceptions,但有些情况下,返回结果更简洁,更简单。例如,我经常使用操作结果,因为我对从SOA层中抛出非域相关异常有非常具体的要求,因此我需要捕获与域相关的异常才能创建新的异常。这不符合逻辑,它不可读,它影响了性能,所以我们用一点基础结构糖转换成结果。
值得一提的另一件事是,当您需要运行并返回所有验证的结果时,例外情况往往是PITA,而不会在第一个无效规则上制动。