首页 文章

用于测试和报告多个函数调用返回错误的技术

提问于
浏览
1

我正在研究函数调用中的错误测试和报告技术,特别是在调用多个函数时 . 作为我的意思的一个例子,为简单起见,每个函数返回一个bool:

success = false;

if (fnOne ())
{
    if (fnTwo ())
    {
        if (fnThree ( ))
        {
            success = true;
        }
        else
        {
            cout << "fnThree failed" <<endl;
        }
    }
    else
    {
        cout << "fnTwo failed" <<endl;
    }
}
else
{
    cout << "fnOne failed" <<endl;
}

我发现上面的例子(我随处可见)代码很快变得难以理解,特别是当它调用代码变成多屏高度时 .

目前我在C中处理这个问题的方式(包括'c'标签,以防某人有一个平滑的C技术)我在我的对象中存储了一个bool和一个字符串 . bool表示成功/失败,字符串表示失败状态的原因 . 我调用一个函数,如果函数失败,函数会在内部将对象设置为失败状态并提供基于字符串的原因 . 我对这种方法仍然不是100%满意......但它是迄今为止我所拥有的最好的方法 . 它的样子示例:

void myobj::fnOne (void)
{
    if (m_fluxCapacitorProngCount > 3)
    {
        setState (false, "myobj::fnOne - Flux capacitor has been breeding again");
    }
}

void myobj::fnTwo (void)
{
    if (m_answerToLifeUniverseAndEverything != 42)
    {
        setState (false, "myobj::fnTwo - Probability drive enabled?");    
    }
}

void myobj::setup (void)
{
    // Ensure time travel is possible
    if (valid())
    {
        fnOne ();
    }

    // Ensure the universe has not changed
    if (valid())
    {
        fnTwo ();
    }

    // Error? show the reason
    if (valid() == false)
    {
        cout << getStateReason () << end;
    }
}

其中valid()返回true / false,getStateReason()返回错误发生时函数中提供的字符串 .

我喜欢这种增长而不需要嵌套条件,对我来说,我觉得这更具可读性,但我确信有问题......

处理检测和报告多个函数调用返回条件的最佳[最干净]方法是什么?

3 回答

  • 0

    处理代码中的错误(错误)和用户输入引起的错误本身就是一个很大的话题 . 您使用的技术取决于代码的复杂性和代码的预期寿命 . 您将用于家庭作业项目的错误处理策略不如您在一个学期项目中使用的错误处理策略复杂,这将比您将用于内部项目的错误处理策略复杂化,这将是比一个广泛分发给客户的项目更简单 .

    Strategy 1: Write an error message and abort

    您可以在家庭作业项目中使用的最简单的错误处理策略是将消息写入 stdout ,然后调用 abort() .

    void fun1(int in)
    {
      if (in < 0 )
      {
        printf("Can't work with a negative number.\n");
        abort();
      }
    
      // Rest of the function.
    }
    

    Strategy 2: Set a global error code and return

    下一级错误处理涉及检测错误输入并在不调用 abort() 的情况下处理它 . 您可以设置全局可访问的错误代码以指示错误类型 . 我建议将这种方法用于家庭作业项目,学期项目和探索性项目 .

    void fun2(int in)
    {
      if (in < 0 )
      {
        // Indicate that "fun2" came accross a NEGATIVE_INTEGER_ERROR.
        setErrorCode(NEGATIVE_INTEGER_ERROR, "fun2");
        return;
      }
    
      // Rest of the function.
    }
    
    void funUser(int in)
    {
      // Call fun2
      fun2(in);
    
      // If fun2 had any errors, deal with it.
      if (checkErrorCode())
      {
         return;
      }
    
      // Rest of the function.
    }
    

    下一级错误处理涉及检测错误输入并使用其他选项处理它 . 您可以从函数返回错误代码 . 如果您使用的是C,则可能会抛出异常 . 这两种选择都是处理大型项目的有效方式 - 无论是内部还是分发以供更广泛的消费 . 它们适用于用户群超出开发人员团队的任何项目 .

    Strategy 3: Return an error code from the function

    int fun3(int in)
    {
      if (in < 0 )
      {
        // Indicate that "fun3" came accross a NEGATIVE_INTEGER_ERROR.
        return NEGATIVE_INTEGER_ERROR;
      }
    
      // Rest of the function.
    }
    
    void funUser(int in)
    {
      // Call fun3
      int ecode = fun3(in);
    
      // If fun3 had any errors, deal with it.
      if (ecode)
      {
         return;
      }
    
      // Rest of the function.
    }
    

    Strategy 4: Throw an error code from the function (C++)

    void fun4(int in)
    {
      if (in < 0 )
      {
        // Indicate that "fun4" came accross a NEGATIVE_INTEGER_ERROR.
        throw NEGATIVE_INTEGER_ERROR;
      }
    
      // Rest of the function.
    }
    
    void funUser(int in)
    {
      // Call fun4. Be prepared to deal with the exception or let it be
      // dealt with another function higher up in the call stack.
      // It makes sense to catch the exception only if this function do
      // something useful with it.
      fun4(in);
    
      // Rest of the function.
    }
    

    希望这为您提供足够的背景,为您的项目采用适当的错误处理策略 .

  • 2

    如果你真的想要一个函数返回一个代表几个其他函数成功/失败的值(而且只是 - 不是每个函数的通用返回值,这需要某种方式返回数组/元组/值向量) ,这是一种方法:

    int bigFunction()
    { int return_value = 0;
    
      if (function1() != 0)
        return_value |= (1 << 0);
    
      if (function2() != 0)
        return_value |= (1 << 1);
    
      if (function3() != 0)
        return_value |= (1 << 2);
    
      // ....
    
      return return_value;
    }
    

    想法是在返回值中分别分配一位以指示每个子功能的成功/失败 . 如果您的子函数有一小组您可能想要捕获的可能返回值,则每个函数可以使用多个位 - 即两个位将允许您为该字段设置四个不同的值 .

    另一方面,这样的事情意味着你可能要么a)编写一些非常低级的代码,比如设备驱动程序或内核或者b)可能有更好的方法来解决手头的问题 .

  • 0

    此代码应该比您的第一个变体更清晰:

    if (!fnOne ())
    {
        cout << "fnOne failed" <<endl;
        return;
    }
    if (!fnTwo ())
    {
        cout << "fnTwo failed" <<endl;
        return;
    }
    if (!fnThree ())
    {
        cout << "fnThree failed" <<endl;
        return;
    }
    success = true;
    

    通常,对于C,您可以使用异常进行错误处理 .

相关问题