假设我有一个方法
public Patient(int id)
{
----
}
返回给定id的Patient对象..我可以用2种方式定义合约
我应该使用哪种合约?还有其他建议吗?
更新:请对这个案子发表评论...... 如果它不是一个分配了Id的数据库,那就是用户在UI中输入的东西......比如SSN ..那么哪一个更好..
评论史蒂夫的Null模式,我认为是有效的: 这里可能不是一个好主意,因为当ID不存在时立即知道它真的很有用。
而且我也认为这里的Null模式会有点重量
Rob Wells关于抛出异常的评论,因为它的错误ID: 我不认为患者姓名中的拼写错误是一种特殊情况“恕我直言”
答案 0 :(得分:15)
请记住,“通过线路”到另一层(无论是数据库还是应用程序服务器)是您可以执行的最昂贵的活动之一 - 通常网络呼叫将比以下任何时候都要长几个数量级。记忆电话。
因此,在构建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()。
这允许您的调用代码获取适当的行为,如果出现错误则抛出异常,并避免在不需要的情况下处理异常。
答案 1 :(得分:4)
另一种选择是Null Object pattern。
答案 2 :(得分:4)
你应该抛出异常。如果您的id
没有指向有效的患者,那么它来自哪里?可能发生了非常糟糕的事情。这是一个特例。
编辑:如果您正在执行基于整数的检索以外的操作,例如基于文本的搜索,则返回null
就可以了。特别是因为在这种情况下,您将返回一组结果,这些结果可能不止一个(多个患者姓名相同,出生日期相同,或者您的标准是什么)。
搜索功能应与检索功能具有不同的合约。
答案 3 :(得分:2)
对于这种情况,我会让方法为不存在的患者返回null。
当系统本身出现问题时,我更倾向于使用异常来帮助降低graeful降级。
在这种情况下,很可能是:
因此,返回null而不是异常。
如果联系数据库时出现问题,那么我会让该方法引发异常。
编辑:刚看到签名中的患者ID是一个整数,感谢Steven Lowe,所以我已经更正了我的原因列表。
关于描述何时使用异常(对于系统错误)与其他返回错误的方法(对于简单的数据输入拼写错误)的基本观点仍然存在。 IMHO。
HTH
欢呼声,
罗布
答案 4 :(得分:2)
取决于:
如果您认为正常操作会导致数据库编号与数据库中的文件不匹配,则应返回空(NULL)记录。
但是如果你期望给定的ID应该总是打到一个记录,那么当找不到一个(这应该是罕见的)然后使用异常。
DB连接错误等其他问题应该会产生异常 正如您在正常情况下所期望的那样,对DB的查询始终有效(尽管它可能返回0条记录)。
P.S。我不会返回指针。 (谁拥有指针?)
我会返回一个可能有或没有记录的对象。但是你可以在内部记录存在的内存。可能是智能指针或比理解cotext的智能指针更聪明的东西。
答案 5 :(得分:1)
在这样的简单情况下1.似乎绰绰有余。您可能希望实现类似于客户端调用的回调方法,以了解它返回null的原因。只是一个建议。
答案 6 :(得分:1)
将你的descriptiong用于面值,你可能需要两者:
答案 7 :(得分:0)
假设我正确阅读了...... 当您致电Patient(100)时,它将返回ID为100的患者的对象参考。 如果不存在id为100的患者,我认为它应该返回null。例外是过度使用IMO,这种情况并不需要它。该函数只返回null。它没有创建一些可能导致应用程序崩溃的错误情况(当然,除非您最终没有处理该null并将其传递给应用程序的其他部分)。
我肯定会让该函数返回'null',特别是如果它是某些搜索的一部分,用户将搜索具有特定ID的患者,并且如果对象引用最终为null,则它只会声明没有患有这种身份的患者。
答案 8 :(得分:0)
抛出异常。
如果返回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的呼叫之间删除患者。此外,这将意味着两个数据库查询而不是一个。通常,最好只是尝试调用,并处理异常。
请注意,返回多个值的查询的情况不同,例如作为清单;在这里,如果没有匹配则返回空列表是合适的。