---
title: 'KISSing It: On Revisiting Old Code'
teaser: 'One of the many things that''s cringeworthy but worth it.

  '
tags: development,refactoring,code,continuous improvement
author: EJ Mitchell
published_on: 2021-01-04
---

My journey as a programmer began in college when, in my numerical methods
course, I was introduced to Matlab and Python. Unfortunately, that class was in
my senior year. So after working for a year after that, I had the pleasure of
joining [Launch Academy](https://launchacademy.com) in 2017, where I was treated
to a deep dive in web development in a bootcamp-style learning environment.

(It was also where I first learned about thoughtbot.)

Fastforward to now, it’s been three years since I’ve graduated, and a little
over a year since I’ve started at thoughtbot. Though it’s been a relatively
short while, I feel like I’ve learned enough from my colleagues to fill
lifetimes.

However, I realized there’s one person I hadn’t learned from yet: myself.

Looking back at old code, like looking back at old writing, can be cringeworthy.
But, it can be extremely valuable, even if you get a cold chill going down your
spine when revisiting it.

My first solo project at Launch was a tour-de-force of everything I learned
while there. It tried to use every tool I had come across, every framework,
every bell and whistle I could think of to make myself look valuable to
potential employers. As a result, it was a bloated and showy React-on-Rails app.

_Don’t even ask how long it took to load on Heroku._

From the description, you can see how this was prime for refactoring. What I was
in for was quite different than I expected.

(Surprise!)

## New Rails, New You

For one thing, I was on Rails 5 for the original app. That meant, if I wanted to
do anything with React, I had to configure
[Webpacker](https://github.com/rails/webpacker). I wanted to cry when, after
running `rails new` for the refactored app, I saw Webpacker was already
configured for me. I remembered the hours my fellow Launchers and I had gone
through, each of us whooping in victory when we finally managed to get Webpacker
to work. Or groan when something failed.

(Mostly, it was groaning.)

Too bad that, in my bid for simplification, I didn’t need Webpacker. Everything
I was going to do for the refactored version of this app was going to be in
Rails 6. The reason for this was my recent exploration of
[sustainable](https://www.sustainablewebmanifesto.com) web design and
development.

You can have beautiful, functional websites while keeping things simple. Of
course, having a website like this doesn’t necessarily absolve you from
polluting the Earth, as fellow co-worker Eric Bailey
[discusses](https://thoughtbot.com/blog/so-you-wanna-create-an-eco-friendly-website),
but it definitely contributes to harm reduction.

That reason aside, there are a lot of really [neat
changes](https://www.toptal.com/ruby-on-rails/rails-6-features) going from
Rails 5 to Rails 6, if you haven’t already discovered them. Though it wasn’t
necessary in the refactored app I’m working on, I definitely benefited from it
in client work. Namely, using the new `create_or_find_by` method, which
addresses a race condition I’d been faced with before. As someone who works
primarily in the backend for clients, I also took advantage of [`insert_all` and
`upsert_all`](https://blog.saeloun.com/2019/11/26/rails-6-insert-all.html).

In addition to the shiny features of Rails 6, I also applied some of my own new
knowledge to make my life easier when working with model relationships across
the application. One of these things was writing class methods for scopes
instead of using the `scope` syntax.

In fact, class methods and scopes were something new to me altogether. Once I
started digging into more complex codebases after Launch, I started seeing
syntax for both rather frequently. Here is an example from my refactor:

```rb
class BusinessEvent < ApplicationRecord
  belongs_to :business
  belongs_to :event

  validates :business, presence: true
  validates :event, presence: true

  def self.for_business(business)
    where(business: business)
  end

  def self.for_event(event)
    where(event: event)
  end

  def self.user_events(user)
    where(business: user.businesses)
  end
end
```

In the refactored version of my app, a user can own many businesses, and these
businesses can indicate their attendance at events. However, there are places
where I would like to list businesses that are attending an event (e.g., the
`event#show` page). There are also places where I would like to list events that
a business is attending (`business#show` page). In addition, a user (whose
profile is visible only to them) might want a list of _all_ of the events their
businesses are going to.

Writing a class method for each of these on the `BusinessEvent` model allows
this to be so. Now, learning about `scope`, I found that the preference was for
writing them in the above class method notation vs. using `scope` itself. There
seem to be a few reasons for this, one of them being intent and readability, the
other being simply historical as Rails evolved over time.

Even though I had learned about scopes and class methods long before refactoring
my app, I was able to see the utility for them in real time, which was a moment
of pride for me. I learned something!

## Keep It Simple, Stupid (KISS It)

Keeping it simple came about in two different ways. The first is that I was
giving myself a shortened timeline to come up with an MVP. The first time
around, I was panicking and throwing around as many ideas as possible in two
weeks. Instead, I learned from past-me's mistakes and came up with a roadmap for
5 work days.

To implement the roadmap, I used GitHub issues with labels to keep track of what
I wanted to do. If something changed, I put a comment in the issue. Instead of
merging everything to `main` right away, I opened up PRs and linked them to the
issues.

Being at thoughtbot for over a year now, I had seen colleagues work on quite a
few MVP and rapid validation projects that had benefited greatly from a
streamlined sense of organization like this.

Also, in seeing these projects going through our pipeline, I learned the value
of only having a few core features in the first release as opposed to as many as
possible from the original idea.

This is a powerful switch in thought process:

During the first iteration of this app, I was looking for my first job in the
field. I felt like I needed to prove myself - throw everything at the wall and
hope it stuck.

This time, I was not doing this for someone else to accept me. I was doing it to
apply my new experiences and understand how far I had come in the last three
years.

In the first iteration, the user could sign up, attend/create events, have
products, and create orders.

In this new iteration, a user could sign up, create businesses, create events,
and attend events.

That’s it. The products and orders from the first iteration would come later.

Now, the only new thing in this MVP compared to the original was adding the
concept of businesses. Observing local shop owners over the course of the
pandemic created this new piece of business intel. Many restaurants in the area
were owned by the same family, often under one name.

Evolution of the MVP aside, another simplification came in the form of the
design. What I discovered was that 90s nostalgia can not only be friendly in
terms of sustainability, but it can also be quick to set up and quite pretty in
its own way.

I will admit that my pitfall here was spending a little _too_ much time on
styling. In the end, I was not pleased with the naming conventions I chose
in my stylesheet.

(Time management was clearly another lesson here.)

In future iterations, I'd like to spend time organizing my design, because I’ve
quickly learned that organized stylesheets make life easier. Observing the work
of thoughtbot designers and how they organized stylesheets on our apps only made
this clearer to me.

## There’s Always More to Learn

While there were many takeaways from refactoring my application, I know there’s
more that I could be learning. During my investment time, I came up with a plan
for future enhancements - not necessarily features here, but _knowledge
enhancements_.

One enhancement is to take the newly refactored app and take the test
coverage from "zero to hero". 🦸🏻 Here, my plan is to set up CI and
configure the test suite on my own. (In past projects, I’ve come in after the
MVP had been built or configuration had already been established.)

When you’re working with your own code, you can shuffle the order of things as
you see fit - which is a huge benefit if you want to focus on growing one or two
skills at a time.

Another possible knowledge enhancement is adding [Sorbet](https://sorbet.org) to
the codebase. Since the codebase is so small, this would be great to do earlier
on before I go beyond the MVP features. I haven’t used Sorbet yet, but have
grown to know and love the power of typed languages thanks to my first project
at thoughtbot using Scala and Elm.

This enhancement is less about strengthening current skills and about
cultivating a new one with a tool that interests me.

This is another benefit to revisiting your old code - you can see what’s changed
in the last several years and try things that have come out since you’ve last
worked on it.

## Parting Thoughts

As much as you might want to avoid it, returning to old code has a ton of
benefits. It might not be something you use to make the next Fortune 500
company, but it can be personally affirming and deeply satisfying.

In a world where we’re constantly trying to keep up with one another, and
beating ourselves up if we perceive we’re not "making the cut", taking the time
to remind yourself about how far you’ve come is immensely important.
