EAFP in Python VS. LBYL in Java/C++


There are basically two error handling strategies:
  • Look Before You Leap (LBYL)
  • It's Easier to Ask Forgiveness than Permission (EAFP)

Consider these two snippets(小段代码,Python):

# Look before you leap(LBYL)--这是注释
if not os.path.exists(filename): 
    raise SomeError("Cannot open configuration file")
f = open(filename)
vs.
# ... Ask Forgiveness ...(EAFP)--这是注释
try: 
    f = open(filename)
except IOError: 
    raise SomeError("Cannot open configuration file")

My question is this: I had never even heard of using EAFP as the primary data validation construct, coming from a Java and C++ background. Is EAFP something that is wise to use in Java? Or is there too much overhead from exceptions? I know that there is only overhead when an exception is actually thrown, so I'm unsure as to why the simpler method of EAFP is not used. Is it just preference?

先谈谈LBYL的缺点:考虑前提知识太多,代码冗余,不够优雅,代码间连贯性很差

LBYL is the 'old' way. We validate every piece of data before we use it. It has some problems: Basically, that we have to know, and say, what 'valid' means. That requires a lot of knowledge of the function/object we're trying to validate, so it can violates encapsulation. Idioms help a little: in C, a NULL pointer generally indicates an error. Unfortunately, it doesn't contain very much information about why the error occurred, and there are no idioms for functions that return other non-pointer types. 

We have to write all the validation code, which in practice means writing lots of boilerplate(模板) code (not to mention frequently forgetting to check some arcane(晦涩难懂的) condition.) This is particularly annoying when it prevents us from chaining expressions naturally.
举个例子(用C语言)
: Instead of

int key_length = strlen(getval(map,key));// 连贯性强,不用考虑过多出错细节

We are constrained to write

int key_length = 0;
char* value = getval(map,key);
if (value != 0 ) { 
    key_length = strlen(value);
}// 必须考虑方方面面,如果错误太多,会级联很多if

以下是答案

1 首先是EAFP的原子操作性。

第一种解释版本:Equivalent? Not really. OSes(操作系统es) are multi-taking systems. What happens if the file was deleted between the test for 'exists' and 'open' call?

What happens if the file exists but it's not readable? What if it's a directory name instead of a file. There can be many possible failure modes and checking all of them is a lot of work. Especially since the 'open' call already checks and reports all of those possible failures.

The guideline should be to reduce the chance of inconsistent state, and the best way for that is to use exceptions instead of test/call.
 

第二种解释版本:If you are accessing files, EAFP is more reliable than LBYL, because the operations involved in LBYL are not atomic, and the file system might change between the time you look and the time you leap. Actually, the standard name is TOCTOU - Time of Check, Time of Use; bugs caused by inaccurate checking are TOCTOU bugs.

Consider creating a temporary file that must have a unique name. The best way to find out whether the chosen file name exists yet is to try creating it - making sure you use options to ensure that your operation fails if the file does already exist (in POSIX/Unix terms, the O_EXCL flag to open()). If you try to test whether the file already exists (probably using access()), then between the time when that says "No" and the time you try to create the file, someone or something else may have created the file.

Conversely, suppose that you try to read an existing file. Your check that the file exists (LBYL) may say "it is there", but when you actually open it, you find "it is not there".

In both these cases, you have to check the final operation - and the LBYL didn't automatically help.


2 其次Python的动态类型(Duck-typing)决定了EAFP,而Java的强类型要求( strong typing )决定了LBYL。
In addition to the relative cost of exceptions in Python and Java, keep in mind that there's a difference in philosophy / attitude between them. Java tries to be very strict about types (and everything else), requiring explicit, detailed declarations of class/method signatures. It assumes that you should know, at any point, exactly what type of object you're using and what it is capable of doing. In contrast, Python's "duck typing" means that you don't know for sure (and shouldn't care) what the manifest type of an object is, you only need to care that it quacks when you ask it to. In this kind of permissive environment, the only sane attitude is to presume that things will work, but be ready to deal with the consequences if they don't. Java's natural restrictiveness doesn't fit well with such a casual approach. (This is not intended to disparage either approach or language, but rather to say that these attitudes are part of each language's idiom, and copying idioms between different languages can often lead to awkwardness and poor communication...)
   

3 最后是效率要求。 
Exceptions are handled more efficiently in Python than in Java, which is at least  partly why you see that construct in Python. In Java, it's more inefficient (in terms of performance) to (并不是说使用exceptions不efficient,而是 use exceptions in that way不efficient ).

总结:
The guideline should be to reduce the chance of inconsistent state, and the best way for that is to use exceptions instead of test/call.来句感叹: 哲学真的无处不在,无所不渗透啊。
 

摘自 - http://stackoverflow.com/questions/404795/lbyl-vs-eafp-in-java 和
http://oranlooney.com/lbyl-vs-eafp/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值