Samurai principle

    In the world of software development, there are many ideas and “metaphors” borrowed from other areas that seem to be not very related to programming. You can recall the design patterns borrowed from architects, or the concept of “technical debt”, which came from the financial industry, and the designers of any systems, not just software (*), suffer from the “second system effect”. All this simplifies communication between developers or between developers and customers, and also simplifies understanding of a particular problem in software development.

    Another metaphor, or rather a design principle, is the “ samurai principle", Designed to describe the" contract "between the function and the code that calls it, is as follows. Any function that implements a certain unit of work must follow the same code of honor "bushido" by which any samurai lives. So, the samurai will not perform any tasks that contradict his "code of honor" and if you approach him with an "obscene" proposal, he will blow your head off before you have time to blink an eye. But if the samurai gets down to business, then you can be sure that he will bring it to the end (**).




    Any open source should follow the same principles.function. If she was “slipped” by inadequate input that violates her precondition (that is, her code of honor), then she should clearly say this with the exception (this is an analogue of the demolition of the head, because you yourself are to blame for this). But if the arguments are valid and it is called in the correct state, then the calling code can be sure of the result: the function will either succeed or “crash”. A function, like a samurai, must follow the do-or-die principle, but if a samurai makes a seppuku to avoid shame, then a function, if it is not able to do its job, should “fall” with an exception.

    This seemingly simple principle provides answers to many difficult questions of exception handling. Is it necessary to check the arguments of the function and what to do if they are incorrect? Do I need to swallow the exceptions that occur in the guts of this function? Do I need to return null or an empty list if something went wrong and the function cannot do its job? (***)

    If the function receives invalid input parameters or it is called in an incorrect state, throw an exception; if an internal function throws an exception when doing its job, then this means that your function will not be able to do its job either. In this case, either throw the exception or wrap it in another exception.

    It follows from this principle that “swallowing” exceptions is bad, because you, in fact, hide your problems from the eyes of the calling code and prevent the external code from learning about it. You don’t have to take too much on yourself, let your “client” have a headache, what to do with “your body” (that is, with the exception), when you have failed in your task and decided to follow the principles of the samurai.

    Returning a null object in case of exceptions is also a dangerous practice, because the calling code simply cannot determine whether an empty object is a valid value or an error occurred while receiving it:

    public SomeEntry ReadEntryById(int id)
    {
      try
      {
        // Читаем SomeEntry из базы данных
      }
      catch (Exception)
      {
        // Ядрёна кочарыжка! Как же вызывающему коду узнать,
        // была ли ошибка, или записи с таким id нет в базе?
        return null;
      }
    }

    * This source code was highlighted with Source Code Highlighter.


    There are times when a function can catch an exception and not throw it to the calling code; it may be a function of the highest level and the calling code may not be. In other cases, the function can try to recover on its own after an error occurs, but, ultimately, if this attempt is unsuccessful, then it will have no other choice but to follow the samurai principle - "do your job or die."

    --------------

    (*) For details on what kind of metaphors are, refer to the corresponding notes: “Technical Debt” and “Effect of the Second System” , respectively.

    (**) Most of the articles on the “principle of the samurai” speak only of the second part of the agreement that, they say, any method, like a true samurai, must either do their job or die. But the calling code is not the chief of the samurai or his emperor, whom the samurai must obey unquestioningly. A samurai, like a function, should not perform tasks that run counter to their "code of honor"; in the relationship between the function and the calling code, it is important that both parties comply with their agreements.

    (***) The samurai principle is not a revolution in software development; The principles have been following this for a long time, and some do it in a rather formal way with the help of design by contract. If you want to get acquainted with the concepts of preconditions and postconditions, you can start with the article “How not to write code”, or turn to a series of articles on the subject of design by contract .

    Also popular now: