JavaScript を疎結合にしたかった。 (original) (raw)

PubSub パターンという考え方を適用した話です。Publish, Subscribe の略です。

コードはこんな雰囲気です。

export class PubSub {

#subscribers;

constructor() {

this.#subscribers = {};

}

subscribe(event, callback) {

this.#subscribers[event] = callback;

}

publish(event, data) {

const callback = this.#subscribers[event];

if (callback) {

callback(data);

}

}

}

export class Controller {

#model;

#ui;

#pubsub;

constructor(model, ui, pubsub) {

this.#model = model;

this.#ui = ui;

this.#pubsub = pubsub;

}

initialize() {

const eventMappings = {

"event_name_1": this.#callback_name_1.bind(this),

"event_name_2": this.#callback_name_2.bind(this),

};

for (const [eventName, handler] of Object.entries(eventMappings)) {

this.#pubsub.subscribe(eventName, handler);

}

export class Model {

#pubsub;

constructor(pubsub) {

this.#pubsub = pubsub;

}

publicMethod() {

this.#doSomething()

this.#pubsub.publish("event_name_1", this.#getStatus());

もともと1つのファイルに関心のある処理をすべて書いていたが、次第に肥大化していったため、ファイルを分割しようと思った。

主要な処理担当と画面担当に分割したのは良かったが、どうしてもお互いに依存する形となった。

そこで MVC の考え方に基づけば解決するかと思ったが、Model 側のプライベートメソッドと連動する場合、結構深いところとやり取りしなくちゃいけないし、結構歪になるなあって思った。

そこで登場するのが pubsub の考え方。

モデルの内部状態によって表示内容を変えたい場合、コールバックをイベントの subscriber として登録し、イベントの publisher はコールバック関数を実行すれば、疎結合に作れるみたい。

今までの案件では 1 つのファイルに数千行書いてあるのが当たり前だったので、このようなやり方があることを知らなかった。

あれはそもそもバッドプラクティスだったんじゃないかって気がしている。

コールバック関数って名前は聞いたことがあったけど、どういうものか知らなかったな…。