异常和耦合

时间:2013-01-06 10:27:19

标签: c# exception coupling

我有这个主类接收队列消息,然后使用其他一些类来做一些工作。所有这些其他类本身都使用一些较低的类,最终将数据写入数据库或发送到wcf服务。

根据较低类的结果,主类必须决定删除队列消息,或者将其再次放入队列,或将其发送到死信号。

例如,如果数据库无法访问,则可以将队列消息放入队列中以便稍后再次尝试。但是如果wdcf服务返回它不接受某些数据,则必须将消息发送到deadletterqueue。

我有几种方法可以实现这种情况:

  1. 抛出异常并仅在主类中处理它们。
  2. 抛出异常,但在每个调用类中捕获它们。并重新抛出一个新例外
  3. 返回表示错误/成功状态的结果对象
  4. 这些是关于场景的想法:

    1. 如果其中一个最低类抛出一个异常,并且main-class必须处理它,它会将main-class一直耦合到最低类。如果其中一个最低类决定更改异常,我必须更改主类异常处理。

    2. 没有好办法让上层人员知道C#中被调用的类会抛出哪些异常。

    3. 这是我更喜欢的。每个被调用的方法都可以返回一个结果对象,其中一个枚举表示成功或失败,以及失败的类型。

    4. 所以,我首选的方法是选项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
          }
      }
      

1 个答案:

答案 0 :(得分:1)

  
      
  1. ...它将主要班级一直带到最低级别。
  2.   

没有。它将您的主类与异常类型相结合。是的,如果您将更低的异常更改,则需要将处理更高,但耦合处于异常级别。

3不是一个好的选择,因为你可以忘记检查回报。您最终得到了在选项1中列出的完全相同的问题,就像您将结果对象更改为低,您需要在主类中进行更改...

例外情况被视为superior option,因为您无需检查以查明是否发生了错误。