JavaScriptにおける表明(assertion)の話
表明(assertion)
表明(ひょうめい、英: assertion)とは、プログラミングにおける概念のひとつであり、そのプログラムの前提条件を示すのに使われる。アサーションとも呼ばれる。表明は、プログラムのその箇所で必ず真であるべき式の形式をとる。
表明の例
引数が数値型であることを事前条件とする表明
code:js
function add (a, b) {
assert(typeof a === 'number');
assert(typeof b === 'number');
return a + b;
}
この場合はTypeScriptなら number 型にすることでも表明できるが、NaNチェックは実行時にしかできない
code:ts
function add (a: number, b: number) {
assert(!isNaN(a));
assert(!isNaN(b));
return a + b;
}
ゼロでない数であることを事前条件とする表明
code:ts
function divide (a: number, b: number) {
assert(!isNaN(a));
assert(!isNaN(b));
assert(b !== 0);
return a + b;
}
表明の利点
早期のデバッグ
想定しない値が混入するコードと、その値が問題を起こすコードの距離が遠いとデバッグが大変
中間チェックポイントとしてその時点で満たしていなければならない条件を表明しておくと原因と近いところで問題を発見しやすい
当然だがユニットテストの実行時にも有効
契約による設計 (DbC)的な利点
ある関数や処理の事前条件をコード中で表明してあれば、ある種のドキュメントとしても機能する
間違った使い方・呼び出し方について開発者に修正を促すことができる
表明を行う
表明はソースコードに書く
しかしエンドユーザー向けにエラーを出してクラッシュさせたいわけではない
開発時やステージング環境などではエラーを投げたいが、プロダクション環境では無効化したい
条件によって表明を無効化・除去する仕組みが必要
JavaScriptにおける表明
ECMAScript自体には表明に関する機能はない
Node.jsには node:assert 標準パッケージがある
しかしプロダクション環境で無効化・除去するような仕組みはない
babelパイプラインの中でビルド時に表明を除去するツール
ブラウザには console.assert() 関数がある
しかしこれはログとしてアサーションエラーを出すだけで、例外は投げない
ブラウザでの表明を自作する
Angularアプリを題材にしたけど、Angularかどうかはあまり関係ない
ビルド時に決定できるパラメータによって2種類の実装を切り替えるアプローチ
例外を投げてアプリケーションをクラッシュさせられる unsafeAssert と、ログを出すだけの safeAssert
ビルド設定の値によって window.assert にセットする関数を切り替える
code:ts
function unsafeAssert(condition: boolean, message: string) {
if (!condition) {
const error = new Error(message);
error.name = 'AssertionError';
throw error;
}
}
function safeAssert(condition: boolean, message: string) {
console.assert(condition, message);
}
export function setupGlobalAssert() {
if (THROW_ASSERTION_ERROR) {
window.assert = unsafeAssert;
} else {
window.assert = safeAssert;
}
}
まとめ
表明を取り入れていきたいというお気持ち
堅牢なコードにするための方法論としてユニットテストに頼りすぎていたことを自覚した
必要な仕組みはわずかなので、自分のプロジェクトに合わせて自作してもよい