What is the Spaghetti code?
Spaghetti code also referred to as the big ball of mud, is code without a definite structure and resembles spaghetti. This form of code is tightly coupled, hard to maintain, and refactor and a nightmare for the devs working on it.
Spaghetti code is a software design anti-pattern found in applications where the delivery speed of application features is prioritized over code quality resulting in massive technical debt.
Let’s understand this with the help of a real-world use case.
Spaghetti code use case – Online food delivery service
Imagine an online food delivery service comprising multiple business functionalities such as taking orders, routing those orders to the right restaurant and the delivery person, accepting payments, user memberships, inventory, and so on.
The Spaghetti code for this application will have total discard for the software design principles and would have all the features coded tightly coupled with each other. The code will have no layers (controller, service, business, DAO, etc.), no use of SOLID OOP principles, no use of interfaces and modular design; rather, everything coded together like a big ball of mud.
With an application having Spaghetti code, it would be overly painful to add new features since—first, the devs would have to figure out the code flow for a certain feature and then make the changes hoping the new code doesn’t break the existing functionality.
This may result in an endless cycle of bug fixing with the spawning of new bugs due to the former bugs being fixed, which will eventually throw a wrench into the gears resulting in financial loss.
Why do we end up with the Spaghetti code?
There are several reasons, stated below, behind dev teams ending up with Spaghetti code:
- Primarily due to the lack of time investment in code design during the initial phases of product development. Here in this article, I’ve discussed how important is knowledge of system design for developers.
- Lack of developer experience. If the developers working on the code have little knowledge of software design, the code will end up being a big ball of mud.
- Several developers developed the project over the years, writing code in their style without following a definite structure, making the code look like Spaghetti. This is where programming frameworks like Spring come in handy as they help standardize coding structure.
- The team always preferred delivery speed in contrast to code quality. Developers were happy to take the easy route without thinking much about leveraging OOP principles, design patterns and such.
- No team code reviews led by seasoned devs. If the code worked, it was pushed to the repo mainline.
- No regular code cleanups (Refactoring, rewriting, code quality checks, test coverage and such).
What can we do to avoid the Spaghetti code?
Use a layered architecture as opposed to stuffing everything in a single layer.
In most enterprise projects, you’ll find code split up into layers like the controller, service and data access layers. We can always add more layers to our code based on the requirements and the complexity of the project.
When it comes to Java Spring enterprise projects, layered architecture is the defacto pattern that is leveraged.
In the layered architecture, also known as the lasagna code, every layer has its specific role; for instance, the controllers will handle requests specific to a certain business feature or domain, the service layer will execute the business logic, the data access layer will communicate with the database and so on. They communicate with each other via interfaces to keep things loosely coupled and abstracted.
With this, specific layers, such as the service layer, wouldn’t worry about what is going on in the controller or the DAO layer. It just does its job, that is, executing business logic and passing the data across the DAO and the controller. Having a layered architecture helps implement the separation of concerns.
With this architecture, a change in a certain layer of the code won’t impact other layers much. The layers are isolated. This facilitates easy development and testing, keeping the code maintainable and extendable.
Hopping back to our online food delivery service use case, we will have the business functionalities like order management, order routing, payment, user memberships, inventory, etc., implemented as verticals in a layered architecture as opposed to having all these in a single layer in Spaghetti code.
End-to-end request flow in a layered architecture
Now, with the layered architecture, when a user searches for food items in their app, the request is handled by the inventory controller and then moves to inventory service and the inventory DAO and back.
When they book an order, the request is handled by the order management (controller, service, DAO) flow. And when they pay for the order, the request is handled by the payment flow and so on.
So, you see, the business functionalities are spread across the layers vertically. Anytime we need to update any business feature, we can do it without nudging the code of other business features much.
Why do I say much?
Because however, the business functionalities are separated in layers, they are not completely isolated. There is cross-communication between them, and in complex projects, this might again lead the code to become a big ball of mud/Spaghetti.
To tackle this, we either move to microservices or implement a modular monolith architecture. I’ve discussed that in a separate article here.
If you wish to master the fundamentals of web architecture and learn to design large-scale distributed systems starting right from zero, check out the Zero to Software Architect learning track that I’ve written.
Besides implementing a layered architecture, there are a few other ways to avoid ending up with the Spaghetti code
- Always have code reviewed by seasoned devs before pushing it to the main branch. Always have team code reviews. Make this a rule of thumb.
- Educate junior devs on the importance of software design knowledge. Check out the best resources to learn software architecture and system design.
- Practice domain-driven development with a thorough understanding of the domain.
- No disorganized and chaotic bug fixing just to make things work. This might create more bugs in the code. Focus on the root cause of the issue and understand if it needs any design changes as opposed to applying duct tape to the code to make it work.
Folks, this is it. If you found the content helpful, consider sharing it with your network for better reach. Check out the Zero to Software Architect learning track. I wish I had a similar learning product in the initial years of my career.
I am Shivang. You can catch me on LinkedIn here. I’ll see you in the next write-up. Until then, Cheers!
Zero to Mastering Software Architecture Learning Path - Starting from Zero to Designing Web-Scale Distributed Applications Like a Pro. Check it out.
Master system design for your interviews. Check out this blog post written by me.
Zero to Mastering Software Architecture is a learning path authored by me comprising a series of three courses for software developers, aspiring architects, product managers/owners, engineering managers, IT consultants and anyone looking to get a firm grasp on software architecture, application deployment infrastructure and distributed systems design starting right from zero. Check it out.
- System Design Case Study #5: In-Memory Storage & In-Memory Databases – Storing Application Data In-Memory To Achieve Sub-Second Response Latency
- System Design Case Study #4: How WalkMe Engineering Scaled their Stateful Service Leveraging Pub-Sub Mechanism
- Why Stack Overflow Picked Svelte for their Overflow AI Feature And the Website UI
- A Discussion on Stateless & Stateful Services (Managing User State on the Backend)
- System Design Case Study #3: How Discord Scaled Their Member Update Feature Benchmarking Different Data Structures
CodeCrafters lets you build tools like Redis, Docker, Git and more from the bare bones. With their hands-on courses, you not only gain an in-depth understanding of distributed systems and advanced system design concepts but can also compare your project with the community and then finally navigate the official source code to see how it’s done.
Get 40% off with this link. (Affiliate)
DataCamp offers courses, skill tracks, and career tracks in data science, AI, and machine learning. With interactive exercises, short videos, and coding challenges, learners can master the data and AI skills they need.
With the data engineering courses, you can learn how to design and create the data infrastructure businesses need to scale and master one of the most lucrative skills worldwide. Check out the website here. (Affiliate)