モダンなJSフレームワークは宣言型プログラミングを選ぶ


モダンなJSフレームワークであるVue.jsReactなどは宣言的という特性を取り柄としている。

Reactの公式サイトによると、宣言的なViewを

アプリケーションの各状態に対応するシンプルな View を設計するだけで、React はデータの変更を検知し、関連するコンポーネントだけを効率的に更新、描画します。

宣言的な View を用いてアプリケーションを構築することで、コードはより見通しが立ちやすく、デバッグのしやすいものになります。

と解釈している。

この記事では、宣言的方式なとそうではない方式との違いを理解した上で、なぜモダンなJSフレームワークは皆宣言的方式を選ぶのかについて考える。

宣言的プログラミングと命令的プログラミング

Wikipediaにあるわかりやすい定義によると、宣言的プログラミング(Declarative programming)は「何を得たい」というWhatの部分を記述し、命令的プログラミングは(Imperative programming) は「どうやって得るか」つまりHowの部分を記述する。

具体例を挙げる。

文字列の表示をコントロールするボタンを作るとする。

命令的方式では、DOM(Document Object Model)に対して、文字列やボタンなどのHTML要素の生成と表示/隠すロジックの実装を逐一記述することが必要。最終的にDOMがどういう風になるのかはコードからでは分からない。

const ctn = document.getElementById("container");

const txt = document.createElement("p");
txt.className = "text";
txt.id = "text-to-toggle";
txt.innerHTML = "This is sample text.";

const btn = document.createElement("button");
btn.innerHTML = "toggle text";
btn.onclick = function (event) {
  const txt = document.getElementById("text-to-toggle");
  txt.classList.toggle("hidden")
};

ctn.appendChild(txt);
ctn.appendChild(btn);

動く実例は以下を参照。


See the Pen
Imperative Sample
by shiiyan (@shiiyan)
on CodePen.


一方で、Vue.jsを使った宣言的方式では、構築したいDOMを最初から宣言することになる。

<div id="container">
  <p v-show="isVisible">This is sample text.</p>
  <button @click="toggle">toggle text</button>
</div>

v-showはVueが提供するディレクティブの一つで、isVisibleという変数が真の場合に対象要素<p>を表示し、偽の場合に表示しないという意味を持つ。

どういうことを実装したいのかはHTMLのテンプレートを見るだけでわかる。JavaScriptでやるのはボタンをクリックすると文字列の表示をコントロールする変数の値が逆転する関数を定義すること。実際のDOM操作はフレームワークがやってくれる。

var app = new Vue({
  el: "#container",
  data: {
    isVisible: true
  },
  methods: {
    toggle() {
      this.isVisible = !this.isVisible;
    }
  }
});

動く実例は以下を参照。

See the Pen Declarative sample by shiiyan (@shiiyan) on CodePen.

感想

宣言的方式とインタラクティブUIとの相性がいい。上記のような簡単な例では大差ないが、宣言的方式は明示的に状態管理の変数が存在し、複雑なインタラクティブUIを実装する時に、直接DOMをいじることより、状態変数をいじった方がやりやすい。

宣言的に方式はコード全体の見通しが良い。特に最初から実現したいHTMLテンプレートを記述することによって、HTMLからコンポーネントの設計が可能となり、高度なデザインを実装する難易度を下げられる。また、後からスタイルや表示内容の修正箇所の特定にも貢献する。

宣言的に方式により、画面表示と状態管理が別々のコンポーネントで定義することも可能となり、良い設計の起点となるかも。

参考