exception与ad-hoc类型。 什么可能会倒下?

我在阅读MVC 3项目时正在阅读企业应用程序的书籍开发。 我目前正在决定如何处理exception。 以前我会让exception在堆栈中冒泡,然后在最高层处理它。

本书建议在域模型中创建一个ad-hoc类并返回它。 例如

public sealed class MissingCustomer: Customer { } // On method failure return new MissingCustomer(); 

我可以看到这个想法,但我正在努力certificate需要这个。 代码明智我同意返回一个新的缺失客户更简洁,而不是抛出exception。

您如何看待这种方法并且您遇到过哪种情况会产生重大影响?

如果我们假设客户必须始终存在,那么抛出一个例外说“嘿,客户应该总是存在而且由于某种原因它不存在,所以我将通知用户说某些特殊情况发生了”是有意义的。 另一方面,我可以假设客户可能被另一个人移除,因此我需要优雅地处理这个问题。

无论哪种方式,我认为我们需要一个MissingCustomer类或一个MissingCustomerException,因为客户是一个非常常见的实体,在整个系统中使用。 如果视图模型需要一个客户并且我们返回一个MissingCustomer – 它很好,因为inheritance将使这个工作。

例如,我有一个返回OrderViewModel的action方法。 此操作方法需要引用客户。

 Customer customer = CustomerRepository.Find(10); if(customer == null) { return new MissingCustomer(); } 

这将会失败因为action方法将返回OrderViewModel类型的视图模型,所以现在我更倾向于使用exception而不是MissingCustomer对象。

编辑

此外,MissingCustomer类型对象将从Customer类型inheritance属性。 我们唯一不需要这些属性,就是通知用户无法找到客户。

谢谢

我总是从用于获取客户的方法返回null 。 通过查看名为GetCustomer的函数,人们永远不会期望它可以返回一个真正不是客户的客户对象。

你使用像var customer = repos.GetCustomer(1) ?? Customer.Empty这样的东西要好得多var customer = repos.GetCustomer(1) ?? Customer.Empty 如果可以的话, var customer = repos.GetCustomer(1) ?? Customer.Empty 。 意图很明确,代码变得不容易出错。

如果您的方法期望始终获得客户,则您之前未能validation输入。 而不是创建一个解决方法来使代码工作,尝试在早期修复它。 也许检查一下客户是否存在?

更新

我现在注意到问题确实是你的视图模型。 在其中使用这种逻辑是完全正确的。 毕竟视图模型用于调整MVC中的“M”以适应视图(因此从视图中删除逻辑)。

我会用

 public class YourViewModel { public Customer Customer { get { return _customer ?? Customer.Empty; }} } 

这听起来类似于Null对象模式 ,如果您有一些接受Customer对象的代码,并且您需要该代码能够运行并且即使您没有Customer对象也不会抛出错误给它。

例如,假设您有一个显示订单详细信息的视图,并且在某些情况下订单可能将其Customer设置为null。 在这种情况下,您不希望显示错误消息,您仍希望显示订单的详细信息,并且可能为客户显示“无”。

您有两种选择:对视图进行编码以专门检查空客户并输出“无”,或者使用名称为“无”的特殊MissingCustomer对象填充订单并忘记空检查。

根据具体情况,您可能会发现此模式可以节省大量“if null”代码。

另一方面,如果您打算使用MissingCustomer类进行错误检查,请按以下方式…

 Customer c = ... if (c is MissingCustomer) { // Display error, no customer found } 

…这就是抛出一个非常好的error handling机制(例外)并使用更容易出错的东西。 你必须记得一直检查MissingCustomer,在你忘记的地方,你可能会得到一些难以检测和难以调试的不正确的程序行为。

在我看来:

  • 如果它是您通常期望返回对象的方法,则无法生成对象是错误,并且应该如此指示(有例外)。 如果在某些情况下应该处理错误,请使用自定义exception类并在这些情况下捕获exception。
  • 如果它是您期望的方法可能会或可能不会返回对象,请使用null作为“无记录”结果,以及其他错误的例外。 该方法的命名方式可能会提醒您可以返回null,例如“TryGetCustomer”,或者甚至只是存储库“Find”方法可以返回null的约定。
  • 如果您有一些代码正在执行大量“if null”检查,您可以考虑Null对象/特殊情况模式来潜在地简化该代码。

我现在有完全相同的问题,我将使用ad-hoc类型方法。

我选择这种方法的原因是因为我想将我的“客户”实例显示为“无法找到客户’名称’”。 在我的解决方案中,其他任务正常执行非常重要。 未发现此特定客户实例的事实不是停止问题。

因此,如果您对缺少客户的情况有某些行为,请使用ad-hoc。 如果您无法在没有客户的情况下继续,请抛出exception。

无论如何,这就是我要做的。

这取决于……exception只应在特殊情况下抛出,例如,当你真的无法知道发生了什么或应该如何处理时。

如果你对如何在顶层处理这个特殊exception有一个具体的想法,那么我会说你不应该使用exception。

假设您的程序允许用户按名称搜索客户,并且找不到该客户:这不是一个例外,它是应用程序应该构建来处理的部分内容。

在MVC中,我发现从可寻址资源的角度思考问题是有用的。

如果您的用户导航到资源/ YourApp / Customer / 22,并且客户22存在,那么您可以执行以下操作之一:

  • 将它们路由到通用404页面(未找到资源)。
  • 给他们一个量身定制的响应,例如“抱歉,找不到客户”。

想想您希望如何向用户传达这种情况。

本书中提出的方法并不错,但我可能通过向Customer对象本身添加一个静态只读字段来实现与String.Empty属性相同的想法。

 static readonly Customer Missing = new Customer(); 

这是一个责任问题,但返回一个null对象确实意味着调用堆栈中的层将知道如何处理它。

  • 返回MissingCustomer类型对象还意味着您在MissingCustomer的创建内/下进行了适当的错误记录。 如果你不是那么你需要让exception数据冒泡(返回exception将是最好的 – 假设它是例外的)。

例如,我有一个返回OrderViewModel的action方法。 此操作方法需要引用客户。

您可以始终采用隔离类型的方法:而不是将视图耦合到客户,将其耦合到所需数据的表示(例如,“CustomerOrderSummary”对象/接口)。 这与接口隔离原则一致 ,并且与MVVM的部分保持一致:您可以在其中定制交换到使用场景的数据。