📜 ⬆️ ⬇️

About interfaces

First of all, the problem concerns grocery soft-developers, although in the project one, too, things are not going smoothly.

Let's start with a recent story. COM technology (and others, but the essence is the same) has enabled component developers to easily separate interfaces from implementation. For application developers, this meant, for example, that when updating components, old interfaces would continue to work. In theory, of course. But in practice, it looked much better than the “hell of dynamic libraries”, which always have the “current” version.

What is the mechanism? He is very simple.

Declares the component programmer interface
')
[uuid(a03d1421-b1ec-11d0-8c3a-00c04fc31d2f)] interface ICoolPrinting { void Print(const string fileName); } 

Then the programmer implements this interface. The compiled program is installed on the user's device, where in some registry the designated UUID is associated with an executable module. For example, in Program Files \ CoolPrinting1_0 \ cool.exe.

In a third-party application using this interface, an interface is requested from the same “registry” using the UUID and the required function is called.

 ICoolPrinting printing = GetInterface(...); printing.Print("c:\myfile.pdf"); 

What happens if a component developer changes functionality?

In a simple form, the interface is extended. This means that the developer is voluntarily obliged (feel this wonderful combination of words):

 [uuid(d26d1421-g1ec-12d0-8c3a-12c84ef31d2f)] interface ICoolPrinting2 : ICoolPrinting { bool SetupPrinter(); } 

Now even installed instead of old, the new version continues to work as before. An application programmer using a component doesn't need to redo anything. That is, absolutely nothing. Cool, yeah?

In a more complex version, the developer releases a new version that does not support the old interface. But at the same time, he again voluntarily is obliged to provide for the possibility of simultaneously installing a new version next to the old one, somewhere in Program Files \ CoolPrinting2_0.

And in this case, the application programmer also does not need to redo anything.

However, the above only happens in a world where programmers at least roughly have an idea of ​​what they produce. And their clerks know the business they are in charge of. This also happens.

More often the opposite happens.

In the most humane form, the programmer does not create a new interface, but simply rules the old one, changing its UUID at the same time. It is necessary to change the UUID, otherwise it will be impossible to distinguish the new interface from the old one. The new version is installed instead of the old one.

A program that uses a component stops working immediately. Because the link is still UUID leads to emptiness. But to get around this problem is quite simple, since the interface can be:

 OleVariant printing = GetInterface("ICoolPrinting"); printing.Print("c:\myfile.pdf"); 

Such a “cunning” technique will work until the component programmer deletes the old methods and interfaces. Then when you try to use the functionality in your application program, an error will occur.

The situation is aggravated by the fact that it is often impossible to install two versions of a component on the same device. Because if the developer failed to ensure compatibility at the interface level, then to ensure the conflict-free operation of different versions of the component, he will certainly not have enough brains.

The puck goes to the application programmer. Well-wishers from the forum whisper: "Pattern adapter." And even the "strategy". And why be surprised? The main purpose of the so-called design patterns is to create crutches and props.

And here is a simple and clear two-line application program — getting a reference to a component and calling a method turns into a mess of hundreds of lines of “patterned” code and several classes, according to the number of versions of the component. Of course, I will not bring them here.

Examples? You are welcome. The PdfCreator component, developing from version 0.x to the current version 2.x, was developed in this way. First, edit the old interfaces with the replacement of the UUID, and then the creation of new ones that are incompatible with the old, but already deleted ones. Two different versions on the same computer can not be installed.

One could argue that PdfCreator is a free open source utility. But what does that change? Is the negligence of developers can be compensated by the proverb "Do not look a gift horse in the mouth"? There are other examples of completely commercial components that do not provide compatibility between versions.

Morality. The rule “Made not here” (not invented here) has good reasons. At a minimum, having the source code at hand will be superfluous.

Source: https://habr.com/ru/post/254803/


All Articles