rubocopを導入してコードを直していくフロー

rubocopを使ったことがなかったのですが、ここへきて使ってみることにしました。 Railsを使って開発中の幾つかのWebアプリやAPIに対して試験的に導入してみて、rubocopでチェックして、指摘を確認し、修正し、またチェックして・・・っていう一連の流れがつかめたように感じたので、自分なりのプラクティスを纏めておきます。


rubocopとは

rubocopは、rubyのコードに対して、コーディング規約に準拠していることをチェックする、いわゆる静的コード解析ツール。

bbatsov/rubocopでオープンソースとして公開されていて、ライセンスは、独自ライセンスっぽい。

チェックする内容は、rubocop作者によるrubyのコードスタイル標準に則っているか、で、その標準は、bbatsov/ruby-style-guide で公開されており、様々な言語に翻訳されている。日本語版は、https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md にある。

フロー

開発中のRailsアプリに、何も考えずにrubocopを入れてチェックすると、大量の規約違反が検出されて途方に暮れる(僕はなった)。 そのあと、闇雲に直し始めて、場合によっては、

  • 種類の異なる違反を一緒に直してしまい、コミットログが汚れていく。
  • 直し方がわからず、あるいは途方に暮れてしまい、rubocopの運用を諦めてしまう。

などの弊害が生まれてしまうので、それは避けたい。

そうならないために、事前にrubocopを使っていく際のフローを確立して、意識しておく必要があると思った。

そこで、

  1. rubocopでチェックする
  2. 違反の内容を確認する
  3. ルールをカスタマイズする
  4. コード修正する
  5. 修正を確認する
  6. 1〜5をひたすら繰り返す

という単純なフローを定義して、このフローに乗っかってみることにした。

前提

ここでは、開発中のRailsアプリにrubocopを導入することを前提としている。

環境は、

  • ruby2.3.3p222
  • rails5.0.0.1
  • rubocp0.47.1

導入

Gemfileに、

group :development do
  gem 'rubocop', require: false
end

を追記して、bundle installする。

準備

まず、アプリケーションルートディレクトリに、.rubocop.ymlを作成し、

Rails:
  Enabled: true

を記述する。 これによって、標準の規約+Rails固有の規約が有効になる。

続いて、bundle exec rubocop --auto-gen-configを実行し、.rubocop_todo.ymlが生成されることを確認する。 この.rubocop_todo.ymlは、現状の規約違反が全て記録される。

さらに、.rubocop.ymlの先頭に

inherit_from: .rubocop_todo.yml

を追記する。

そうすると、違反はあるけど一旦無視する、という状態ができ、この状態をスタートラインとする。

rubocopでチェックする

.robocop_todo.ymlの中の特定のルールについて、コメントアウトし、bundle exec rubocopを実行する。

すると、コメントアウトしたルールに対する違反が出力される。

違反の内容を確認する

rubocopの違反の出力に含まれるメッセージを確認し、何が指摘されているのかを把握する。

よくわからない場合は、RuboCop: The Ruby Linter that Serves and Protectsの「Cops Documentation」を見ると、ルールの内容がわかる。「bad」、「good」のように例が書かれているものもあるのでわかりやすい。

ルールのカスタマイズ

指摘された違反を「正しい」と見做したい場合がある。 例えば、日本語のコメントを正しいと解釈したり、1行あたりのカラム数を100にしたい(デフォルトは80)、など。

こういった場合は、.rubocop_todo.ymlでコメントアウトした内容を、.rubocop.ymlに書くことで、 検証のルールをカスタマイズすることができる。

例えば、日本語のコメントを認めるには、

Style/AsciiComment:
  Enabled: false

.rubocop.ymlに追記する、など。

コードを修正する

指摘された違反が確かに違反であると言える場合は、素直にコードを直す。 この時、修正が単純なもので済むこともあるし、場合によっては、リファクタリングが必要になるケースもあると思う。 なので、修正内容をよくよく検討する必要がある。

  • 修正方法がわからない
  • 修正規模が大きくなる

の違反は、一旦.rubocop_todo.ymlをそっと元に戻して、修正を後回しにした方が効率がいい。

修正を確認する

再度、同じ条件で(.rubocop.yml、.rubocop_todo.ymlを書き換えずに)bundle exec rubocopを実行し、違反がなくなっていることを確認する。 そして、テストがあるならここでテストする。テストがないなら追加する。 テストにパスして、同じルールに対する違反の修正が全て解消できたなら、この時点でコミットしてしまうのがいい気がした。

繰り返す

あとは、.rubocop_todo.ymlの中身に対して、1つずつ上記の作業を繰り返していき、 .rubocop_todo.ymlが空っぽになるまで続ける。


以上が、僕なりのフローです。 今後、しばらくこのフローに乗っかってrubocopライフを生きていきたい。