Hacker News new | ask | show | jobs
by SomeGermanGuy 3804 days ago
Isn't it either way best practise to better be sorry than to be safe? So the second approach is as far as I can see favoured by the community, because it declutters the code and keeps it simple.
1 comments

I think it's usually better to be safe than sorry. If the community favours the second approach it's probably because they're unaware of the side-effects (hence this article) or because they're writing Python 3 - as they should be.
The principle the above commenter refers to is known as "Easier to Ask Forgiveness than Permission", i.e. you're not meant to check preconditions – you should just try to do whatever thing you want to do, and it should signal an error if it didn't succeed.

The reason for this has little to do with "clean code" and more to do with the fact that when checking preconditions, programmers have a tendency to check proxies rather than the actual thing they want to do. An an example, it is common to see the following:

    if not file_exists(filepath):
        stderr("Invalid config filepath!")

    config = read_file(filepath)
    ...
This code has the glaring problem that even if the file exists, that doesn't mean you have the required permissions to read it. What you really want to do is read the config file, but you check a proxy (does the file exist at all?) as your precondition.

How would you check for the right thing, that you can read the config file? Well, by trying to read the config file, of course!

    try:
        config = read_file(filepath)
    except IOError:  # can make this more fine-grained
        stderr("Invalid config filepath!")
This is longer code (one extra line, gasp!) but it avoids the problem of checking the wrong precondition which is so easy to do by mistake.

You may have heard of this concept in a different situation – e-mail validation. A lot of people go to great lengths to validate e-mail addresses by regex. Even if the address is perfectly conforming and passes the regex with flying colours it might not lead to an inbox. To really verify that the user can receive e-mail at the address they've specified, guess what you have to do? Send an e-mail and ask them to confirm they got it. It's the only way.

Don't forget the part where checking for preconditions opens you up to race conditions e.g.

    if not file_exists(filepath):
        stderr("invalid config filepath!")
    # filepath is removed by an external tool
    config = read_file(filepath) # blows up file does not exist
Is there still a chance of a race condition when you use the "with" operator? It seems like this is one of the major use cases it was designed for
It depends on how you use it! If you use it to acquire the resource, as in

    with open(fn, 'r'):
        ...
then generally the answer is no, since that is the same thing as the equivalent `try…finally`. If someone removes the file after it's being opened it will not be completely wiped until it's closed.