DEV Community

Cover image for How to Refactor Spaghetti Code - One Bite at a Time!

How to Refactor Spaghetti Code - One Bite at a Time!

Monty Harper on February 23, 2024

This week, I’ve been learning things the hard way! I’m refactoring my calendar app, partly because I’m applying for jobs now, and I want to presen...
Collapse
 
efpage profile image
Eckehard • Edited

I´m not sure, SOLID is useful for all cases. Classes can be a way to organize your code, but if you have a class that serves only a single purpose and covers a single state, you will end up with the same spagehtti, just wrapped in classes.

If you use classes, they should have a clear focus, maybe we can say: a single task. But this task may consist of a larger number of functions. Think of a class that encapsulates all the database handling. It will need more than one function to do so, but can still be a consistent unit.

Try to split your codebase into smaller units. If you manage to run and test each unit separately, you are sure there are no unexpected dependencies.

Refractoring can be hard work. But if your code is split into smaller units with different topics, it will run much more stable. You will encounter all the sloppy spaghetties that tie one unit to the other. Even if you find it is necessary to rebuild a complete part, this will be easier than rewriting everything.

And the most important advice: If you are confused, your code will be not better. Wait some time, drink a beer, take a break and revisit your code some day´s later. Write down what you have done and analyze your work. This will help to find better solutions.

Collapse
 
montyharper profile image
Monty Harper

Thanks - sounds like great advice, especially the part about taking a break! Interesting thought about ending up with the same spaghetti if your classes are too specialized - I think that's what you mean, and I can picture that for sure.

Collapse
 
efpage profile image
Eckehard • Edited

No, it´s just that the SOLID principles seem to apply to a very specific case. If you look how classes have been used in large projects, this is a different picture. I can agree that a class should have a well defined task, but in SOLID this sounds different:

A class should have one and only one reason to change, meaning that a class should have only one job.

Possibly this is simply an ambigous wording, but classes have been used in a very different way in the past. Often we are not talking about single classes, but about a class hierarchy.

Image description

All methods and properties implemented in a class will be inherited by the childs, that can make some adjustments on the existing methods or add new features. If you find you added something that could be useful for the siblings, just shift it to the parent class, so all siblings will inherit the new methods. As this method is not used in the parent class, it will be called "abstract".

Done right you can assure, that each method is only implemented once in a class hierarchy, so it acts as a "single source of truth", there is only one place you have to edit, if you need to refractor your code.

Many OS-APIS are organized as class trees. If you check the Android API or the Windows GDI, you will find deeply nested class hierarchies that give each child access to hundreds of properties. This is quite useful, as it makes the class part of an ecosystem. I simply cannot find any parallels to the SOLID principles in this.

Can this help you, to write better code?

When I started coding in C, I found my projects went great until the source code reached a size of about 30kB. Beyond that, things got creepy, unwanted side effects where hard to find. Things where simply too complex to keep all the strings in hand. Using classes allowed me to isolate parts of my code, put it in a self contained unit that was less complex. With well defined interfaces this classes could be used like LEGO-blocks. Often I found that a well designed class could be used in later projects, so it saved me some time.

There are different ways to organize your code. OOP is only one way. The most important advice is to keep things as simple as possible. Don´t trust yourself, make things idiot-proof, as you will find that - how slim you may be today - tomorrow you will be the idiot, that simply forgot a comma that crashed your whole project :-)

Thread Thread
 
montyharper profile image
Monty Harper

Thanks @efpage,
I had to read a couple of times, but it all makes good sense. Yeah, the classes I'm using in SwiftUI do not have any inheritance behind them. In UIKit, all the UI elements are classes with a lot of inheritance, but in SwiftUI, UI elements are structs. I'm using classes for data because they are reference types, so all my views can have access to the same instance of the data.

Collapse
 
danielrendox profile image
Daniel Rendox

I've hit the wall quite a few times on my previous project. Sometimes, I'd rewrite the whole thing from scratch and then realize the previous solution was actually better. 😁 In the end, I came to the same conclusion — refactor it step by step: add more test cases, make the code cleaner, run the app, and commit to save the history.

Now, the biggest challenge for me is to make the right decisions from the outset, be a lazy developer, plan smarter, and do everything faster. Because I sometimes waste my time on something that could be done a lot simpler or isn't even necessary. 😔

Collapse
 
montyharper profile image
Monty Harper

Hi Daniel, thanks for your response. Glad you came to the same conclusion about refactoring step-by-step.

As for the need to refactor sometimes - it's all part of the learning process.

I have a feeling making the "right decisions from the outset" is a good thing to strive for, but also might be one of those goals nobody ever fully reaches, since there is always another tool or method or philosophy you just didn't know about at the time.

Also, I imagine as soon as you start thinking, "I basically do everything the best way from the start", then you're closing yourself off to learning, and I wouldn't want to do that.

I know from songwriting there's a basic level of competence to be reached where you can say, "I almost always start off in generally the right direction."

I used to waste a lot of time trying to write songs that never worked out. These days I can take a song idea and quickly figure out whether it will work well and how to organize it into a song structure that has promise. I still re-write and polish - I don't think that can ever be avoided - but I don't usually get stuck or backtrack or waste time on an idea that just won't work.

I'm sure competency at app-writing follows a similar curve. And I know I still have a ways to go, but having got there before in another creative pursuit, I can say with confidence that I'll get there with app development as well. It just takes time and experience.

I have no doubt you'll get there too, Daniel! Don't be too hard on yourself along the way!

Collapse
 
bwca profile image
Volodymyr Yepishev

You might want to look into some unit testing before actually refactoring. Those sometimes help catching bugs early when introducing changes to the existing codebase.

Collapse
 
montyharper profile image
Monty Harper

Yes, thanks! Unit testing is on my list of things to learn next.

Collapse
 
joebloggs profile image
Joe

Missed an opportunity in the headline, should have been "One byte at a time" 🤣

Collapse
 
montyharper profile image
Monty Harper

Actually, do you mind if I change it to that?

Collapse
 
montyharper profile image
Monty Harper

You're so right! 😲