Software anti-patterns are a well covered topic, but I thought I would highlight some of the ones I’ve encountered most frequently. These may seem obvious and at times innocent looking but make no mistake, they are sinister and will sabotage your efforts to add features to a codebase. I’ve gone ahead and made up my own names for some of the more specific anti-patterns.
I would consider this a blanket anti-pattern which hosts an array of other anti-patterns. What’s special about accidental complexity is its ability to grow exponentially. One bad decision early on could trigger a bunch of (incorrect) defensive decisions later on.
New anti-patterns start surfacing like ‘Reinventing the square wheel’. A popular way for this to happen is when developers make the decision to solve a certain problem using their own code, as opposed to using tried and tested solutions that already exist, i.e. “Let’s create our own CMS!”
You will be too focussed on trying to fix your code to consider the bigger picture.
We’ve all been there, when you try and add a specific version of a gem to your project, run bundle install and are then met with a wall of red text complaining about versions being incompatible.
Also, when dealing with external systems (which has become ever more popular as systems become decentralised), they’re liable to get into a tug of war over what they consider correctness of data. Your app sits in the middle and has to keep both happy. Accidental complexity lies in wait, ready to complicate your code.
An example of this that I ran into recently is where I had Salesforce and Carmen expecting different names for the same country.
Salesforce would only accept ‘Korea’, and Carmen would only accept ‘Korea, Republic of’. It is not hard to solve without inheriting Accidental Complexity. One way to solve this is to create an intermediate representation of the data housed in your application (good luck to the next developer to inherit the codebase in figuring out what exactly is going on!).
Catch me if you can
Have you ever looked at a codebase to try and find the place to make your change, only to be thrown down a never ending rabbit hole of abstractions?
I was unable to find an existing anti-pattern that describes this situation, so I just named it myself. It also falls under the all encompassing Accidental Complexity anti-pattern, like most others do.
I am a huge fan of abstractions and small methods, but have hunted through some frameworks where the search just never seems to stop. This can be a result of premature optimisation, or just making things too general before it is needed. It may have been designed to deal with a huge amount of complexity, but will never be needed.
Without some sort of IDE functionality to navigate between the files you are left stranded.
Friday afternoon, and everything is going great. You push your commit to production, check New Relic, and all hell breaks loose.
Your fix has broken a bunch of other code, and your customer’s shop is now offline. All you can hear is money falling on the floor.
It takes 30 minutes to run your test suite locally. That is a lot of time for the website to be down. You cannot roll back using your awesome blue/green deployment system because your commit has changed the database schema (doh!). You frantically revert your commit, and push it back into the master branch.
Jenkins starts building your project and your test suite FAILS. You have introduced more bugs than there used to be in the first place. You are not moving forward, you are moving backwards at a rapid pace. The only advice I have in this situation is to remain calm. Your ability to solve the problem only decreases when you start getting stressed. Formulate a plan before just trying to solve the problem on the spot.
Abstractions of deceit
Also not a formal anti-pattern but definitely a descendant of Accidental Complexity.
There is a huge difference between reading:
It is good to introduce code seams as a way to add new functionality if your abstraction is not accurately named, it can be worse than having no abstraction at all.
On the other side of this is the “names that are too long and verbose” anti-pattern which I consider way less harmful this anti-pattern. It may hinder your ability to scan the codebase quickly, but at least once you read it, you will have a clear understanding of what it aims to achieve.
Naming is hard but it is good to label things so that they can be easily discussed. Be on the lookout for anti-patterns that you may come across on your travels, and flag them by name as soon as you recognise them. It also facilitates discussions when you can reference something by name, as opposed to explaining what you mean every time.