0

キューメッセージを受信し、他のいくつかのクラスを使用して何らかの作業を行うこのメインクラスがあります。これらの他のすべてのクラスは、いくつかの下位クラス自体を使用し、最終的にデータはデータベースに書き込まれるか、wcf サービスに送信されます。

下位クラスの結果に基づいて、メインクラスは、キューメッセージを削除するか、キューに再度配置するか、デッドレターキューに送信するかを決定する必要があります。

たとえば、データベースに到達できない場合は、後で再試行するためにキューメッセージをキューに入れることができます。しかし、wdcf サービスが一部のデータを受け入れないことを返した場合、メッセージをデッドレターキューに送信する必要があります。

このシナリオを実装するには、いくつかの方法があります。

  1. 例外をスローし、メイン クラスでのみ処理します。
  2. 例外をスローしますが、呼び出し元の各クラスで例外をキャッチします。そして、新しい例外を再スローします
  3. エラー/成功状態を示す結果オブジェクトを返します

これらは、シナリオに関する私の考えです。

  1. 最下位クラスの 1 つが例外をスローし、メインクラスがそれを処理する必要がある場合、メインクラスを最下位クラスに結合します。最下位のクラスの 1 つが例外を変更することを決定した場合、メインクラスの例外処理を変更する必要があります。

  2. C# で呼び出されたクラスからスローされる例外を上位クラスに知らせる良い方法はありません。

  3. これは私が好むものです。呼び出されたすべてのメソッドは、成功または失敗を示す列挙型と失敗のタイプを含む結果オブジェクトを返すことができます。

したがって、私の好みの方法はオプション 3 ですが、それがアーキテクチャ的に受け入れられるかどうかはわかりません。または何か良い方法があれば。

コード

コードは次のようになります (簡略化された形式)。

QueueHandler

private static void HandleQueueMessage(Message message)
{
    var deliveryOrder = deserialize(message.body);

    var deliveryOrderHandler = new DeliveryOrderHandler();

    var result = deliveryOrderHandler.Execute(deliveryOrder.PubId);

    switch (result)
    {
        case DeliveryOrderHandlerResult.DeliverySucceeded:
            break;

        case DeliveryOrderHandlerResult.FataleErrorInExternalSystem:
        case DeliveryOrderHandlerResult.MAndatoryDocuhmentTransformationFailed:
            SendDeliveryOrderToDeadletterQueue(deliveryOrder);
            break;

        default:
            deliveryOrder.AbortCount = deliveryOrder.AbortCount + 1;
            ResendDeliveryOrderToQueue(deliveryOrder);
            break;
    }
}

DeliveryOrderHandler

private DeliveryOrderHandlerResult Execute(long pubId)
{
    DeliveryOrderHandlerResult deliveryOrderHandlerResult;

    var transformationResult = GetTransformationResultaat(pubId);

    if (transformationResult == TransformationResult.Success)
    {
        var deliveryResult = DeliverDocumentToExternalSystem(pubId); 

        if (deliveryResult.Status == DeliveryResult.Success)
        {
            SaveDeliveryResult(pubId, deliveryResult);
        }

        deliveryOrderHandlerResult = deliveryResult.Status;
    }
    else
    {
        switch (transformationResult)
        {
            case TransformationResult.NotStarted:
                deliveryOrderHandlerResult = DeliveryOrderHandlerResult.TransformationNotStarted;

            case TransformationResult.Busy:
                deliveryOrderHandlerResult = DeliveryOrderHandlerResult.TransformationBusy;

            case TransformationResult.MandatoryTransformationFailed:
                deliveryOrderHandlerResult = DeliveryOrderHandlerResult.MandatoryTransformationFailed;

            default:
                throw new Exception(--unknown enum value --);
        }
    }

    return deliveryOrderHandlerResult;
}

DeliverDocumentToExternalSystem

pseudo:
- Create Delivery package by reading data from database and transformed files from disk
- Send package to external system

ご覧のとおり、うまくいかないことがたくさんあります。データベース接続の失敗、wcf サービス呼び出しの失敗、ファイルが存在しないなど。

私はこれを防ぐことができると思っていました:

QueueHandler

private static void HandleQueueMessage(Message message)
{
    var deliveryOrder = deserialize(message.body);

    var deliveryOrderHandler = new DeliveryOrderHandler();

    try
    {
        var result = deliveryOrderHandler.Execute(deliveryOrder.PubId);

        switch(result)
        {
           case DeliveryOrderHandlerResult.Success:
              // remove message from queue

           case DeliveryOrderHandlerResult.NotStarted:
              // resent message to queue

           case DeliveryOrderHandlerResult.MandatoryTransformationFailed:
              // send message to deadletterqueue

           case ...
              // handle

           case ...
              // handle

        }
    }
    pseudo catches:
    catch (DatabaseNotFoundexception ex)
    {
        // resent message to queue
    }
    catch (ExternalWcfServiceDownException ex)
    {
        // resent message to queue
    }
    catch (FileNotFoundException ex)
    {
         // send message to deadletterqueue
    }
    catch (...)
    {
        // handle
    }
    catch (...)
    {
        // handle
    }
}
4

1 に答える 1

1
  1. ...メインクラスを最下位クラスに結合します。

いいえ。メインクラスを例外タイプに結合します。はい、例外を下位に変更する場合は、処理を上位に変更する必要がありますが、カップリングは例外レベルにあります。

返品を確認するのを忘れる可能性があるため、3 は適切なオプションではありません。結果オブジェクトを下に変更した場合、メインクラスに変更を加える必要があるため、オプション1にリストしたのとまったく同じ問題が発生します...

エラーが発生したかどうかを確認する必要がないため、例外は優れた オプションと見なされます。

于 2013-01-06T10:33:00.757 に答える