Chapter 7 - Practical Object Oriented in Ruby

Sharing Role Behavior with Modules

まとめ

dock typeの章で説明したような共通の振る舞いを発見した際に、それをモジュール化することで、コードを1つの箇所に置くことができる。

シーケンス図の各ノードに、具体的なクラス名を書くのではなく、求められていること、実際にやっていることを記述することで、モジュール化する役割の名前を見つ出すことができることがある。


ある1つのことに関して実現させようとするとき、それ以外のことを知っていないと実現できようなケースは余計な依存性があると考えることができる。

例えば、文字列に関して、空がどうかの判定にStringUtils.empty?(str)とする必要がある場合、単純にstring.empty?とできるケースと比較すると、StringUtils#empty?の存在を知っていないといけないという依存性ができる。

stringのようなコアのオブジェクトに関しては、頻繁に変更が起きることもないし、基本的な使い方はすぐに覚えることができてるのでそれほど大きな問題にはならないと思うけど、アプリケーションに定義したオブジェクトでこういった余計な依存性が増えていくと、やりたいことに対して、実現させるコストが増えそうだし、変更のコストも結構変わってきそう。


抽象的な役割を見つけた時に、対処しなければいけない問題として、どうやってその役割を実現させるかと、どこにそのコードを置くかという2つが発生する。

こういったケースでは問題を分けて対処するのがわかりやすくて、まず1つのクラスに対して、役割を実現できるようなコードを実装した後に、抽象化させる部分をモジュールに移して動作させ、その後に他の同じ役割のクラスでも動作させるようにするといい。


同じ役割を持つクラスは、その役割を果たす工程において、クライアントからは全て同じインターフェースに対応する必要がある。(同じメソッド名、引数、戻り値)

同じ役割を持っているのに、クライアントで、どのクラスかどうかで処理を分けるのはなるべく避けるべき。


継承、モジュールを使うと、構成をどんどん複雑化させることができるので注意して扱う必要がある。

これらの技術はデザイン設計の技術よりコーディング作業に密接に連携しているので、うまくできるどうかで、アプリケーションに対する影響は大きい。