重构'执行和记录'模式

时间:2015-06-05 06:14:59

标签: c++ c function logging refactoring

我发现自己一次又一次地遵循相同的模式:

if((return_code = doFoo1(...)) != CODE_OK) {
    log("useful log message based on return code");
    // very likely to return an error code. 
}

// continue

if((return_code = doFoo2(...)) != CODE_OK) {
    log("useful log message based on return code");
    // very likely to return an error code. 
}

有任何见解如何避免这种烦人的模式并保持逻辑清洁?

1 个答案:

答案 0 :(得分:2)

有很多方法可以解决这个问题,这里有一个基本方法:

bool CheckAndLog( int code )
{
  if( code == CODE_OK )
    return true;
  log( "<some error based on code>" );
  return false;
}

if( !CheckAndLog( doFoo1(...) ) )
  return;

如果你还需要返回代码以供以后使用,你可以从CheckAndLog返回它,或者将它作为pass-by-reference参数,或者甚至将CheckAndLog变成一个存储最新错误代码并用实例化的类。要使用的(可能是作用域的)记录器实例。

更新如果您需要文件和行信息,则需要__FILE____LINE__宏,并且无需在整个地方输入简单的宏就足够了:

bool CheckAndLog( int code, const char* file, unsigned line )
{
  if( code == CODE_OK )
    return true;
  std::cerr <<  "file " << file << " line " << line
            << "<errormessage>" << std::endl;
  return false;
}

#define CHECK( what ) (CheckAndLog( what, __FILE__, __LINE__ ))

进一步将被调用的函数放入其中:因为它可用作宏参数,所以它由预处理器进行扩展。这意味着如果您键入CHECK( foobar( 65 ) )what参数字面上会被视为foobar( 65 ),而不是它的返回值。这是理想的,因为预处理器也可以turn that into a string

bool CheckAndLog( int code, const char* desc, const char* file, unsigned line )
{
  if( code == CODE_OK )
    return true;
  std::cerr <<  desc << " from file " << file << " line " << line
            << "<errormessage>" << std::endl;
  return false;
}

#define STRINGIZE1( x ) #x
#define STRINGIZE( x ) STRINGIZE1( x )
#define CHECK( what ) (CheckAndLog( what, STRINGIZE( what ), __FILE__, __LINE__ ))

我建议不要使用CHECK作为宏的名称,因为它经常被单元测试库使用。另外要小心,不要将你的宏(偶然或故意)重新定义为类似#define CHECK( what ) (true)的东西,因为如果你写的话就意味着 CHECK( foobar( 65 ) ),函数将永远不会被调用。