私は文字通りの意味で「不変」を理解しています。コードを入力するときにも認識します。しかし、コンピュータサイエンスの文脈でこの用語の重要性を理解しているとは思いません。
有名なプログラマー\コンピューター科学者からの言語設計に関する会話\ホワイトペーパーを読むときはいつでも、 "不変"という用語が専門用語として浮かび上がってきます。そしてそれは私が理解していない部分です。何がそんなに特別なのですか?
アルゴリズムは反復可能なプロセスです。繰り返し可能な場合、繰り返しても変化しない属性を持つ必要があります。これらはあなたの不変条件です。不変条件は、アルゴリズムに入力される(潜在的に)変化するデータと組み合わせたり、操作したりします。
したがって、プログラミングの全体の要点は、変化しないもの、つまり本質的にはあなたのプログラムであることを識別することです。
オブジェクト指向プログラムでは、各オブジェクトが1つのことをうまくやるべきだという考えがあります。これは、本質的に(クラスベースのOOPの場合)クラスが単一のアルゴリズムの不変式を、オブジェクトが必要とする可能性のあるバリアントデータのプレースホルダー(変数)とともに定義することを意味します。理想的には、オブジェクト指向では、変化するものをできるだけ分離し、各オブジェクトがほとんど不変になるようにします。
不変の概念は「副作用」と強く関連しています。これは、ソフトウェア設計のためのバートランド・マイヤーの「契約による設計(DbC)」アプローチによって促進されたと思います。
DbCは、3つの重要な概念前提条件、事後条件、不変条件で抽象データ型(クラスのバックボーン)を強化します。手順を参照すると簡単に説明できるので、参考にして説明します。
preconditionは、プロシージャを呼び出すために、そのプロシージャの条件入力データが順守する必要があることを表します。この前提条件は、その特定の手順のクライアントが尊重し、強制する必要があります。ただし、プロシージャーの設計者は、前提条件を順守していないクライアントから、その条件をプロシージャーの最初の行としてアサートすることで防御できます。たとえば、メソッドdouble divide(double dividend, double divisor)
を前提条件とすると、_divisor != 0
_になります。
postconditionは、プロシージャが戻った後の出力データの条件を表します。前提条件が順守されている場合、この事後条件を順守することは、完全にプロシージャデザイナーの仕事です。戻る前の防御プログラミングスタイルでは、事後条件をアサートできます。
不変式は、前提条件と事後条件の両方と見なすことができますが、前提条件と事後条件の理解は上記の概念とは異なります。不変条件は、基本的に、入力がプロシージャが呼び出される前に特定の条件が満たされた場合、その特定の条件はプロシージャが呼び出された後に有効になると述べています。たとえば、プロシージャboolean search(int term, int array[])
の有効な不変条件は、呼び出し前のarray
の状態が呼び出し後と同じであると言う場合があります。
副作用;を減らすため、プロシージャ(およびプロシージャだけでなく)に不変条件を適用することは素晴らしいことです。副作用はプログラミングにおいて非常に悪いので、これは便利です。特定のプロシージャは、入力引数の状態を変更したり、一部のグローバル変数の状態を変更したり、一部のグローバル変数に依存したりする場合があります。これは、(同じ入力を使用した)同じプロシージャでの2つの同一の呼び出しが異なる出力を生成する可能性がある厄介な状況につながる場合があります。これは、呼び出しの履歴を知ることにつながり、特にマルチスレッドのコンテキストではデバッグが非常に困難です。
インバリアントは、いくつかの操作で保持される論理プロパティです。
ループについて推論するには、不変条件が必要です。反復の数が事前にわからないため(またはループが必要ない場合)、反復ごとに不変式を保持する必要があるため、最後にループに関する有用なプロパティを証明できます。
カプセル化されたデータのプロパティについて推論するには、不変条件が必要です。多くの場合、モジュールまたはオブジェクト内のさまざまなデータは、正しい操作のために特定のプロパティを満たす必要があります(たとえば、セットを表すリストは常に並べ替える必要があります)。データを操作する各関数またはメソッドがこれらのプロパティを保持するため、それらも不変です。
プログラミング言語の型システムのコンテキストでは、不変型は変換できない型です。たとえば、Javaでは、メソッドをオーバーロードすると、すべてのパラメーターは不変ですが、戻り値の型は共変です(同じまたはサブタイプの場合があります)。
不変量の重要性は、アルゴリズムが特定の関数を計算することを証明するための構成要素であるという事実からわかっています。たとえば、新しい並べ替えアルゴリズムを開発しましたが、実際にすべての入力またはすべての正しい出力で並べ替えられるようにするにはどうすればよいでしょうか。次のステップは、アルゴリズムのフローに対応する不変量を作成し、不変量を使用してソートされることを証明することです。