The general performance, maintenance, and scalability of an application or system depend highly on the code structure. Unfortunately, due to the complex nature of software development, developers working on an application might resolve to use anti-patterns as a quick solution to a problem. Unfortunately, most of these anti-patterns end up causing problems to the general functionality of an application and future code maintenance.
Here are 10 code anti-patterns you should avoid in software development:
- The Golden Hammer
- Spaghetti Code
- Reinventing the Wheel
- Dependency Hell
- God Object or God Class
- Hard Coding
- Boat Anchor
- Copy – Paste Programming
- Lava Flow
- Cargo – Cult Programming
Remember when you had to explain to a fellow developer (probably a senior) why you used a particular code pattern that ended up causing problems in production? Well, this post will save you from experiencing such a situation again. You will learn the ten most common Code Anti-Patterns you must avoid in Software Development.
Table of Contents
What are Antipatterns?
The term “Anti-patterns” first appeared in the tech field in 1998 in the book AntiPatterns and C Traps and Pitfalls. The latter was written by Andrew Koenig, a Bell Labs programmer. According to him:
“An antipattern is just like a pattern, except that instead of a solution it gives something that looks superficially like a solution but isn’t one.” Andrew Koenig
In other words, anti-patterns might look like a good solution at first but eventually turn out to be the opposite, doing more harm than good.
Anti-patterns have a negative impact on your software. They either introduce more bugs, raise security issues, or hinder code readability and maintenance. Below are ten code anti-patterns that will help you improve how you write your code.
The Golden Hammer
This anti-pattern is a well-known solution in software development and is commonly used to make the development process much faster. It refers to the concept of using the same solution used to solve problem “A” to solve problem “B.”
Let’s use an example to give you a better understanding. You are developing an application, and you encounter several problems. You manage to come up with a solution that helps you solve problems “A,” “B”, and “C.” When you encounter a problem “D,” you still want to use the same solution because it worked for the others.
You are using this solution as the “Golden Hammer” for all your problems. Unfortunately, that is not a good practice, and you might end up with an overly complicated code by trying to fit the solution where it’s just impossible.
In software development, every problem has a unique solution. Always remember to choose the right tools, libraries, frameworks, and architecture for every problem. It is always recommended to come up with at least two solutions for each problem. Weigh the pros and cons of each before deciding to implement one that you find suitable.
Spaghetti Code
Have you ever looked at a plate of spaghetti and just observed how each spaghetti is tangled and jumbled with each other? You can’t even know the start or the end of every spaghetti. Well, in software development, it is not a surprise to come across code similar to that. It’s called Spaghetti Code.
It is one of the most popular code anti-patterns, and most applications today are a victim of it. It mainly arises when a developer starts working on a project before taking note of the program flow and understanding the documentation well.
This type of code ends up messy. It lacks proper conditional blocks, numerous GoTo statements, threads, and exceptions, has code snippets that belong to other places, has functions that invoke multiple functions from other parts, and methods or classes that the program cannot reuse.
Things become worse as your program grows. Your already messy code becomes messier. You start having multiple functions in different files invoking each other. You start copying and pasting a piece of already working code to solve a problem in a different part of your application. Whenever you delete a single function, half of the application breaks.
This type of code becomes hard to scale, extend and maintain. And in situations where a new developer takes over, they will have to spend a lot of time fixing and optimizing the existing code before working on new tasks.
Reinventing the Wheel
That is another anti-pattern you will come across that often leads to spending too much time on a project. It refers to a scenario where developers opt to come up with a custom solution instead of using the existing solution in the market with the help of API and libraries.
Think of a company that wants to add a blog/posts page on its website. It will take time and resources if developers decide to develop a custom CMS (Content Management System) from scratch. Instead, they can opt for already existing solutions such as WordPress, Joomla, and even headless CMS like Strapi, Ghost, or Contentful.
The concept of creating a custom solution (which might end up not being so good) when there is already an existing and working solution is known as “Reinventing the Wheel.” This anti-pattern mainly arises when developers think the current problem is unique to solve with the existing solution and poor communication between development teams.
Dependency Hell
In most cases, when you focus much on avoiding “Reinventing the Wheel,” you will most likely fall into the “dependency hell.” Instead of developers developing custom solutions, they import many third-party libraries into their projects. Unfortunately, some of these libraries also rely on other external libraries.
Therefore, if you want to import a library to help you implement an image carousel or get system logs, you eventually get to a situation where you have libraries with multiple sub-sub-dependencies. That makes the code quite hard to manage and maintain.
To avoid this anti-pattern, use package managers that update and maintain every package and its dependencies smartly. If you are a NodeJS developer, check out our post “Difference Between package.json and package-lock.json.” It will give you a detailed guide on how NPM uses the “package.json” and “package-lock.json” files to manage your dependencies.
God Object or God Class
Do you have an object or class that handles practically everything in your code? User’s first name, surname, location, employee id, salary amount, number of vacations, etc. That’s the typical God object. It has too many responsibilities and dependencies.
This anti-pattern goes against the Principle of Single Responsibility in programming. According to this principle, every class should only have a single responsibility or single purpose in your project.
This issue arises when developers ignore creating additional classes during the project’s initial phase and plan to do that later. Unfortunately, they continue adding more responsibilities to the initial class that even other functions and methods depend solely on. In most cases, it is perceived as the application’s main class.
Below is an example of a Javascript object that acts as a “God Object.”
const schoolObject = {
studentID:"",
studentCourse:"",
studentClass:"",
teacherID:"",
teacherSalary:"",
staffID:"",
staffSalary:""
}
The schoolObject
above has so many responsibilities. It can be subdivided as follows.
const studentObject{
studentID:"",
studentCourse:"",
studentClass:"",
}
const teacherbject = {
teacherID:"",
teacherSalary:"",
}
const staffObject = {
staffID:"",
staffSalary:""
}
Hard Coding
This anti-pattern is most common in web development. A developer directly adds various parameters into the source code instead of fetching them from, say, a database, API, user input, the ‘.env’ file, etc.
Two main issues arise with this anti-pattern. The first is security. If you hardcode an authentication parameter such as an API access token or JWT token, somebody can easily access it by just viewing the source code from the browser.
The other issue is environmental change. When you hardcode parameters when working in “development,” your application will work perfectly. However, the application breaks when you push the changes to the “production” environment. You will need to edit the source code every time to suit every environment.
Boat Anchor
This anti-pattern mainly arises when developers code an application with the “what if” question in mind. What if I need to add this functionality in the future? What if this particular scenario occurs in my code while in production? What if a user tries to access this feature?
With all these “what if” questions in mind, developers eventually write additional lines of code not needed by the application at that particular moment. According to them, these extra lines might become helpful in the future. Unfortunately, this anti-pattern does more harm than good.
In the future, when other developers look at your code, they can see some methods and classes that they are unsure of their purpose in the application. They spend much time understanding and debugging the code instead of focusing on other tasks.
This “unneeded” code becomes like a “boat anchor.” It does nothing as of that moment, but your application still has to carry it because you think you might require that code in the future.
Copy – Paste Programming
You are likely to encounter this anti-pattern when reviewing the code of a developer who is not well experienced with the programming language in use. Probably a junior or an intern. Since they may not be well familiar with implementing solutions for complex problems, most copy and paste code snippets from stack overflow, GitHub, blogs, and youtube videos.
Unfortunately, most developers don’t analyze the impact of this copy-pasted code; the only thing that matters is that “it works!” Using these code snippets in different project sections leads to highly repetitive code, which goes against the Don’t Repeat Yourself (DRY) programming principle.
This anti-pattern is not only limited to junior developers. Seniors developers are a victim too. Most opt to copy-paste their already working and well-tested code for specific tasks. Unfortunately, that eventually leads to unintended repetitions in the code.
Lava Flow
Lava flow anti-pattern refers to the concept where developers have to deal with redundant or low-quality code but appears to have a role in the general working of the application. Removing or editing this code becomes quite risky since you are unaware of what will happen to the app.
Most of these issues arise from legacy code written during the project’s initial phase. Maybe the developer did not follow the documentation, or the project was moving too fast, and they didn’t have time to optimize and refactor the code.
Alternatively, maybe the project started as simple research, and no one took the development phase seriously. When it eventually becomes a product, you find many redundant code pieces whose purpose and function in the program are unknown. And it becomes more hectic if the developer is no longer part of the company or they can’t remember anything to do with the code.
This anti-pattern derives its name from how the Lava from a volcano behaves. Initially, the Lava is hot and in liquid form, making it quickly flow down the mountain. When it cools down and solidifies, you cannot remove it.
The best solution to lava flows is extensive testing and refactoring. Unfortunately, it’s easier said than done. Developers will spend much time trying to understand the code, and they might end up leaving it as it is for fear of breaking the application.
Cargo – Cult Programming
This anti-pattern derives its name from an interesting story. After the second world war, tribal societies from the south pacific came into contact with the advanced Western Civilization. It was the first time for the natives to see manufactured products such as radios, Coca-Cola, etc., brought to the island.
Since they had never seen such things (cargo) before and didn’t understand how they were manufactured, they saw the Americans as gods. They started imitating whatever the Westerners were doing, hoping the gods would send more cargo to the island. That led to the rise of the name “cargo cults.”
Cargo-cult programming refers to using libraries and frameworks that work well for others without understanding why you need them in your project and how they work behind the scenes.
A good example is a developer who wants to develop an application similar to Facebook. When they do a quick online research and discover that Facebook uses C++ as one of the underlying programming languages, they decide to use C++ in their code without an in-depth analysis of whether they need it.
Conclusion
Don’t panic or feel bad because some of the anti-patterns discussed in this post are in your code. That is a phase that every experienced developer goes through before they become better. Take that as an opportunity to learn and develop. Luckily, you can quickly solve most of these anti-patterns using two standard solutions – code reviewing and code refactoring.
Was this article helpful? Do you have any comments or suggestions?
Let us know by replying on Twitter of Become A Better Programmer or to my personal Twitter account.