RuboCopの運用ルールを見直した話
はじめに
Ruby on Railsの開発では、RuboCopを使用したコーディングスタイルの統一が一般的だと思います。
弊社でもRuboCopを使用しているのですが、設定ファイルは数年前にコミットされたままであり、十分にメンテナンスされている状態ではありませんでした。
そのため、適用されているルールについての共通認識がなく、コード内でルールを無視するケースも多く見られました。
このような状況では、ルールが実質的に機能していないため、コードの一貫性が低下し、その結果として可読性も低下します。
また、明確なルールが決まってないことは、新しいメンバーがプロジェクトに参加する際の障壁にもなり、チームの開発生産性に悪影響を及ぼす恐れがありました。
これらの問題に対処するため、RuboCopのルールを見直し、新たな運用ルールを策定しました。
この記事では、そのプロセスと成果について書きたいと思います。
ルールの絞り込みと rubocop_todo 削除
.rubocop_todo.ymlファイルはRuboCopによって検出された、まだ修正されていないコードの違反や違反を一時的に記録するために使用されます。
私たちのリポジトリには.rubocop_todo.ymlファイルに1000行以上の記載があったため、まずこのファイルに記載されているルールの必要性を判断するために、チームメンバーと一緒にルールを精査することから始めました。
そのために、RuboCopのルールに関するアンケートを事前に実施し、各メンバーから必要と考えられるルールや不要と考えられるルールについての意見を集めました。また、クックパッドさんなど他社が公開しているコーディングガイドラインも判断の参考にしました。
このような検討の結果、.rubocop_todo.ymlファイルに記載されていたすべてのルールを精査し、最終的にファイル内のコードを0にすることができました。
必要と判断されたルールについては、既存のコードを手動で修正し、一部はRuboCopの自動修正機能を利用しました。
This cop supports safe autocorrection (--autocorrect)
と記載されたルールは、以下のコマンドを使用して安全に自動修正を実施しました。
rubcop -a
ちなみにRuboCopの自動修正は以下のように -A をつけると unsafe(挙動が変わってしまうかもしれない)な自動修正もできるのですが、今回は安全に修正できるものだけ自動修正しました。
rubcop -A
この作業では、変更されるコードの量がかなり多かったため、システム障害を起こさないためにもリリースを数回に分けて行いました。そのため全て完了するには数ヶ月かかってしまいました。
時間はかかりましたが、これらの対応によりコードの統一性が向上し、.rubocop_todo.ymlファイルへの安易な追加も難しくなり、チーム全体のコード品質に対する意識が高まったと思います。
RuboCopの設定変更
ルールの絞り込みはできたのですが、そもそも適用されているルールが分かりづらいという課題があったので、rubocop.ymlファイルを見ただけでルールがわかるように変更しました。
元々、Enabled: true
と Enabled: false
が混ざっていて、適用しているルールなのか、無視しているルールなのかが分かりづらい状態でした。
そのため、以下の設定を書き、デフォルトで全てのルールをオフにしました。
AllCops:
DisabledByDefault: true
その後、適用したいルールのみを Enabled: true
にして追加していきました。
また、ルールの内容が一目で分かるように、各ルールの上にコメントを追加しました。
例:
# `when` の後に `then` を使う
Style/WhenThen:
Enabled: true
# 単語の配列は `%w` で書く
Style/WordArray:
Enabled: true
# シンボルの配列は `%i` で書く
Style/SymbolArray:
Enabled: true
これにより、どのルールが適用されているかが一目で分かるようになり、新たにチームメンバーが加わった際のコーディングルールの理解のしやすさも向上しました。
定期的なルールの見直し
RuboCopをバージョンアップすると新たなルールが追加されますが、これによりrubocopコマンドの実行時に次のような警告が頻繁に表示されるようになりました。
The following cops were added to RuboCop, but are not configured. Please
set Enabled to either `true` or `false` in your `.rubocop.yml` file:
- Style/HashEachMethods (0.80)
- Style/HashTransformKeys (0.80)
- Style/HashTransformValues (0.80)
For more information: https://docs.rubocop.org/rubocop/versioning.html
これらの警告が続くと、rubocopコマンド実行時の結果の可読性が低下します。また、ルールをホワイトリスト方式で管理するようにしたため、新しいルールをすべて Enabled: false
に設定することはできませんでした。
そこで、新しいルールの追加をデフォルトでオフに設定するために以下のコードを追加しました。
NewCops: disable
この設定によりデフォルトでルールが追加されなくなったため、定期的に保留中になっているルールを適用させて、必要に応じてルールを追加することにしました。
具体的には、数ヶ月に一度以下のコマンドを実行し、新しい保留中のルールを適用させてRuboCopを実行します。
rubocop --enable-pending-cops
その結果に基づき、新しいルールを追加するか検討する会議を開催し、必要とされるルールの選定を行うようにしました。
また、新しいルール以外にも、実装していて気になったルールなどについても検討し、ルールを定期的にアップデートするようにしました。
このアプローチにより、RuboCopの設定ファイルが放置されずに適切にメンテナンスされるため、メンバー全員が快適に開発を進められる柔軟な環境が構築できたと思っています。
まとめ
RuboCopを用いたコーディングスタイルの統一は非常に便利ですが、適切にメンテナンスされていないと、逆に開発生産性を損なう恐れがあると思います。
特に、チームメンバーが納得していないルールに基づくコードの統一や、新メンバーが既存のルールを理解するのに時間がかかることは、チームの開発生産性に悪影響を及ぼしていたと思います。
今回の取り組みにより、RuboCopのルールの重要性と定期的な更新の必要性を再認識することができました。
これからもRuboCopを効果的に活用できるようにメンテナンスしていこうと思います。
Discussion