Milestones and how CodeClimate helped us reach them

Written by on

Goals are your lifeblood.

If you don't pick a destination, you'll never get there. Even if you have a map, you'll never find your way. You have no target.

A few months ago, we started using CodeClimate. We knew we had some bad code, and bad code comes in many forms.

Some code was just dusty. We hadn't touched it in over a year. As we all know, you learn a lot in a year. If you think code you wrote a year ago is still great, you probably haven't learned much.

Some code was poorly designed. It was a tightly coupled mess. We've written about this recently on how you should opt into your business logic. Tightly coupled pieces of code will cause you to pull out your hair. Avoid it at all costs. You should check out Ruby Science if you currently feel this pain. It's a great eBook written by thoughtbot which we used to further train ourselves into thinking about code in a better way.

CodeClimate helped us set the goal. It gave us a destination. When wet set our goal, our GPA was 2.5.

At first, we were slightly depressed that our code base received such a terrible score. A few bad classes and bad practices were pulling our GPA down. After all, our code base was almost two years old - and every code base incurs technical debt at some point. With client work, it was debt we couldn't always pay back.

When wet set our goal, our GPA was 2.5.

Don't be like us and get depressed. Many of our favorite code bases have relatively poor GPAs. ActiveMerchant is stuck at a 1.7 GPA right now (although this also includes many third party gateways). Discourse is a 2.8. Paperclip is a 3.1. Rails is a 3.4. Devise is a 3.5. Rails and Devise are pretty damn good.

These aren't amazing 4.0 GPAs like you might expect. Every code base has some parts that are complex.

We set a goal of 3.0. It was achievable in the short term (within a few months). It wasn't unrealistic (like 4.0).

To achieve that goal, we did a number of things:

  • We stopped the bleeding. We stopped allowing any questionable code into our code base. We were very strict with this. No longer were we shipping things and saying "we'll come back to this later."
  • We fixed broken windows. Anytime we were adding a new feature or fixing a bug, we'd refactor.
  • We started having weekly technical discussions with our engineering team. We'd talk about accomplishments over the past week and we'd prepare examples for all of us to talk about and work through.
  • We took some risks and aggressively refactored with proper unit tests. We took the time to extract important pieces of our application into smaller, thoroughly-tested units. This was risky in we were refactoring payment processing and handling of student credits.
  • We collected momentum while watching our GPA rise. We did not tolerate decreases in our GPA, only increases.

As it stands today, our GPA is 3.21 and rising.

We've eliminated numerous code smells. We've properly extracted business logic which transformed F classes into A classes. We have better test coverage for the important pieces of our application. The application is more stable overall. We're not afraid of breaking anything. Classes are better loosely coupled. We've eliminated most ActiveRecord callbacks (and I recommend you eliminate yours, too). Avoid callback hell.

As you can see in the charts above, we still have some work to do. There are still some hairy spots. We still have problems. We work everyday to make our code better as should you.

There's no reason to get depressed though. After all, the most important metric for your product is: Do your customers find it useful? These scores don't mean anything if your product sucks and nobody uses it.

However, improving your scores pay dividends down the road.

  • We're reducing complexity. It's much easier to jump into the code base and understand what's going on.
  • We solve bugs more quickly.
  • It's much easier to refactor for a number of reasons. We have simpler tests. We don't rely on the database much for testing since our business logic is composed of small, simple Ruby classes.
  • We can expand upon existing functionality easier. Things are no longer tightly coupled. If we want to reuse something, it's pretty easy to use it in another place.
  • Our developer happiness has increased. We don't have to work in a shitty code base anymore. Watching our GPA improve is a big boost to our confidence.

We've had some fun over the past few months improving our code. I hope you find this advice useful and start using parts of it in your own teams. Let us know how we can help.