Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

Better Stimulusガイド:アーキテクチャ3: ミックスイン(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

hotwired/stimulus - GitHub

🔗 3. ミックスイン

Bad

// overlay_controller.js
import { Controller } from "stimulus";

export default class extends Controller {
  showOverlay(e) {
    // ...
  }

  hideOverlay(e) {
    // ...
  }
}
// dropdown_controller.js
import OverlayController from "./overlay_controller";

export default class extends OverlayController {
  //...
}

// flyout_controller.js
import OverlayController from "./overlay_controller";

export default class extends OverlayController {
  //...
}

Good

// mixins/useOverlay.js
export const useOverlay = controller => {
  Object.assign(controller, {
    showOverlay(e) {
      // ...
    },
    hideOverlay(e) {
      // ...
    }
  });
};
// dropdown_controller.js
import { useOverlay } from "./mixins/useOverlay";

export default class extends Controller {
  connect() {
    useOverlay(this);
  }

  //...
}

// flyout_controller.js
import { useOverlay } from "./mixins/useOverlay";

export default class extends Controller {
  connect() {
    useOverlay(this);
  }

  //...
}

そうする理由

Stimulusのコントローラは、ミックスインとして使うことが想定されています。つまり、1個のDOM要素に複数のコントローラを適用して振る舞いをミックスするということです。しかし、振る舞いをコントローラレベルで共有するのが望ましいこともあります。この場合、継承は必ずしも解決策にはなりません。

たとえば、異なる2つの親から動作を継承する必要があることがわかったとしても、JavaScriptでは不可能です。多くの場合、コントローラ間で利用できる振る舞いを単純な方法でミックスするのが望ましい方法です。

もし、継承とミックスインのどちらが正しいパターンなのかわからない場合は、以下を自分自身に問いかけてみてください。

  • コントローラがターゲットに対して"is-a"関係の場合 => 継承を使う
  • コントローラがターゲットに対して"acts-as-a"関係の場合 => ミックスインを使う

注意

ミックスインが正しい選択ではない可能性もあります。コンポジションの方がニーズに合うこともあります。

今モデリングしているものがトレイト("acts-as-a")かコラボレーター("has a")であれば、コンポジションを使いましょう。つまり、コラボレーターを別のJavaScriptモジュールまたはクラスとしてモデル化し、connectメソッドでそれをインスタンス化するということです。

参考資料

stimulus-use/stimulus-use - GitHub

Codesandboxのサンプル

関連記事

Better Stimulusガイド:アーキテクチャ(1)アプリケーションコントローラ(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。