user32882
user32882

Reputation: 5877

Why catch exceptions when we can simply prevent them from happening in the first place

I've always had trouble understanding the real purpose of catching exceptions in any programming language.

Generally, when you can catch an exception, you can also prevent the exception from ever occurring. Here's an example.

What's the point of doing this:

import os
import argparse

if __name__=="__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("filename", type=str, help="the filename")

    args = parser.parse_args()
    
    try:
        with open(args.filename) as fs:
            fs.write("test")
    except FileNotFoundError:
        print("that file was not found")

If I can do this:

import os
import argparse

if __name__=="__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("filename", type=str, help="the filename")

    args = parser.parse_args()

    if os.path.exists(args.filename):
        with open(args.filename) as fs:
            fs.write("test")
    else:
        print("that file was not found")

What is the added value of catching anything as an exception, when it is often more feasible to prevent the exception from ever happening in the first place?

Upvotes: 1

Views: 149

Answers (1)

Lajos Arpad
Lajos Arpad

Reputation: 76554

Exceptions are exceptional situations being thrown when an undesired, erroneous issue happened. It is true that in many cases it is unnecessary to use the exception pattern as you can check for the possibility to perform the operation before giving it a chance to err. But, sometimes that's not possible.

For instance, let's consider the example that you are running a database query. You cannot know whether that will succeed without actually running it. So, there are cases when you cannot prevent exceptions by doing validations.

Also, there are cases when there could be many exceptions upon many levels. Your code would become very difficult to read and work with if you validate everything. Consider the case when you have a method that receives an object and calls 100 other methods, passing the same object.

When do you validate whether that object was properly initialized? Do you validate it at the method that calls the other methods only? But then, later somebody else might call one of the 100 methods from another place without validating it. So, if we are to only validate, then we will end up writing the same validating code in 101 methods, instead of catching the exception at a single place, regardless of which method throws it.

You will also need to use third-party libraries. Are they perfect? Probably not quite and not all of them. How do you validate everything in the code written by someone else?

Summary:

  • sometimes there is no way to know whether an operation succeeds before running it
  • third-party libraries will come as they are, possibly with errors, you cannot apply validation for them, unless you get into their code and refactor the whole thing (you could as well write the whole library instead)
  • doing validation-only may lead to code repetition, unreadable code, code difficult to maintain and very long refactoring when the duplicated validation needs to be changed
  • you cannot think about all the possible errors, you need at least a layer that catches the problems you didn't foresee
  • when you upgrade some versions, like Python version for example, it is quite possible that something will no longer work

Validating operations is often a good idea, but it cannot substitute exception handling. They are going hand-in-hand. You validate what makes sense to be validated and that's often a subjective decision, but, if still an exception occurs, you need to handle that properly

Upvotes: 1

Related Questions