はじめに
ここではRubyでアプリケーションを開発していくにあたってより柔軟な設計をしたいと言う方向けの記事を書いていきたいと思います。
なお、オブジェクト指向設計実績ガイドの第3章に記載されている内容です。
概要
開発する上でクラス間の依存が強ければ強いほど要件変更に対して大幅な修正が必要になります。次のコードを見てください。
class A
attr_reader :a_one, :a_second
def initialize(a_one,a_second)
@a_one = a_one
@a_second = a_second
end
def method_a
a_one * B.new(a_one,a_second).method_b
end
end
class B
attr_reader :b_one, :b_second
def initialize(b_one,b_second)
@b_one = b_one
@b_second = b_second
end
def method_b
b_one + b_second
end
end
puts A.new(1,3).method_a
依存関係にある状態とは以下状態を指します。
- Aクラスの内部に他クラス(Bクラス)が存在していることを記述している
- Aクラスの内部でBクラスのインスタンスがbクラス内で定義されているメソッドBを呼び出そうとしている
これらの依存関係をできる限り解消していく。
疎結合的なコードをかく
クラス間での依存が多ければ多いほど二つのクラスは一つのクラスとして見なされる傾向が高まる。これらの依存関係を少しづつ解消していきより柔軟なアプリケーションづくりの一助にしていく。
まず一つ目の課題としてmethod_aがBクラスのmethod_bを明示的に参照している依存についてだが、もしBクラスの名前をBからCに変更したとする。その場合、Aクラス内のmethod_aの記述も少なからず変更する必要が出てくる。この問題を解消すると以下のコードになる。
class A
attr_reader :a_one, :a_second,:b_class
def initialize(a_one,a_second,b_class)
@a_one = a_one
@a_second = a_second
@b_class = b_class
end
def method_a
#途方もなく長い処理
a_one * fromBclassMethod
#途方もなく長い処理
end
#カプセル化することで外部クラスへの依存が一目で管理できる
def fromBclassMethod
b_class.method_b
end
end
Bクラスのインスタンス生成をAクラスの外部に配置することでAクラスは引数b_classにmethod_bを持っているオブジェクトであればどのような名前のクラスから生成されたインスタンスであろうが受け入れることができるようになったと言うわけです。
また、b_class.method_bを専用のメソッド内にカプセル化することで今後のmethod_aに対する変更も容易にすることができます。