JavaScript を ES6(ES2015) で書いてイミュータブルなオブジェクトを実装しよう

イミュータブルという言葉を知っていますか?プログラミングにおける重要なキーワードの1つらしいのですが、私は知りませんでした。

イミュータブルとは何か?どうすればそれを実現できるのか?JavaScript を例にとって考察しようと思います。

イミュータブルとは

イミュータブル(immutable)とは、日本語で「不変」という意味の言葉です。イミュータブルなオブジェクトと言ったら、状態が変わらないオブジェクトのことを指します。

イミュータブルなオブジェクトは状態が変えられないため、変数のオブジェクトを更新する場合は、オブジェクトを作り直さなければいけません。

なぜイミュータブルなオブジェクトにするのか

なぜわざわざオブジェクトを作り直すのでしょうか。イミュータブルなオブジェクトを使用する利点は、いくつか考えられます。

以前の状態を簡単に再現できる

イミュータブルなオブジェクトは、状態が変化しないことが保証されているため、そのオブジェクトを保持しておくだけでいつでも元の状態を再現することができます。

データの更新を簡単に検出できる

イミュータブルなオブジェクトは、前と同じオブジェクトを参照している限り、状態も変化していないことがわかります。そのため、オブジェクトが持っているすべての状態を1つずつ取り出して比較する必要がありません。

React ではパフォーマンスを最適化できる

JavaScript ライブラリの React では、イミュータブルな pure component を構築することで、効率的な再レンダーが可能になります。※詳しくは、Reactのガイドで説明されています。

JavaScript でオブジェクトをイミュータブルなものとして扱う

JavaScript において、文字列や数値、真偽値等のデータは絶対的にイミュータブルです。そのため、これらのデータを扱う場合はイミュータブルを意識する必要はありません。※こちらの資料で詳しく説明されています。

一方で、オブジェクトや配列は中の状態が変えられるため、基本的にイミュータブルなデータではありません。

// オブジェクトの場合
var obj1, obj2;

obj1 = {a: 1};
obj2 = obj1;

obj2["1"] = 2;
obj2.a = "b";

console.log(obj1); // {1: 2, a: "b"}

// 配列の場合
var ary1, ary2;

ary1 = [1, 2];
ary2 = ary1;

ary2.push(3);
ary2[0] = "a";

console.log(ary1); // ["a", 2, 3]

オブジェクトや配列をイミュータブルなデータとして扱いたい場合は、少し工夫が必要です。基となるオブジェクトの状態は変えずに、新しい状態を持った別のオブジェクトを作成し、古いデータと置き換えて使用します。

// オブジェクトの場合
var obj1, obj2;

obj1 = {a: 1};
obj2 = obj1;

obj2 = Object.assign({}, obj2, {"1": 2});
obj2 = Object.assign({}, obj2, {a: "b"});

console.log(obj1); // {a: 1}

// 配列の場合
var ary1, ary2;

ary1 = [1, 2];
ary2 = ary1;

ary2 = ary2.concat(3);
ary2 = ["a"].concat(ary2.slice(1));

console.log(ary1); // [1, 2]

イミュータブルなオブジェクト操作に使えるメソッド

Object.assign() は、ES6 から使えるようになった新しいメソッドです。コピー先として空のオブジェクトを指定することで、コピー元オブジェクトからプロパティをシャローコピー (1段階の深さのコピー)した新しいオブジェクトを返します。

配列では concat() メソッドや slice() メソッドを使うことで、元の配列を変更せずに要素を結合したり、元の配列を変更せずに要素を切り取ったり、非破壊的な配列操作が可能になります。反対に、sort()push() 等のメソッドは元の配列を直接変更してしまうため、イミュータブルな配列には使用できません。

他に、オブジェクトのプロパティや配列の要素に値を直接代入するようなコードも、イミュータブルなデータ更新では使うことができません。

データの変化を伴うメソッドのことを破壊的メソッド、データの変化を伴わないメソッドを非破壊的メソッドといいます。イミュータブルなオブジェクト操作では非破壊的メソッドを使いましょう。

参照の値をコピーする意味

上記のメソッドは、コピー元のプロパティがオブジェクトを参照している場合、参照の値のみをコピーします。また、オブジェクトを別の変数に代入する際も、参照の値をそのまま代入して、同じオブジェクトを参照するようにしています。

var ary1 = [
  {a: 1},
  {b: 2},
  {c: 3},
];

var ary2 = ary1;

ary1 = ary1.slice(1);

console.log(ary1[0] == ary2[1]); // true

このように同じオブジェクトを参照することで、オブジェクトの状態が等しいかどうかを簡単に調べることができます。オブジェクトを1から作り直すわけではないので、メモリが無駄に使用されることもありません。

スプレッド構文でより簡潔に

オブジェクトや配列をイミュータブルなデータとして扱うコードは、スプレッド構文を使ってより簡潔に書くことができます。

// オブジェクトの場合
var obj1, obj2;

obj1 = {a: 1};
obj2 = obj1;

obj2 = {...obj2, "1": 2};
obj2 = {...obj2, a: "b"};

console.log(obj1); // {a: 1}

// 配列の場合
var ary1, ary2;

ary1 = [1, 2];
ary2 = ary1;

ary2 = [...ary2, 3];
ary2 = ["a", ...ary2.slice(1)];

console.log(ary1); // [1, 2]

オブジェクトのスプレッド構文は ES2018 から、配列のスプレッド構文は ES6 から使えるようになりました。

まとめ

オブジェクトの状態は変えず、新しく作り直すようにすることで、イミュータブルなオブジェクトを実現することができました。

ES6 から使えるようになった新しいメソッドやスプレッド構文を活用して、イミュータブルなオブジェクトを実装しましょう。

サイトが妙に遅いときは画像の圧縮に失敗しているかも!

モバイルサイトの読み込み速度をテストできる Google のサービスをご存知でしょうか。

参考

モバイルサイトの読み込み速度とパフォーマンスをテストする – Google

あるイベントサイトを作成して、このサービスで読み込み時間を計測したところ、17秒という非常に悪い結果が出てしまいました。

読み込み速度を優先するために HTML で静的なサイトを作成して、画像の総容量も1MB以下なのになぜ…とずっと悩んでいたのですが、画像を圧縮しなおしてみたところ、すんなり5秒以下に改善しました。

おそらく、画像の圧縮がうまくできていなかっただけのようです。

WordCamp Osaka 2018 に当日スタッフとして参加してきました

6月2日に関西大学梅田キャンパスで開催された WordCamp Osaka 2018 に当日スタッフとして参加してきました。
ついでに、大阪観光もしてきました。

6月1日:大阪観光

松本から高速バスで大阪まできました。
電車で名古屋まで行って乗り継いだ方が早いのですが、私は特急しなのの揺れが苦手で耐えられません。
大阪に着いたらノープランで歩き回ってましたが、結構楽しかったです。

写真撮ってませんけどはなだことかいうお店でたこ焼き食べました

おしゃれなビル
エスカレーターでは皆右側に乗っていました
梅田
東通りの商店街にあるお店の半数以上は無料案内所
一蘭のラーメンは2回替え玉したが…

ホテルに戻って少ししたらお腹がピーピーでした

6月2日:WordCamp

WordCampはとても盛り上がりました!

お世話になった方やはじめましての方、多くの方とお話できました
グッズもたくさんもらいました

スタッフとしての参加ですがセッションもいくつか見られました

懇親会の写真は撮るの忘れました

二次会もあったみたいですが、前日に調子こき過ぎてお腹の調子が悪いのと、WordCampでも調子こき過ぎて周りに無礼を振り撒いてしまったので、自重して寝ます。

ありがとうございました。

おやすみなさい。

安心して WordPress を利用するためのライセンスの話

4月28日に松本市のコワーキングスペース「SWEET WORK」で開催した WordBench Nagano vol.18 でライセンスの話をしました。

自分自身、登壇したことでとても勉強になったので、内容を整理したいと思います。

オープンソースソフトウェア (OSS) について

オープンソースソフトウェア (以下 OSS) とは、目的を問わずソースコードを実行、調査、複製、再頒布、改変できるソフトウェアのことです。
目的を問わないというところがミソでして、営利目的でソフトウェアを販売したり軍事目的でソフトウェアを実行したりできるわけです。
ソフトウェアのソースコードが公開されているだけでは著作権によって利用が制限されるため、OSS にはなりません。ソースコードをオープンソースとして利用するにはオープンソースライセンスが必要です。
オープンソースライセンスとは、ソースコードの利用に対する許可または許可証のことです。
オープンソースライセンスには、ソースコードの著作権情報や利用条件等の内容が含まれています。

WordPress と GPL

WordPress に適用されているライセンスについて

WordPress は OSS であり、代表的なオープンソースライセンスのひとつである GPL が適用されています。
GPL では基本理念として、以下に挙げる4つの自由を保証しています。

  • 実行する自由
  • 研究する自由
  • コピーし共有する自由
  • 改変する自由

自由というのは、これらのことをしてもいいししなくてもいいという意味です。
そして、これらの自由がすべての利用者に与えられるように、コピーレフトという手法を採用しています。ソフトウェアを再配布する際には、同じライセンスを適用しなければなりません。
コピーレフトは、利用者の自由を保証するために著作権を使います。
著作権表示も、ソフトウェアを配布するのに必要です。著作権表示には、著作権のシンボル(丸の中にC)か、“Copyright”  という表記が必ず含まれます。
また、ここでいう配布とは、一般公衆に利用可能とすること等を指し、Webサービスとして実行することやクライアントに納品することは含まれません。
つまり、WordPress を使ってWebサイトを制作するからといって、ソースコードの開示や WordPress の著作権表示が必要になるわけではありません。
しかし、私のサイトではフッターの “Proudly powered by WordPress” という表記は消さないようにしています。
これには “Copyright” の表記も含まないため、そもそも著作権表示でもありませんが、WordPress に同梱されている readme ではさりげなく https://wordpress.org/ へのリンクを推奨しています。
減るものでもないし、これくらいの表記は残してあげてもいいんじゃないかなと思います。

100%GPL とスプリットライセンス

GPL はソフトウェアに対して適用されるため、WordPress のテーマに同梱される画像や css のようなファイルには適用されません。
PHP 以外のファイルには、どのようなライセンスでも適用することができます。
配布するすべてのファイルを GPL もしくは GPL 互換のライセンスにすることをWordPressコミュニティ内では 100%GPL と呼び、強く推奨しています。
逆に、ファイルによってライセンスを使い分けることをスプリットライセンスと呼びます。
WordPress のテーマ等をスプリットライセンスで配布することは、法的には問題ありません。しかし、スプリットライセンスにして PHP 以外のファイルに GPL より制約の厳しいライセンスを適用すると、GPL が保証する4つの自由の良さが薄れてしまいます。
100%GPL を推進するため、WordPress.org へ掲載するテーマやプラグインは 100%GPL であることが条件になります。また、WordCamp や WordBench 等のイベントで登壇する場合も、配布・宣伝しているすべての WordPress 派生物が 100%GPL である必要があります。
WordPress は GPL だったからこそこれほど発達したと、創始者の方も仰っていたそうです。
配布するファイルには 100%GPL を適用しましょう。そして、100%GPL で配布された WordPress 派生物を安心して利用しましょう。

まとめ

  • WordPress は、どのような目的で実行、研究、コピーや共有、改変しても良い。
  • WordPress 本体、テーマやプラグイン等を配布する際は、GPL を適用して、利用者の自由を保証しなければならない。
  • WordPress 派生物は 100%GPL 推奨。

参考

サイトを GAE から GCE に移行しました

この度、Google App Engine (GAE) で運用していた「四次元のおともだち」を Google Compute Engine (GCE) に移行しました。
このサイトの場合、GCE へ移行したことで運用コストが全体的に下がりました。

費用面では、メモリ 0.6GB と仮想 CPU を1つまで使用できる f1-micro インスタンスに加えて、30GB までの HDD が無料なので、ほぼ独自ドメインにかかる費用だけで運用できるようになりました。

一方で、WordPress 自体はランチャーで簡単にインストールできたものの、SSL を導入したりメールを送れるように設定したり、導入時の手間は増えました。

ただ、管理画面から WordPress を更新したりプラグインやテーマをインストールしたり、楽になった部分も大きいので、やはり結果的には運用しやすくなったと思います。