2013-01-06 112 views
0

我有这个主类接收一个queuemessage,然后使用其他几个类来做一些工作。所有这些其他类自己使用一些较低类,最终数据被写入数据库或发送到wcf服务。异常和耦合

根据较低类别的结果,主类必须决定是否删除queuemessage,或将其放在队列中,或者将它发送到一个deadletterqueue。

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

我有一对夫妇的方式来实现这样的场景:

  1. 抛出异常,只有处理它们在主类。
  2. 抛出异常,但在每个调用类中捕获它们。并重新抛出一个新的异常
  3. 返回结果的对象这表明错误/成功状态

这是我对场景的想法:

  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 
    } 
} 
+0

你有什么迄今为止关于代码,你可以展示,从而使他人可以提供一个更好的方法..如果您确实张贴了这种性质..它可能会在计算器上的代码审查部分可以提供最好的服务代码。 – MethodMan

回答

1
  1. ...这夫妻主级一路到最低等级。

不是。它将您的主类耦合到异常类型。是的,如果您更改了异常,则需要将处理更改为更高,但耦合处于异常级别。

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

例外情况被视为superioroption, “T不得不检查找出是否发生了错误。

+0

很抱歉,如果我误解你了,但基本上在大尺度水平,你推荐使用'解析()的''代替的TryParse()',在.net中的下来说的。 –

+0

@IlyaIvanov - 你在说什么?您的评论似乎并不涉及这里的问题和答案。 – Oded

+0

我问过同样的问题,当你在链接了:“异常或错误代码”。一种方法是依靠返回值,另一种方法 - 抛出异常抛出方法。 –