blog

紫陽花

Rubyを用いてデザインパターンを学ぶ

オブジェクト指向には設計原則とデザインパターンが存在する。

デザインパターンとは

Gang Of Four(GoF)が定義したもの Javaで書かれた本がある。 「オブジェクト指向における再利用のためのデザインパターン」 1999/10 出版

  • プログラミングにおいて繰り返し現れる問題に対する、適切解のパターン
  • 無駄なく設計されたオブジェクト指向プログラムの実現をサポート
  • 諸刃の剣

パターンとしてカタログ化されていることで 車輪の再発明を防ぐ

デザインパターンに重要な5つの考え

  • 変わるものを変わらないものから分離する
  • プログラムはインターフェースに対して行う (実装に対しては行わない)
  • 継承より集約
  • 委譲、委譲、委譲
  • 必要になるまで作るな (YAGNI)

変わるものを変わらないものから分離する

理想的なシステムは、すべての変更が局所的であるべき。 ソフトウェアに完璧は存在しない。 変わるものを変わらないものから分離することによって、 将来起こりうる「新たな変更」に対して柔軟に対応できるようにしておく。

プログラムはインターフェースに対して行う (実装に対しては行わない)

可能な限り「一般的・抽象的なもの」に対してプログラミングすること。 (ここで言うインターフェイスは、Javaの組み込み構文としてのインターフェイスではなく、 より広いレベルで、「抽象度を高めたもの」を意味する。)

Bad

具象性が高く、密結合なコード

if is_car
    my_car = Car.new
    my_car.drive(200)
else
    my_car = get_vehicle
    my_vehicle.travel(200)
end

Good

抽象度が高く、疎結合なコード

my_vehicle = get_vehicle
my_vehicle.travel(200)

抽象度を高くすることによりコードにより変更に強くなる

継承より集約

継承はよろしくない繋がりをつくってしまう

class Vehicle
  def start_engine
    # エンジンスタートの処理
  end

  def stop_engine
    # エンジンストップの処理
  end
end

class Car < Vehicle
  def drive(distance)
    start_engine()
    # driving....
    stop_engine()
  end
end
  • Carからエンジンの実装が丸見え
  • エンジンを使用しない乗り物を作りたい場合には大きな変更を加える必要が出てくる

-> 変わりやすい部分(Engine)を変わりにくい部分(Vehicle)から分離できていない

じゃあどうするのか?

集約を使い解決する。 オブジェクトに「他のオブジェクトに対する参照」を持たせる。 オブジェクトが何かの一種である(is-a-kind-of)関係(継承)を避け、 何かを持っている(has-a)関係(集約)にする

依存オブジェクトの注入

class Engine
  def start
    # エンジンスタートの処理
  end

  def stop
    # エンジンストップの処理
  end
end

class Car
  def initialize
    @engine = Engine.new() # 依存オブジェクトの注入
  end

  def drive(distance)
    @engine.start()
    # distanceだけ走る処理
    @engine.stop()
  end
end

これでEngineをVehicleから分離し、カプセル化された 依存オブジェクトの取り扱いには注意する必要がある。

委譲、委譲、委譲

委譲(delegation)
class Car
  def initialize
    @engine = GasolineEngine.new
  end

  def drive
    @engine.start
    # driving..
    @engine.stop
  end

  def switch_to_diesel
    @engine = DieselEngine.new
  end

  def start_engine
    @eigine.start  # Engineクラスに任せる
  end

  def stop_engine
    @eigine.stop  # Engineクラスに任せる
  end
end
集約と委譲の組み合わせは、強力かつ柔軟な継承代替手段となる。

必要になるまで作るな (YAGNI)

You Ain't Gonna Need It
「将来使うかも」は、大抵は使わない

これはデザインパターンに限った話ではなくアプリケーション開発全般においても言えること。 不要な処理は書かない。 必要になった時に必要な分だけの実装を行い無駄のないシステムを作る。

Special Thanks