如何构建有很多故障点的代码?

tar*_*yte 4 c return-value

我有一段代码在很多地方都可能失败。每增加一个操作(也可能会失败),可读性就会变差。有没有更好的方法来构建这个?有这方面的设计模式吗?

int32_t InitializeMyThingy(void) {
  int32_t retcode;

  retcode = DoA();
  if (retcode != 0) return retcode;
  retcode = DoB();
  if (retcode != 0) return retcode;
  retcode = DoC();
  if (retcode != 0) return retcode;
  retcode = DoD();

  return retcode;
}
Run Code Online (Sandbox Code Playgroud)

或者(更具可读性?):

int32_t InitializeMyThingy(void) {
  int32_t retcode;

  retcode = DoA();
  if (0 == retcode) {
    retcode = DoB();
    if (0 == retcode) {
      retcode = DoC();
      if (0 == retcode) {
        retcode = DoD();
      }
    }
  }

  return retcode;
}
Run Code Online (Sandbox Code Playgroud)

jam*_*lin 5

在 C 语言中,SESE(单次进入,单次退出)模式goto通常是合适的:

int32_t InitializeMyThingy(void) {
  int32_t retcode;

  retcode = DoA();
  if (retcode != 0) goto exit;
  retcode = DoB();
  if (retcode != 0) goto exit;
  retcode = DoC();
  if (retcode != 0) goto exit;
  retcode = DoD();

exit:
  return retcode;
}
Run Code Online (Sandbox Code Playgroud)

return就其本身而言,这与您的第一个示例(每次检查后都有语句)没有任何不同。但是,一旦您的代码开始分配资源,该goto方法就会更加清晰:

int32_t InitializeMyThingy(void) {
  int32_t retcode = E_FAIL;
  A* a = NULL;
  B* b = NULL;
  C* c = NULL;

  a = AllocateA();
  if (a == NULL) goto exit;

  b = AllocateB(a);
  if (b == NULL) goto exit;

  c = AllocateC(b);
  if (c == NULL) goto exit;

  retcode = DoSomething(c);

exit:
  free(c);
  free(b);
  free(a);
  return retcode;
}
Run Code Online (Sandbox Code Playgroud)

现在您不必担心弄清楚在每个单独的出口点要清理什么。

不管许多反对者怎么说goto,如果使用得当,它是 C 中最明智的错误处理形式。

关于添加附加操作的可读性,我认为用空格分隔操作有很大帮助。或者,如果您确实想要紧凑性,您可以考虑内联执行操作和错误检查:

if ((retcode = DoA()) != 0) goto exit;
Run Code Online (Sandbox Code Playgroud)