
Each programmer once, at the beginning of his Path, wrote something like this:
double div( double a, double b ) { return a / b; }
And I was fully confident that this function does exactly what it needs - divides a into b. But sooner or later a friend or a teacher was around, explaining that this function does another important thing in the life of any program: knocks it down with the exception of dividing by zero if b is zero. After that, the future programmer came to understand the need to verify the input data. Someone on this solved the issue exhausted, and someone came to the conclusion that this is only half of Tao.
In fact, putting checks at every step is a common practice. This is taught in the university, before you reach it with your mind. But over time, the thought comes that something is wrong:
- Checking various things takes up a lot of space in your code. Behind the checks, this same code generally ceases to be visible.
- Profiler shows that a significant part of the time is spent on checks. The program slows down. Users complain.
- The same checks are repeated many times. If in some class there are functions that call each other and work with the same data - the checks are written in each of them and some of them are triggered "idle."
The concept of the barricade offers a way out of this situation.
')
McConnell, Fowler and maybe someone else wrote about the barricade. The essence of the approach is to draw an analogy between the work of the program and some armed conflict (war). There are always Ours and Not Ours in war. Ours are close by in the trenches, on this side of the barricade. You can trust them, with them you can break the bread and not be afraid to bend over the soap in the bath. Not Ours are those who are on the other side of the barricade. They can not be trusted. Among them can be both enemies and civilians. But you can't trust anyway. Everyone needs to check and find out what breathes.
The concept of the barricades proposes to draw a line between the entities, separating them from each other with a sort of barrier. By “entities” you can mean different things. Depending on the scale and architecture of your system, a barricade can pass between class methods, between classes, between individual modules (libraries), etc.
Some entities (let's call them “barricaded”) live in an active and aggressive environment, interact with the outside world, are called by outside classes, and any nonsense can be transferred to them. They must begin with all the necessary checks and trust no one. Invalidity of the input data should be considered as a normal mode of operation. He should not blame the program. Depending on the ideology adopted in the project, upon the arrival of invalid data, you can write a message to the log, give a message to the user, or silently correct the data to valid data and continue working.
The next group of objects is the barricade itself. The role of the barricades is to guarantee everyone who is inside security. Nothing should get inside the barricade unchecked, unconverted into internal formats, invalid, etc. This includes a variety of converters, validators, wroppers and other similar things.
And the last part of the concept is “intra-barricade” residents. They are those for the sake of which all this venture began. The method inside the barricade may not check the input parameters or the current state of the object to which it belongs! For him, it is already guaranteed to make a barricade. In all intra-barricade methods, ASSERTs are obliged to stand, since the invalidity of something is no longer a problem of interaction with the external environment, but a specific error in the barricade. Her debug version needs to be detected and corrected. And in the release, ASSERTs will be thrown by the compiler and will not disturb anyone.
Of course, there are drawbacks in the barricades - you need to clearly differentiate things relative to the barricades by levels of trust in them, checks inside the barricades are still necessary (ASSERTs), even though they are much smaller. All this solves somewhere between one and a half or two of the three problems described at the beginning of the article, so it can sometimes be useful.