使用清理代码优化多个出口点

Optimize multiple exit points with cleanup code

本文关键字:出口 代码优化      更新时间:2023-10-16

我正在实现串行通信协议。在此实现的接收函数中,我有多个出口点,其中包含用于清理的重复代码。我不确定表达式 SESE 在结构/OO 编程语言的情况下是否有效。我正在使用C++。这不是 MCVE,而只是我在代码中的结构。代码如下所示:

bool receive()
{
  bool status = false;
  initializeCommunication();
  if (receiveOneByteIsNotWhatExpected())
  {
     cleanupCode();
     return status;
  }
  processFirstParam();
  if (receiveTwoBytesIsNotWhatExpected())
  {
    cleanupCode();
    return status;
  }
  processSecondParam();
  if (receiveOneByteIsNotWhatExpected())
  {
    cleanupCode();
    return status;
  }
  processThirdParam();
  if (receiveFourBytesIsNotWhatExpected())
  {
    cleanupCode();
    return status;
  }
  processFourthParam();
  status = true;
  cleanupCode();
  return status;
}

我想重构它。一种方法是使用一种状态机,例如:

bool receive()
{
  status = true;
  state = START;
  while (status && state != POSTENDED)
  {
    switch(state)
    {
      case START:
        initializeCommunication();
        state = RECEIVEFIRSTONEBYTE;
        // fall-through
      case RECEIVEFIRSTONEBYTE:
        if (receiveOneByteIsNotWhatExpected())
        {
          status = false;
        }
        else
        {
          processFirstParam();
          state = RECEIVESECONDTWOBYTES;
        }
          break;
      case RECEIVESECONDTWOBYTES:
       if (receiveTwoBytesIsNotWhatExpected())
       {
         status = false;
       }
       else
       {
         processSecondParam();
         state = RECEIVETHIRDONEBYTE:
       }
       break;
       case RECEIVETHIRDONEBYTE:
        if (receiveOneByteIsNotWhatExpected())
        {
          status = false;
        }
        else
        {
          processThirdParam();
          state = RECEIVEFOURTHFOURBYTES;
        }
        break;
        case RECEIVEFOURTHFOURBYTES:
        if (receiveFourBytesIsNotWhatExpected())
        {
          status = false;
        }
        else
        {
          processFourthParam();
          state = ENDED;
        }
        break;
        case ENDED:
          status = true;
          state = POSTENDED;
        break;
    }
  }
  cleanupCode();
  return status;
}

编写上述代码的第三种方法是使用 nested if 语句,该语句将生成四个嵌套的 if 语句级别,但这将是简洁的。编写这种代码的优化方法是什么,它们各自的优缺点是什么。

清理守卫呢:

bool receive()
{
    bool status = false;
    initializeCommunication();
    struct CleanupGuard
    {
        ~CleanupGuard()
        {
           cleanupCode();
        }
    } g;
    if (receiveOneByteIsNotWhatExpected())
    {
        return status;
    }
    // [...]
}

内联功能:

namespace
{
   inline bool doReceive()
   {
       // [...]
   }
}
bool receive()
{
    initializeCommunication();
    bool status = doReceive();
    cleanupCode();
    return status;
}

循环方法:

bool receive()
{
    bool status = false;
    initializeCommunication();
    do
    {
        if (receiveOneByteIsNotWhatExpected())
        {
            status = false;
            break;
        }
        // [...]
    }
    while(false);
    cleanupCode();
    return status;
}

虽然标签和goto的使用通常不受欢迎,但这通常是许多人认为可以使用的情况之一。

因此,而不是例如

if (receiveOneByteIsNotWhatExpected())
{
  cleanupCode();
  return status;
}
...

你会有类似的东西

if (receiveOneByteIsNotWhatExpected())
{
  goto end;
}

在函数的末尾:

  processFourthParam();
  status = true;
end:
  cleanupCode();
  return status;
}

这将最大限度地减少通用代码的重复,并且是"一次返回"或"单进入,单退出"原则的基石。