Hidden costs of freeware libraries
There are so many open source libraries and frameworks out there for developers to download and use that it is very tempting to use them universally, without asking oneself if a given library or a framework is really necessary for the project. With the popularity growth of package managers, it became extremely easy to add another dependency to a project, encouraging even more the behavior where one has to justify not using a third-party component. Finally, the performance impact of just another layer is so small that nobody would care about that for most products anyway.
Every library and framework, however, has an inherent cost, which is paid during the whole lifespan of the product. This cost manifests itself in four ways:
One has to learn the component, its quirks, its tricks, its incompatibilities. If the component is maintained, new versions are released, introducing new features to learn, and new issues to handle, so learning becomes a constant process, which can take, for some of them, considerable time. One should note that contrary to REST APIs, libraries, and moreover frameworks, have a large and intrusive interface which could be very complex.
Of course, it all depends on the APIs, the libraries and the frameworks; some APIs such as Amazon S3 could get rather complex, but their interface is still small compared to the frameworks such as Laravel.
Every library and framework being designed for the purposes slightly different from the purposes of a specific project using it, constraints need to be circumvented. This could ultimately lead to a fork of the component; for more basic aspects, it translates into man-hours wasted searching of a way to circumvent a given limitation.
As a furry friend, a component seeks regular attention and care. New versions should be deployed, architectural preferences should be followed. Every new version brings new surprises, and the code should be tweaked on regular basis to fit anything framework developers throw at their users.
As an illustration of those points, I recently worked with a team of four developers who maintain a web application. The application is not that big: a few pages, a few highly interactive forms, lots of AJAX—well, the routine. It could be done with plain jQuery and jQuery UI, and some lightweight library for data binding. Those developers, however, have chosen the path of a warrior—AngularJS, TypeScript, and a few dozen of npm
dependencies, given that I'm uncertain of the purpose of more than half of them.
Well, one would say, what AngularJS and other things bring is what the team doesn't have to develop from scratch, and this is good. But there are a few issues:
One of four developers spends practically all the time dealing with purely technical aspects related to AngularJS and the libraries. Others deliver features needed by the users of the web app, but not him: he's too busy upgrading to the next version of something, or tweaking something else, or fixing code which was broken by the upgrade to the next version of a package. When all
npm
libraries are up to date, he'll find that TypeScript needs to be updated, and this leads to a global fixing of some fancy things which were deprecated by the new TypeScript. And when this is fixed, it appears that one of the libraries is incompatible with the new code, and should be tweaked.As if it wasn't enough to waste one person's time for that, he constantly requires help from other members, or even from other teams, meaning even more money thrown without bringing any actual value to the users.
And of course there are new libraries, and new testing frameworks, and... new stuff. Since new is always exciting, one should absolutely use it in the project, so from time to time, new furry pets join us, requiring attention and care as well.
I practically don't know AngularJS, so it is not surprising that it takes me hours to do things I would do in a matter of minutes with plain jQuery. What surprises me is to see the time my colleagues spend on problems which could be solved very fast without all those fancy frameworks and libraries. There is some weird stuff where nobody knows how to handle a limitation of TypeScript or AngularJS, and then someone ends up hacking a thing which doesn't look nice or maintainable.
Leaky interfaces suck. TypeScript made me waste numerous hours, pretending that it will handle something in some way, while it would leak JavaScript aspects through it; therefore, I hate TypeScript.
While those frameworks and libraries do occasionally reduce the code the team needs to maintain, there are cases where it adds too much needless complexity. Maintaining those parts of the codebase is complex, and usually results in constant code growth, leading to technical debt inflation.
My impression is that, overall, those frameworks and libraries tend to bring a slight benefit in terms of code maintainability compared to the same solution developed with bare jQuery, a few libraries and a lightweight data binding mechanism, but the slight benefit is too minor compared to all the issues.
I'm not certain why we got at the point where the default choice is to add another library. However, I'm certain that this is a wrong approach. It makes products rigid, and ultimately wastes more time that it saves. Libraries, and even more frameworks, should be selected on the basis of an actual, materialized need, and on a firm decision that introducing this dependency into the project will benefit more than writing code from scratch. I'm not saying that things such as AngularJS shouldn't exist: what I'm saying is that they shouldn't be used until it becomes clear that they bring a visible benefit in terms of time-to-market, code maintainability, structure, or whatever measurable factor matters for a given team. All those components, despite being free to download and play with, do have a cost, which translates itself in thousands of dollars per month for even a small team. There should be something truly valuable they bring to be worth paying that much to use them.