RubyでNull Objectパターンを使えるようにするgem「Naught」のすすめ

Null Objectパターンの実装を支援するgemとして、`Naught` というgemがあるのですが、Qiitaでは、業界の[joker1017さん](http://qiita.com/joker1007)の [俺がGitHubでスターを付けたリポジトリ一覧](http://qiita.com/joker1007/items/be5dc3f3b1e93132a4f7) という記事ぐらいしか見つからなかったので、その使い方と有用性をざっくり説明したいと思います。

# Null Objectパターン is 何？
私も最近になって知ったのですが、
こちらの記事 [NullObjectパターン](http://qiita.com/kasei-san/items/af10a948c34c317e7380) によると、

> あるオブジェクトが nil でなければ、メソッドを呼び出す
> こういうパターンが頻出する場合、obj に **nil の代わりに何もしないメソッドを持つオブジェクト** を格納しておく
> 
> インターフェースだけ持って、何もしないオブジェクトを用意することで、
> そのオブジェクトを使う側は、オブジェクトが生成されなかった場合を気にする必要がなくなる
> → オブジェクトの状態を意識する必要が無い
> → 結合度が下がる

とのことです。なるほど、コード書いているとよく遭遇する「あるある」ですね。

# Naught is 何？
*A toolkit for building Null Object classes in Ruby*
https://github.com/avdi/naught

「Null Objectパターンの実装を支援するgem」とのことですが、具体的にはどんな使い方ができるのでしょうか？
ちょっと、代表的なものを抜粋して紹介します。

## オブジェクトのメソッド呼び出しは全てnilを返す NullObject
`Naught.build`で、NullObjectを生み出すことができます。
NullObjectは、当該オブジェクトへのメソッド呼び出しに対して、すべて`nil`を返してくれます。

```ruby
require 'naught'

NullObject = Naught.build

null = NullObject.new
null.foo                        # => nil
null.bar                        # => nil
```

## 関連先だろうがメソッドチェーンだろうが全てを飲み込む black_hole
NullObjectは大変便利なものですが、場合によっては無効化したいオブジェクトについて、
`null.foo.bar.baz`
などと関連先のメソッドを呼び出していたり、メソッドチェーンが続いていたりして、「そのオブジェクト(`null`)の向こう側も無効化しておきたいんですけど！」というケースもあると思います。
`null`から先のオブジェクトをすべてNullObjectにしておかなければならないのでしょうか？
否。そんなケースにも`Naught`はCOOLに対応していて、以下のように`black_hole`というものを使うことができます。

```ruby
require 'naught'

BlackHole = Naught.build do |config|
  config.black_hole
end

null = BlackHole.new
null.foo                           # => <null>
null.foo.bar.baz                   # => <null>
null << "hello" << "world"         # => <null>
```

## そのクラスに定義されたメソッドだけnilを返すようにする mimic
`black_hole`は大変便利なものですが、一方でちょっとやりすぎ感が拭えません。
「`black_hole`だと、本来そのクラスに定義されていないメソッドまで無効化される。定義されていないメソッド呼び出しはエラー検知できるようにしておきたい」
ということもあると思います。
そんなケースにも`Naught`はCOOLに対応していて、以下のように`mimic`というものを使うことができます。

```ruby
require 'naught'

NullIO = Naught.build do |config|
  config.mimic IO
end

null_io = NullIO.new

null_io << "foo"                # => nil
null_io.readline                # => nil
null_io.foobar                  # =>
# ~> -:11:in `<main>': undefined method `foobar' for
#  <null:IO>:NullIO (NoMethodError)
```

また、`Naught.build`のブロック内では、メソッドを定義できるようになっていて、関連先をNullObjectに差し替えたり、特定のメソッドだけ返り値を偽装する、ということもできます。

```ruby
require 'naught'

NullIO = Naught.build do |config|
  config.mimic IO

  def relation
    true
  end

  def readline
    "This is mimic!"
  end
end

def mimic
  null_io = NullIO.new

  null_io << "foo"           # => nil
  null_io.relation           # => true
  null_io.readline           # => "This is mimic!"
end
```

# Naughtを活用した実装例
## 外部サービス(API)へのアクセスを封鎖する
記事表題に反して、Null Objectパターンを活用した例ではなくて申し訳ないですが......

**「productionでは実際のAPIにアクセスさせているが、sandbox環境が用意されていない、あるいは利用制限があるなどの事情があってstagingやdevelopmentではAPIにアクセスさせないようにしたい」**
という状況があったとします。あったとさせてください。(少なくとも私は遭遇しました)
testではWebMockを使えば良いと思うのですが、stagingやdevelopmentでもWebMockを使うか？ というと、そこまで厳密にスタブしなくても良いんだよなー、APIのインタフェースさえ無効化できれば十分なんだよなー、ということもあるかと思います。あるとさせてください。

そこで！ `Naught`を使って、APIクラス生成時にMimicに変えてしまうというアプローチを取ることができます。

例をあげてみます。
`Hogehoge::API`という実際に外部にアクセスしてしまうクラスと、そのAdapterがあったとします。
この時、production環境以外では、Adapterのコンストラクタ内で保持するオブジェクトをMimicの方に差し替えてしまうことができます。

```ruby
class HogehogeApiAdapter
  NullObject = Naught.build { |config| config.singleton }
  HogehogeApiMimic = Naught.build do |config|
    config.mimic Hogehoge::Api
  end

  def initialize(init_params)
    @api = Rails.env.production? ? Hogehoge::Api(init_params).new : HogehogeApiMimic.new
  end

  # Hogehoge::Apiに生えているメソッドは全て握り潰されるので、APIクラスの先にある実装を意識する必要がない
  def insert(args)
    record = Hogehoge::Type::Record.new(args)
    @api.register(record)
  end

  def bulk_insert(args_array)
    records = args_array.map { |args| Hogehoge::Type::Record.new(args) }
    @api.bulk_register(records)
  end
end
```

`Rails.env.production?` を使っているので、これはRailsの例ですが、別に`Naught`はRailsに限ったgemではないので、Rubyで書かれたコードには何にでも適用することができます。
また、Mimicにすることにこだわりがなければ、`black_hole`で全て吸収してしまえば良いと思います。

なお、本例ではAPIクラスとの間にAdapterを噛ませていますが、噛ませない場合でも、呼び出し元をMimicに差し替えれば良いです。
が、それだとMimicに差し替えるコードが散らばるので、実際にはAdapter的なものを一個噛ませておいて、その中でMimicに差し替えた方が楽かなと思います。

# おわりに
以上です。
`Naught`の手軽さ、有用性を少しでも実感いただけたでしょうか？
実装例を一つだけ紹介しましたが、私の引き出しが足りないだけで、実際にはもっと有用な`Naught`の使い方が考えられると思います。

「自分のプロジェクトではこんな使い方をしている」
「お前の`Naught`の使い方は間違えている！」
など、情報・ご指摘あれば是非、コメントに寄せていただければと思います。