前項の無効をサポートするオブジェクトがどんなものかを、他の手法と比較して考えて見ます
・テストファースト
仕様の洗い出しのためにテストを作成するという意味では同じです。
どちらも動的なテストができるという意味では同じです。
クラスを作成するときに、最初にSelfTest()を作ってしまうのも同じです。
違いは、繰り返しテストを削除したことと、このテストを本番コードにも組み込むということです。
繰り返しテストを取るのか、本番コードに組み込むことによるさまざまなメリットをとるのか・・。
両方のいいとこ取りをするのがベストですかね。
・ダックタイピング
クラスの作成権、編集権が見る側に全権があるという意味で、SelfTest()オブジェクト指向とほぼ同じです。
理念は同じなのですが、現在のダックタイピングは静的に表現されることが多いです。
見る側の思惑と現実が同じかどうかの検証は動的である必要があります。
現在のダックタイピングと、SelfTest()オブジェクトは、動的か静的かが主な違いです。
・契約プログラミング
SelfTest()は、事前条件そのままという意味で同じです。
事前条件以外を使用しないという意味では違います。
現在の契約プログラミングでは、静的解決を目標にしているものが多いため、
現在の契約プログラミングとはかけ離れているかもしれません。
SelfTest()は、動的テストを重要視しています。
・ネットワーク
オブジェクト指向を、オブジェクト間、オブジェクト-リソース間の通信と考えれば、通信の手法が使えるはずです。
ネットワークの場合、切断の要因が相手にあることがあるため、
常に接続されているかどうかを確認しなければいけません。この考えはSelfTest()と同じです。
・デザインパターン
Nullオブジェクトが最も近いです。
全てのクラスがNullオブジェクトにもなれることをサポートしなければいけない、と考えるとSelfTest()と同じです
・ガード句
極めて相性がよい、というよりはオブジェクト指向をガード句に対応させたものがSelfTest()オブジェクト指向といっても過言ではないです。
どんなクラスに対しても有効なガード句を使用可能になります
・関数型
全てのクラスが"無効な状態"をサポートするため、戻り値でクラスのインスタンスを安全に返すことができます
(初期化に失敗しても例外を出さない。コード上に矛盾も起きない)。
この使い勝手が、関数型と少し似ているかもしれません
・状態遷移
必要性を感じなくなります。
SelfTest()は、全ての状態を考慮した上でどんな時にでも正しく動くことを目指すため、
特定のパターンに依存する状態遷移は必要がなくなります。
むしろ状態遷移の上位互換に近い(全てのパターンを考慮するという意味で)のですが、その分難しいともいえます
もっともイメージしやすいのはおそらく、テストファーストを本番コードに組み込んだもの、ですかね。
実際メリットの半分くらいはテストファーストと同じです。
なぜ本番コード、つまり動的にテストをしなければいけないのかは、
オブジェクト-リソース間の通信(メッセージ)と捉えているからです。
通信であれば、接続テストは必須ですよね?
オブジェクト指向の外を見てみれば、案外と普通の手法です
無効をサポートするオブジェクト手法のメリットを考えて見ます。
まず一つは、テストファーストと同様、仕様の理解を深めます。
もう一つは、プログラムの構造をシンプルにすることが可能な点です。
??わかりませんね。
まず構造化定理を思い出してください。
全てのプログラムは順次、反復、分岐で表現できます。
このうち分岐は全て、あるオブジェクトが有効か無効かで表すことができます。
ある処理をするとき、"全ての必須のオブジェクトが有効であれば"、
順次、反復のみであらわすことが可能です。
分岐がなければ、反復は順次と読み替えても対して問題にならないでしょう。
必須のオブジェクトが一つでも無効であれば、それは制約を満たしていないので処理が中断します。
つまり、プログラムを順次と中断だけで表現することができるようになります。
分岐をなくすというよりはむしろ、初期化に持ってくるイメージに近いです。
RAII(Resource Acquisition Is Initialization リソースの確保は初期化時に)をもじって
SII(Selection Is Initialization 選択は初期化時に)とかどうでしょうか
もっともっと実装よりに言えば、全てのオブジェクトに対してガード句を使えるのが最大のメリットです
いったんこの手法に慣れてしまうと、引数のオブジェクトにガード句を使えないのが不満で不満でしょうがなくなりますw
int Func(Object obj){
if(int res = obj.SelfTest()){return res;}//←これ。
//何か
return 0;
}