Declarative Programmingメモ

React関連の記事を読んでいると、よく「Declarative」という言葉に出くわします。

宣言型プログラミング | Wikipedia

Declarative(宣言型)に対して「Imperative(命令型)」という考え方があり、それぞれプログラミング手法を表した言葉です。

大まかには、

  • Imperative: 動作を説明する
  • Declarative: 達成したいことを説明する

といった方法の違いです。

Imperativeなプログラムの場合

  1. 棚からカップを取る
  2. お湯を沸かす
  3. コーヒー豆を2杯分見るに投入する
  4. ハンドルを回してコーヒー豆を挽く
  5. 全て挽けたら、ドリッパーにフィルターをセットする
  6. フィルターに挽いた豆を入れる
  7. お湯が沸いたらドリッパーにお湯を注ぐ
  8. 20秒蒸らす
  9. 1杯分のコーヒーを抽出する
  10. 私にカップを渡す

というような命令を記述することで、自分にコーヒーを出してもらえます。

対してDeclarativeなプログラムの場合、「コーヒー頂戴」と言うだけです。この場合、コーヒーを淹れてくれる人が、コーヒーをどのように淹れるのかを知っているということが重要になります。

シンプルな例として以下のような関数を作るとします。

toLowerCase(['Foo', 'BAR']);  // ['foo', 'bar']  

toLowerCaseをimperativeに実装すると以下のようになります。

const toLowerCase = input => {  
  const result = [];
  for(let i = 0; i < input.length; i++) {
    result.push(input[i].toLowerCase());
  }
  return result;
};

結果を格納する配列を用意し、小文字に変換した文字列をその配列に入れ、返すことで、結果を得ることができます。対してdeclarativeな方法だと以下のようになります。

const toLowerCase = input => input.map(val => val.toLowerCase());

toLowerCase(['Foo', 'BAR']); // ['foo', 'bar']  

declarativeなコードで注目するべきは、関数内で変数も使わず、処理に際して特定の値の変化を気にせずに結果を得ているということです。declarativeなコードでは変数、つまり状態を作ったり、変更したりということをしなくて済む傾向にあります。

例えばリストのデータを表すUIを作る場合、

  1. データを取得してから
  2. 各要素のデータをHTMLテンプレートに渡し
  3. 1要素分のHTMLを作ったら、ドキュメントフラグメントへ追加し
  4. 最終的にコンテナ要素へフラグメントをappendする

という手法ではなく、以下のように(かなり大雑把ですが

// list component 
// リストデータを受取りリストを出力する
<SomeList list={myList} />

// list item component
// リストデータの1要素を受取り1アイテムを表すコンポーネントを出力する
<SomeListItem item={item} />  

のようにコンポーネントを定義することで、コンテナ側はコンポーネントを配置するだけで良くなるので、メンテナンス性が高いコードにすることができる、ということです。