私たちはどれほど守勢すべきですか?


11

私たちはいくつかのコードでPexを実行しており、いくつかの良い点を示してきました(悪い点はありますが、本番環境に到達する前にそれらを示しています!)。

ただし、Pexの優れた点の1つは、問題の検出を必ずしも停止する必要がないことです。

見つかった1つの領域は、文字列を渡すときに空の文字列をチェックしていなかったことです。

そこで変更しました:

if (inputString == null)

if (string.IsNullOrEmpty(inputString)) // ***

それは最初の問題を修正しました。しかし、その後、Pexを再度実行すると、次のことが決定されました。

inputString = "\0";

問題を引き起こしていました。その後

inputString = "\u0001";

私たちが決定したのは、遭遇// ***した場合にデフォルトを使用でき、他の奇妙な入力によって引き起こされた例外を見て喜んでいるということです(そしてそれを処理します)。

それで十分ですか?


警告の一部をオフにできるかどうかを確認しましたか?私もJTestがそれを行うことを知っていますが、それはいくつかの推奨事項をオフにするオプションでもありました。好みのコードテストプロファイルを取得するために設定を調整するのに時間がかかりました。
FrustratedWithFormsDesigner

@Frustrated:はい、私たちができることや実行しているプロファイルには確かに微調整があります。ところで、Pexは素晴らしいツールです。それが示した結果は、単に質問を促しました。
ピーターK.

答えはありませんが、このPexのことへのリンクに感謝します。それが私がそう思うとかなりきれいに見え、既存のコードの単体テストを自動的に(?)作成します。私が取り組んでいるコードは巨大であり、テストも非常に密結合されたコードもないので、何もリファクタリングすることは不可能です。
ウェインモリナ

@WayneM:はい、それはかなり良いですが、それが何をしていたかを理解するためにいくつかの例を試す必要がありました。レガシーコードの場合、それは素晴らしいことです。新しいコードの場合はさらに良いです!
ピーターK.

回答:


9

3つの質問は、コーディングの防御力を判断するのに役立ちます。

まず-悪い入力が通過することの結果は何ですか?開発者のPCのいずれかでエラーメッセージが表示される場合は、防御することはそれほど重要ではないかもしれません。IEの会計情報の混乱、クライアントでの経済的混乱につながる可能性がありますか?それは命が危険にさらされているリアルタイムシステムですか?生死のシナリオでは、おそらく実際の機能コードよりも多くの検証およびエラー処理コードがあるはずです。

第二に、この関数またはコードを再利用する人は何人ですか?あなただけ?あなたの部署?あなたの会社?あなたの顧客?コードの使用範囲が広いほど、防御力が高まります。

第三-私が検証している入力のソースは何ですか?ユーザーまたは公開Webサイトからの入力である場合、私は超防御的です。入力が常にコードから来ている場合は、多少防御的にしてください。ただし、チェックに時間をかけすぎないでください。

システムにエラーチェックと検証を追加することは常に可能です。重要なのは、このコードの記述と保守のコストが、コードのエラーによって引き起こされる問題のコストを上回ることです。


6

ユーザーは悪であり、入力したものはすべて厳しくチェックする必要があります。

ユーザー入力の恩恵なしに生成されたもの、または事前にサニタイズされたデータから生成されたものは、同じレベルでチェックする必要はありません。ここでの問題は、コードが強化されていないことを忘れてしまったため、これらのメソッドを無効なデータで忘れて使用することです。

常に確認する必要がある1つのことは、オーバーフローまたはクラッシュを引き起こす可能性のあるものです。その方法がどれほど深く埋まっているか、そしてその状態が決して起こらないことをあなたがどれだけ確信しているかは関係ありません。とにかくマーフィーをなだめるために、あなたはそれのためにプログラムする必要があります。


2

私はあなたがする必要があるのと同じくらい防御的だろう。少しあいまいですが、そう思いますが、説明しようと思います。

メソッドを修正するときに、そのメソッドに入力パラメーターがある場合、それらのパラメーターが何であるかを決定する必要があります。アプリケーション内の状況や場所では、これは異なります。たとえば、メソッドまたはコードがユーザー入力からデータを受け入れている場合、すべてのコードベースをカバーし、エラーメッセージまたは受け入れられないデータを表示する良い方法を介して入力を適宜処理します。

メソッドが公開されたAPIである場合。入ってくるものを制御することはできませんので、すべての側面をカバーし、それに応じてプログラムすることを期待する必要があります。

プロジェクトのコアエンジン内で生成されるメソッドについては、ここで決定する必要があります。到着するデータは事前​​にスクリーニングされ、到着前に検証されていると思いますか、それとも必要なチェックを入れるべきですか?これは、メソッドの概念レベルと、これがチェック可能な場所であるかどうかに依存すると思います。だから私が考えるかもしれないことは次のとおりです。

1)このチェックを行う必要があるのはこれだけですか?この変数は、この条件のためにさまざまな場所でチェックする必要がありますか?もしそうなら、チェーンの上位で一度チェックを行い、その後有効性を引き受けることができます

2)システムの他のコンポーネントは、私が書いたメソッドとインターフェースで動作することが期待されています。その場合、デバッグアサートステートメント、デバッグ例外、メソッドのコメント、および一般的なシステムアーキテクチャを使用して、必要な結果を制御できるか、データのチェックが必要になります。

3)コードのこの時点での失敗の結果は何ですか。全体が失敗しますか?エラーは他の場所でキャッチされ、そのエラーは少なくともキャッチされます。

4)ここにチェックを入れるのは理にかなっていますか?破損している可能性のあるデータにチェックを入れることもありますが、その時点でエラーを解決するのではなく、問題を解決するのに役立つ場合があります。その時点で、実際の問題を見つけるためだけに別の問題を追跡するのに何時間も費やす可能性があります。これは、ユーザー/開発者が報告したイベントに連鎖するイベントチェーンのデータの有効なチェックによるものです。

一般的に私は防御的なプログラマーですが、徹底したTDDと適切なユニットテストにより、必要なレベルでコードのチェックを行い、下位レベルのセクションに到達したら正常に動作することを確信できると信じています。


1

私は数週間前に、このような事前の5分間の追加作業で検出できたバグに費やしました。私の考えでは、この前もっての作業は常に価値があります。最終的にはバグを修正します。唯一の質問は、それがあなたにどれくらいかかるかです。

これらの種類の分析ツールがしばしば明らかにすることの1つは、必ずしもバグではないものの、バグが発生する可能性が高くなる悪いプログラミング習慣です。そのような一般的な習慣の1つは、変数の初期化です。空の文字列が変数の完全に有効な値である場合があります。その場合、その特定のインスタンスのエラーを考慮しないようにツールを構成します。ただし、多くの場合、空の文字列は変数の有効な値ではありませんが、人々はそれを設定しています。なぜなら、コンパイラはそこに何かがないと文句を言うか、有効であるかどうかにかかわらず、言語が空の文字列に自動的に初期化されるためです。

有効な解決策がないキャッチ22のように見えるため、これは人々をイライラさせますが、解決策はコードをリファクタリングすることで、そこに入れる有効な値があるまで変数を初期化する必要はありません。それには事前にいくつかの特別な考えが必要ですが、コードがより堅牢になり、実際には長期的に記述および保守が容易になります。

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