代码设计:业务逻辑和表示层分离与状态信息

时间:2013-02-19 13:37:06

标签: design-patterns optimization

长话短说......

我希望我的客户端(客户端如“服务使用者”,例如REST)获取有关业务层执行或未执行操作的状态信息。只返回一个null对象或只是null并不是非常具有描述性。任何事情都可能发生。

该死的 - 我制作了一个很好的UML序列图来说明问题但StackOverflow不会让我发布它,因为声誉点不足:'(

问题可能是世界上最古老的问题。但是我找不到令人满意的答案。 我可以解决这里描述的解决方案How Do You Communicate Service Layer Messages/Errors to Higher Layers Using MVP?,但它不会让我跳过循环。在整个地方抛出异常并不是一件好事。毕竟例外是昂贵的。此外,我需要为很多“可能发生的”场景创建一个例外。

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

我会继续并在其中输入状态代码,消息和类型T的实际请求信息。 我们假设这个泛型返回值是“ServiceResult”。

我做的考虑:

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

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

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

1 个答案:

答案 0 :(得分:3)

  

在整个地方抛出异常并不是一件好事。

当然不是。当异常事件发生时抛出异常。例如:如果你调用方法Repository.UpdateUser(var user),你需要一个用户对象,并且它指定了一个Id(你还能怎样更新它)。

如果不是,则应该抛出异常,因为未遵循方法合同。通过抛出异常,您还会强制开发人员采取措施来防止异常。例如,通过确保用户对象有效。

  

毕竟例外是昂贵的。

不那么贵。调试没有进行适当的健全性检查的应用程序可能要比购买新硬件以弥补异常性能损失要昂贵得多。 (看?这听起来很荒谬,因为异常不太可能会影响你的整体表现)。

  

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

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

  

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

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

而是设计方法以期望错误或抛出异常。比较int.TryParseint.Parse。第一个告诉你它可能会失败(因为它正在尝试),而另一个期望值是一个整数(因此抛出一个异常,因为它不能像承诺的那样完成,如果不是)。