3

引数(Answer)が正しいかどうかをチェックし、質問のリストにすでに正しい回答があるかどうかをチェックするメソッドがあるとします。

public void addAnswer(Answer answer) {
    if (answer.isCorrect()) {
        ...
    }
}

ただし、リスト内で正しい答えは1つだけにします。複数のオプションがあります。例外をスローしたり、無視したり、addAnswerからブール値を返したりして、操作が正常かどうかを通知することができます。そのようなシナリオでどのように考えることになっていますか?

4

7 に答える 7

8

ルールは非常に単純です。例外的で、誤った、予測できない障害に対して例外を使用します。何かが起こると予想される場合、または何かが本当に頻繁に起こる場合は、例外を使用しないでください。

あなたの場合、答えが正しくないのはエラーでも本当にまれなことでもありません。それはあなたのビジネスロジックの一部です。例外をスローすることはできますが、特定の時点での回答が常に正しいと予想され、突然正しくない(前提条件の失敗)場合にのみ、何らかの検証(アサーション)の一部としてのみ行われます。

そしてもちろん、正当性のチェック中に何らかの障害が発生した場合(データベース接続が失われた、配列インデックスが間違っている)、例外が望まれます。

于 2012-10-28T10:10:42.880 に答える
6

これは完全にあなたが達成したいことに依存します。メソッドの呼び出し元は、2つの正解が追加されていないことをすでに確認している必要がありますか?それが起こった場合、それはプログラミングエラーの兆候ですか?次に、例外をスローしますが、チェックされていない例外は間違いなくあります。

メソッドの目的が、呼び出し元が1つの真の答えの不変条件を適用するのを防ぐことである場合(ただし、それは疑わしいです)、boolean戻り値を介してシグナルを送信するように調整できます。これにより、呼び出し元のオプションの情報チャネルになります。

他に正しい答えがあるかどうかを事前に知る方法がない場合(たとえば、答えが複数のスレッドまたはプロセスから(データベースを介して)同時に追加される場合)、チェックされた例外をスローすることは意味があります。

結論:万能のベストプラクティスはありませんが、達成したいすべてのシナリオにベストプラクティスがあります。

于 2012-10-28T10:12:34.043 に答える
5

例外警察は、大量のレンガのようにあなたを監視します。この答えについては、「フロー制御に例外を使用しないでください」や「通常の状態に例外を使用しないでください」などのステートメントを使用します。

最初のステートメントの問題は、例外フロー制御の形式であるということです。これにより、引数が自己矛盾するため、無効になります。

2番目のステートメントの問題は、それが必然的に例外的な条件を通常どおり無限に再定義することに伴うように見えることです。このサイトに例があります。たとえば、警察がEOFは「正常」であり、したがって、何も提供しないJava APIが多数存在するにもかかわらず、EOFExceptionをキャッチすべきではないと主張した活発な議論です。問題の選択。この道を十分に進んでいくと、例外的なものは何もないので、それらを使用する機会はまったくありません。

これらは論理的な引数ではありません。これらは未検討の教義です。

1989年頃に最初に作成された当初の本当のポイントは、同じ方法で処理するために、自分自身に例外をスローするべきではないということでした。つまり、GOTOとして扱わないでください。この原則は引き続き有効です。

チェックされた例外についてのポイントは、呼び出し元にそれらの処理について何かを強制することです。自分の分析で、これが必要なものであると確信している場合は、例外を使用してください。または、それらを強制的にキャッチするAPIを使用している場合は、適切なレベルでそれらをキャッチします(つまり、読者の演習として残しておきます)。

言い換えれば、現実の世界のほとんどのものと同様に、それはあなたの裁量と判断次第です。この機能は、他の機能と同様に、使用または悪用される必要があります。

@例外警察:あなたは電話帳で私を見つけるでしょう。しかし、議論に備えてください。

于 2012-10-28T10:32:11.783 に答える
1

ここでの問題は、APIがエラーを起こしやすいことです。代わりに次のスキームを使用します。

public class Question {

    private List<Answer> answers;
    private int mCorrect;

    // you may want a List implementation without duplicates
    public void setAnswers(List<Answer> answers, int correct) {
        this.answers = answers;
        // check if int is between bounds
        mCorrect = correct;
    }

    public boolean isCorrect(Answer answer) {
        return answers.indexOf(answer) == mCorrect;
    }
}

なぜなら、Answerそれ自体は単なるステートメントであり、通常はに関連付けられていない状態にすることtrueはできないからです。このAPIを使用すると、正解を0個または複数持つことができなくなり、ユーザーが解答を追加するときに正解を入力するように強制されるため、プログラムは常に一貫した状態になり、失敗することはありません。falseQuestion

エラーの通知方法を決定する前に、エラーができるだけ一般的でないようにAPIを設計することをお勧めします。現在の実装では、自分の側でチェックを行う必要があり、クライアントプログラマーも自分の側でチェックする必要があります。提案された設計では、チェックは不要であり、両側に正確で簡潔で流暢なコードがあります。

いつaを使用するかboolean、いつExceptionsを使用するかについては、基礎となるAPI(主に低レベルのCコード)をミラーリングするためにブール値が使用されることがよくあります。

于 2012-10-28T10:18:13.733 に答える
1

メソッドからスローされた例外は、一部の入力で発生する例外を見越して、呼び出し元に何らかのアクションを実行するように強制します。戻り値は同じことを強制しないので、それをキャプチャして何らかのアクションを実行するのは呼び出し元の責任です。

呼び出し元がシナリオを処理して修正アクションを実行するようにする場合は、チェックされた例外(のサブクラスjava.lang.Exception)をスローする必要があります。

于 2012-10-28T10:04:08.323 に答える
0

TomaszNurkiewiczの回答に同意します。私は新しいユーザーなので、コメントすることはできません。また、addAnswer()メソッドが常に答えを追加するとは限らない場合(正しい答えがすでに存在するため)、この動作を示唆する名前を付けることをお勧めします。「追加」は、通常のコレクションの動作を提案します。

public boolean submitAnswer(Answer answer); // returns true is answer accepted

あなたの正確な解決策は、私たちが知らないあなたのアプリケーションについての全体像に依存するかもしれません。例外をスローしたいだけでなく、回答の追加が有効かどうかを確認するのは呼び出し元の責任にしたいと思うかもしれません。

それはすべて豊かなタペストリーです。

于 2012-10-28T10:20:31.780 に答える
0

私はそれを次のように実装します:

 public class Question { 

    private int questionId; 
    private final Set<Answer> options = new HashSet<Answer>();
    private final Set<Answer> correctAnswers = new HashSet<Answer>();

    public boolean addAnswer(Answer answer) throws WrongAnswerForThisQuestionException {
        if(!answer.isValid(questionId)) {
            throw new WrongAnswerForThisQuestionException(answer, this);
        }
        if (answer.isCorrect(questionId)) {
           correctAnswers.add(answer);
        }
        return options.add(answer);
    }
}
于 2012-10-28T11:06:55.497 に答える