スクリーンショット_2018-09-20_14

オブザーバパターン完全に理解した

10/8の技術書典5に向けて締め切りと格闘中のerukitiです、ごきげんよう。

技術書典5では、あ15東京ラビットハウスにて、最近流行のNextやNuxtなどJavaScriptフレームワークの仕組み解説の本とV8を崇める本を出します。(NextやNuxtの入門書ではないのでご注意を)

宣伝はそれくらいにして、本記事ではプログラマ向けの記事、デザインパターンの一種であるオブザーバパターンについて解説します。

オブザーバパターンはあらゆるところで使われていて、おそらく皆さんが知らず知らずのうちにお世話になっているでしょう。特にGUIやウェブプログラミングなどではまず間違いなく利用しているはずです。

画像の元ネタはこれです。

Twitterでつぶやくときは、#マンガでわかるDocker とか #わかばちゃんと学ぶ のハッシュタグを付けると湊川さんが喜ぶと思います。

その前にデザインパターンとは

デザインパターンとは、プログラムの設計をある程度パターン化して名前を付けることで開発者が設計に関して意思疎通しやすく、あるいは設計をする時の指針として使いやすくしたものです。

プログラミングをしていると、ある局面では大体みんな似たようなコード設計に至ることがあります。

コンピュータのプログラミングで、素人と達人の間では驚くほどの生産性の差があり、その差はかなりの部分が経験の違いからきている。達人は、さまざまな難局を、何度も何度も耐え忍んで乗り切ってきている。そのような達人たちが同じ問題に取り組んだ場合、典型的にはみな同じパターンの解決策に辿り着く。これがデザインパターンである。

らしいです。まぁこれは正直言いすぎだとは思いますが、元々そういった考えのもとデザインパターンというものが発表されました。

ちなみに元ネタは建築業界で生まれた言葉ですが、そちらではあまり使われずプログラミング界隈で圧倒的に使われるようになりました。

デザインパターンの効能

たとえば朝、開発者たちが相談をします。

「このモジュールどういう風に作る?」
「外から状態変更を検知できる必要があるね」
「それならオブザーバパターンで良さそう」
「そうだねー。じゃぁそれで」

これは「オブザーバパターン」という名前があり、メンバーがそれがどういうものかを知っているため、これだけ簡略化できているのです。

もしオブザーバパターンというものを知らなければ、

「このモジュールどういう風に作る?」
「外から状態変更を検知できる必要があるね」
「どうやって検知する?検知したい側がこのモジュールにコールバック関数を登録すればできそうだよね」
「じゃぁ、モジュールは状態変更時に、登録されたコールバックを叩くことになるね」
……延々細かい話が続く
「とりあえずこれでいけそうだね。疲れたけど」

こんな感じで中身について延々話をしなければなりません。似たようなものに「pub/sub」とか「リスナー」とかもありますが、オブザーバパターンという言葉は他のものよりも浸透しているので、こちらを使う方が会話はスムーズにいくでしょう。

オブザーバは日本語でいうと観察者とか傍聴者という意味です。別のオブジェクトの状態変化を観察するために生まれたパターンということです。

class Observer {
  constructor() {
    this.observers = {}
  }

  on(name, cb) {
    if (!(name in this.observers)) {
      this.observers[name] = []
    }

    this.observers[name].push(cb)
  }

  emit(name, ...args) {
    if (name in this.observers) {
      this.observers[name].forEach(cb => cb(...args))
    }
  }
}

const observer = new Observer()

observer.emit('hoge')
console.log('------') // ==> ------
observer.on('hoge', () => console.log('hoge'))
observer.emit('hoge') // ==> hoge

JavaScript(Node.js)で書くとこのようなコードになります。observer.onで通知を受け取るコールバック関数を登録し、observer.emitで実際に通知を受け取ります。

通知をしたいモジュールはこのObserverクラスを継承するかメンバーとしてもっておいて委譲することになります。(継承よりも委譲をオススメします。)

オブザーバパターンの真価

今回紹介したオブザーバパターンは観察者に通知を送る仕組みではありますが、別の観点で見るとプログラムの元コードをいじらなくても拡張できるという仕組みでもあります。

さきほど説明したObserverを使えば通知元のコードを改変せずに動作を付け足せるからです。モジュールの外からemitを叩けば、さらにできることは増えるでしょう。

また、JavaScriptのtapableパッケージのように通知内容を改変できるライブラリもあります。ここまでくるとそれなりの拡張性を持たせることができるでしょう。

応用・発展系としては、FluxとかReactiveExtensionsのようなものもあります。

オブザーバパターンを使う

オブザーバパターンは、言語機能として持っているケースもありますし、さまざまなライブラリとして車輪の再発明的にたびたび生まれてたりもします。

あるいは上記のObserverのようにサクっと簡単に自作できるものでもあります。

JavaScriptならNode.jsのEventEmitterEventEmitter2パッケージを使うと良いでしょう。後者はウェブブラウザ上でも動きます。お好みで使うといいでしょう。

デザインパターンの注意点

デザインパターンは、大昔にGoFという4人組が生み出したものがプログラミングの世界では大本になるのですが、実際のところGoFのパターンのうち半分くらいは言語仕様が貧弱だったせいで生まれたもので、今となっては化石となっています。

あるいは、デザインパターンのようなものを知ったプログラマは「ハンマーを持っていれば、何でも釘に見える」症候群というものに罹患するかもしれません。それは視野を狭めるものなので、早めに罹患して早めに治療しておくといいかもしれません。

意思疎通には便利ですが、必須というほどではないので、デザパタ全部暗記してみた!!!!みたいなのはやんない方がいいです。(身もふたもない締め)

この記事が気に入ったらサポートをしてみませんか?