DEV Community

Cover image for Refactoring Adventure: Cleaning Up My Code One Step at a Time🚀
Tasbi Tasbi
Tasbi Tasbi

Posted on

Refactoring Adventure: Cleaning Up My Code One Step at a Time🚀

Hello, world! 🌍 Today, I’m excited to share my epic journey of refactoring a project that had slowly morphed into a wild jungle of duplicated functions, inconsistent error handling, and missing logs. It was like trying to read a map in the dark! 🗺️ But with the magic of refactoring, I turned this project from chaotic into clean and efficient code!

Let’s talk about what I did, how I did it, and the aha! moments (and mini disasters) I encountered along the way. Grab some popcorn 🍿 and let’s dive in!

🚀 Setting the Scene: The Problem

Picture this: I’m working on this open-source project, a tool to generate auto-awesome README files from code snippets. It’s a great tool, but as features grew, so did the complexity of the code. Suddenly, I was looking at functions that were duplicating logic, and error handling was scattered everywhere. Plus, no logging to speak of! 🤯

That’s when I knew it was time for some Refactoring Magic. 🪄✨

🌟 What’s Refactoring, Anyway?

Refactoring is like spring cleaning for your code. It’s when you take existing code and reorganize it – without changing its functionality. The goal is to make the code more readable, maintainable, and modular.

Sounds simple? Well, let’s dive into the journey and see how it works in action.

🎯 Step 1: The Game Plan

First things first – I created a new branch called refactoring so I could clean up my code without accidentally breaking everything on my main branch. That way, my project could keep running smoothly while I got into the weeds.

\bash
git checkout -b refactoring
\
\

With my refactoring branch ready, it was time to tidy things up – piece by piece.

Step 2: Extract Functions and Modularize

The first issue I tackled was code duplication. File handling logic, API request logic, and other tasks were all over the place. If I had to make a change, I'd have to do it in several places – yikes!

Here’s what I did:

  • Extracted reusable functions for handling file input/output and making API requests.
  • Created a ConfigManager class to centralize configuration handling.
  • Modularized the output handling into a new OutputManager class.

This cleaned up my code quite a bit. Now, whenever I need to adjust file handling or API logic, I can do it in one place instead of hunting down multiple lines of repeated code like some lost treasure. 🏴‍☠️


🌟 Refactor #2: Configurations Under Control

Issue: Configuration settings were handled inconsistently throughout the code. I was manually setting API keys, models, and paths in multiple places. If I had to switch the model or tweak an API key—good luck finding all the places!

Solution: Time to centralize! I introduced a ConfigManager class to bring everything under one roof. It handled:

  • API keys.
  • Model selections.
  • Output directory settings.

Now, all config-related changes are managed in one place, making the code easier to read and modify. Plus, no more scrambling to find where I set the API key last! 🔍


🌟 Refactor #3: Output Handling on Fleek

Issue: Saving files and output handling was, well, a mess. Markdown files, JSON files… they were being saved all over the place. There was no proper system, and if I needed to update how files were saved, I was staring down at scattered logic across the project.

Solution: Enter the OutputManager! This new class took over the responsibility of saving all output, whether it was a README file or a JSON file. Modularized output means cleaner, more maintainable code and fewer chances of accidentally overwriting files or saving them in the wrong location. 📂


🌟 Refactor #4: Logging the Journey

Issue: Logs? What logs? My program was silently running without any feedback. If something went wrong, I’d be scratching my head wondering what happened. Debugging? Pfft, forget about it. 🧠

Solution: I added logging! I made sure the program would let me know what was happening at every step:

  • Info logs to confirm when things were running smoothly.
  • Error logs to tell me when something went wrong (and, more importantly, where it went wrong).

Now, I get to watch my program work in real-time and catch errors before they turn into nightmares. Logging is my new best friend! 📜✨


🤯 Interactive Rebase: Squashing the Chaos

After all that refactoring, my Git history was looking a bit… cluttered. Four separate commits for different refactors. I decided to clean up my Git history using an interactive rebase.

  • What is this magic? It allows you to combine (or “squash”) multiple commits into one!

Here’s how it went:

  1. I ran git rebase -i main\ and got to pick and squash the commits into one.
  2. I had the chance to rewrite the commit message to reflect everything I’d done in one clean summary.
  3. It felt like tidying up my workspace after a project. It was so satisfying!

Once the rebase was done, my Git history was clean, and my commit message looked professional. 👌


🐞 Bugs and Breakdowns Along the Way

Now, I wish I could say everything went perfectly, but this is coding—we know that’s not the case! 😅

  • Mini disasters? Oh, definitely! There was a moment when I accidentally added files to the commit that shouldn’t have been there. That’s when I met my new friend, git reset\, to undo that mess.
  • Did I break the program? Of course, a few times! When I refactored the output manager, I momentarily forgot to handle streaming properly, and the JSON files weren’t saving. Oops! But after a few logs (thanks to refactor #4), I was back on track.

In the end, those bumps along the way just made the final result all the more satisfying.


🎉 Final Thoughts: A Clean Codebase is a Happy Codebase!

Refactoring is like spring cleaning for your code. It can be frustrating and slow-going at first, but once you see the results, you’ll never go back. With all the changes I made—modularizing code, centralizing configurations, cleaning up output handling, and adding logging—I feel like I’ve turned this project into a well-oiled machine. 🛠️✨

And let’s not forget the Git rebase. There’s something deeply satisfying about squashing all those commits and seeing a clean, tidy history. It’s like looking at a neatly organized closet after decluttering. 👕

If you’re working on a project and things feel out of control, don’t be afraid to refactor. You’ll thank yourself later. And remember, a clean codebase isn’t just about keeping things pretty—it’s about making sure your future self doesn’t hate your past self. 😉

Happy coding! 🧑‍💻🎉


P.S. You can check out the refactor commit here: My Refactor Commit

Top comments (2)

Collapse
 
aloisseckar profile image
Alois Sečkár

Congratulations for successful refactoring! However, I'd like to point out two things, so you and especially your readers have easier time in the future:

1) I understand you wont go back in time and some refactoring is better than nothing. And I also have projects that desperately needs to rework.

However, in general refactoring shouldn't be a spring clean happening on rare occasions and having to deal with a lot of things. We, developers, should tend to smaller refactors like every time we touch the code base. The goal is: "Always try to leave the codebase in better shape than you find it." You see variable with unclear name? Rename it. You see duplicated code that should be extracted into function? Do it. Of course sometimes you find out more complex changes that would be hard to deal right now when you just fixing a small typo or something and then it is ok to postpone refactoring. But the more things you have to deal with at the time, the higher probability something breaks.

2) Commits are generally advised to be kept as small and atomic as possible. One thing at the time. Your squash got you a clean message, but made it harder to investigate what was going on in there. Usually you won't need it, but once you will, you will understand...

Squashing has its use cases, but it is better to develop a habit of writing clear commit messages and commit frequently than creating big squashed commits that obsfucate the history.

This is not meant as a criticism of your programming or your article, thanks for sharing your experience. But I just wanted to add my point of view.

Collapse
 
tasbi03 profile image
Tasbi Tasbi

Thank you so much for the valuable feedback! You're absolutely right—refactoring should be an ongoing process, not just a big cleanup. I'll definitely keep that in mind for future projects. Also, I really appreciate the advice on keeping commits small and atomic for better traceability. It's something I aim to improve on as I continue working on open-source projects. Thanks again for the tips!