hiyoko-programingの日記

プログラミングを勉強したてのひよっ子。   エンジニア目指して勉強中。

コードレビューを補助するツール

コードレビューツールとは

コードレビューツールとは、文法・バグ・コーディングスタイルを自動で分析するツールのことを指す。

コードレビューはコードの品質を高めるためには必須の作業である。
しかし、人によってどこまでの粒度でレビューを行うか異なっていたり、そもそもチームメンバーにレビューを行えるだけの知見が溜まっていないケースが考えられる。
このような場合、コードの質を高めるのに有効なレビューを行うことができない。

そこでコードレビューツールを導入することによって、
質の高いレビューを自動で・高速に行えるようになる。代表的なものとしてRubocopESlintなどがある。

Rubocop

https://tech-master.s3.amazonaws.com/uploads/curriculums//e19cb148f84fc5400a7ccb1322030cc9.png

Rubocop(ルボコップ)はRubyの静的コード解析ツール。「インデントが揃っていない」 「無駄な改行・スペースがある」などの指摘をRubyStyleGuideに基づいて行ってくれる。Rubocopを導入することにより、レビューに掛かる時間を減らし、コードの品質を担保できるようになる。

ESlint

https://tech-master.s3.amazonaws.com/uploads/curriculums//f857f381c0ce2dc1d5360b4178db00bc.png
EslintJavascriptの静的コード解析ツール。Javascriptで書かれたコードを解析し、明らかなバグ・不適切なコーディングスタイルを指摘してくれる。

Rubocopを導入する

Rubocopを利用することで、不要なコードレビューを減らすことができる。

ChatspaceのgemfileにRubocopを利用するよう書く

Chatspaceのgemfileを開き、Rubocopを利用できるようにする。

Gemfile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#省略
group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.0.5'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  gem 'better_errors'
  gem 'binding_of_caller'
  gem 'bullet'
  gem 'rubocop', require: false
end
#省略

書けたら、bundle install

ターミナル
1
2
#chatspaceのディレクトリにて
$bundle install

Rubocopを実行してみる

以下のコマンドで実行することができる。

ターミナル
1
2
#chatspaceのディレクトリにて
$bundle exec rubocop

すると、以下のように大量の出力が得られたはず。
これが、現時点でRubocopが検知したコード規約違反である。

https://tech-master.s3.amazonaws.com/uploads/curriculums//dfcbb1fe7fcdbbe7d07597a9fb2e97c4.jpeg

Rubocopは、デフォルトでRubyのコードの書き方についてのルールを保持している。例えば、1行あたり何文字を超えてはいけないとか、文字列はすべてシングルクォーテーションで囲まなければならない、など。こうしたルールはすべて、文法的にはエラーにはならないもののコードの可読性を下げるという理由で設定されている。しかし、デフォルトのすべてのルールに従ってしまうとあまりにも窮屈で、コードを書くのが大変になってしまう。また、チームの中でこれは許容しても良いだろう、という書き方も出てくる。

実は、Rubocopの設定ファイルを作成することで、ルールをカスタマイズすることができる。

設定ファイルを作成

設定ファイルは、.rubocop.ymlという名前にする必要がある。このファイルをchatspaceディレクトリに作成し、以下のように編集。なおSublimetextでファイルを作成すると警告が出る可能性があるが、無視して作成してしまって構わない。

.rubocop.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
AllCops:
  # 除外するディレクトリ(自動生成されたファイル)
  # デフォルト設定にある"vendor/**/*"が無効化されないように記述
  Exclude:
    - bin/*
    - db/schema.rb
    - node_modules/**/*
    - db/migrate/*
    - vendor/**/*
  # Rails向けのRails copsを実行。"rubocop -R"と同じ
  Rails:
    enabled: true

# "Missing top-level class documentation comment."を無効
Style/Documentation:
  Enabled: false

# "Prefer single-quoted strings when you don't need string interpolation or special symbols."を無効
Style/StringLiterals:
  Enabled: false

# "Line is too long"を無効
Metrics/LineLength:
  Enabled: false

#'frozen_string_literal: true'を無効
Style/FrozenStringLiteralComment:
  Enabled: false

内容について多少解説。まず1 ~ 9行目はRubocopの規約の調査から除外するファイルやディレクトリを指定する。例えば、schemaファイルやmigration関連ファイルについてはほとんど書き直したりすることが無いため、規約に従わせる方がコストが掛かってしまう。そういったものについては、あえて見逃すということができる。

1
2
3
4
5
6
7
8
9
AllCops:
  # 除外するディレクトリ(自動生成されたファイル)
  # デフォルト設定にある"vendor/**/*"が無効化されないように記述
  Exclude:
    - bin/*
    - db/schema.rb
    - node_modules/**/*
    - db/migrate/*
    - vendor/**/*

続いて10 ~ 12行目は、Rails用にカスタマイズされた規約にてチェックを行うかを決めている。この場合trueなので、Rails向けの規約でチェックを行う。

10
11
12
  # Rails向けのRails copsを実行。"rubocop -R"と同じ
  Rails:
    enabled: true

14行目以降は、厳しすぎる規約を無効にする記述。このように、個別の規約について有効/無効を切り替えられるのがRubocopの便利なところ。

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# "Missing top-level class documentation comment."を無効
Style/Documentation:
  Enabled: false

# "Prefer single-quoted strings when you don't need string interpolation or special symbols."を無効
Style/StringLiterals:
  Enabled: false

# "Line is too long"を無効
Metrics/LineLength:
  Enabled: false

#'frozen_string_literal: true'を無効
Style/FrozenStringLiteralComment:
  Enabled: false

再度Rubocopを実行

設定ファイルを作成できたので、再度Rubocopを実行。

ターミナル
1
2
#chat-spaceのディレクトリで実行
#$bundle exec  rubocop

すると、先程よりも規約違反が少なくなったことがわかる。

https://tech-master.s3.amazonaws.com/uploads/curriculums//b4df7ed106d7b44ab5f0bc648e5d5925.jpeg

少なくなったとはいえ、未だ多くの規約違反があるようである。ここから徐々に、これらを修正していく。

現在の違反を徐々に修正していく

以下のような手順を踏んで修正を行う。

1.現在の違反をすべて記録した上で、いったん違反では無いことにする

2.記録した違反のうち1つを、違反していることに戻す

3.その違反を解消する

1を行ったら、2と3を繰り返すことで徐々に規約違反を減らしていく。それでは、まず1から行う。

以下のコマンドを実行すると、現在の規約違反がまとめられた.rubocop.todo.ymlというファイルが生成される。

ターミナル
1
$bundle exec rubocop --auto-gen-config

生成された.rubocop.todo.ymlは以下のような中身になっている。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2018-05-31 14:11:52 +0900 using RuboCop version 0.56.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 7
# Cop supports --auto-correct.
# Configuration parameters: Include, TreatCommentsAsGroupSeparators.
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
Bundler/OrderedGems:
  Exclude:
    - 'Gemfile'

# Offense count: 5
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: with_first_parameter, with_fixed_indentation
Layout/AlignParameters:
  Exclude:
    - 'app/models/user.rb'
    - 'config/initializers/generators.rb'
    - 'spec/controllers/messages_controller_spec.rb'

#続く

このように、その時点で違反している規約自体をすべて無効にするように書かれる。そして、同時に.rubocop.ymlに以下が追記される。

.rubocop.yml
1
inherit_from: .rubocop_todo.yml

これは、.rubocop.ymlに.rubocop.todo.ymlの内容が書かれているのと同じことにしてくれる、という記述。なので、もう一度rubocopを実行すると、違反が無い状態になるはずである。

ターミナル
1
$bundle exec rubocop

https://tech-master.s3.amazonaws.com/uploads/curriculums//e95caa412c929509e6d7f228802a2db0.jpeg

では手順2。現在.rubocop.todo.ymlにある違反回避の記述の一つを削除する。

削除するのは以下。

1
2
3
Bundler/OrderedGems:
  Exclude:
    - 'Gemfile'

再度rubocopを実行すると、こちらの規約の警告が復活していることがわかる。

bash[1]:ターミナル
$bundle exec rubocop
`

https://tech-master.s3.amazonaws.com/uploads/curriculums//4b5b9ac362246900e5f78eba829c7864.jpeg

これは、Gemfileのgroup do ~ endのグループの中に書いたGemはアルファベット順に並べる、という規約に対しての違反。
これを手動で修正しても良いが、Rubocopには、ある程度の規約違反は自動で修正してくれる機能がある。この機能を利用するには、実行時に-aオプションを利用する。以下のコマンドを実行。

ターミナル
1
$ bundle exec rubocop -a

すると、Gemfile内のgemの並びが、アルファベット順になっていることがわかる。

このように、.rubocop.todo.ymlから違反を消しrubocopを実行 → 修正という流れで修正作業を進めていく。ちなみに、-aオプションが利用できるかどうかは、.rubocop.todo.ymlの各設定の上にコメントアウトで「# Cop supports --auto-correct.」と書かれているかどうかでわかる。書かれていれば、-aオプションを利用することができる。

コードレビューツールは採用している言語毎に導入する必要があり、設定や実行が手間になる可能性がある。
必要なコードレビューツールをまとめて導入したい際は、Siderを活用することで簡単に設定ができる。

Siderとは

 

https://tech-master.s3.amazonaws.com/uploads/curriculums//d0a3ef8b9fc934018a45bf12d83bb988.png
Siderはコードレビューツールを一括で導入できるサービス。RubyJavascriptPython、Goなど幅広い言語に対応している。SiderはGithubリポジトリ毎に導入することができ、プルリクエストが作成されると自動でコードレビューを行ってくれる。パブリックリポジトリへの導入は無料で行える。

Siderを導入する

導入の流れ

  1. SiderにGithubでログインする
  2. リポジトリを追加する
  3. プルリクエストを作成する
  4. レビューを受けて修正する

1.SiderにGithubでログインする

https://sider.review/

を開いて、Githubアカウントを使ってログイン。

スクリーンショット 2019-05-01 14.20.13.png

スクリーンショット 2019-05-01 14.20.25.png
スクリーンショット 2019-05-01 14.21.37.png

2.リポジトリを追加する

ログイン後、Siderを導入したいリポジトリを選択する必要がある。
ヘッダーから「リポジトリ追加」ボタンをクリックする。

スクリーンショット 2019-05-01 14.22.09.png
スクリーンショット 2019-05-01 14.23.59.png

連携したGithubに登録されたリポジトリの一覧が表示されるので、追加したいリポジトリをクリック。

スクリーンショット 2019-05-01 14.24.16.png

追加するリポジトリで使用している言語・フレームワークをチェックし、「自動コードレビューを開始する」ボタンをクリック。これで、該当するリポジトリでプルリクエストを作成すると、自動でコードレビューが行われるようになる。
スクリーンショット 2019-05-01 14.24.33.png

解析ツール、解析結果の言語など、さらに詳細に設定したい場合、サイドバーの「プロジェクト設定」から設定を変更できる。

3. プルリクエストを作成する

実際に自動レビューの流れを体感するため、プルリクエストを作る。
プルリクエストが作成されると、コードの解析が行われる。
解析終了後に問題のあったコードの一覧が確認できる。

下記のスクリーンショットは、31行目に不要なスペースが含まれていたコードの例である。
検査をして指摘しているのはRubocopである。

スクリーンショット 2019-05-01 14.52.58.png

Siderによる解析のステータスは、Github上からも確認できる。

スクリーンショット 2019-05-01 14.53.37.png

どの解析ツールを使用するかなどはSiderの「設定」から選べるので、どんな解析ツールがあるのか時間があるときに調べてみる。

4.レビューを受けて修正する

解析で問題のあったコードを修正して、もう一度プッシュ。
指摘されたものの、個人で問題がないと判断したコードは、「クローズ」することができる。
全てのコードが修正もしくは「クローズ」されると、解析結果がグリーンになる。

参考資料

 
Rubocop 公式(英語)

https://rubocop.readthedocs.io/en/latest/

ESLint 公式(英語)

https://eslint.org/

Sider 公式ブログ Ruby on Railsタグのついた記事一覧
Siderの設定・コードレビューツールについて書かれた記事。

https://blog-ja.sideci.com/archive/category/Ruby%20on%20Rails