在Java中LBYL vs EAFP?
我最近在教自己的Python,并在代码执行之前发现了LBYL / EAFP成语,用于错误检查。 在Python中,EAFP似乎是可以接受的风格,并且它似乎与该语言一致。
LBYL(L OOK 乙安伏Ÿ欧大号 EAP):
def safe_divide_1(x, y):
if y == 0:
print "Divide-by-0 attempt detected"
return None
else:
return x/y
EAFP(IT公司的E asier到一个 SK˚Forgiveness除P ermission):
def safe_divide_2(x, y):
try:
return x/y
except ZeroDivisionError:
print "Divide-by-0 attempt detected"
return None
我的问题是:我从来没有听说过使用EAFP作为主要数据验证结构,来自Java和C ++背景。 EAFP是否明智地在Java中使用? 或者是有太多的异常开销? 我知道只有在实际抛出异常时才会有开销,所以我不确定为什么不使用EAFP的简单方法。 这只是偏好吗?
就个人而言,我认为这是按惯例支持的,EAFP从来不是一个好的选择。 您可以将其视为与以下内容等效:
if (o != null)
o.doSomething();
else
// handle
而不是:
try {
o.doSomething()
}
catch (NullPointerException npe) {
// handle
}
此外,请考虑以下几点:
if (a != null)
if (b != null)
if (c != null)
a.getB().getC().doSomething();
else
// handle c null
else
// handle b null
else
// handle a null
这可能看起来不那么优雅(是的,这是一个粗糙的例子 - 与我一起),但它在处理错误时给你更大的粒度,而不是将它全部包装在try-catch中以获得NullPointerException
,并且然后尝试找出你在哪里以及为什么得到它。
我看到它的方式永远不会被使用,除非是极少数情况。 此外,由于您提出了这个问题: 是的,即使不抛出异常,try-catch块也会产生一些开销 。
如果您正在访问文件,EAFP比LBYL更可靠,因为涉及LBYL的操作不是原子操作,并且文件系统可能在您查看时间和跳跃时间之间发生变化。 实际上,标准名称是TOCTOU - 检查时间,使用时间, 由于不正确的检查而导致的错误是TOCTOU错误。
考虑创建一个必须具有唯一名称的临时文件。 找出所选文件名是否存在的最好方法是尝试创建它 - 确保使用选项来确保在文件已经存在的情况下操作失败(以POSIX / Unix的方式,用于open()
的O_EXCL标志)。 如果您尝试测试文件是否已经存在(可能使用access()
),那么在表示“否”的时间与尝试创建文件的时间之间,某人或其他人可能已经创建了该文件。
相反,假设您尝试读取现有文件。 你检查文件是否存在(LBYL)可能会说“它在那里”,但是当你真正打开它时,你会发现“它不存在”。
在这两种情况下,您都必须检查最后的操作 - 而LBYL不会自动提供帮助。
(如果你正在搞乱SUID或SGID程序, access()
提出一个不同的问题;它可能与LBYL有关,但代码仍然需要考虑失败的可能性。)
除了Python和Java中相对的例外成本之外,请记住,它们之间的哲学/态度有所不同。 Java试图对类型(和其他所有东西)非常严格,要求明确的,详细的类/方法签名声明。 它假设你在任何时候都应该知道你正在使用什么类型的对象以及它能做什么。 相比之下,Python的“鸭子打字”意味着你不知道(而且不应该关心)一个对象的清单类型是什么,你只需要关心它在你提出要求时是否嘎嘎。 在这种宽容的环境中,唯一理智的态度是假定事情会发挥作用,但如果事情没有做好准备应对后果。 Java的自然限制性并不适合这种随便的方法。 (这并不是要贬低任何一种方法或语言,而是说这些态度是每种语言成语的一部分,并且在不同语言之间复制习语往往会导致尴尬和沟通不畅......)
链接地址: http://www.djcxy.com/p/54557.html