📜 ⬆️ ⬇️

Resist adding new libraries to your project.

What we build a house to build So, you needed to implement the X functionality in the project. Software theorists at this point say that for this you need to take the already existing library Y and use it to implement the things you need.

Actually, this is a classic approach to software development - the reuse of their own or others' developments (third-party libraries). And it is in this way that most programmers move.

However, theorists in articles and books forget to mention what hell the support of several dozen third-party libraries living in your project turns into, say 10 years later.

I recommend strongly resisting the addition of each new library to the project. But please understand me correctly. I don’t say that you don’t need to use libraries and write everything yourself. This is simply stupid. However, often a new library is added to a project at the whim of a single developer, with the goal of using some small little thing in it. Add a new library is not difficult. Only then the whole team will have to bear the burden of its support for many years.
')
Observing the development of some large projects, I can list a number of problems with a large number of third-party libraries. Probably, I will list by no means all the problems, but even the following list should make you think:
  1. Adding new libraries quickly increases the size of the project. In our era of fast Internet and large SSD drives, this is not a significant problem. However, when the project starts to be downloaded from the version control system not in 1 minute, but in 10 minutes, this is already unpleasant.
  2. Even if you use 1% of the library's capabilities, as a rule, it will be included in the project as a whole. As a result, if libraries are used as ready-made modules (for example, DLL), the size of the distribution kit grows very quickly. If you use libraries as source code, the compilation time increases significantly.
  3. Complicated infrastructure associated with the compilation of the project. Some libraries require additional components. A simple example: assembly requires the presence of Python. As a result, after some time to build a project, you need to first grow a whole garden of support programs on your computer. The probability that something will stop working increases. It is difficult to explain, it must be felt. In large projects, that one thing another constantly “falls off” and one must constantly make an effort to make everything work and compile.
  4. If you care about vulnerabilities, you should regularly update third-party libraries. It is advantageous for attackers to study the code of libraries in order to find vulnerabilities. First, many libraries are open, and second, by finding a hole in one of the libraries, you can get a master key at once to many applications where this library is used.
  5. You will have problems moving to a new version of the compiler. There will definitely be several libraries that will not rush to adapt to the new compiler. And you will have to wait or make some development in the library yourself.
  6. You will have problems switching to another compiler. For example, you use Visual C ++, and you want to use Intel C ++. Be sure there are a couple of libraries with which something goes wrong.
  7. You will have problems moving to another platform. Not even necessarily on a “very different platform”. It is enough to want to turn the Win32 application into Win64. You will have all the same problems. Several libraries will not be ready for this and it will be unclear what to do with them. The situation is especially unpleasant when the library is abandoned and no longer develops.
  8. Sooner or later, if you use a lot of C-libraries, where the types are not in the namespace, your names start to intersect. This leads to compilation errors or hidden errors. For example, it starts using a constant not from the enum from which you planned.
  9. If a project uses many libraries, adding one more does not look like something harmful. You can draw an analogy with the theory of broken windows . As a result, the growth of the project becomes uncontrollable.
  10. There are a lot of other negative points about which I do not remember and do not know. But in any case, additional libraries very quickly increase the complexity of project support. This difficulty can manifest itself in the most unexpected places.

I stress once again. I do not urge you to abandon the use of third-party libraries. If the program you need to work with images in PNG format, then you need to take the library LibPNG and not reinvent the wheel.

But even working with PNG, you need to stop and think. Do you need a library? What operations need to be performed with images? Perhaps, if the whole task comes down to saving some image in a * .png file, you can get by with system functions. For example, if you have a Windows application, then WIC will help you. And if you already use the MFC library, you don’t need to complicate the code at all, because there is a CImag class (see the discussion on the StackOverflow website). Minus one library - great!

I will give an example from my own practice. In the process of developing the PVS-Studio analyzer, a couple of diagnostics required the use of simple regular expressions. In general, I am convinced that regular expressions have no place in static analysis. This is a very ineffective approach. I even wrote an article on this topic. However, sometimes you need to find something in a string using a regular expression.

It would be possible to “tie” some of the existing libraries. It was clear that all of them would be redundant, but regular expressions are still needed, and some decision had to be made.

Quite by chance, at that very moment I was reading the book “Beautiful Code” (ISBN 9780596510046). This book is about simple and elegant solutions. And in it, I met an extremely simple implementation of regular expressions. Literally a few dozen lines. And that's it!

I took this implementation from the book and started using it in PVS-Studio. And you know what? Until now, the possibilities of this implementation are enough for us. We just don’t need any complex regular expressions.

Total. Instead of some additional library appearing in the project, about half an hour was spent on writing the necessary functionality. The desire to use the library “for all occasions” was suppressed. And it turned out it was the right decision. This is confirmed by the fact that for several years this very functionality “for all cases” was not needed.

This case finally convinced me that we should, if possible, look for simple solutions. Whenever possible, abandoning libraries makes the project simpler.

It may be interesting for readers to find out what kind of code this is for searching regular expressions. I will reprint it from the book.

See how elegant. This code was slightly modified by me when integrating into PVS-Studio, but its essence has not changed.
Code from the book
//   . // c    "" // .()     // ^     // $     // *        //   int matchhere(char *regexp, char *text); int matchstar(int c, char *regexp, char *text); // match:        int match(char *regexp, char *text) { if (regexp[0] == '^') return matchhere(regexp+1, text); do { /*      */ if (matchhere(regexp, text)) return 1; } while (*text++ != '\0'); return 0; } // matchhere:        int matchhere(char *regexp, char *text) { if (regexp[0] == '\0') return 1; if (regexp[1] == '*') return matchstar(regexp[0], regexp+2, text); if (regexp[0] == '$' && regexp[1] == '\0') return *text == '\0'; if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) return matchhere(regexp+1, text+1); return 0; } // matchstar:     *    int matchstar(int c, char *regexp, char *text) { do { /*  *       */ if (matchhere(regexp, text)) return 1; } while (*text != '\0' && (*text++ == c || c == '.')); return 0; } 



Recommendation. Resist adding new libraries to your project. It is necessary to add only when, when it is obvious that one cannot do without a library.

Here are some possible maneuvers:
  1. Perhaps the required functionality is already provided by your system's API or one of the libraries already in use. Explore this question.
  2. If you plan to use a very small piece of functionality from the library, then it makes sense to implement it yourself. The argument "it is better to connect the library, then suddenly something else is needed" is no good. Almost always from this library in the future nothing else will be used. Programmers are too addicted to universality, which is not really needed.
  3. If there are several libraries to solve the problem, then choose the simplest one that meets the requirements. As I wrote above, chase away the thoughts "just in case, take the library more abruptly."
  4. Before you start adding a library, just wait and think. Have some tea, get distracted, discuss the problem with your colleagues. Perhaps in the process it turns out that it is possible to solve the problem in a completely different way, without resorting to the help of third-party libraries.

PS Many told here will not like. For example, what I recommend using is not a portable universal library, but let's say WinAPI. There will be objections to this, based on the fact that we thereby tie the project to one operating system. And then it will be very difficult to make the program portable. I disagree with that. Often the idea of ​​“later transferring the operating system to a friend” lives only in the developer’s head. In fact, such a task in general can never be set by management. Or the project will be "bent" because of the excessive complexity and universality, even before the moment of popularity and the need for porting. Plus, do not forget point (7) in the list of problems given above.

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


All Articles