How to initiate Refactoring?

Moiz Ali
4 min readMay 24, 2022
Just Refactor stuff

Introduction

4 years later, when I started programming I used to write code and just care about the results mainly It's working how it’s intended to be stance. But as time passed I realized that whenever I want to add new functionality within, it becomes nearly impossible for me.

However Rails defaults enable us to stick with OOP principles and good practices, but as the codebase grows you have to be a champion to hold up things properly!

So I have to compromise and search for escape routes. My bad. Being proactive and habit of thinking to extend the genre is what I’m missing. By the time I learned from different experiences, features, other people’s code, and mainly from Google (How can I miss this!)

Why do we need Refactoring?

Its an Art.

As I described above that it becomes hard to extend features and add new stuff but mainly you lose control of your codebase. You become a slave of an unknown compelling force established within your app. Produced by your bad code and mismanagement.

Just think about big tech giants and social media apps, and how code is being managed and scaled to reach a bigger audience. You’ll get the answer for sure!

Jumping into the Playground

Today I’m going to share my initial 5 steps approach to refactor a bad piece of code. It can be a starting point for those who don’t have an idea about Where to start?.

Let's start this!

As an example, we’ll discuss this controller action in Rails which has code smells. It enables the admin to assign user a specific subscription membership group.

Bad piece

Dry run each line of code, understand meanings?

I have added comments against each line. See

Code with comments

Identify responsibilities with Divide & Conquer rule

  • Authorization check for user’s role
  • Query user from db and figure out user old membership and new group for further addition
  • Update user with new attrs
  • Send membership email
  • Perform subscription expiry job
  • Handle failure case of #update
  • Handle failure case of authorization

Extract methods by Single Responsibility Principle

The single-responsibility principle (SRP) is a computer-programming principle that states that every module, class or function in a computer program should have responsibility over a single part of that program’s functionality, and it should encapsulate that part.

Single Responsibility Principle

In accordance with responsibilities obtained in Step 2. I’ve added separate methods. Each doing its own thing.

check_user_role! depicts authorization check, continue only if user is an admin otherwise redirect. The ! at the end describes that it's going to follow up immediately

grab_user_and_associated_group find user, get membership names, group, and expiry date. Here I switched local variables with instance variables to manipulate them among micro-actions. Provided the fact we can also use them inside views.

user_params prepares hash to pass inside update call

update_user updates user and call forward_emails_then_set_job. It has an else case to describe if something goes wrong.

forward_email_then_set_job calls mailer and job classes respectively. For sake of simplicity, I'm skipping the discussion for them!

Notice about usage of redirect_back in this context, instead of using redirect_to with request.referrer You can find it here

Filter out performance gaps and fill them

If you notice down, there is a performance gap inside forward_email_then_set_job. The problem is deliver_now and perform_now. When we have a queue backend like Sidekiq in place, it's essential to configure queues that can hold up jobs to perform one by one. deliver_now halts this priority queue and we can face the situations where jobs received at same time instant would be dropped, thus creating load on queue backend.

For the solution, I’ve used deliver_later and perform_later which takes care of priority queue. Jobs are processed one by one, providing minimal drop chances and optimized queue backend

Performance gaps

Put all pieces and ask yourself Is it improved?

Put all pieces

The answer can be Yes or No. But the new version would be better than the worst. A stable form!

Refactoring is costly if not done from the start. It's a habit towards self improvisation and a better understanding of code.

I haven’t come up with a perfect version. There are certain improvements we can do here. I would like to hear from you guys. Do Share and Like if you find it useful ..

--

--

Moiz Ali

I am a Software Engineer who loves to transform ideas into reality, devise solutions, write code and articles.