[EffectiveJavaScript輪読会8]不必要な状態を排除する

GAS

どうも。つじけ(tsujikenzo)です。このシリーズでは2021年8月からスタートしました「ノンプロ研EffectiveJavaScript輪読会」についてお送りします。

前回のおさらい

前回は、「オプションオブジェクトで、キーワード付き引数群を受け取ろう」をお届けしました。

[EffectiveJavaScript輪読会8]オプションオブジェクトで、キーワード付き引数群を受け取ろう
どうも。つじけ(tsujikenzo)です。このシリーズでは2021年8月からスタートしました「ノンプロ研EffectiveJavaScript輪読会」についてお送りします。前回のおさらい前回は、「undefinedは「値...

今日は4回目で、「不必要な状態を排除する」をお届けします。

テキスト第6章「ライブラリとAPI設計」の項目56に対応しています。

今日のアジェンダ

  • ステートフルAPIとは
  • ステートレスAPIとは
  • ステートレスAPIを選ぼう

ステートフルAPIとは

ステート(状態)がフルなAPIとはなんでしょうか。

テキストでは、話の流れに沿ってAPIと呼ばれていますが、これは、オブジェクトでもかまいません。

状態を持っているオブジェクトといえば、Dateオブジェクトが挙げられます。

new演算子で呼ばれるコンストラクタは、現在時刻を状態としてもつでしょう。

//ステートフルなオブジェクト
const d = new Date();
console.log(d); // => Wed Dec 22 2021 00:32:50 GMT+0900 (Japan Standard Time)

なので、このように、状態をもつオブジェクトを使って処理が進められます。

function myFunction56_01() {

  //ステートフルなオブジェクト
  const d = new Date();
  console.log(d); // => Wed Dec 22 2021 00:41:07 GMT+0900 (Japan Standard Time)

  const formatDate = Utilities.formatDate(d, 'JST', 'yyyy年MM月dd日 HH時mm分ss秒');
  const strNow = `現在時刻は${formatDate}です`;
  console.log(strNow); // => 	現在時刻は2021年12月22日 00時41分07秒です
}

しかし、このコードは、あずかり知らずな箇所で、状態を変更する処理が書かれているばあい、破綻しかねません。

function myFunction56_02() {

  //ステートフルなオブジェクト
  const d = new Date();
  console.log(d); // => Wed Dec 22 2021 00:47:43 GMT+0900 (Japan Standard Time)

  //あずかり知らずな処理
  d.setDate(31);

  const formatDate = Utilities.formatDate(d, 'JST', 'yyyy年MM月dd日 HH時mm分ss秒');
  const strNow = `現在時刻は${formatDate}です`;
  console.log(strNow); // => 	現在時刻は2021年12月31日 00時47分43秒です
}

ステートレスAPIとは

なので、状態をもたない(ステートレス)な、オブジェクトを実装しよう、というのがテキストに書かれています。

上記の例でいくと、このように書き換えができます。

function myFunction56_03() {

  //ステートレスなオブジェクト
  const formatDate = Utilities.formatDate(new Date(), 'JST', 'yyyy年MM月dd日 HH時mm分ss秒');
  const strNow = `現在時刻は${formatDate}です`;
  console.log(strNow); // => 	現在時刻は2021年12月22日 00時51分49秒です

}

デフォルト値をもつようなオブジェクトを、ステートレスにする例がテキストに掲載されていました。

function myFunction56_04() {

  //このコードは動きません

  //ステートフル
  c.fillText("text1", 0, 0); //デフォルト⾊
  c.fillStyle = "blue";
  c.fillText("text2", 0, 30);//⻘
  c.fillStyle = "black";
  c.fillText("text3", 0, 60);//黒に戻る

  //ステートレス化
  c.fillText("text1", 0, 0); //デフォルト⾊
  c.fillText("text2", 0, 30, { fillStyle: "blue" });//⻘
  c.fillText("text3", 0, 60);//デフォルト⾊

}

ステートレスAPIを選ぼう

INIファイルは、構造の単純なテキストファイルであり、設定ファイルのフォーマットとしてよく使われています。

テキストでは、サーバーの設定を行うINIファイルが用意されていました。

[Host]
address = 172.0.0.1
name = localhost
[Connections]
timeout = 10000

このファイルデータを処理するAPIを考えたとき、ホスト(サーバーのパソコンのこと)の状態を確認し、設定する必要があります。

const ini = INI.parse(src);
ini.setSection("Host");

const addr = ini.get("address");
const hostname = ini.get("name");
ini.setSection("Connection");

const timeout = ini.get("timeout");

const server=newServer(addr,hostname,timeout);

しかし、このままだと、Dateオブジェクトのときと同様、どこか違う場所からホストの状態が変更されている可能性もあり、破綻します。

ステートレスなAPIにするなら、このように書けるでしょう。

const ini = INI.parse(src);
const server = newServer(ini.Host.address, ini.Host.name, ini.Connection.timeout);

もし、ステートフルなAPIを実装するばあいは、ドキュメントで明示しなければならない、というルールをオススメしていました。

まとめ

以上で、「不必要な状態を排除する」をお届けしました。

次回は、「柔軟なインターフェイスのために、構造的な型付けを使う」 をお届けします。

参考資料

このシリーズの目次

タイトルとURLをコピーしました