我应该从返回日期的函数中返回null还是将"空对象"模式应用于返回Date的函数?
假设我们有一个返回日期的函数:
Date myFunc(paramA, paramB){ //conditionally return a date? }
从这个函数返回null
是否合适?这看起来很丑陋,因为它迫使客户检查null
。
"空对象"模式是解决此问题的一种实现模式。
我不是空对象模式的忠实拥护者,但是是的,总是返回一个列表(即使是空的),而不是返回" null"是有意义的。
但是,用Java来说,空日期将是一个已清除并具有1970年的日期。
这里最好的实现方式是什么?
解决方案
null是完全可以接受的。但是,如果要在错误时返回null,请考虑抛出异常。
如果有可能找不到日期,则使用null有意义。否则,我们最终会返回一些不可思议的日期(例如1970年),这将使人们迷上函数,而不仅仅是返回null。
记录它可能返回null,但是...
如果它不影响性能,我希望有一个显式的查询方法,然后使用异常:
if(employee.hasCustomPayday()) { //throws a runtime exception if no payday Date d = emp.customPayday(); }
我不喜欢空对象模式。
如果null为有效的预期返回值,则将其返回。如果是由错误条件引起的,则异常会更有意义。
有时,真正的问题是该方法应该返回确实表示更多信息的更复杂的类型。在这些情况下,很容易陷入陷阱并返回一些基本类型,再加上一些特殊的魔术值来表示其他状态。
空对象模式不适用于我们要尝试执行的操作。这种模式是关于在实现中创建一个没有功能的对象,我们可以将其传递给要求对象不为null的给定函数。一个示例是Eclipse中的NullProgressMonitor,它是IProgressMonitor的空实现。
如果我们返回一个"空"日期,例如1970,则客户仍然需要通过查看是否为1970来检查它是否为"空"。如果不这样,则会发生不当行为。但是,如果我们返回null,那么他们的代码将很快失败,并且他们知道应该检查null。同样,1970年可能是一个有效日期。
我们应该证明方法可能返回null,仅此而已。
如果这不是通常应该发生的情况,请使用例外。
否则,(例如,如果这是事件的结束日期),则仅返回null。
在任何情况下都请避免魔术值;)
我们可以尝试使用输出参数
boolean MyFunction( a,b,Date c) { if (good) c.SetDate(....); return good; }
那你可以叫它
Date theDate = new Date(); if(MyFunction(a, b ,theDate ) { do stuff with C }
它仍然需要我们进行检查,但是在这种情况下,无法避免进行检查。
尽管不建议使用SetDate,但是Calendar实现很丑陋。
Sun做过的最愚蠢的API更改。
看来此方法的预期结果是一个日期,或者找不到任何结果。未找到的情况通常由返回null表示。尽管有些人会使用异常来表示这种情况,但我不会(因为这是预期的结果,而且我从不喜欢异常处理)。
如前所述,Null对象模式不适用于这种情况。实际上,根据我自己的经验,这并不适合许多情况。当然,由于一些经验,我有一些偏见,因为它被严重滥用;-)