【问题标题】:how to keep track of status through many steps如何通过多个步骤跟踪状态
【发布时间】:2013-12-03 07:24:46
【问题描述】:

我正在处理一些由于状态检查而难以重构的代码。我试图找出更好的方法来解决这个问题,这样我就可以保持我的代码干净/可读。这是代码的 sn-p:

int status = FAILED;

status = fn_action_one();

if (status != SUCCESS)
{
    printf("ERROR: returned from fn_action_one()\n");
}
else
{
    status = fn_action_two();
}

if (status != SUCCESS)
{
    printf("ERROR: returned from fn_action_two()\n");
}
else
{
    status = fn_action_three();
}

对我来说,问题是我现在想重构这段代码并循环遍历其中的一部分:

int status = FAILED;

status = fn_action_one();

if (status != SUCCESS)
{
    printf("ERROR: returned from fn_action_one()\n");
}
else
{
    // This task is now required to be done multiple times...
    for (int i = 0; i < numLoop; i++)
    {
        status = fn_action_two(i); // Keeping track of the status here is now an issue
    }
}

// If any of the looped action_two's had a fail this check should fail
if (status != SUCCESS)
{
    printf("ERROR: returned from fn_action_two()\n");
}
else
{
    status = fn_action_three();
}

这现在变得很困难,因为在循环时我想继续循环遍历所有 numLoop 次(无论是什么),但如果一个失败,状态应该保持失败。

有没有一种干净的方法可以做到这一点?或者也许有一个模式?

编辑:状态值的枚举

enum status_vals
{
    SUCCESS = 0,
    FAILED = -1,
    FAILED_TIMEOUT = -2,
    FAILED_FATAL = -3,
        etc...
}

【问题讨论】:

  • FAILEDSUCCESS的值是多少?
  • 我将使用真实代码中的值添加一个枚举

标签: c++ status


【解决方案1】:

“模式”是使用异常处理。如果你不能修改 fn_action_xxx() 然后写包装器

void my_action_one()
{
    int status = fn_action_one();
    if (status != SUCCESS)
         throw std::runtime_error("ERROR: returned from fn_action_one()");
}

...

try
{
    my_action_one();
    for (int i = 0; i < numLoop; i++)
    {
        my_action_two(i);
    }
    my_action_three();
}
catch (const std::exception& e)
{
    printf("%s\n", e.what());
}

状态检查的脆弱性是异常的动机之一。通过将错误处理与程序的主要流程分开,您可以获得更清晰的代码。

【讨论】:

  • 这个might 太重了,无法在我的代码库中的任何地方使用——即使它是正确的做法 :(,但我可以在某些地方使用它并用于新的代码位,谢谢!
【解决方案2】:

作为一种“C”方法,我会使用宏和 goto 的组合。

#define CHECK(expr) \
  { \
    if( SUCCESS != (status = expr) ){ \
    printf("ERROR: returned from " #EXPR "\n"); \ 
    goto End
  } \
}


int status = FAILED;

CHECK(fn_action_one());

End:
return status;

在循环中我会这样做

  if (status != SUCCESS)
  {
     status = fn_action_two(i);
  }

【讨论】:

  • Definatley 有用,谢谢 :),但我想尝试更多地使用 c++
【解决方案3】:

如果您想尽可能地保持当前的代码结构,并尽量减少实现所需功能所需的更改,您可能会通过添加一个布尔值来跟踪循环中的任何调用是否失败,然后在此基础上设置status

int status = FAILED;

status = fn_action_one();

if (status != SUCCESS)
{
    printf("ERROR: returned from fn_action_one()\n");
}
else
{
    bool failed = false;
    // This task is now required to be done multiple times...
    for (int i = 0; i < numLoop; i++)
       failed |= (fn_action_two(i) == FAILED);
}
if (failed)
    status = FAILED;

// If any of the looped action_two's had a fail this check should fail
if (status != SUCCESS)
{
    printf("ERROR: returned from fn_action_two()\n");
}
else
{
    status = fn_action_three();
}

【讨论】:

  • 是的,我认为这可能是我“复古适合”我的代码的最佳解决方案,直到我可以进行某种全面检修:o。谢谢:)
猜你喜欢
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 2021-04-02
  • 1970-01-01
相关资源
最近更新 更多