我在阅读MVC 3项目时正在阅读企业应用程序的书籍开发。我目前正在决定如何处理异常。以前我会让异常在堆栈中冒泡,然后在最高层处理它。
本书建议在域模型中创建一个ad-hoc类并返回它。 E.g。
public sealed class MissingCustomer: Customer
{
}
// On method failure return new MissingCustomer();
我可以看到这个想法,但我正在努力证明需要这个。代码明智我同意返回一个新的缺失客户更加整洁,而不是抛出异常。
您如何看待这种方法,并且您遇到过这会产生重大影响的情况?
如果我们假设客户必须始终存在,那么抛出一个例外说“嘿,客户应该总是存在而且由于某种原因它不存在”是有意义的,所以我将通知用户说某些例外情况发生”。另一方面,我可以假设客户可能被另一个人移除,因此我需要优雅地处理这个问题。
无论哪种方式,我认为我们需要一个MissingCustomer类或一个MissingCustomerException,因为客户是一个在整个系统中使用的非常常见的实体。如果视图模型需要一个客户并且我们返回一个MissingCustomer - 它很好,因为继承将使这个工作。
例如,我有一个返回OrderViewModel的动作方法。此操作方法需要引用客户。
Customer customer = CustomerRepository.Find(10);
if(customer == null)
{
return new MissingCustomer();
}
这将会失败,因为action方法将返回OrderViewModel类型的视图模型,所以现在我更倾向于使用异常而不是MissingCustomer对象。
修改
此外,MissingCustomer类型对象将从Customer类型继承属性。我们唯一不需要这些属性,就是通知用户无法找到客户。
谢谢
答案 0 :(得分:2)
这听起来类似于Null Object pattern,如果您有一些接受Customer对象的代码,并且您需要该代码能够运行而不会抛出错误,即使您没有有一个Customer对象来提供它。
例如,假设您有一个显示订单详细信息的视图,并且在某些情况下订单可能将其Customer设置为null。在这种情况下,您不希望显示错误消息,您仍希望显示订单的详细信息,并且可能为客户显示“无”。
您有两种选择:对视图进行编码以专门检查空客户并输出“无”,或者使用名称为“无”的特殊MissingCustomer对象填写订单并忘记空检查。
根据具体情况,您可能会发现此模式会保存大量“if null”代码。
另一方面,如果您打算使用MissingCustomer类进行错误检查,请按以下方式...
Customer c = ...
if (c is MissingCustomer)
{
// Display error, no customer found
}
...这只是抛出一个非常好的错误处理机制(异常)并使用更容易出错的东西。你必须记得一直检查MissingCustomer,在你忘记的地方,你可能会得到一些难以检测和难以调试的不正确的程序行为。
在我看来:
答案 1 :(得分:2)
我总是从用于获取客户的方法返回null
。通过查看名为GetCustomer
的函数,人们永远不会期望它可以返回一个真正不是客户的客户对象。
如果可以的话,使用像var customer = repos.GetCustomer(1) ?? Customer.Empty
这样的东西要好得多。目的很明确,代码变得不易出错。
如果您的方法希望始终获得客户,则您之前未能验证输入。而不是创建一个解决方法来使代码工作,尝试在早期修复它。也许检查一下客户是否存在?
<强>更新强>
我现在注意到这个问题确实适用于你的视图模型。在其中使用这种逻辑是完全正确的。毕竟视图模型用于调整MVC中的“M”以适应视图(因此从视图中删除逻辑)。
我会用
public class YourViewModel
{
public Customer Customer { get { return _customer ?? Customer.Empty; }}
}
答案 2 :(得分:1)
我现在遇到完全相同的问题,我将使用ad-hoc类型方法。
我选择这种方法的原因是因为我想将“客户”的实例显示为“无法找到客户'名称'”。在我的解决方案中,其他任务正常执行非常重要。未发现此特定客户实例的事实并非停滞不前。
因此,如果您对缺少客户的情况有某些行为,请使用ad-hoc。如果您无法在没有客户的情况下继续,请抛出异常。
无论如何,这就是我要做的。
答案 3 :(得分:1)
取决于......例外情况只应在特殊情况下抛出,例如:当你真的无法知道发生了什么或者应该如何处理它时。
如果您对如何在顶层处理此特定异常有一个具体的想法,那么我会说您不应该使用异常。
假设您的程序允许用户按名称搜索客户,并且找不到该客户:这不是一个例外,它应该构建您应用程序的一部分。
在MVC中,我发现根据可寻址资源来思考问题是有用的。
如果您的用户导航到资源/ YourApp / Customer / 22,并且客户22存在,那么您可以执行以下操作之一:
考虑一下您希望如何向用户传达这种情况。
本书中提出的方法并不错,但我可能会通过向Customer对象本身添加一个静态只读字段来实现与String.Empty属性相同的想法... < / p>
static readonly Customer Missing = new Customer();
答案 4 :(得分:1)
这是一个责任问题,但返回一个空对象确实意味着调用堆栈中的层将知道如何处理它。
例如,我有一个返回OrderViewModel的动作方法。这个 action方法需要引用客户。
您可以始终采用隔离类型的方法:而不是将视图耦合到客户,将其耦合到所需数据的表示(例如,“CustomerOrderSummary”对象/接口)。这与Interface Segregation Principle一致,并且与MVVM的部分保持一致:您可以在其中定制交换到使用场景的数据。