0

我只是想知道你对在哪里定义、抛出和捕获异常有什么看法,看看是否有关于考虑的共识。

让我举一个例子。假设我有解决方案,在该解决方案中我有 2 个项目:DomainProjectControllerProject.

  1. 在 DomainProject 中,我有一个用于执行某些查询的存储库,例如,RepositoryClass我有以下方法:

    GetObjectById(int id) { ... }
    

    我在这个项目中定义了一些异常,比如ObjectNotFoundException.

  2. ControllerProject我想查询我的存储库中,所以我做了一些看起来像这样的事情:

    MyObject obj = repo.GetObjectById(11);
    

现在的问题是谁应该负责检查 id 是否确实存在。如果您选择 ControllerProject 应该检查 id 的存在,您最终会得到如下代码:

MyObject obj = repo.GetObjectById(11);
if (obj == null) {throw new ObjectNotFoundException();}

但不利的一面是它往往在使用的地方都是重复的GetObjectById。当然,在某些情况下,您不会关心是否获得空值,因此不直接在 DomainProject 中抛出异常以某种方式是合法的。但我首先不喜欢重复 if 测试,其次,与我的问题更相关,我不喜欢在当前项目之外使用异常定义。

我觉得应该只在定义它的项目中抛出异常,而其他项目应该只捕获它们。

回到我的例子,我将如何解决这种情况。一个简单的想法是在我的域项目中定义 2 方法。一个抛出异常,一个不抛出异常。我唯一不确定的是我必须使用哪种命名约定:GetObjectByIdThrowsIfNotFound()GetObjectById(). 或者我可以只添加一个可选参数GetObjectById(int id, bool isExceptionThrow = true)

您如何看待异常?

谢谢

4

3 回答 3

2

我认为您正在考虑如何让您的设计正确传达意图,这很好。我同意你的疑虑:唯一抛出异常的层应该是定义异常的层。

也就是说,如果 null 返回值不明确,如果将键与null. 如果不是(这应该在您的 XML 注释中注明!),那么 null 返回总是意味着相同的事情(未找到值),您可以在域层中为自己节省代码和处理异常的开销。如果“未找到值”是控制器层中真正的异常事件,请在此处定义并抛出异常。

如果 'stored null'有效IDictionary<T>,我使用由:建立的语义模式bool TryGetObjectById(int id, out object value),并且如果 key-not-found 确实异常,我只包含一个抛出异常的GetObjectById(int key)变体,并且我想保存调用Try...变体所涉及的击键马路。

于 2012-04-19T15:21:34.243 回答
0

我经常看到两种模式:

1) 存储库本身应该抛出异常,如果你想处理获取项目的失败,你的调用方法应该包含在 try / catch 块中。我认为这种模式将是您的应用程序的主要候选者,因为处理异常是调用者的责任。我会假设您的存储库没有捕获SqlException或抛出任何持久层异常对吗?如果是这样,那么您应该让存储库抛出异常并让它在堆栈中冒泡。

如果不....

2)您暴露包装在容器中的对象以告诉您失败或成功:

public class RepositoryItemContainer<DataType>
{
    public DataType Object { get; set; }
    public bool WasFound { get; set; }
}

然后,不只是返回值,而是返回这个包装器,然后代码可以决定它想要做什么:

var repoItem = _repo.GetObjectById(11);

if(repoItem.WasFound)
   var item = repoItem.Object;

else
   throw new ApplicationSpecificException("Wasnt found yo!")
于 2012-04-19T15:02:20.573 回答
0

这里只是几个考虑因素:

  1. Exceptions用于特殊 情况。因此,如果您认为 DB 中没有对象是一种特殊情况,我会说按照您现在实现它的方式进行。

  2. 如果不是例外情况,请以不引发 andException而是返回的方式实现一个方法null,以防id我们查询丢失,自然。对于将使用您实现的 repo 类的开发人员来说,这似乎很自然并保持预期的行为。

  3. 您可以添加一种ContainsId(long id)方法,首先检查idDB 中是否存在所需的。也可能是一个不错的选择,但我个人更喜欢第二点。

希望这可以帮助。

于 2012-04-19T15:03:13.297 回答