假设我有一个方法

public Patient(int id)
{
    ----
}

返回给定 id 的 Patient 对象..我可以用两种方式定义合同

  1. 如果患者不存在,方法将返回 null
  2. 如果患者不存在,方法将抛出异常。在这种情况下,我还将定义一个查询方法,如果数据库中存在患者,则返回 true,否则返回 false...

我应该使用哪个合同?还有其他建议吗?

更新:也请评论这个案例...如果它不是数据库分配的 ID,而是用户在 UI 中输入的内容。比如SSN..那么哪个更好..

史蒂夫对空模式的评论,我认为是有效的:在这里可能不是一个好主意,因为当 ID 不存在时立即知道是非常有用的。

我还认为这里的空模式有点重

Rob Wells 对因 ID 错误而抛出异常的评论:我不认为患者姓名中的拼写错误是特殊情况”恕我直言

有帮助吗?

解决方案

请记住,“通过电线”到另一层(无论是数据库还是应用程序服务器)是您可以执行的最昂贵的活动之一 - 通常网络调用将比内存调用花费几个数量级。

因此,在构建API时避免冗余调用是值得的。

考虑一下,如果您的API是这样的:

// Check to see if a given patient exists
public bool PatientExists(int id);

// Load the specified patient; throws exception if not found
public Patient GetPatient(int id);

然后你可能会两次点击数据库 - 或者依赖于良好的缓存来避免这种情况。

另一个考虑因素是:在某些地方,您的代码可能具有“已知良好”的代码。 id,在其他地方没有。每个位置都需要一个不同的策略来判断是否应该抛出异常。

这是我过去常用的一种模式 - 有两种方法:

// Load the specified patient; throws exception if not found
public Patient GetExistingPatient(int id);

// Search for the specified patient; returns null if not found
public Patient FindPatient(int id);

显然,可以通过调用FindPatient()来构建GetExistingPatient()。

这允许您的调用代码获取适当的行为,如果出现错误则抛出异常,并避免在不需要的情况下处理异常。

其他提示

另一种选择是空对象模式

你应该抛出异常。如果您的 id 没有指向有效的患者,那么它来自哪里?可能发生了非常糟糕的事情。这是一个特例。

编辑:如果您正在执行基于整数的检索以外的操作,例如基于文本的搜索,则返回 null 就可以了。特别是因为在这种情况下,您将返回一组结果,这些结果可能不止一个(多个患者姓名相同,出生日期相同,或者您的标准是什么)。

搜索功能应与检索功能具有不同的合约。

取决于:

如果您认为正常操作会导致数据库编号与数据库中的文件不匹配,则应返回空(NULL)记录。

但是如果你期望给定的ID应该总是打到一个记录,那么当找不到一个(这应该是罕见的)然后使用异常。

其他问题如数据库连接错误应该会产生异常。
正如您在正常情况下所期望的那样,对DB的查询始终有效(尽管它可能返回0条记录)。

P.S。我不会返回指针。 (谁拥有指针?)
我会返回一个可能有或没有记录的对象。但是你可以在内部记录存在的内存。可能是智能指针或比理解cotext的智能指针更聪明的东西。

对于这种情况,我会让方法为不存在的患者返回null。

当系统本身出现问题时,我更倾向于使用异常来帮助降低graeful降级。

在这种情况下,很可能是:

  1. 患者身份证中的拼写错误(如果已输入搜索表单),
  2. 数据输入错误,或
  3. 工作流程问题,即患者的记录尚未输入。
  4. 因此,返回null而不是异常。

    如果联系数据库时出现问题,那么我会让该方法引发异常。

    编辑:刚看到签名中的患者ID是一个整数,感谢Steven Lowe,所以我已经更正了我的原因列表。

    关于描述何时使用异常(对于系统错误)与其他返回错误的方法(对于简单的数据输入拼写错误)的基本观点仍然存在。 IMHO。

    HTH

    欢呼声,

    罗布

在这样的简单情况下1.似乎绰绰有余。您可能希望实现类似于客户端调用的回调方法,以了解它返回null的原因。只是一个建议。

从表面上看你的描述,你可能需要两者:

  • 正如 Adam 指出的那样,坏 ID 是错误/异常,但是
  • 如果您在其他地方获得的 ID 可能已消失,则需要使用查询方法来检查它们

假设我正确阅读了...... 当您致电Patient(100)时,它将返回ID为100的患者的对象参考。 如果不存在id为100的患者,我认为它应该返回null。例外是过度使用IMO,这种情况并不需要它。该函数只返回null。它没有创建一些可能导致应用程序崩溃的错误情况(当然,除非您最终没有处理该null并将其传递给应用程序的其他部分)。

我肯定会让该函数返回'null',特别是如果它是某些搜索的一部分,用户将搜索具有特定ID的患者,并且如果对象引用最终为null,则它将简单地说明没有患有这种身份的患者。

抛出异常。

如果返回null,则代码如下:

Console.WriteLine(Patient(id).Name);
如果id不存在,

会因NullReferenceException而失败,这不如说是PatientNotFoundException(id)。在这个例子中,它仍然相对容易追踪,但考虑:

somePatient = Patient(id)

// much later, in a different function:

Console.WriteLine(somePatient);

关于添加检查患者是否存在的功能:请注意,这不会完全阻止PatientNotFoundExceptions。例如:

if (PatientExists(id))
    Console.WriteLine(Patient(id).Name);

- 另一个线程或其他进程可以在对PatientExists和Patient的呼叫之间删除患者。此外,这将意味着两个数据库查询而不是一个。通常,最好只是尝试调用,并处理异常。

请注意,返回多个值的查询的情况不同,例如作为清单;在这里,如果没有匹配则返回空列表是合适的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top