こんにちは。ゆうすけです。
先日ついに Rubyによるデザインパターン を読み終えた(!)ので、次は リファクタリング Rubyエディション を読み始めました。
リファクタリング Rubyエディションは、復刻版が最近発売された名著でリファクタリングの様々なパターンをRubyのサンプルコードと共に紹介していく形式です。
パターンの数は膨大なので、いいなと思ったパターンを1つずつブログにまとめていこうと思います。
今回はその第一弾で「委譲の隠蔽」についてまとめます。
問題のあるコード
例えば、こんなコードがあったとします。
class Article attr_accessor :blog end class Blog attr_reader :writer def initialize(writer) @writer = writer end end
前提として、ブログ(Blog)の中にたくさんの記事(Article)があり、同じブログに属している記事の作者は同じとします。
ある記事の作者(writer)が知りたい場合は、下記の実行コードの「article1.blog.writer」のように呼び出す必要があります。
article1 = Article.new blog1 = Blog.new('ブロガーくん') article1.blog = blog1 puts article1.blog.writer # -> ブロガーくん
このコードだと、呼び出す側が「作者の管理はブログが行なっている」という知識を持っている必要があります。(言い換えると、article1.blog.writer という呼び出し方を知っている必要があるということ)
知識が必要だということは、呼び出す側からブログクラスへの依存が生じており、ブログクラスに変更があった際には呼び出す側にも影響が生じてしまいます。辛いですね。。
委譲の隠蔽を使ったリファクタリング
これを、記事クラスに簡単な委譲メソッド(writer メソッド)を作って改善します。
class Article attr_accessor :blog def writer blog.writer end end class Blog attr_reader :writer def initialize(writer) @writer = writer end end
こうすることによって、下記実行コードのように「article1.writer」と呼び出せるようになり(ブログクラスへの処理の委譲を記事クラスが隠蔽している!)、「作者の管理はブログが行なっている」という知識を呼び出す側が持つ必要がなくなります。(言い換えると、article1.writer と呼び出せばいいことだけを知っていればよいということ)
先ほどの問題点をクリアしていますね!
article1 = Article.new blog1 = Blog.new('ブロガーくん') article1.blog = blog1 puts article1.writer # -> ブロガーくん
図で表すとこのようなイメージです。
矢印の向いた先に依存していることを示しています。
図から分かるように、呼び出し側からブログクラスへの依存がなくなり、ブログクラスの変更の影響を呼び出し側が受けなくなりました。これは嬉しいですね。
「委譲の隠蔽」とは、元々は記事クラスが作者を取得するための処理をブログクラスに委譲していたところを、記事クラスの writer メソッドに隠蔽した(呼び出す側から分からなくした)という意味です。
Forwardableモジュールを使うと
やっていることは同じなのですが、Ruby標準ライブラリに含まれている Forwardable モジュールを使うことで以下のように書くこともできます。
require 'forwardable' class Article extend Forwardable def_delegator :blog, :writer attr_accessor :blog end class Blog attr_reader :writer def initialize(writer) @writer = writer end end
def_delegator は、2つ目の引数のメソッド(この場合は writer)を1つ目の引数のオブジェクト(この場合は blog)へ委譲します。
よりスッキリしていい感じですね。
おわりに
ここまでお読みいただきありがとうございます。
サンプルコードと依存関係の図は リファクタリング Rubyエディションを参考にさせていただきました。本書の中では、Person クラスと Department(部門)クラスの関係を例に説明しています。
- 作者:ジェイ・フィールズ,シェーン・ハービー,マーティン・ファウラー
- 発売日: 2020/03/21
- メディア: 単行本
「委譲の隠蔽」使えそうですね。
次回はまた違うパターンをまとめていきます!
(追記)
第2弾として「モジュールの抽出」についてまとめました。
是非合わせてご覧ください。
ysk-pro.hatenablog.com