Collection Accessor Method

インスタンス変数がコレクションを保持する場合、コレクションに処理を委譲するアクセサを用意しましょう。

インスタンス変数に関するパターンです。
インスタンス変数がコレクションを保持する場合、Getting Methodを使ってコレクション自体をクライアントに返してしまうと以下のようなリスクが発生します。

  • オブジェクトがどのようにデータを管理しているかが外部に出てしまうため、クライアントが内部構造に依存するコードを書く危険があり、内部構造が柔軟に改善できなくなる可能性があります。
  • オブジェクトの知らないところでコレクション自体、もしくはコレクションの中身を変更されてしまう可能性があります。オブジェクトが管理しなければならないのはコレクションの器ではなくコレクションの中身なのですが、それに対してオブジェクトは責任を保てません。
class Department
  def initialize
    @employee = ["foo", "bar", "baz"]
  end
  
  attr_accessor :employee
end

general_affairs = Department.new
general_affairs.employee = "破壊された" # => "破壊された"
general_affairs.employee # => "破壊された"

コレクションを直接クライアントに見せないようにし間接的な操作をいくつか用意することで、このようなリスクを回避することが出来ます。

class Department

  def initialize
    @employee = []
  end
  
  def employs(employee)
    @employee.push(employee)
  end

  def dismisses(employee)
    @employee.delete(employee)
  end

  def employed?(employee)
    @employee.include?(employee)
  end

end

general_affairs = Department.new
general_affairs.employed?("foo") # => false
general_affairs.employs("foo") # => ["foo"]
general_affairs.employed?("foo") # => true
general_affairs.dismisses("foo") # => "foo"
general_affairs.employed?("foo") # => false