Rubyのクラスとモジュールの書き方のスタイルガイド
クラス定義では一貫した構造を使用します。
class Person
# extend and include go first
extend SomeModule
include AnotherModule
# constants are next
SOME_CONSTANT = 20
# afterwards we have attribute macros
attr_reader :name
# followed by other macros (if any)
validates :name
# public class methods are next in line
def self.some_method
end
# followed by public instance methods
def some_method
end
# protected and private methods are grouped near the end
protected
def some_protected_method
end
private
def some_private_method
end
end
クラスは、インスタンスを作成することが意味のある場合にのみ使用する必要があります。
# bad
class SomeClass
def self.some_method
# body omitted
end
def self.some_other_method
end
end
# good
module SomeClass
module_function
def some_method
# body omitted
end
def some_other_method
end
end
モジュールのインスタンスメソッドをクラスメソッドにしたい場合は、extend self よりも module_function を使うことをお勧めします。
# bad
module Utilities
extend self
def parse_something(string)
# do stuff here
end
def other_utility_method(number, string)
# do some more stuff
end
end
# good
module Utilities
module_function
def parse_something(string)
# do stuff here
end
def other_utility_method(number, string)
# do some more stuff
end
end
クラス階層を設計する場合、その階層は必ず
リスコフ置換原理。
クラス階層を設計する際には、Liskov Substitution Principleに適合していることを確認する。(注意:LSP原則とは、大まかに言うと、ある関数が親クラスのインスタンスを参照している場合、その関数を子クラスのインスタンスに置き換えなければならず、関数の基本機能はそのままである、というものです。(ただし、関数は拡張することができる)。
リスコフ置換の原則:サブタイプは、そのベースタイプを置換できなければならない <br/>
1. T1型のオブジェクトo1に対して、T1型で定義された全てのプログラムPの動作が、全てのオブジェクトo1をo2に置き換えても変わらないようなT2型のオブジェクトo2が存在するならば、T2型はT1型のサブタイプである。 <br/>
2. つまり、ベースクラスを使用するソフトウェア・エンティティは、そのサブクラスにも適用しなければならず、ベースクラスのオブジェクトとサブクラスのオブジェクトの違いを全く検出することができない。ベースクラスが真に再利用されるのは、派生クラスがソフトウェア実体の機能を維持したままベースクラスを置き換える場合のみである <br/>
3. リヒター置換原理は、バーバラ・リスコフ(Barbar Liskov)によって、継承の原理として紹介されたものである。継承再利用の基礎となるものである。 <br/>
4. リヒター置換の原則に適合しているかどうかは、その相続が合理的かどうか(欠点を隠しているかどうか)を判断する方法である。
クラスをできるだけ堅牢にするよう努力する [SOLID](http://en.wikipedia.org/wiki/SOLID_object-oriented_design)). (
このクラス(インスタンス)オブジェクトに含まれるオブジェクトを表現するために使用されるto_sメソッドを必ず自クラスに用意すること。
class Person
attr_reader :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def to_s
"#@first_name #@last_name"
end
end
attr関数メンバを使用して、各インスタンス変数のアクセッサまたはモディファイアメソッドを定義します。
# bad
class Person
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def first_name
@first_name
end
def last_name
@last_name
end
end
# good
class Person
attr_reader :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
end
attrの使用は避けてください。attr_reader や attr_accessor を代替に使ってください。
# bad - creates a single attribute accessor (deprecated in 1.9)
attr :something, true
attr :one, :two, :three # behaves as attr_reader
# good
attr_accessor :something
attr_reader :one, :two, :three
Struct.newの使用を検討してください。これは、いくつかの些細なアクセサを定義しています。
のコンストラクタと比較演算を行う。
# good
class Person
attr_reader :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
end
# better
class Person < Struct.new(:first_name, :last_name)
end
Struct.newを使用することを検討してください。これは、些細なアクセサ、コンストラクタ、および比較演算子を定義してくれます。
# good
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
end
# better
Person = Struct.new(:first_name, :last_name) do
end
Struct.new を拡張してはいけない - それはすでに新しいクラスであり、拡張すると冗長なクラス階層を作ることになる。
また、ファイルが何度も読み込まれると、変なエラーが発生することがあります。
特定のクラスインスタンスを柔軟に作成するためのファクトリーメソッドの追加を検討する。
class Person
def self.create(potions_hash)
# body omitted
end
end
継承よりもアヒル型(Duck-typing)が好まれる。
# bad
class Animal
# abstract method
def speak
end
end
# extend superclass
class Duck < Animal
def speak
puts 'Quack!
end
end
# extend superclass
class Dog < Animal
def speak
puts 'Bau!
end
end
# good
class Duck
def speak
puts 'Quack!
end
end
class Dog
def speak
puts 'Bau!
end
end
クラス変数(@@)の使用は、その厄介な動作のために避けてください。
を継承しています。
クラス変数(@)は厄介な継承の癖があるので使わないようにしましょう(子クラスでも親のクラス変数を変更することができます)。
class Parent
@@class_var = 'parent'
def self.print_class_var
puts @@class_var
end
end
class Child < Parent
@@class_var = 'child'
end
Parent.print_class_var # => will print "child"
上の例でわかるように、すべてのサブクラスはクラス変数を共有し、それを直接変更することができますので、クラスのインスタンス変数を使用する方がよいアイデアです。
メソッドにはその用途に応じて適切な可視性(private, protected)を割り当て、すべてのメソッドをpublicにしない(これがデフォルト)。これはRubyであり、Pythonではありません。
public、protected、private などの Visibility キーワードは、その(指定された)メソッドと同じインデントを使用する必要があります。そして、異なる可視性キーワードの間にはスペースを空けてください。
class SomeClass
def public_method
# ...
end
private
def private_method
# ...
end
def another_private_method
# ...
end
end
シングルトンメソッドを定義するにはdef self.methodを使用します。コードをリファクタリングするときに、クラス名が繰り返されないので、簡単になります。
class TestClass
# bad
def TestClass.some_method
# body omitted
end
# good
def self.some_other_method
# body omitted
end
# Also possible and convenient when you
# have to define many singleton methods.
class << self
def first_method
# body omitted
end
def second_method_etc
# body omitted
end
end
end
class SingletonTest
def size
25
end
end
test1 = SingletonTest.new
test2 = SingletonTest.new
def test2.size
10
end
test1.size # => 25
test2.size # => 10
この例では、test1 と test2 は同じクラスですが、test2 は size メソッドを再定義しているため、異なる動作をすることになります。単一のオブジェクトしか与えないメソッドをシングルトンメソッドと呼びます。
関連
-
redisクラスタ構築のチュートリアルと発生した問題
-
基本的なユーザー登録とログイン機能を実装するためのRuby on Railsチュートリアル
-
Rubyフックメソッド使用例
-
Rubyにおけるフックメソッドとメソッド呼び出しへのフックの追加例
-
Ruby on Rails:rakeとデータベースのデータ移行作業
-
Rubyのgemパッケージマネージャの使い方とbundlerによる複数バージョンのgemの管理
-
RubyのSimple FactoryパターンとFactory Methodパターンを利用する
-
Rubyの基本的な環境変数の設定と一般的なインタープリタコマンド
-
Ruby on Railsのメーラーの使い方を説明します。
-
Rubyでの正規表現の使い方基本ガイド
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Rubyの乱数生成方法のまとめ
-
Rubyオブジェクト指向プログラミングにおけるクラスメソッドとクラスエクステンション
-
RubyのMonkey Patchの開発例
-
Rubyオブジェクト指向の知識まとめ
-
RubyのProcクラスとProc.newメソッドの使用法
-
Rubyのオブジェクト指向プログラミングにおけるスコープの簡単な説明
-
RubyアプリケーションでHTTPベースのリクエストを送信する簡単な例
-
デザインパターンにおけるDecoratorパターンを用いたRubyの例
-
Builderビルダーパターンを用いたRubyデザインパターンプログラミング例
-
Rubyのデザインパターン。アダプタパターン実践ガイド