How to use exceptions correctly

    It is a pity if your study of the concept of exceptions ends with reading the corresponding section of the official documentation for your language.

    After examining the syntax of the try {...} catch (Exception $ e) {...} construct, learning about the ability to create your own exception classes, inheriting them from the Exception class and superficially realizing the power of the mechanism in your hands, you can go one at a time of two ways:
    • Start using exceptions right away . Let's say screw them to a system in which they have never been used. Or pin them on a project in which OOP doesn't smell. Or, worst of all, trying to use them everywhere, especially where it is not needed.
    • Try to understand where to apply them, how to do it right, and why they are needed.

    1. You need to be able to clearly distinguish between an exception and an ordinary error in the program, for example: an incorrect username or password is not an exception! This is a user error, not a program, and it can happen very often. On the other hand, the failure of the mysql_connect () function due to the inaccessibility of the database server is an exceptional situation, an exception must be thrown! More on this later.

    2. Class methods should notcatch exceptions thrown by other methods of the same class. The library should not know anything at all about what to do in case of an exceptional situation in its methods, since depending on the system where it is used, this behavior can vary greatly. Her job is to throw an exception. For example, if the file required for the correct operation of your entire class does not exist, you should not deal with this. This is a matter of higher levels of the application.

    On the other hand, you can very well catch the exceptions thrown by lower levels (if you want). If you don’t want to, they will be passed along the stack to the nearest catch {} (more precisely, to catch {} , corresponding to the nearest try {}) Suppose you have a wrapper class for working with a database, with methods like connect () , query (), and so on. Of course, if you can’t connect to the server, you need to throw an exception in the connect () method .

    However, neither the connect () method itself , nor even the query () method , which could call connect (), should intercept it.automatically! This exception should be caught at a higher level that works with methods of this class, and a decision should be made there - try to connect to another server, use a different type of data source, just display an error, or pass the exception even higher (on different systems in different ways, let them decide what to do). I hope the idea is clear.

    3. In a large application, you must use your own exception classes (inherited from the built-in Exception ). This allows you to build a hierarchy of error classes and separate them by importance, type, and so on. Let's say we have a class Application_Exception :

    class Application_Exception extends Exception{...}
    и несколько его потомков:

    class Logic_Exception extends Application_Exception{...}
    -- логические ошибки, например, нарушение связности таблиц в БД или уникальности ключей.

    class Data_Access_Exception extends Application_Exception{...}
    -- ошибки доступа к необходимым данным, вроде отсутствия файла, или устройства, или связи для доступа к какому-то источнику.

    class Security_Exception extends Application_Exception{...}
    -- ошибки с безопасностью, например человек присылает куку, которой у него просто не может быть ;)

    All these types of errors should be handled differently, for example, you shouldn’t shout about security errors on the entire Internet, but in case of a database server failure, you can display an intelligent plate with an apology (in general, for taste and color).

    4. For the maximum amount of error information, use the capabilities of the built-in Exception class , do not reinvent the wheel! If the file name and the line where the exception was thrown is not enough for you, the getTrace () and getPrevious () methods are at your service , which will certainly lay out the whole “picture” of what happened before you (for more details, see the documentation).

    In this note, I tried to state the main theoretical points that I consider most important when using exceptions. The original entry is on my blog.
    Good luck!

    Also popular now: