この質問の焦点:一部のソフトウェアは、1つまたは複数の「ソフトウェアの内部エラーが増えると、これらのエラーが発生したときに実行時間が長くなります。結果が成功した場合、これらすべてはユーザーの知らないうちに起こります。
複雑なソフトウェアの定義:
編集:複雑とは何ですか?ご覧ください 複雑なものと複雑なものの間には大きな違いがあります 。 ((直接リンク)
冗長性/堅牢性の定義この質問内:
(コメントに基づいて堅牢性を追加)
そのようなソフトウェアの例:
この質問は元々 故意に悪いコードにどう対処するのですか?
しかし、現在はソフトウェア膨張の原因の1つにのみ焦点を当てています。この質問は、新機能の追加など、ソフトウェアの膨張のその他の原因には対応していません。
おそらく関連している:
これはビジネス上の問題であり、技術的な問題ではありません。
研究者やプロトタイプを使ってコーディングしていることもあるので、堅牢性の非常に低いものを構築します。壊れた場合は修正します。コードをすぐに捨てるつもりなら、余分な魔法に投資しても意味がありません。
しかし、システムのユーザーが堅牢である必要がある場合は、そのように構築する必要があります。そして、彼らが必要としない種類の冗長性/堅牢性を無視しながら、あなたと彼らが長期的な成功を最大化するために必要な方法で、それを特に堅牢にする必要があります。
一般的に、私はラフから始めて、その後堅牢性を追加します。私は通常の計画プロセスのこの部分で頻繁に質問をします。私は通常、Extreme Programmingスタイルで作業します。このスタイルでは、必要な機能の長いリストを作成し、堅牢性機能もそこに配置します。たとえば、「システムは単一のボックスの障害に耐える」、「ユーザーはFacebookの資格情報を使用して参加できる」などと混同されます。どちらが先に表示されても、最初にビルドします。
複雑なソフトウェアは一般的にisおそらくご存知のように冗長ですが、それが最善の方法であることは明らかではありませんが、開発者がソフトウェアを詳細に理解しようとするのではなく、既存のコードを「攻撃」する傾向があるためです。動作します。
ただし、どの程度の冗長性を許容できるかを尋ねられた場合、私は何も言わないでしょう。冗長性は、複雑さの多くの副作用の1つであり、単純さの先祖です。時間が重要である場合は、間違いなく単純さが後回しになるはずですが、時間の本質を主張する人は、実際にソフトウェアの開発に注意を払う人であることはめったにありません。通常、プロジェクトマネージャーは、できるだけ早く仕事を終わらせて、より差し迫った問題に戻ることができるように頼みますが、仕事がいつ完了したかを知るのはプログラマーの義務です。本来の目的であるプログラムへの統合が成功するまで、仕事は完了しないと思います。おそらくプログラムは複雑ですが、少なくとも変更はパターンに適合しているため、同様のコードを見るのに慣れているプログラマーにとっては理解しやすいでしょう。
ただし、そうすることで、冗長なコードを生成する必要がある場合があります。プロジェクトがすでに非常に冗長である場合、もちろん上司がプロジェクト全体を再構築できるようにするために殺すのに数週間はないと想定すると、パターンを続行する方が実際にはより簡単かもしれません。
編集:質問の言い換えに照らして、堅牢性について少し追加します。私の意見では、パラメーターのチェックは、A)日付の値などの非常に具体的な形式を文字列として受け入れるか、B)さまざまなパラメーターが互いに競合する可能性があるか、相互に排他的である場合にのみ行う必要があります。
A)では、パラメーターが特定の形式に一致するという要件は、通常、メソッドの必要性(文字列から日付への変換など)にとって重要です。技術的にはそれが必要でなくてもプログラムで発生する可能性がありますが、これらの可能性を排除し、探しているデータのタイプを表すことがわかっているパラメーターのみを受け入れることを強くお勧めします(もし文字列ではなく日付を受け入れますポイントは、たとえば変換することではありません。変換も実行する必要がある場合は、ユーティリティメソッドを使用して文字列を変換してからメソッドに渡します)。
B)に関しては、相互に排他的なパラメーターが不適切な構造を表しています。 2つのクラスがあるはずです。1つは1つのケースを処理し、もう1つは別の方法で処理します。冗長性を回避するために、すべての一般的な操作を単一の基本クラスで実行できます。
メソッドのパラメーターの数が10以上になる状況では、頻繁に変更されない可能性が最も高いこれらのパラメーターをすべて含むプロパティファイルを検討し始めます。変更する場合は、デフォルトをプロパティファイルに保存し、実行時にデフォルトをオーバーライドできる「setPropertyName()」メソッドを追加できます。
ソフトウェアはユーザーのミスを許し、プログラマーのミスを完全に許容できないものでなければなりません。
つまり、ソフトウェアは非常に堅牢で、ユーザー入力エラーやシステム構成エラーなどをスムーズに回復できる必要があります。少なくとも、エラーが発生した場所(入力ボックス、構成ファイル、コマンドライン引数など)と違反した制約(「X文字未満でなければならない」、「有効なオプションは[X 、Y、Z] "、etc ...)追加の堅牢性のために、ソフトウェアは代替案を提案するか、妥当なデフォルトを使用できます(ただし、ユーザーが指定したものを正確に使用していないことを常に示す必要があります)。
さまざまなデフォルトでの自動再試行が保証される多くの状況を考えることはできませんが、いくつかあります(通信リンクを確立するための自動再試行は妥当と思われます)。このレベルの「冗長性」はビジネスの決定であると@Williamに同意します。
一方、プログラマのエラーに対する実行時の堅牢性はありません。関数のパラメーターに事前条件がある場合は、実行時チェックではなく、アサートでチェックする必要があります。冗長なエラーチェックと、コールスタックへの同じパラメーターの3つまたは4つのレベルでのレポートを確認することは、私の大きな喜びです。
int A(int x)
{
if (x==0) return -1
...
}
int B(int x)
{
if (x==0) return -1
err = A(x)
if (err) return err;
...
}
// and so on and so on....
これは、追加の不要な複雑さです。ある関数が別の関数を誤用することによって引き起こされたエラーをどのように処理すべきかを理解するためにタイミングを費やすべきではありません。これが「堅牢性」のタイプである場合、それは必要ありません。これをアサートおよび完全な統合テストに置き換えます。
それは要件です。
堅牢性の要件はありますか?
「通信リンクに障害が発生すると、誤ったパケットは破棄されます」「リンクが動作を再開すると、トランザクションは2回処理されません」
エラー回復のユースケースがあるはずです(それ以外の場合、どのようにしてそれがどのように発生するかを知るのですか?)
プログラマーに任せて、必要に応じて堅牢性を発明することで、「魔法の」システムが生まれます。
すべての魔法のシステムは、時間の経過とともにくだらない魔法になります。バックグラウンドでのエラー訂正は、障害の発生を隠し、障害は訂正されないため、システムは最終的にエントロピーの大きい状態に低下します。常にエラーを修正するので、がらくたのように実行します。システムが完全に機能低下状態になるのを停止するには、制限が必要です。
一部の操作は、特にデータベースのような外部リソースに依存している場合は、おそらく「再試行」アプローチを保証します。たとえば、データベースに接続できない場合、またはクエリが失敗した場合、操作を特定の回数再試行してから、中止してエラーをより高いレベルにスローすることがあります。ただし、一部のロジックでは、同じことを複数回試行すると、多くの場合、実際の問題を隠す悪いコードと不思議な思考の症状が現れます。