
Recently, an interesting article about the problems in the concept of encapsulation caught my eye -
read if you have time.
For those who have no time, I will quickly retell the essence: encapsulation does not perform one of its main tasks (to give a black box with the described inputs and outputs) for a number of reasons:
- Programmers do not trust other "black boxes".
- In foreign "black boxes" mistakes happen that have to be fixed, getting into their insides (and breaking this whole idea).
- Inputs and outputs are not always described clearly. Sometimes it’s easier to build your bike than to figure out how to ride someone else’s.
All this is a despicable reality that programming theorists ignore. And how to live with it?
No idea. There is hardly any “silver bullet” here (and where is it?), And in each case you have to decide something of your own. The story will be about one such case and one of the solutions.
I once caught one big project - it was written for many years and many people. Accordingly, for each task in the spirit of encryption \ parsing \ archiving \ etc. long ago their modules were written. It would seem - lafa, take it and use it. But the trouble is that there were so many of these modules and they were written so long ago that no one remembered either their authors or the details of their implementation. Classic "black boxes". Sometimes understandable, sometimes not. Sometimes working, and sometimes buggy. Well, how to use it?
I thought a bit and decided to make a “wrapper” for each class used, according to something like the following principle: here is a HUGE encryption class that has a lot of options and a monster in general. (Who has seen serious classes for encryption, he knows what I mean - there are all the initialization vectors, constants, etc.). I need it for only one purpose - to encrypt and decrypt the file using a symmetric key. And that's all. Well, then we take and write a wrapper of two methods:
- Encrypt File (what, where, key)
- Decrypt File (what, where, key)
Inside the methods we pull complex methods of the base class. Next on the code we use our wrapper. What are the advantages?
- The problem of non-customization of an ALIEN black box has been solved - now everywhere on the code I use MY OWN black box. I believe him. It will start vykobenivatsya - change the insides, to use some other means of encryption (without changing the interface).
- On such a simple wrapper, I now instantly write tests. What to write them: encrypted - decrypted - checked files. 5 lines of code. Plus, checking for errors in file operations is another 10. I wouldn’t undertake writing tests on that big and terrible base class — long and difficult (they weren’t even written by its author). Moreover, my tests will be better than the tests of the author of the class, even if he wrote them. Because the author of the code always has some idea of ​​how this code will be used. And this is reflected not only in the code, but also in the tests. Well, the author would have believed that files for encryption always exist and are readable - and would not check it in tests. And I know that this is not my case - and I will definitely check these situations. Well, because I really need it.
- The inputs and outputs have become much clearer. Well, at least to me. Yes, and others, I think so. And do not care that I created another entity, the old Occam will forgive me.
At the end of the article, the idea crept up to me that I unwittingly retold some chapter of the book by Fowler or McConnell, it sounds so simple and banal. But it seems to be not (correct, if I am mistaken).
Update: I am told from the audience here that I am telling about the Patterns of the Facade and the Adapter from the book of the Gang of Four - it may well be.
')
Short moral
If you use someone else’s code that you don’t trust, write a wrapper for it that would be convenient for testing and for real use. Test this wrapper as it will be used by real code.