Personally I like Spaghettis. Especially Spaghetti in pesto sauce. Twirling up the spaghetti in a fork, putting that tangled noodles into the mouth, thats quite a fun. But thats the same thing I don't like about spaghetti.
I won't be able to get a proper spoon of spaghetti in one go. I need to twist my fork, try to untangle them, cut off the ends of the infinite spaghetti tangles by biting them so that I can chew a mouthful.
And to make it worse, If I am wearing a white shirt, there is a high probability that I am going to mess it up. There is no proper way to eat a spaghetti. Well, you can show me some fine dining youtube videos on "how to eat spaghetti?", but still.. It is slightly a pain.
In the same way spaghetti code causes a lot of pain to the developers and maintainers of the code base. After that extensive food references you might want to know what a spaghetti code is. Let us see what internet says about it.
Spaghetti code is a pejorative phrase for source code that has a complex and tangled control structure, especially one using many GOTO statements, exceptions, threads, or other "unstructured" branching constructs. It is named such because program flow is conceptually like a bowl of spaghetti, i.e. twisted and tangled. Spaghetti code can be caused by several factors, such as continuous modifications by several people with different programming styles over a long life cycle.
"program flow is conceptually like a bowl of spaghetti" - In early days people used "GOTO" statements to alter the control flow of the program. This eventually lead to messy control flow like this 👇
Imagine the struggle of a new developer to understand the flow of the program, who has been assigned to maintain this code. Even the guy who developed it, won't be able to work on the code out of the box.
It will take some time for him to understand the code base after staying few months away from it. That is why in 1960's argued that the GOTO statement should be removed from programming languages, in favor of structured control flow statements and the reference "spaghetti code" was mentioned for first time by him.
Even with all the GOTO statements removed in modern programming languages, it got replaced with the structured control flow statements like "if", "else", "for". And this is where the spaghetti code still follows us.
Object Oriented concepts were invented for a better and easier design of the code but it comes with a cost. Your code becomes annoyingly messy when there are too many object references with multiple dependencies, finally resulting in a modern spaghetti code.
When your code base grows, more people get to work on the code with their different coding styles, moreover, more non-standard coding styles. Eventually your code becomes as tangled as a bowl of spaghetti and it will be a pain to develop new feature or fix bugs because the code is tightly coupled. Changing one small thing might break an entire build.
Now we know what spaghetti code is and how it affects the software developers and development. Let's see some ways to avoid them.
Pay attention to all the details in your code. If you have a slight feeling that this is going to be a dirty hack you are doing to meet the release deadline or demo. Note it down on your issue tracker and put that in the to-do list of next release already. Don't let the code base rot by being lethargic and lazy.
By strictly paying attention to what you create, you can avoid the spaghetti code much earlier before it grows out of hands, twisted and tangled.
You should write your code in such a way that it can be unit tested. Period.
Make your code modular, abstract it with minimum interconnections. You cannot write unit test cases for a large monolithic, tightly coupled code. Every method in your code should have only one responsibility.
If you find it difficult to write unit test cases for your code, then you know that something is not right and you should start looking into the code and eventually refactor it. It's much harder to unit test a spaghetti code.
Don't worry if you are not able to write unit test cases before hand itself. In today's startup world, everyone is rushing to release their product in order to survive. Even I rant about it everywhere.
But always remember to write testable code so that when you get the bandwidth, you will be able to write test cases for it. If you write untestable code today, even if you get some time to write test cases, you probably might end up not doing that, because it involves in 3 steps now instead of 1:
- Spend time and understand the code base.
- Abstract the code to make it testable
- Write test cases
[P.S] Ideally unit tests should be a part of your development process, When I say "Don't worry if you are not able to write unit test cases before hand itself", I am not recommending you to not to write test cases. You should always write them!
Never ship a version until at least two pairs of eyes have seen the code.
When was the last time you spent time with your team to do a code review before merging the changes to master branch? If it was recent and you do it often, well and good. Else you really need to start practicing code reviews.
Code review helps both the reviewers and the code owners. Owners can get the essential feedbacks and critics so that they can learn and improve themselves. Reviewers on seeing various code bases, will get to know how a problem can be solved in different ways.
Yes, code reviews take time, they are not easy. If the reviewer is stating the obvious bugs and anti patterns in your code, you would get defensive, go into tech debates et cetera. But I tell you, its worth it. Code reviews can help you to maintain a clean code base without ending up in a spaghetti code.
Process of restructuring existing code without changing its external functional behavior to improve nonfunctional attributes of the software.
In software development, all the functionality is not known while starting the development. It starts with some basic requirements, and we keep adding or changing the existing code as we learn more about it.
We also change the code later, to fix bugs and edge cases. In this process, as the time progress, the code becomes complex, bloated and gets hard to understand and ultimately end up being a large bowl of spaghetti.
Your customer doesn't care about refactoring your code. In fact they are not going to pay for it as refactoring is not going to change the end results for them. But as the code base grows, it is essential to spend time regularly in refactoring the code.
Before refactoring your code, try refactoring your attitude
“The attitude that developers have toward the design of the software is the same attitude that surgeons have toward sterile procedure. Sterile procedure is what makes surgery possible. Without it, the risk of infection would be far too high to tolerate. Developers should feel the same way about their designs. The risk of letting even the tiniest bit of rot begin is too high to tolerate.” - Martin C. Robert, a.k.a UncleBob
"The risk of letting even the tiniest bit of rot begin is too high to tolerate." - You should make attention to details and software ethics as a part of your attitude while developing. Apart from the coding attitude, you also should change your attitude to perceive critics, even if they are negative ones.
Especially this happens during code reviews, when someone suggests or points out something, first analyze your code and try to find out the mistakes you made, if any.
You can totally be defensive about your approach and start a tech debate, but going offensive will bother the reviewers and next time they will stop pointing out your mistakes that you made. Ultimately you end up growing the code base into a smelly spaghetti, on contrary you will never grow.
Decoupling, Reusability and Microservices
Always build with reuse in mind. Go for generic solutions. Hacks are good for deadlines and demos. But don't let the hack to hack your code base. Hacks are like cocaine, they give you short immense pleasure and make you want to do it again and again, but it is not healthy for your project's long run.
Your code necessarily doesn't have to be a microservice from the very beginning. But it surely should be decoupled, so that it will be easier for any developer to break it down into microservices in future. Always remember, decoupling your code early and turning them into microservices when the time comes will avoid spaghetti code.
So, when are you going to analyze your code base and save it from becoming a bowl of smelly spaghetti?. If you already have encountered spaghetti code, what counter measures you took to get rid of them or to avoid them? Let me know in comments!
If you find this article useful, like it, tweet it and share it:)