1
长话短说……

我希望我的客户(“服务消费者”中的客户,例如 REST)获得有关业务层做了什么或没做什么的状态信息。仅返回一个空对象或仅返回空值并不是非常具有描述性。任何事情都可能发生。

该死 - 我制作了一个很好的 UML 序列图来说明问题,但由于信誉点不足,StackOverflow 不允许我发布它:'(

这个问题可能是世界上最古老的问题。但是我没有找到令人满意的答案。我可以满足这里描述的解决方案如何使用 MVP 将服务层消息/错误传达给更高层?但它不会让我跳过循环。到处抛出异常听起来不是一件好事。毕竟例外是昂贵的。此外,我需要为很多“这可能发生”的场景创建一个异常。

****所以问题是......你是设计“通用返回值”还是抛出异常?****
不幸的是,到目前为止我还没有找到答案......这就是你发挥作用的地方: )

我会继续在其中放入一个状态代码、一条消息和 T 类型的实际请求信息。假设这个通用返回值是“ServiceResult”。

我做的考虑:

  • 好的,所以我的业务层方法都返回 ServiceResult 对象。好的。
  • 这很容易使用 - 前提是您所有的业务层魔法都发生在您调用的一个公共方法中。嗯 - 它没有。通常不会。
  • 因此,您要么必须使所有私有方法都可以访问 ServiceResult,要么将其作为参数传递。你不想通过它大约 100 次...相信我。
  • 这就是您决定将 ServiceResult 属性添加到“控制”业务类的时候。但是等等..您不会在 c# 中添加通用属性。因为它不是受支持的功能。
  • 接下来是什么?而是使用“对象”作为属性?几乎……你不想一直施放,而且你一开始就不知道要施放什么,因为 T 可以是任何东西。而且您的私有方法(比您最初调用的公共方法低 3 级)根本不知道类型 - 当然您也可以将其设为类的属性。我猜它仍然是糟糕的设计..
  • 假设您解决了该问题,如果 ServiceResult 尚未处于“故障”状态并且进一步处理无用,则每次调用下一个方法之前都需要检查 ServiceResult.Status。当然你可以把所有的魔法都放在一个 Run(Func func) 方法中,但是如果你在这一点上......最迟......你开始考虑再次使用 Exceptions :)

基本上这就是为什么我认为人们只是抛出异常并在最高级别捕获它们(在您的业务逻辑中 - 而不是在控制器中)。

这个问题有我不知道的设计模式吗?

4

1 回答 1

3

到处抛出异常听起来不是一件好事。

当然不是。发生异常时抛出异常。例如:如果你调用Repository.UpdateUser(var user)你期望一个用户对象的方法并且它得到了一个指定的 Id(你怎么能更新它)。

如果不是,你应该抛出异常,因为没有遵循方法契约。通过抛出异常,您还可以强制开发人员采取措施防止异常发生。例如通过确保用户对象是有效的。

毕竟例外是昂贵的。

没那么贵。调试一个没有进行适当完整性检查的应用程序可能比购买新硬件来弥补异常性能损失要贵得多。(看到了吗?这听起来很荒谬,因为异常不太可能对您的整体表现产生太大影响)。

此外,我需要为很多“这可能发生”的场景创建一个异常。

不,您需要确保在调用无法处理这些情况的方法之前处理那些“可能发生”的情况。

所以问题是......你是设计“通用返回值”还是抛出异常?

在大多数情况下,通用返回值毫无价值。忽略返回值的懒惰开发人员可能会引入一个休眠错误,该错误将在稍后出现并导致数小时的调试。

而是设计方法来预期错误或引发异常。比较int.TryParseint.Parse。第一个告诉您它可能会失败(因为它正在尝试),而另一个希望该值是整数(因此抛出异常,因为如果不是,它就无法按承诺完成)。

于 2013-02-19T14:13:17.873 回答