- Ruby / Rails関連
READ MORE
こんにちは、hachi8833です。Rubyスタイルガイドを読むシリーズ、今回の「クラスとモジュール編」は2回に分けてお送りします。
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
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さんからいただきました。
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
「クラスはインスタンスを生成するために使う」のが適切であるという考え方ですね。
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
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
後半はクラス設計関連の記述が多いので次回にいたします。ご期待ください。