Elegant Ruby: Code Quality Automated
A Rubyist discusses a library that allows your development team to use automation to enforce maintainable code in their Ruby files.
Join the DZone community and get the full member experience.Join For Free
Have you ever found yourself staring at photos of someone’s dog, cat, or kids, only to grind through a smile that’s not authentic? It’s a universal fact that we all think the things we do and produce are wonderful. The code we write is so witty! We’re like the fable of Jupiter and the Monkey; it doesn’t even matter if others scoff, we believe our creation is beautiful.
So how do we get objective with such a curse?! In what way can we protect ourselves from such bias? We could always ask our fellow developers, but is that effective? As fun as it sounds, even if you did, there’s no guarantee that they wouldn’t apply their own bias until your code reached some kind of median between the both of you.
No, the best thing you can do is arm yourself with a grouping of best practices, and then do what you can to automate enforcement of those best practices on your code base going forward. Setting up a feedback loop would help you internalize those concepts.
You may ask, what’s the cost? The initial answer is speed. Many people know the Project Management Triangle. If you want good feedback, for free, you have to give up “fast.” You can only ever select one side of the triangle (2 circles).
Fortunately, given the feedback loop, as you internalize these concepts, the speed will increase again.
I’ll identify firstly, how to automate testing code quality, and then secondly how to enforce that feedback loop so you can speed up your personal feedback loop. You can familiarize yourself with basic concepts and important dimensions of code quality in this write up from my friends at SeaLights.
Automatic Objective Code Quality Verification
For verifying your code quality, we’ll be implementing a linter. The term linter comes from the C programming days, where it would originally flag suspicious and non-portable constructs which would result in errors. Today, a linter is a program that tries to analyze your code for known mistakes, readability issues, and “code smells.”
The linter we’ll use for Ruby is called “Rubocop,” a play on the classic movie Robocop and the language Ruby.
To install Rubocop, we’ll add the following to our Gemfile for bundler.
gem 'rubocop', require: false
I’m a fan of keeping the same regulations locked in.
If you’re unfamiliar with why we said “
require: false ” it’s because we want Rubocop, but we’ll be using it outside our application, so we don’t want it to automatically load the library when we start the bundler.
bundle install we can now run Rubocop on our codebase
bundle exec rubocop
Understanding the Rubocop Report
It’s quite simple to read, but here’s a review. As the files are being processed, you’ll get a progress update that looks like so:
These will identify the different severity of issues, with code that should be refactored, convention issues, warnings, errors, and even fatal bugs in your application.
Each “offense” (anything more than a green dot) will get reported. You can then identify these issues and fix them.
What If I Don’t Agree With Every “Offense”?
It might be that Rubocop identifies something that you’re OK with. Perhaps single-quoted strings are something you’ve considered and identified as too nit-picky. Fortunately for you, there’s a way to calibrate the behavior of Rubocop to your identified standards.
By creating a `.rubocop.yml` file in the root of your project, you can override the configuration of Rubocop settings. With the help of the Rubocop repository, you can identify the rules and configure them for yourself. I highly recommend copying this default.yml on your first-time usage. Each rule is outlined with comments to help you fine-tune your reports.
Returning to our double quotes issue from before, we can configure our rule to prefer double-quoted strings, unless they are using single quotes to avoid backslashes.
Style/StringLiterals: EnforcedStyle: double_quotes SupportedStyles: single_quotes double_quotes
As indicated earlier, it’s not a bad start to start chomping through linting issues after each report. But more importantly, this will give you smaller feedback loops. How can we quickly associate the code cleanliness with our day-to-day work?
For that, there are two methods I would recommend.
Feedback on Push
Let’s say your code is 100% lint free! You’re good to go, and now you need to protect that code and keep it lint-free. One excellent way to do that is to add some git-hooks that will bark if anyone tries to perturb our utopia.
Some people will enforce feedback every time you commit your code, allowing even the smallest fragment of code to be pure. This can slow down the development process a bit more than I would prefer. Sometimes incomplete code isn’t lint-free.
I would highly recommend linting your codebase on every push. If you’re using overcommit to manage your project commits, you can turn on Rubocop by adding the following to your `.overcommit.yml` file.
PrePush: RuboCop: Enabled: true
If you ever find yourself in a situation where you MUST push your code, and skip ALL your checks, you can pass the
--no-verify flag to your commit message, and this will bypass ALL hooks, including the RuboCop one.
If you simply want to skip only RuboCop, you can push an environment variable into the scope of your commit with
ONLY=RuboCop git push origin master
You’ve set up feedback, you’ve placed a guard at the gate with git-hooks. Now the final step is to get friendly messages directly in your editor. Lots of editors have plugins that help you run linting. The advantage is that the second you’ve created a linting issue, you can get a warning or notification that the code is problematic. This might feel noisy compared to a guard solution, but I’ve found it much more insightful because the goal is to not type the errors at all.
The underlined code is a friendly identifier that something isn’t right.
Now Go Forward to Protect and Serve With Rubocop
In summary, you and your team can identify the coding style that works best for everyone, and then use automation to enforce maintainable code. You’re doing a great service for yourself and each other.
Opinions expressed by DZone contributors are their own.