In the world of software development, there are many ideas and "metaphors", borrowed from other, seemingly, not strongly associated with programming areas. We can recall the design patterns borrowed from architects, or the concept of “technical debt”, which came from the financial industry, and the “second effect” of the system suffers designers of any systems, not just software (*). All this simplifies communication between developers or between developers and customers, and also simplifies the understanding of a particular problem in software development.
Another metaphor, or rather the principle of development, is the "
samurai principle ", designed to describe the "contract" between the function and its calling code, and is as follows. Any function that implements a certain unit of work must follow the same code of honor "bushido", according to 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 “indecent” offer, he will blow your head off before you have time to blink. But if a samurai gets down to business, then you can be sure that he will bring it to the end (**).

')
The same principles should be followed by any
open function. If she was "slipped" inadequate input data that violates her precondition (that is, her code of honor), then she should clearly say this with the exception (this is analogous to the demolition of the head, because you 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 confident in the result: the function either succeeds or “crashes”. A function, like a samurai, must follow the “do-or-die” principle, but if a samurai, to avoid shame, does seppuku for itself, then the function, if it is not able to do its job, must “fall” with an exception.
This seemingly simple principle provides answers to many difficult questions of exception handling. Do I need to check the function arguments and what to do if they are incorrect? Do I need to swallow exceptions that occur in the guts of this function? Do I need to return a
null or empty list if something went wrong and the function cannot do its job? (***)
If invalid input parameters are passed to the function or it is called in an incorrect state, generate an exception; if, when performing its work, an internal function generates an exception, this means that your function will not be able to perform its work either.
In this case, you must either throw an exception, or wrap it in another exception.It follows from this principle that it is bad to “swallow” exceptions, since you, in fact, hide your problems from the eyes of the calling code and do not allow the external code to know about it. There is no need to take on too much, let your “client” have a headache, what to do with “your body” (that is, with an exception) when you did not cope with your task and decided to follow the principles of a samurai.
Returning a null object in the case of exceptions is also a dangerous practice, since the calling code simply cannot determine whether the empty object is a valid value or if an error occurred when it was received:
public SomeEntry ReadEntryById( int id)
{
try
{
// SomeEntry
}
catch (Exception)
{
// ! ,
// , id ?
return null ;
}
}
* This source code was highlighted with Source Code Highlighter .
There are cases when a function can intercept an exception and not forward 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 independently try to recover from the occurrence of an error, but ultimately, if this attempt does not succeed, then it will have no choice but to follow the samurai principle - “do your job or die.”
--------------
(*) For details on what these metaphors are, refer to the corresponding notes:
“Technical debt” and
“Effect of the second system” , respectively.
(**) In most articles about the "principle of the samurai," it says only the second part of the agreement that, say, any method, like a true samurai, must either do its work or die. But the calling code is not the head of the samurai or his emperor, whom the samurai must obey without question. A samurai, like a function, should not perform tasks that contradict 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; This principle has been followed a long time ago, and some do it in a rather formal way with the help of contractual design. If you want to get acquainted with the concepts of preconditions and postconditions, then you can start with the article
“How not to write code” , or refer to a whole series of articles on the subject of
designing under a contract .