0

私はMVCフレームワークで次のようなコードを書きました。

class Controller_Test extends Controller
{
   public function action_index()
   {
      $obj = new MyObject();
      $errors = array();

      try
      {
         $results = $obj->doSomething();
      }
      catch(MyObject_Exception $e)
      {
         $e->getErrors();
      }
      catch(Exception $e)
      {
         $errors[] = $e->getMessage();
      }
}

私の友人は、コントローラーはMyObjectについて何も知らないはずなので、MyObject_Exceptionをキャッチするべきではないと主張しています。

彼は、コードは代わりに次のようなことをするべきだと主張しています。

class Controller_Test extends Controller
{
   public function action_index()
   {
      $obj = new MyObject();
      $errors = array();

      if($obj->doSomething())
      {
         $results = $obj->getResults();
      }
      else
      {
         $errors = $obj->getErrors();
      }
}

私は彼のアプローチを確かに理解していますが、状態管理が意図しない副作用につながる可能性があるように感じます。

正しいまたは好ましいアプローチは何ですか?

編集:$ e-> getErrors();の代わりに誤って$ obj-> getErrors()をMyObject_Exceptioncatch句に入れました。

4

3 に答える 3

1

一般的に重要なのは、コントローラーが例外の意味を理解し、それを適切に処理できるかどうかです。多くの場合(ほとんどではないにしても)、コントローラーは例外を適切に処理する方法を知らないため、例外をキャッチして処理するべきではありません。

一方、コントローラーは、MyObjectデータベースをどのように、またはなぜ使用したかがわからない場合でも、「DatabaseUnavailableException」などの特定の例外を理解することを合理的に許可される場合があります。MyObjectコントローラは、実装方法を知らなくても、特定の回数だけ呼び出しを再試行できる場合がありMyObjectます。

于 2013-02-12T05:16:02.287 に答える
1

例外と返されたエラーコードについての議論は長くて血なまぐさいものです。

彼の議論は、getErrors()関数を使用することで、オブジェクトに関する情報を学習しているという点で分解されます。それが成功を示すためにブールリターンを使用する理由である場合、あなたは間違っています。コントローラがエラーを適切に処理するためには、コントローラが接触していたオブジェクトと特定のエラーが何であるかを知る必要があります。ネットワークエラーでしたか?メモリエラー?なんらかの方法で知る必要があります。

よりクリーンで、より制御された方法でより多くのエラーを処理できるため、例外モデルを好みます。また、例外に関連するデータを渡すための明確な方法も提供します。

ただし、getErrors()のような関数の使用には同意しません。例外の処理に役立つ例外に関連するデータはすべて、例外に含める必要があります。何が悪かったのかについての情報を得るために、オブジェクトをもう一度探しに行く必要はありません。

ネットワーク接続がタイムアウトしましたか?例外には、接続を試みたホスト/ポート、待機時間、および下位のネットワークレベルからのデータが含まれている必要があります。

これを例でやってみましょう(psuedo c#で):

public class NetworkController {
    Socket MySocket = null;
    public void EstablishConnection() {
        try {
            this.MySocket = new Socket("1.1.1.1",90);
            this.MySocket.Open();

        } catch(SocketTimeoutException ex) {
            //Attempt a Single Reconnect
        }
        catch(InvalidHostNameException ex) {
            Log("InvalidHostname");
            Exit();
        }

    }
}

彼の方法を使用して:

public class NetworkController {
    Socket MySocket = null;
    public Boolean EstablishConnection() {
        this.MySocket = new Socket("1.1.1.1",90);
        if(this.MySocket.Open()) {
            return true;
        } else {
            switch(this.MySocket.getError()) {
                case "timeout":
                    // Reattempt
                    break;
                case "badhost":
                    Log("InvalidHostname");
                    break;
            }
        }
    }
}

最終的には、オブジェクトに何が起こったのかを知る必要があり、それに応答する方法を知る必要があります。複雑なifステートメントセットまたはswitch-caseを使用してそれを判断する意味はありません。例外を使用して、それらを愛してください。

編集:私は誤って文の後半をしました。

于 2013-02-12T05:17:55.407 に答える
1

まず第一に、コントローラーは、クラスによってスローされた根本的な例外を処理するためのものではありません。

発生した場合でも、コントローラーは根本的なエラーで何か間違ったことを言うのをやめるべきです。

このようにして、コントローラーが実際にフロー制御の役割のみを実行することを確認します。

コントローラーに出力を与える他のクラスは、エラーがコントローラー固有のものでない限り、エラーがないはずです。

于 2013-02-12T08:03:47.657 に答える