Walking Dead Libraries

This is not a new post, this post is related to other posts and issues that I'm talking about in this blog for at least +10 years. When I started doing SOA I fall in love with it because was all about Services and not about libraries. +15 years doing SOA and this problem still exists in the industry. Dependency management is a lost discipline, and it's super needed nowadays. Every company on earth has internal shared libraries. However, libraries often are a huge trap. There are ways to deal with this issue. The biggest problem often people dont realize is that OSS libs are often maintained by small teams that cannot afford to maintain several old versions of libs for free. Some companies behind popular and big OSS solutions have a paid support service where often you can bigger support for longer. However, that's not the reality for all and the majority of libs out there. Often product teams are focused on release features. Product teams often dont have Slack. The outcome is that libs are practically never updated. Sure, if you have a bug, there will be attempts to update libs, but very few teams update libs proactively. To make it worse, shared libs are full of binary coupling. I work in several companies, all had this issue, sometimes with Guava, other times with Spring, but one lib or another does not change the nature of the problem. 

The walking Dead Libraries

A walking dead library is a library that is nor live nor dead. It's an undead lib. That means an alive lib? An alive means that the lib is maintained and has been updated.  A walking dead lib is a lib that does not have a team maintaining or for a specific set of versions dont have updates(bug fixes and sec patches) and therefore is dead but at the same time is used by your business code.  

The business side and Options

Think like a business owner(BO) or even as a product manager. Lib versions sound very futile or even as an optional thing to do. There is no direct benefit for the business. Meaning you will not get new customers; it could be almost hidden for end users. All true. But by having binary coupling in shared libs and several libs being dead(no patches, no updates, not being actively supported. This is a real issue for the business because it creates the following problems:
 * Security Vulnerabilities (could disrupt your customer experience and brand image). 
 * Slowness (Mantainence cost getts bigger and new features take longer or engineer turnover). 
 * Cost (Development time takes longer, Lack of online resources, developer experience is affected). 

All these issues are only visible to the business after time; there is a compound effect here. Unfortunately, if not capture early, the fix's high and potentially meaning re-writing a lot of software. There is an "easy" solution, which is to build a new bridge. Meaning: Don't use your shared-libs and create a new service from scratch. This solution works, and you can isolate legacy from new services via Service Interface(REST, gRPC, GrpahQL, etc...); however, when you need to touch the legacy, there is nothing to save you. This approach is hard and takes a long time to get it there. But it's hard to do it as we have data involved, and data migration is not easy(part 1 and part 2). To make it more interesting, often these issues are related to Team Erosion issues as well. 

Fixing the Problem at the Source

Some things can be done to "stop the bleeding"; however, it's hard to keep consistency between several teams at Scale. But their actions can be done. The biggest challenge here is not the actions per-se but the discipline to keep actions happening consistently over a long time. That's why you need to automate as much as you can. Because automaton does not lose discipline over time. Frequent Retrospectives give you a chance also to remember and dont lose sight of recurrent problems. 

In the sense of actions, here are some Possible Actions:
 * During Code Review has a checklist to verify if you have libs to be updated. 
 * Avoid creating shared-libs; even consider stop doing them or deleting code. 
 * Have to Slack for the team, so they have update libs organically
 * If you need to have a lib, avoid coupling with 3rd party or consider creating a service 
 * Move code from the lib to your service, making feature changes more isolated and under control. 
 * Take control over repository-creating and ask people(if it is a lib) why they are doing that. 
 * Have mono-repos and therefore have libs inside your repo(Bazel or Buck).

What does a Shared-Lib Do anyway? 

Shared-Libs do hypercomplex math algorithms, using machine learning and often with +1M LOC with several branches and low-level system programming with extreme performance. If that was the answer, I would be super happy. However, the reality is completely different. Shared-libs, in several case, have:
 * Configurations (property files, Spring Beans for Config) 
 * Developer Preference often related to Configuration or frameworks selection 
 * Often rarely used over-engineer features 

Developers dont like to duplicate code. However, there are other ways to fix these "issues." First of all, code duplication is not a problem, especially if it is a config or preference. Secondly, we have better ways to ship this kind of code; some possible options are:
 *  Template Service (A project on github people can fork and start a new service using it). 
 *  CLI (NodeJS Comunity has several CLI for React, Angular, and so on and on, we could do the same).
 *  Documentation: Explain what libs show be used and why and what should never be on libs.

I said this multiple times over the years, and I will keep saying: Shared Libraries(Binary Coupling) create distributed monoliths with kills any microservice approach. Unfortunately, the industry is closer to kill all forms of microservices than fixing the libs issues. 

Cheers,
Diego Pacheco

Popular posts from this blog

Kafka Streams with Java 15

Rust and Java Interoperability

HMAC in Java