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


33

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

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


2
Agda2内のコードも
SK-ロジック

具体的な例は、あなたの主張をするのに大いに役立ちます。:)
ジョアンポルテラ

あなたが本当に堅牢性、すなわち「無効な入力やストレスの多い環境条件の存在下で動作し続けるシステムの能力」についてあなたが本当に求めていることを確認できますか?
DJClayworth

私はクレイジーな締め切りの下で働いていますが、デモウェア用ですので、完全に麻痺することなく、楽しくハッキングできます。
ジョブ

1
こちらの記事は、その対象についての協議:code-tag.com/2017/04/02/...
サン

回答:


39

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

堅牢なコードとは何ですか?すでに将来の証拠であり、あらゆる状況に対処できるほど強力なコードですか?間違っている、誰も未来を予測できない!繰り返しますが、これは複雑で維持できない混乱です。

私はさまざまな原則に従います:何よりもまずYAGNI(まだ)とKISSなので、不必要なコードを書きません。それはまた、効果的にオーバーエンジニアリングを防ぎます。拡張が必要な​​ときにアプリケーションをリファクタリングします。最新のリファクタリングツールを使用すると、インターフェイスを簡単に作成し、必要なときに実装を交換できます。

それから、私が書いたコードを可能な限り堅牢にすることを試みます。これには、プログラムが取り得るパス(およびステート)をできるだけ排除し、Spartanプログラミングを少しだけ含めます。非常に役立つのは、外部状態に依存しない、または少なくともプログラムが失敗した場合に矛盾した状態のままにしない「アトミック」な関数/メソッドです。それを上手に行えば、スパゲッティコードになることはまずないでしょうし、メンテナンス性にも恵まれています。また、オブジェクト指向設計では、SOLID原則は堅牢なコードへの優れたガイドです。

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

堅牢なコードはほとんどの場合シンプルでクリーンなコードですが、シンプルさは常に容易に達成できるとは言えない特性です。それでも、あなたはそれのために努力すべきです。常にできるだけ単純なコードを記述し、他に選択肢がない場合にのみ複雑さを追加してください。

シンプルさは堅牢であり、複雑さは脆弱です。

複雑さは殺します。


2
クラス、ファクトリー、抽象化のトンがないので。それはパラドックスですが、そのようなものが好きな人もいます。理由はわかりません。
コーダー

5
これはスパルタです!!!
トムスクワイアズ

4
20年間これを行っていない人は、複雑さがあなたを殺すことができる方法を取得しません。彼らはとても賢いと思います。彼らは愚かで、賢くない。その複雑さはあなたを死に至らしめるでしょう。
PeterAllenWebb

1
堅牢性とは将来を保証することではなく、無効な入力やストレスの多い環境で機能し続けることです-Code Complete p464。
DJClayworth

5
質問者が私が理解しているのとは異なる意味で「堅牢」を使用していない限り、あなたは別の質問に答えていることになります。彼は「将来の要件を考慮してコーディングすべきか」とは問いません。「どのような異常な入力ケースを処理すべきか」と問いかけています。YAGNI、KISS、SOLIDのいずれも関係ありません。同時にログオンしようとする100万人のユーザーを許可する必要がありますか?ログイン名がバックスラッシュで始まる場合はどうなりますか?これらの質問にはYAGNIが回答していません。
DJClayworth

8

私はバランスを保ち、

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

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


例は素晴らしいここになり、既存のユースケースで可能なすべての実行パスを扱う
CodeYogi

5

堅牢性とオーバーエンジニアリングの違いは、考えられるすべてのユースケースをうまく処理することの違いです。優雅に言うと、ユーザーは奇妙な例外ケースに入るか、定義されていないサポートされていないまたは指定されていない機能を呼び出す状況に陥り、クラッシュせずにコードが正常に終了するか、サポートされていない機能をユーザーに通知します。

一方、オーバーエンジニアリングは、不要または要求されていない機能の完全な実装の領域に分類される可能性があります(クライアントが必要とするが、要求されなかった機能もあります!)比較的単純な問題を処理するコード。


4

1)要件を取得します。

2)要件を満たすために最小限のコードを記述します。あいまいなものがある場合は、経験に基づいた推測を行います。もしそうであれば、スーパーあいまいな、1に戻ります。

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

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

テストを予測するのではなく、テストに合格することに焦点を合わせます。テスターがいない場合...テスターを入手してください!これらは、コードの正確性を検証するためだけでなく、開発プロセス全体にとって不可欠です。


1
テストを予測するのではなく、テストに合格することに重点を置きますが、私のような多くの開発者は、強力なビジネスアナリストがいない場合でも両方を行うことが期待されています。
maple_shaft

@maple_shaft-非常に真実です。重要なのは、これらの問題は他の誰かの能力不足のために生じるということです。他の人の仕事に重点を置くことは、燃え尽き症候群への道です。私の会社がその月の売掛金を処理するのに十分なほど愚かだった場合、うまく行かなければ、私は自分自身に失望しません。要件を定義することは通常、あなたが毎日何をするかを記述することを必要とするだけなので、自動化することができます。従業員の誰もそれをすることができない場合、まあ...会社はトラブルに陥っているかもしれません。
モーガンハーロッカー

3

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

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

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

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

先ほど言ったように、冗長性が必要な場合(そしてチャンスが十分にある必要がある場合)、a)許容し、b)修復できることが最善です。メッセージ、通知、トリガーなどだけで不整合を防止しようとすると、堅牢にするのは非常に困難になります。


3
  • 再利用のために書き込みます。
  • テストを書きます。このような状況でどのように処理されるかを見るために、些細な、自明ではない、いくつかのばかばかしいほど複雑なもの。テストは、インターフェイスの形式を判断するのにも役立ちます。
  • ハードに失敗するようにプログラムを記述します(アサーションなど)。私のコードには大量の再利用があり、多数のケースをテストしています-実際の実装(行数に基づく)よりも多くのエラーチェック/処理があります。
  • 再利用。
  • 問題が発生した場合はすぐに修正します。
  • 経験から学び、構築します。

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

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


2

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


2

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

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

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

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

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

人々があなたのプログラムを予期せぬ方法で使用することができる-することを忘れないでください。予測可能な何かが発生した場合、それはより良いことです。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.