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