web-dev-qa-db-ja.com

堅牢なコードの作成とオーバーエンジニアリングの比較

オーバーエンジニアリングなしで可能な限り最も堅牢なコードを書いていることをどうやって知るのですか?

私は自分のコードが取ることができるすべての可能な経路について考えすぎていることに気づき、時々それは時間の無駄のように感じられます。それはあなたが書いているプログラムの種類に依存すると思いますが、決して起こらない状況を考慮して、あまり多くの時間を使いたくありません。

34
Fran Sevillano

オーバーエンジニアリングなしで可能な限り最も堅牢なコードを書いていることをどうやって知るのですか?

堅牢なコードをどう思いますか?すでに将来の証拠であり、どんな状況にも対処できるほど強力なコードですか?間違っています。未来を予測することはできません。そしてまた間違っています。それは複雑で保守不可能な混乱になるからです。

私はさまざまな原則に従います。何よりもまず [〜#〜] yagni [〜#〜] (まだ)と [〜#〜] kiss [〜#〜] なので、不要なコードは書きません。また、オーバーエンジニアリングを効果的に防止します。拡張機能が必要な場合は、アプリケーションをリファクタリングします。最新のリファクタリングツールを使用すると、インターフェイスを簡単に作成し、必要に応じて後で実装を交換できます。

次に、私が作成するコードをできるだけ堅牢にするようにします。これには、プログラムが取ることができる多くのパス(および状態)をできるだけ排除し、 Spartanプログラミング を少し含めることを含みます。大きな助けとなるのは、外部状態に依存しないか、少なくともプログラムが失敗したときにプログラムを矛盾した状態のままにしない「アトミック」関数/メソッドです。あなたがそれをうまくやれば、スパゲッティコードになってしまう可能性も非常に低くなり、保守性の恩恵にもなります。また、オブジェクト指向の設計では、 [〜#〜] solid [〜#〜] 原則は堅牢なコードの優れたガイドです。

多くの場合、プログラムパスや状態の組み合わせの爆発など、可能な限り最も直線的なパスとして設計する方法を深く考えることで、複雑さを軽減できることがよくあります。サブルーチンの最適な順序を選択し、この目的のためにそれらを設計することにより、可能な組み合わせを最小限に抑えるようにしてください。

堅牢なコードは、常にシンプルでクリーンなコードですが、シンプルさは常に簡単に実現できるとは限らない特性です。しかし、あなたはそれのために努力すべきです。常に可能な限り最も単純なコードを記述し、他に選択の余地がない場合にのみ複雑さを追加してください。

シンプルさは堅牢で、複雑さは壊れやすいです。

複雑さの殺害

39
Falcon

私はバランスを保ち、

  • 既存のユースケースで可能なすべての実行パスを処理する(これは「堅牢性」の部分です)、
  • 機能/要件を有効にすることは、近い将来に起こると確信しています。
  • コードベースの長期保守性(つまり、コードをクリーンでテスト可能な状態に保つ)に必要となる経験から知っていること。

それはぼんやりとした境界領域です-時々私はいくつかの不要な仕事をすることができます、時々私は後で必要になることが判明した何かをすることができないことがあります。ミスが大きくなければ、元気です。とにかく、私は自分の過ちから学ぶよう努めています。

8
Péter Török

ロバストとオーバーエンジニアリングの違いは、起こりうるすべてのユースケースを適切に処理することの違いです。つまり、ユーザーが奇妙な例外ケースを入力したり、定義されていないサポートされていない機能や指定されていない機能を要求したり、クラッシュしたり、サポートされていない機能をユーザーに通知したりせずにコードが正常に終了したりします。

一方、オーバーエンジニアリングは、不要または要求されなかった機能の完全な実装の領域に分類される可能性があります(クライアントが必要とするが、要求されなかった機能の一部!)OR定義可能非常に複雑な設計または過度に複雑なコードを導出して、比較的単純な問題を処理する。

5
maple_shaft

1)要件を取得します。

2)要件を満たす最小のコードを記述します。何かがあいまいな場合は、知識に基づいて推測してください。 superがあいまいな場合は、1に戻ります。

3)テストに送信します。

4)テスターが良いことを言った場合、承認を文書化します。何かがオフになっている場合は、1に戻ります。

テストの予測ではなく、テストの合格に重点を置きます。テスターがいない場合...テスターを取得してください!これらは、コードの正当性を検証するだけでなく、開発プロセス全体に不可欠です。

4
  • 再利用のために書きます。
  • テストを書きます。そのような条件下での処理方法を確認するために、取るに足らない、重要ではない、とんでもないほど複雑なもの。テストは、インターフェースの形式を判別するのにも役立ちます。
  • ハードに失敗するようにプログラムを記述します(アサーションなど)。私のコードには大量の再利用があり、多数のケースをテストしています-実際の実装(行数に基づく)よりもエラーのチェック/処理が多くなっています。
  • 再利用。
  • うまくいかないことをすぐに修正します。
  • 経験から学び、構築します。

エラーwillは途中で発生しますが、(幸いにも)ローカライズされ、(ほとんどの場合)テストの非常に早い段階で表示されます。再利用のもう1つの利点は、クライアント/呼び出し元が、実装によってもたらされるエラーチェック/スキャフォールディングのほとんどを節約できることです。

テストでは、プログラムの機能とその堅牢性を定義します-成功率と入力に満足するまでテストを追加し続けます。必要に応じて改善、拡張、強化する。

3
justin

そもそも、できる限りデータを正規化(冗長ではない)してください。データが完全に正規化されている場合、データを1回更新するだけでデータが不整合になることはありません。

データを常に正規化することはできません。つまり、冗長性を排除できない可能性があります。その場合、一貫性のない状態になる可能性があります。次に行うべきことは不整合を許容であり、定期的にそれをスイープしてパッチを当てるある種のプログラムで修復します。

通知によって冗長性を厳しく管理しようとする強い傾向があります。これらは、正しいことを確認するのが難しいだけでなく、巨大非効率になる可能性があります。 (OOPでは、通知が実際に推奨されるため、通知を作成する誘惑の一部が発生します。)

一般に、イベントやメッセージなどの時系列に依存するものはすべて脆弱になり、大量の防御コーディングが必要になります。イベントとメッセージは、ある部分から別の部分への変更を伝達し、不整合を防ごうとするため、冗長性を備えたデータに特徴的です。

すでに述べたように、冗長性が必要な場合(および可能性がかなり高い場合は、そうする必要があります)、a)許容でき、b)修復できることが最善です。メッセージ、通知、トリガーなどによってのみ不整合を防止しようとすると、堅牢にするのが非常に難しくなります。

3
Mike Dunlavey

この区別は、明確に定義されたコードを書くことで行いますが、実行パスが非常にまれである場合に必ずしも最適な動作とは限りません。たとえば、マトリックスが正定であることが確実である(ただし、テストされていない)場合、プログラムにアサーションまたは例外を挿入して状態をテストしますが、独自のコードパスを記述しません。これにより、動作は定義されますが、最適ではありません。

2
thiton

堅牢性:無効な入力またはストレスの多い環境条件が存在してもシステムが機能し続ける度合い(コード完了2、p464)

ここで重要な質問は、あなたにとって堅牢性がいかに重要であるかを尋ねることです。 Facebookの場合、誰かが特殊文字を入力してもWebサイトが機能し続け、1億人のユーザーが同時にログオンしてもサーバーが稼働し続けることが非常に重要です。自分だけが行う一般的な操作を実行するスクリプトを記述している場合は、それほど気にする必要はありません。中間にはたくさんのレベルがあります。どの程度の堅牢性が必要かを判断することは、開発者が習得すべき重要なスキルの1つです。

YAGNIの原則は、プログラムが必要とする可能性のある機能の追加に適用されます。しかし、その原則は堅牢性には適用されません。プログラマーは、特定の将来の拡張が必要になる可能性を(特にクールな拡張の場合)過大評価する傾向がありますが、問題が発生する可能性を過小評価しています。また、後で省略された機能が必要であることが判明した場合、プログラマは後でそれを書くことができます。結局省略されたエラーチェックが必要であることが判明した場合、損傷が行われる可能性があります。

したがって、実際には異常なエラー条件のチェックを行う側でエラーを発生させる方が適切です。しかし、バランスがあります。このバランスで考慮すべき事項のいくつか:

  • このエラーはどのくらいの頻度で発生しますか?
  • このエラーが発生するコストはどのくらいですか?
  • これは内部用ですか、外部用ですか?

人々があなたのプログラムを予期しない方法で使用しようとすることができるし、しようとすることを忘れないでください。彼らが行うときに予測可能な何かが起こった場合、それはより良いです。

防御の最後の行として、アサートまたはシャットダウンを使用します。対処方法がわからないことが発生した場合は、プログラムをシャットダウンしてください。これは通常、プログラムを続行して予測できないことを行うよりも優れています。

2
DJClayworth