ウィキペディアから:理論的なコンピューターサイエンスでは、アルゴリズムが仕様に関して正しいと言われているときに、アルゴリズムの正当性が主張されます。
しかし問題は、「適切な」仕様を取得することは簡単な作業ではなく、正しいものを取得するための100%正しい方法(私が知る限り)がないため、単なる推定であるため、 「1つ」のように「見える」という理由だけで述語を仕様としてとるのは、プログラムが「正しく」見えるという理由だけでプログラムを正しいとみなさないのはなぜですか?
ウィキペディアから:理論的なコンピューターサイエンスでは、アルゴリズムが仕様に関して正しいと言われているときに、アルゴリズムの正当性が主張されます。
しかし問題は、「適切な」仕様を取得することは簡単な作業ではなく、正しいものを取得するための100%正しい方法(私が知る限り)がないため、単なる推定であるため、 「1つ」のように「見える」という理由だけで述語を仕様としてとるのは、プログラムが「正しく」見えるという理由だけでプログラムを正しいとみなさないのはなぜですか?
回答:
まず、あなたは絶対に正しいです:あなたは本当の懸念に向かっています。フォーマル検証は、プログラムの正確性に対する信頼性の問題を仕様の正確性に対する信頼性の問題に移行するため、特効薬ではありません。
ただし、このプロセスがまだ有用である理由はいくつかあります。
多くの場合、仕様はコード自体よりも単純です。たとえば、整数の配列をソートする問題を考えてください。パフォーマンスを改善するために巧妙なことを行うかなり洗練されたソートアルゴリズムがあります。ただし、仕様の記述はかなり簡単です。出力は昇順でなければならず、入力の順列でなければなりません。したがって、コード自体の正確さよりも、仕様の正確さに対する信頼を得る方が間違いなく簡単です。
単一障害点はありません。ある人が仕様を書き、別の人がソースコードを書き、そのコードが仕様を満たしていることを正式に検証するとします。その場合、仕様とコードの両方に未検出の欠陥が存在する必要があります。場合によっては、一部のタイプの欠陥については、これはあまり起こりそうにありません。仕様を検査するときに欠陥を見落とし、ソースコードを検査するときに欠陥を見落とす可能性は低くなります。すべてではなく、いくつか。
部分的な仕様は、コードよりもはるかに簡単です。たとえば、プログラムにバッファオーバーランの脆弱性がないという要件を考慮してください。または、配列インデックスの範囲外エラーがないという要件。これはシンプルな仕様であり、明らかに証明できる便利で有用なものです。正式な方法を使用して、プログラム全体がこの仕様を満たしていることを証明できるようになりました。それはかなり複雑な作業かもしれませんが、成功すれば、プログラムに対する自信が高まります。
仕様はコードよりも頻繁に変更されない場合があります。正式な方法がなければ、ソースコードを更新するたびに、更新によってバグや欠陥が発生しないことを手動で確認する必要があります。正式な方法はこの負担を潜在的に軽減できます。仕様が変更されず、ソフトウェアの更新にはコードの変更のみが含まれ、仕様の変更は含まれないとします。その後、更新ごとに、仕様がまだ正しいかどうか(変更されていないため仕様に新しいバグが導入されるリスクがない)を確認する負担と、コードがまだあるかどうかを確認する負担から解放されます。正しい(プログラム検証ツールが確認します)。元の仕様が正しいことを確認する必要がありますが、開発者が新しいパッチ/更新/変更をコミットするたびに確認し続ける必要はありません。
最後に、仕様は一般に宣言的であり、必ずしもコードに直接実行したりコンパイルしたりできるわけではないことを忘れないでください。たとえば、再度並べ替えを検討してください。仕様では、出力が増加し、入力の順列であると書かれていますが、この仕様を直接「実行」する明確な方法はなく、コンパイラが自動的にコードにコンパイルする明白な方法はありません。そのため、仕様を正しいと見なして実行することは、多くの場合オプションではありません。
それにもかかわらず、最終結果は同じままです。正式な方法は万能薬ではありません。コードの正確性に対する(非常に難しい)信頼の問題を、仕様の正確性に対する(単に難しい)信頼の問題に単純に移行します。仕様のバグは本当のリスクであり、一般的なものであり、見逃すことはできません。実際、正式なメソッドコミュニティでは、問題を2つの部分に分けることがあります。検証とは、コードが仕様を満たしていることを確認することです。検証とは、仕様が正しいことを確認することです(ニーズを満たします)。
あなたも楽しむことがあります実際には正式なプログラム検証をし、なぜ我々は、コンパイル時の保証に向けてより多くの研究をされていませんか?これに何らかの関係があるより多くの視点のために。
for each integer I
<sub> N
</ sub> in set S (where N > 1) { assert I
<sub> N
</ sub> > I
<sub> N - 1
</ sub>のように簡単に記述できます}
。表記について100%確実ではありません。
DWの答えは素晴らしいですが、私は1つの点で拡張したいと思います。仕様は、コードが検証される単なる参照ではありません。正式な仕様を持つ理由の1つは、いくつかの基本的なプロパティを証明することで仕様を検証することです。もちろん、仕様を完全に検証することはできません。検証は仕様自体と同じくらい複雑なので、無限のプロセスになります。しかし、検証により、いくつかの重要な特性についてより強力な保証を得ることができます。
たとえば、自動車の自動操縦装置を設計しているとします。これは多くのパラメーターを含む非常に複雑なものです。自動操縦の正確性のプロパティには、「車が壁に衝突しない」、「車は指示された場所を運転する」などが含まれます。「車が壁にぶつからない」というようなプロパティは本当に重要なので、それを証明したいと思います。システムは物理的な世界で動作するため、いくつかの物理的な制約を追加する必要があります。計算システムの実際の特性は、「材料科学に関するこれらの仮定、および車のセンサーによる障害物の認識に関するこれらの仮定の下では、車は壁に衝突しません」のようなものになります。たとえそうであっても、結果は明らかに望ましい比較的単純なプロパティです。
コードからこのプロパティを証明できますか?完全に正式なアプローチを取っている場合、最終的にはそれが起こっています¹。ただし、コードにはさまざまな部分があります。ブレーキ、カメラ、エンジンなどはすべて自律的に制御されます。ブレーキの正確さの特性は、「「ブレーキの適用」信号がオンになっている場合にブレーキが適用される」ようなものになります。エンジンの正確さの特性は、「クラッチ信号がオフの場合、エンジンが車輪を駆動していない」ことです。それらをすべてまとめるには、非常に高レベルのビューが必要です。仕様は、システムのさまざまなコンポーネントを一緒に連結できる中間層を作成します。
実際、自動車の自動操縦装置などの複雑なシステムには、さまざまな量の改良を伴う複数のレベルの仕様があります。設計では洗練されたアプローチがよく使用されます。「車が壁に衝突しない」などのいくつかの高レベルのプロパティから始め、センサーとブレーキが必要であることがわかり、センサー、ブレーキのいくつかの基本的な要件を解決しますそして、パイロットソフトウェアを使用して、これらの基本要件をコンポーネントの設計(センサーの場合、レーダー、DSP、画像処理ライブラリなど)に再度絞り込みます。正式な開発プロセスでは、仕様の各レベルは、最上位のプロパティからコードに至るまで、その上のレベルで設定された要件を満たすことが実証されています。
仕様が正しいことを確認することは不可能です。たとえば、物理学を間違えた場合、ブレーキコードを正式な要件に関連付ける数学が正しい場合でも、ブレーキが有効にならない可能性があります。あなたが実際に5000kgを持っている場合、500kgの負荷で休憩が効果的であることを証明するのは良くありません。しかし、500kgが間違っていることは、ブレーキコード内で車の物理的パラメーターに対して十分ではないことを確認するよりも簡単です。
¹ 完全に正式なアプローチの反対は、「これはうまくいくと思いますが、確信が持てません」です。人生に賭けているとき、それはそれほど素晴らしいとは思えません。