あなたは、あなたがオーバーエンジニアリングなしで可能な限り最も堅牢なコードを書いていることをどうやって知っていますか?
私は自分のコードが取ることができるあらゆる可能なパスについて考えすぎていることに気づき、それは時々時間の無駄のように感じます。それはあなたが書いているプログラムの種類に依存すると思いますが、決して起こらない状況を考慮に入れて私の時間をあまり使いたくありません。
あなたは、あなたがオーバーエンジニアリングなしで可能な限り最も堅牢なコードを書いていることをどうやって知っていますか?
私は自分のコードが取ることができるあらゆる可能なパスについて考えすぎていることに気づき、それは時々時間の無駄のように感じます。それはあなたが書いているプログラムの種類に依存すると思いますが、決して起こらない状況を考慮に入れて私の時間をあまり使いたくありません。
回答:
あなたは、あなたがオーバーエンジニアリングなしで可能な限り最も堅牢なコードを書いていることをどうやって知っていますか?
堅牢なコードとは何ですか?すでに将来の証拠であり、あらゆる状況に対処できるほど強力なコードですか?間違っている、誰も未来を予測できない!繰り返しますが、これは複雑で維持できない混乱です。
私はさまざまな原則に従います:何よりもまずYAGNI(まだ)とKISSなので、不必要なコードを書きません。それはまた、効果的にオーバーエンジニアリングを防ぎます。拡張が必要なときにアプリケーションをリファクタリングします。最新のリファクタリングツールを使用すると、インターフェイスを簡単に作成し、必要なときに実装を交換できます。
それから、私が書いたコードを可能な限り堅牢にすることを試みます。これには、プログラムが取り得るパス(およびステート)をできるだけ排除し、Spartanプログラミングを少しだけ含めます。非常に役立つのは、外部状態に依存しない、または少なくともプログラムが失敗した場合に矛盾した状態のままにしない「アトミック」な関数/メソッドです。それを上手に行えば、スパゲッティコードになることはまずないでしょうし、メンテナンス性にも恵まれています。また、オブジェクト指向設計では、SOLID原則は堅牢なコードへの優れたガイドです。
可能な限りまっすぐなパスとして設計する方法を深く考えることで、プログラムのパスや状態の組み合わせの爆発など、複雑さを軽減できることがよくあることがわかりました。サブルーチンの最適な順序を選択し、この目的のためにそれらを設計することにより、可能な組み合わせを最小限に抑えるようにしてください。
堅牢なコードはほとんどの場合シンプルでクリーンなコードですが、シンプルさは常に容易に達成できるとは言えない特性です。それでも、あなたはそれのために努力すべきです。常にできるだけ単純なコードを記述し、他に選択肢がない場合にのみ複雑さを追加してください。
シンプルさは堅牢であり、複雑さは脆弱です。
複雑さは殺します。
私はバランスを保ち、
それは曖昧な境界領域です-時々私はいくつかの不必要な仕事をなんとかすることができます、時々私は後で必要であることが判明した何かをすることに失敗します。ミスが大きくなければ、私は大丈夫です。とにかく、私は自分の過ちから学ぶよう努めています。
堅牢性とオーバーエンジニアリングの違いは、考えられるすべてのユースケースをうまく処理することの違いです。優雅に言うと、ユーザーは奇妙な例外ケースに入るか、定義されていないサポートされていないまたは指定されていない機能を呼び出す状況に陥り、クラッシュせずにコードが正常に終了するか、サポートされていない機能をユーザーに通知します。
一方、オーバーエンジニアリングは、不要または要求されていない機能の完全な実装の領域に分類される可能性があります(クライアントが必要とするが、要求されなかった機能もあります!)比較的単純な問題を処理するコード。
1)要件を取得します。
2)要件を満たすために最小限のコードを記述します。あいまいなものがある場合は、経験に基づいた推測を行います。もしそうであれば、スーパーあいまいな、1に戻ります。
3)テストに送信します。
4)テスターが良いと言ったら、承認を文書化します。何かがオフになっている場合は、1に戻ります。
テストを予測するのではなく、テストに合格することに焦点を合わせます。テスターがいない場合...テスターを入手してください!これらは、コードの正確性を検証するためだけでなく、開発プロセス全体にとって不可欠です。
そもそも、できる限りデータを正規化(冗長ではなく)してください。データが完全に正規化されている場合、データを1回更新しても一貫性が失われることはありません。
データを常に正規化した状態に保つことはできません。つまり、冗長性を排除できない場合があります。その場合、一貫性のない状態になる可能性があります。その場合、不整合を許容し、それをスイープしてパッチを当てる何らかのプログラムで定期的に修復します。
通知によって冗長性を厳しく管理しようとする傾向が強い。これらは正しいことを確認するのが難しいだけでなく、非常に非効率になる可能性があります。(通知を書く誘惑の一部は、OOPで実際に奨励されているために発生します。)
一般に、イベント、メッセージなどの時系列に依存するものはすべて脆弱になり、大量の防御コーディングが必要になります。イベントとメッセージは、不整合を防ぐために、ある部分から別の部分に変更を伝えているため、冗長性のあるデータの特性です。
先ほど言ったように、冗長性が必要な場合(そしてチャンスが十分にある必要がある場合)、a)許容し、b)修復できることが最善です。メッセージ、通知、トリガーなどだけで不整合を防止しようとすると、堅牢にするのは非常に困難になります。
エラーは途中で発生しますが、(幸いなことに)ローカライズされ、(ほとんどの場合)テストの非常に早い段階で表示されます。再利用のもう1つの利点は、実装によってもたらされるエラーチェック/スキャフォールディングを使用して、クライアント/呼び出し元がほとんどのエラーを保存できることです。
次に、テストでプログラムの機能とその堅牢性を定義します。成功率と入力に満足するまでテストを追加し続けます。必要に応じて改善、拡張、強化します。
堅牢性:無効な入力またはストレスの多い環境条件が存在する場合にシステムが機能し続ける度合い。(コード完了2、p464)
ここでの重要な質問は、あなたにとって堅牢性がどれほど重要かを尋ねることです。Facebookの場合、誰かが入力に特殊文字を入力してもWebサイトが機能し続け、1億人のユーザーが同時にログオンしてもサーバーが稼働し続けることが非常に重要です。自分だけが行う一般的な操作を実行するスクリプトを作成している場合、あまり気にする必要はありません。間には多くのレベルがあります。必要な堅牢性を判断することは、開発者が学ぶべき重要なスキルの1つです。
YAGNIの原則は、プログラムが必要とする機能の追加に適用されます。しかし、その原則は堅牢性には適用されません。プログラマは、特定の将来の拡張が必要になる可能性を過大評価する傾向がありますが(特にクールな拡張機能の場合)、問題が発生する可能性を過小評価します。また、後に省略された機能が必要であることが判明した場合、プログラマは後でそれを書くことができます。結局、省略されたエラーチェックが必要であることが判明した場合、損傷が行われる可能性があります。
したがって、実際には、異常なエラー状態のチェックを行う側でエラーを起こす方が適切です。しかし、バランスがあります。このバランスで考慮すべき事項のいくつか:
人々があなたのプログラムを予期せぬ方法で使用することができる-することを忘れないでください。予測可能な何かが発生した場合、それはより良いことです。
最後の防衛線として、アサートまたはシャットダウンを使用します。対処方法がわからない何かが発生した場合は、プログラムをシャットダウンします。これは通常、プログラムが続行して予測不可能なことを行うことを許可するよりも優れています。