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