こんにちは、hachi8833です。Rubyスタイルガイドを読むシリーズ、今回の「クラスとモジュール編」は2回に分けてお送りします。
- Rubyスタイルガイドを読む: 総もくじ
- 前回: Rubyスタイルガイドを読む: コメント、アノテーション、マジックコメント
- 次回: Rubyスタイルガイドを読む: クラスとモジュール(2)クラス設計・アクセサ・ダックタイピングなど
クラスとモジュール(1)構造
5-01【統一】クラス定義は以下の構造で統一する
Use a consistent structure in your class definitions.
クラス内要素の記述順序を示しています。
class Person
# extendとincludeは他の要素より先に書く
extend SomeModule
include AnotherModule
# インナークラス定義は最初に書く
CustomError = Class.new(StandardError)
# 定数はその次に書く
SOME_CONSTANT = 20
# 属性マクロはその次に書く
attr_reader :name
# その他のマクロがあればここに書く
validates :name
# publicなクラスメソッドはその次にインライン形式で書く(class << selfでもよい: 後述)
def self.some_method
end
# 初期化メソッドはクラスメソッドと他のインスタンスメソッドの間に書く
def initialize
end
# publicなインスタンスメソッドはその後に書く
def some_method
end
# protectedメソッドやprivateメソッドは末尾にまとめる
protected
def some_protected_method
end
private
def some_private_method
end
end
インナークラス定義は本スタイルガイド冒頭でもFooError = Class.new(StandardError)
のようなスタイルが推奨されていますね。
また、「# publicなクラスメソッドはその次にインライン形式で書く」についてはclass << self
での定義も認められます。このスタイルは次回分で登場します。
# Also possible and convenient when you
# have to define many class methods.
class << self
def first_method
# body omitted
end
def second_method_etc
# body omitted
end
end
5-02【統一】mixinが複数ある場合は別々に書く
Split multiple mixins into separate statements.
# 不可
class Person
include Foo, Bar # 複数のmixinが1行で書かれている
end
# 良好
class Person
include Foo # mixinは1行ずつ分けて書く
include Bar
end
mixinを1行ずつ書くことでGitの差分が見やすくなり、mixinの順序変更も行いやすいなどのメリットがあるという指摘をkazzさんからいただきました。
5-03【統一】1つのファイル内で、複数行の大きなクラスを別のクラス内で直接ネストしない
Don't nest multi-line classes within classes. Try to have such nested classes each in their own file in a folder named like the containing class.
そのような場合は、たとえば親のクラス名を持つフォルダを作成し、子のクラスごとに別ファイルを作ってその中に置くようにしてほしいとあります。常にそうできるとも限りませんが、ファイルの適切な分割を促進するためのスタイルだと思います。
# 不可
# foo.rb
class Foo
class Bar
# メソッドが30ほどある
end
class Car
# メソッドが20ほどある
end
# メソッドが30ほどある
end
# 良好
# foo.rb
class Foo
# メソッドが30ほどある
end
# foo/bar.rb
class Foo
class Bar
# メソッドが30ほどある
end
end
# foo/car.rb
class Foo
class Car
# メソッドが20ほどある
end
end
5-04【統一】クラスメソッドしか持たないクラスは、モジュールに書き換えるのが望ましい
「クラスはインスタンスを生成するために使う」のが適切であるという考え方ですね。
Prefer modules to classes with only class methods. Classes should be used only when it makes sense to create instances out of them.
# 不可
class SomeClass
def self.some_method
# body omitted
end
def self.some_other_method
# body omitted
end
end
# 良好
module SomeModule
module_function
def some_method
# body omitted
end
def some_other_method
# body omitted
end
end
5-05【統一】extend self
はmodule_function
に書き換えるのが望ましい
モジュールのインスタンスメソッドをクラスメソッドにする場合は例のmodule_function
が望ましいということですね。
Favor the use of module_function over extend self when you want to turn a module's instance methods into class methods.
# 不可
module Utilities
extend self # 推奨されない
def parse_something(string)
# 何かする
end
def other_utility_method(number, string)
# 何か他のことをする
end
end
# 良好
module Utilities
module_function # おすすめ
def parse_something(string)
# 何かする
end
def other_utility_method(number, string)
# 何か他のことをする
end
end
後半はクラス設計関連の記述が多いので次回にいたします。ご期待ください。
関連記事
- Rubyスタイルガイドを読む: ソースコードレイアウト(1)エンコード、クラス定義、スペース
- Rubyスタイルガイドを読む: ソースコードレイアウト(2)インデント、記号
- Rubyスタイルガイドを読む: 文法(1)メソッド定義、引数、多重代入
- Rubyスタイルガイドを読む: 文法(2)アンダースコア、多重代入、三項演算子、if/unless
- Rubyスタイルガイドを読む: 文法(3)演算子とif/unless
- Rubyスタイルガイドを読む: 文法(4)ループ
- Rubyスタイルガイドを読む: 文法(5)ブロック、proc
- Rubyスタイルガイドを読む: 文法(6)演算子など
- Rubyスタイルガイドを読む: 文法(7)lambda、標準入出力など
- Rubyスタイルガイドを読む: 文法(8)配列や論理値など
- Rubyスタイルガイドを読む: 命名
- Rubyスタイルガイドを読む: コメント、アノテーション、マジックコメント
- Rubyスタイルガイドを読む: クラスとモジュール(1)構造
- Rubyスタイルガイドを読む: クラスとモジュール(2)クラス設計・アクセサ・ダックタイピングなど
- Rubyスタイルガイドを読む: クラスとモジュール(3)クラスメソッド、スコープ、エイリアスなど
- Rubyスタイルガイドを読む: 例外処理
- Rubyスタイルガイドを読む: コレクション(Array、Hash、Setなど)
- Rubyスタイルガイドを読む: 数値、文字列、日時(日付・時刻・時間)
- Rubyスタイルガイドを読む: 正規表現、%リテラル、メタプログラミング(最終回)