Python – Returning a boolean when success or failure is the sole concern

booleandesign-patternspython

I often find myself returning a boolean from a method, that's used in multiple locations, in order to contain all the logic around that method in a single place. All the (internal) calling method needs to know is whether the operation was successful, or not.

I'm using Python but the question isn't necessarily specific to that language. There are only two options I can think of

  1. Raise an exception, though the circumstances are not exceptional, and remember to catch that exception in every place the function is called
  2. Return a boolean as I'm doing.

This is a really simple example that demonstrates what I'm talking about.

import os

class DoSomething(object):

    def remove_file(self, filename):

        try:
            os.remove(filename)
        except OSError:
            return False

        return True

    def process_file(self, filename):

        do_something()

        if remove_file(filename):
            do_something_else()

Although it's functional, I really dislike this manner of doing something, it "smells", and can sometimes result in a lot of nested ifs. But, I can't think of a simpler way.

I could turn to a more LBYL philosophy and use os.path.exists(filename) prior to attempting deletion but there's no guarantees the file won't have been locked in the meantime (it's unlikely but possible) and I still have to determine whether the deletion has been successful or not.

Is this an "acceptable" design and if not what would be a better way of designing this?

Best Answer

You should return boolean when the method/function is useful in making logical decisions.

You should throw an exception when the method/function isn't likely to be used in logical decisions.

You have to make a decision about how important the failure is, and if it should be handled or not. If you could classify the failure as a warning, then return boolean. If the object enters a bad state that make future calls to it unstable, then throw an exception.

Another practice is to return objects instead of a result. If you call open, then it should return a File object or null if unable to open. This ensures the programmers has an object instance that is in a valid state that can be used.

EDIT:

Keep in mind that most languages will discard the result of a function when it's type is boolean or integer. So it's possible to call the function when there is no left hand assignment for the result. When working with boolean results, always assume the programmer is ignoring the returned value and use that to decide if it should rather be an exception.