3

関数呼び出しに関して、関数が機能したか失敗したかを確認する責任を呼び出し元に与える方が良いですか、それとも関数自体によってエラーを通知する必要がありますか?

私が尋ねている理由は、プレゼンテーションとロジックを混在させるのが好きではないためですが、発信者がエラーチェックをしなければならない場合、不正確で面倒になる可能性があります.

if(!login($username, $password)
{
    echo 'Login failed. Please try again.';
}

呼び出し元には、失敗した理由がわかりません。ユーザー名とパスワードの組み合わせが間違っていましたか、それともデータベース接続の失敗でしたか? それとも他の予期しない理由ですか?

関数内でエラーチェック/例外をスローできる場合、これは問題になりません。これは、データベース接続の失敗など、コードの特定のポイントで特定のエラーが発生するためです...しかし、それはプレゼンテーションとロジックが混在することになります. ここでのベストプラクティスは何ですか?

ありがとうございました。

4

3 に答える 3

2

ビジネス ロジック (モデル) レイヤーで例外をスローすることにより、呼び出し元に個人的に責任を負わせます。次に、コントローラーで例外をキャッチできます (そして、エラーはビューで変数に割り当てられます)。プレゼンテーション レイヤーで例外を直接キャッチすることを好む人もいますが、これは Web 開発の場合にはうまく当てはまりません。ただし、例外がビューでの表示目的でのみ使用される限り、それほど問題にはなりません。

したがって、呼び出し元が常にエラーを表示することを望んでいるとは限らないため、単純な例で行ったようにはしません。発信者への責任を処理することにより、発信者は選択を迫られます。また、ビジネス ロジックにコンテンツをエコーするのは好きではありません (例外をスローし、モデルをプレゼンテーションからきれいに保つことを好みます) が、コードは単純化しすぎた例にすぎない可能性が高いです。

編集:次のようなことができます:

モデル:

function login($username, $password) {
    if (login failed) {
        throw new Login_Exception();
    }

    else {
        // Set session
        return true;
    }
}

コントローラ:

try {
    $model->login($username, $password);
}

catch (Login_Exception $e) {
    $view->loginError = 'There was an error logging in.';
}

次に、さまざまな例外をスローして、何が問題なのかを正確に示し (例: Wrong_Username_Exception)、それに応じて処理することができます。あるいは、例外のコンストラクターでユーザーフレンドリーな理由を提供することもできますが、私の意見では、プレゼンテーションとロジックを結合しすぎます。

于 2012-09-03T13:00:10.180 に答える
1

サンプルコードの問題:

if(!login($username, $password)
{
    echo 'Login failed. Please try again.';
}

... login() 関数が、呼び出し元が操作するのに十分な情報を返さないということです。これは、呼び出し元が Web プレゼンテーション層であるか、それ以外であるかに関係なく問題です。

より優れた login() 関数はオブジェクトを返す可能性があるため、呼び出し元は次のことができます。

$response = login($username, $password);
if(! $response->isLoggedIn()) {
    echo "Login failed. " +  $response->getErrorMessage();
}

これで、ログイン方法はユーザー インターフェイスと密接に結び付いていませんが、ログイン失敗の理由をユーザーに伝えることができます。

さて、login() メソッドにはまだ「プレゼンテーション」があると言っても過言ではありません。それによって返されるテキストはそのままユーザーに引用されているからです。さらに疎結合にしたい場合は、エラー コードのリストを定義し、プレゼンテーション レイヤーにそれらをメッセージに変換させることができます。または、メッセージ テーブルを指す値を返すこともできます。国際化について読んでください。それは同じ基本ドメインです。

于 2012-09-03T13:13:10.117 に答える
0

最初の1つ。呼び出し元は、エラー チェックの責任を持つ必要があります。発生したエラーの種類を知りたい場合は、次のように、ログイン関数を書き直して、エラーへの参照を保持する 3 番目のパラメーターを追加できます。

<?php
function login($user, $pass, &$error) {
    // if user or pass wrong
    $error = 'Username / pass wrong';

    // if db failed
    $error = 'unable to connect to db'
};

if(!login($user, $pass, $error)) {
    // do whatever you want with the error
}

さらに良いことに、エラーの種類に定数を使用できます

アップデート

関数を呼び出した後にセッションまたは Cookie を設定している場合は、関数内でエラーを表示したくないでしょう。それは薄いものを壊し、「ヘッダーはすでに送信されました...」のような通知を受け取ります。

于 2012-09-03T12:58:26.173 に答える