Code Libraries — Stop Creating Them
Code libraries can be a really useful and versatile vehicle for wrapping up pieces of code that you need to share. However, they simply aren’t being used correctly. I realise that many people will disagree here but allow me to flesh out my reasoning.
Want free coding tuition with me? I’m offering five people an hour each, first come first served, remote tuition and pairing. Details at the bottom of the post.
DRY is so, well, dry…
DRY stands for Don’t Repeat Yourself, and it is in this context that many libraries come into being. DRY is often misinterpreted, and this misinterpretation is reinforced with a very common misconception about Object Oriented Program which supports code being reusable and extensible. Eurgh, two more ugly words which cause annoyance and pain for all involved.
There is a single core reason why all of this causes pain, and to understand that we need to understand an abstraction layer about code. There are two types of code:
- Boilerplate implementation code
- Business logic and knowledge
The reason why DRY is so annoying is because it is most often applied to code of type 1. You see, bundling up your boilerplate code into a library, maybe it’s a set of entities, maybe its a common set of utilities, means that your actual application no longer controls how it does what it does. Extracting a utility method into a library so it can be shared, manipulated, mutated and turned into something that it shouldn’t be is a major code smell. You see, what happens with a utility method is it keeps getting hacked around, people will use that method to do something and then make a change to make it fit with something else. The problem is that it now doesn’t quite do what it needs to for it’s original purpose. Now we have to constantly hack this utility method, going back and forth. Quite simply, it should never have been extracted as a utility.
Suppose for example it’s a set of shared entities. Well, in this situation you now bind every project using that library into working in a certain way with the same database. Suddenly we are sharing databases across multiple applications. There is no central ownership of said database and there can now be multiple things making changes we don’t know about. No look, of course it’s possible for any application to connect to your database if they have the right connection string and access, but creating a library is literally shouting “Share me, mutate me, make it really difficult to manage me! Go on, you know you want to!”.
Extracting libraries for test purposes is another smell, by extracting a set of entities for the test code to use then the test code is no longer valid. If the set of entities have an ugly bug in them then this makes it pretty much impossible to spot. Tests done in this way provide false confidence and are just a waste of time and CPU cycles.
In reality there is only one genuine reason to create a library, and even then there is a better way of doing it. If there is a common algorithm or piece of business logic that everything needs to call then this is the candidate for a library. It is business logic, it represents business knowledge. If it was done in a different way then it would be incorrect. It needs to have central ownership and not be repeated anywhere. However, the better way of implementing this is as a service and not as a shared library. If it is a service then it is an application in it’s own right, with not only central ownership of what it does, but central ownership of the instance. Changing the algorithm in some way suddenly becomes a lot easier. Managing versions of libraries across applications is costly and painful. Managing a single instance of an algorithm is simple and easy. The only caveat with the service approach is that the service contract needs to remain consistent. If the contract does change then there will be work to do to propagate this through each of the calling applications.
A useful test that a friend of mine came up with recently is, only create a library if that library can be open sourced and shared with other people. If it can’t then don’t.
Dependencies
One of the most difficult things in software development is dependency management. There are applications whose sole purpose is to manage dependencies. The problem with dependencies is that you aren’t just including that dependency, you are including every single dependency that the first dependency needs. If you are in an environment where libraries are used, nay, encouraged then at some point it is highly likely that you are going to have some innocent junior/professional level developer creating a library that seems equally innocent. They will make that library depend on another library, because you know, DRY! Suddenly making changes has gone from simple to time consuming and difficult. I’ve observed countless developers searching for the nearest window through which to eject their laptop because of this.
But people should learn to be disciplined
Whilst this sentiment is true, people should always learn to be more disciplined, the simple matter is that catering only for disciplined individuals makes you elitist. This isn’t an issue in principal, but it does mean that your remuneration needs to reflect the expected level, and you must resign yourself to never taking on and nurturing junior talent. You are purely dependent upon others having taught that discipline. Don’t do this, it’s a recipe for failure and a very expensive bill at the end of the month. Quite frankly, time spent postulating that the problem is with everyone else is time that should be spent looking at how the environment and working practices can be changed to ensure that it is easy for people to work in the right way.
How do I code?
I keep things simple, stupidly simple. I’d much rather write the same piece of code countless times because it means that I have everything right where I need it. It’s much easier to debug, I know if there is a problem then it’s right in front of me, not in some other project. I don’t use abstract classes, I try to avoid using interfaces. I keep this specific and concrete. I break every rule in the rule-book and write code that another developer can easily pick up and read. I don’t like interfaces, seriously, when are you ever going to change databases without needing to change something pretty fundamental to your code. I do use some well established frameworks to handle things I don’t want to worry about. These are frameworks which are proven to simplify things, e.g. Spring Framework and occasionally hibernate. Do I use many other frameworks? Not unless it’s an established pattern where I am going and said place has a solid pipeline of people to take over when I’m done.
Before you go
If you are a junior or starting developer by the way and you want a bit of direct tuition then I’m offering 5 people an hour each of remote pair programming (skype or some other tool). It’s first come first served and you can book in by emailing me at kevin.timmins@socralogic.co.uk and will take place in the evenings and weekends (UK time). Similarly, if you are starting out in your career then checkout https://seed.socralogic.co.uk/ it’s a site built specifically for people learning to code and starting their career as a developer.