3

手順(検証、関連コンテンツの添付、フォーマット、送信)をより簡単にテスト、ログ記録、更新できる個別のクラスに分割することで、「メールの送信」コードをリファクタリングしようとしています。

この一環として、オペレーションが検証または一時的なエラー(「そのアイテムが削除された」)を発信者に通知して、ユーザーに詳細情報を要求したり、悪いニュースを伝えたりできるようにする方法を理解する必要があります。 。これがスレッドがたどるパスです(イェーイ、落書き)

     "Controller"                     
      .   -> Outbox 
      .         -> Validator 
      .         -> Formatter 
      .         -> Sender
      .   <- 

                   -> Parameters, work in progress
                   <- Good, not so good, "you better sit down" news

それで、あなたは「リターン」、「例外」、または「コンテキスト」の間で思慮深い種類です…どれがあなたを幸せにしますか?

A.問題が発生した場合は例外をスローし、コントローラーに、正常に処理できるものと、私の「ブザー」を知っているものを分けさせます。

B.ある種のResultクラスを返し<T>、操作の結果(電子メール)とさまざまな操作の列挙された結果の両方を伝達します。

C.処理できないパラメータを示し、メソッドのシグネチャを非常に単純に保つことができるすべてのステップにコンテキストを渡します。

D.息子、あなたはこれを考えすぎています..これがあなたがやろうとしていることです:<YourSpecialJujuHere/>

ありとあらゆる貢献に感謝します、あなたは一丸となって揺れ動きます。

4

2 に答える 2

4

テンプレートメソッドパターンをストラテジーパターンと一緒に使用できます。

コントローラはテンプレートメソッドになります。電子メール送信プロセスの各ステップについて、そのステップを実装するデリゲート/ストラテジークラスを呼び出します。

public class EmailSender
{
    private iOutboxGetter outboxGetter;
    private iMsgValidator validator;
    private iMsgFormatter formatter;
    private iMsgSender    sender;

    //setters for each stragegy, or a constructor
    //good use for IOC container

    public iSendResult SendMessage(iMsgParams params)
    {
        try
        {
            var outbox = outboxGetter.getOutbox(params.outbox);
            var validationResults = validator.validate(params);
            if(validationResults.IsValid)
            {
                var msg = formatter.formatMsg(params.message);
                sender.send(msg);
                return new AllGoodSendResult();
            }
            else
            {
                return new ValidationFailedSendResult(validationResults);
            }
        } 
        catch(CatastrophicException e)
        {
           Pager.SendCriticalPage(e.message);
            return new CatistrophicFailureSendResult(e);
        }
    }
}

コードがハッピーパスから逸脱する必要がある場合は、例外を使用することを好みます。ロジックとエラー処理をきれいに分離していると思います。

編集:SendMessageメソッドからの戻り値は、検証に合格したかどうか、および検証に失敗したものを呼び出し元に示します。その後、発信者はユーザーに詳細情報の入力を求めて再試行するか、成功を示すことができます。例外は、本当に例外的な状況が発生した場合にのみスローされます。

このアプローチを使用すると、アルゴリズムの各コンポーネントを個別にモックしてテストでき、ストラテジーは他のストラテジーがどのように機能するかを知る必要も、他の誰かのエラーを処理する方法を知る必要もありません。最後に、すべてのエラー処理が1か所に集中化されます。

于 2009-11-03T18:39:15.360 に答える
1

おそらく、問題はアクションの順序付けにあり、アクションが次の呼び出しになります。

別のアプローチは、Controller がすべてのアクションを順番に呼び出すようにすることです。その場合、コントローラーと各アクションの間に直接的な関係があります。

各アクションは単純な結果を返すか、ケースに適した方法でエラーを通知します。

  • 例外による例外的な状況
  • null リターンによる結果なし。
  • ...

あるアクションから別のアクションへの再利用は、ローカル変数として発生する可能性があります。

サンプルコード(必要に応じてパラメータなどを追加):

    class Controller1 {

       private Sender sender = new SenderImpl();

       public void process(String text) {
         try {
           Outbox box = getOutbox();
           List<Errors> errors = validate(text);
           if (!errors.isEmpty()) {
             ....
             return;
           }
           String formatted = format(text);
           sender.send(formatted);
         } catch(MyException e) {
           ....
         }
       }
    }

このコードでは、手順は同じクラスのメソッドに委譲されていますが、他のクラスのインスタンスで同じ構造に従うのは非常に簡単です (ただし、必要な場合にのみ、過度に設計しないでください)。あなたが言及したように、これはテスト容易性のために正当化できます。のサンプルコードを変更しましたsender

于 2009-11-02T17:47:20.713 に答える