2009-12-03 44 views
0

我目前正在重构一个使用逻辑流异常的应用程序。该代码很难阅读和维护,并使得像我这样的S.O.L.I.D迷迷们在阅读时哭泣(更不用提我在职业生涯中见过的最长的catch block)。工作流的重构例外

我的问题是你可以使用什么样的模式来使它更容易维护或你将如何去重构?

public void CallExternalServices(ICriteria criteria) 
{ 
    try 
    { 
     someResult = ExternalService1.SomeMethod(criteria); 
    } 
    catch (Service1Exception service1Exception) 
    { 
     if (criteria.SomeValue == "1") 
     { 
      if (service1Exception.InnerException != null 
       && service1Exception.InnerException.InnerException != null 
       && service1Exception.InnerException.InnerException is TargetSystemException) 
      { 
       TargetSystemException targetSystemException = (TargetSystemException)service1Exception.InnerException.InnerException; 
       if (targetSystemException.ErrorStatus.IsServiceDownForMaintenance()) 
       { 
        // Call internal method to perform some action 
        SendNotification("Service down for maintenance.") 
       } 
      } 
     } 
     else if (criteria.SomeValue == "2") 
     { 
      if (service1Exception.InnerException != null 
       && service1Exception.InnerException.InnerException != null 
       && service1Exception.InnerException.InnerException is TargetSystemException) 
      { 
       TargetSystemException tx = (TargetSystemException)service1Exception.InnerException.InnerException; 
       if (targetSystemException.ErrorStatus.IsBusy()) 
       { 
        // Call to some internal method to perform an action 
        SendDifferentNotification() 

        criteria.SetSomeFlagToBe = true; 

        try 
        { 
         someResult = ExternalService2.SomeOtherMethod(criteria); 
        } 
        catch (Service2Exception service2Exception) 
        { 
         if (service2Exception.InnerException != null 
          && service2Exception.InnerException.InnerException != null 
          && service2Exception.InnerException.InnerException is TargetSystemException) 
         { 
          TargetSystemException tx = (TargetSystemException)service1Exception.InnerException.InnerException; 
          if (targetSystemException.ErrorStatus.HasNumberOfDailyTransactionsBeenExceeded()) 
          { 
           // Call internal method to perform some action 
           SendNotification("Number of daily transactions exceeded.") 
          } 
         } 
         else if (service2Exception.InnerException != null 
          && service2Exception.InnerException.InnerException != null 
          && service2Exception.InnerException.InnerException is FaultException) 
         { 
          FaultException faultException = service2Exception.InnerException.InnerException as FaultException; 

          if (faultException.Detail != null 
           && faultException.Detail.FaultMessage.Equals("SomeValueToCheckAgainst", StringComparison.OrdinalIgnoreCase)) 
          { 
           return someResult; 
          } 
          else 
          { 
           throw service2Exception; 
          } 
         } 
         else 
         { 
          throw service2Exception; 
         } 
        } 

        if (someResult != null) 
        { 
         // perform another action 
         SomeActionInvoker.ExecuteAcitonAgainst(someResult); 
        } 
       } 
      } 
      else if (service1Exception.InnerException != null 
        && service1Exception.InnerException.InnerException != null 
        && service1Exception.InnerException.InnerException is FaultException) 
      { 
       FaultException faultException = service1Exception.InnerException.InnerException as FaultException; 

       if (faultException.Detail != null 
        && faultException.Detail.FaultMessage.Equals("SomeOtherValueToCheckAgainst", StringComparison.OrdinalIgnoreCase)) 
       { 
        return someResult; 
       } 
       else 
       { 
        throw service1Exception; 
       } 
      } 
      else 
      { 
       throw service1Exception; 
      } 
     } 
    } 
} 

回答

1

总而言之,我认为你会打破一些东西来帮助进入一些辅助方法。例如,你可以提取你的支票,看起来像这样

if (<exception-instance>.InnerException != null && 
    <exception-instance>.InnerException.InnerException != null && 
    <exception-instance>.InnerException.InnerException is <exception-type>) 

进入一个布尔方法;你通过我的粗略浏览至少3次调用这样的代码。另外,我建议将第二个顶级案例抽取到错误处理方法中;也可能是嵌套的if语句。

0

首先将该方法重构为多个方法。你有太多的缩进级别了。

之后,考虑一些新方法是否可以提取到其他对象中,并使用IoC风格的方法而不是过程方法。

这是一种高水平的答案,但我累了,没有精力去真正返工代码自己:)

1

结账与Michael Feathers的遗留代码有效地工作,特别是第22章(我需要更改怪物方法,我无法为其编写测试)。那里有许多伟大的技巧,像你的情况。就个人而言,在这种情况下,我通常最终会从较长方法的各个部分中提取方法,并删除在整个方法中使用的局部变量;这些几乎总是麻烦。