Reekメモ
Reek 6.0.3で確認。
以下のGemをインストールする。
group :development, :test do
gem 'reek'
end
bundle exec reek 対象
で実行。-t
で.reek.yml
ファイルが作成され現状のコードの問題をTODO化して後回しにできる。.reek.yml
はreekの設定ファイル。
RSpec matchersも用意されていて、動的に生成されたコードのチェックも行える。
Railsでは以下の設定を追加するのが良い(参照:Reek - Working with Rails)。
directories:
"app/controllers":
IrresponsibleModule:
enabled: false
NestedIterators:
max_allowed_nesting: 2
UnusedPrivateMethod:
enabled: false
InstanceVariableAssumption:
enabled: false
"app/helpers":
IrresponsibleModule:
enabled: false
UtilityFunction:
enabled: false
"app/mailers":
InstanceVariableAssumption:
enabled: false
"app/models":
InstanceVariableAssumption:
enabled: false
共通の設定項目は、Reek - Basic Smell Optionsを参照。
自分の考える推奨設定
directories:
"db":
FeatureEnvy:
enabled: false
"app/controllers":
IrresponsibleModule:
enabled: false
NestedIterators:
max_allowed_nesting: 2
UnusedPrivateMethod:
enabled: false
InstanceVariableAssumption:
enabled: false
"app/helpers":
IrresponsibleModule:
enabled: false
UtilityFunction:
enabled: false
"app/mailers":
InstanceVariableAssumption:
enabled: false
"app/models":
InstanceVariableAssumption:
enabled: false
detectors:
# publicメソッドにのみ適用
UtilityFunction:
public_methods_only: true
# ブロックで1文字変数が使えなくなるため無効化
# キャメルケースチェックはRuboCopでもできる
UncommunicativeVariableName:
enabled: false
# メソッドの行数チェック。RuboCopと重複するので無効化
TooManyStatements:
enabled: false
# モジュールやクラスコメントの有無チェック。RuboCopと重複するので無効化
IrresponsibleModule:
enabled: false
# Serviceクラスでは他のオブジェクトのメソッド呼び出しが多いので無効化する
# app/servicesに対して適用してもよいがドメインサービスも除外するため正規表現で指定する
FeatureEnvy:
exclude:
- "/.*Service#.*/"
# foo_model.idは複数回呼び出すことを許可する
DuplicateMethodCall:
allow_calls:
- id$
# 自己カプセル化が必要になったときのためにセッターは用意しておきたい
# かといって煩雑な記述はしたくない
# そもそも、セッターを外部から利用するような使い方をするのが悪いし
# そういうメンバがいることを想定しないので無効化する
Attribute:
enabled: false
# 除外パス
exclude_paths:
- vendor/bundle
警告の一覧と簡単な説明
公式の一覧はReek - Code Smellsを参照。
- Attribute
- publicなセッターがある場合に警告する
attr_accessor
とattr_writer
がpublicな場合に警告される。def foo=(foo)
のような=
付きメソッドはpublicでも警告されない。
- ClassVariable
- クラス変数を使っていると警告する
- ControlCouple
- メソッド全体が
if param...else...end
になっていて引数param
で処理を振り分けている場合に警告する - BooleanParameter
- 引数のデフォルト値が
true
かfalse
で設定されている場合
- 引数のデフォルト値が
- ControlParameter
- BooleanParameter以外の場合
- メソッド全体が
- DataClump
- 同じ組み合わせの引数が複数のメソッドに現れたり、インスタンス変数に同じ部分文字列が使われているものが複数ある場合に警告する
- DuplicateMethodCall
- 1つのメソッドの中で同じメソッドを複数回呼び出している場合に警告する
return val[index] if val[index].present?
のようなケースでval[index]
が二回実行されていると警告される
- InstanceVariableAssumption
- クラス定義の外でインスタンス変数が設定されると仮定しているコードがある場合に警告する
- メモ化と相性が悪いが、メモを保存するインスタンス変数にコンストラクタでnilを代入しておけば警告は避けられる
- IrresponsibleModule
- モジュールやクラスコメントがない場合に警告
- RuboCopと重複するので無効化して良い
- LargeClass
- TooManyConstants
- TooManyInstanceVariables
- TooManyMethods
- LongParameterList
- LongYieldList
- LowCohesion
- FeatureEnvy
- 自分のインスタンス変数やメソッドよりも、他のオブジェクトのメソッド呼び出しが多いような場合に警告する
- Serviceクラスなどの場合は無効化した方が良いだろう
- UtilityFunction
- 自分のインスタンス変数やメソッドを使っておらず、他のオブジェクトを呼び出しているメソッドを警告
- FeatureEnvy
- ModuleInitialize
- NestedIterators
- MissingSafeMethod
!
付きのメソッドがあるが、同名の!
なしメソッドがない場合に警告- 以前はPrima Donna Methodと呼ばれていた
- SimulatedPolymorphism
- ManualDispatch
- NilCheck
x.nil?
やx == nil
などnilチェックをしている場合に警告x ||= val
やx&.method
、if x
などは警告されない
- RepeatedConditional
- SubclassedFromCoreClass
- TooManyStatements
- メソッドのコード行数が長すぎる場合に警告
- RuboCopでできるので無効化して良い
- UncommunicativeName
- UncommunicativeMethodName
- UncommunicativeModuleName
- UncommunicativeParameterName
- UncommunicativeVariableName
- 1文字変数、数値で終わる変数名、キャメルケースの変数名を警告
list.map {|x| ...}
のx
も警告されるので考えもの- キャメルケースはRuboCopでもチェックするため無効化しても良いのではないか
- UnusedParameters
- UnusedPrivateMethod