95

在设计 C 项目时,是否有任何已知的设计原则、最佳实践和设计模式可以遵循?还是一般程序(命令式)编程的有用设计原则?

(我是“面向对象一代”的孩子,必须第一次设计一个大型 C 项目)

4

4 回答 4

67

信息隐藏——Parnas(软件基础)所提倡的。

仔细管理标题和可见性:

  • 源文件中可以对外界隐藏的所有内容都应该是;只应公开记录在案的外部接口。
  • 公开的所有内容都在标头中声明。
  • 该标头用于需要功能的地方(以及定义的地方)。
  • 标头是自包含的 - 当您需要它时,您可以使用它,并且您不必担心“我还必须包含哪些其他标头”,因为标头通过包含制作它所需的任何内容来确保它工作工作。
  • 标头是自我保护的 - 因此是否多次包含它并不重要。

    #ifndef HEADER_H_INCLUDED
    #define HEADER_H_INCLUDED
    ...rest of header contents, including other #include lines if necessary
    #endif /* HEADER_H_INCLUDED */
    
  • 设计一组函数来处理“对象”(通常是结构)——并使用这些函数,而不是在使用它的代码中探索结构的内部。将其视为自我强加的封装。

于 2010-03-22T13:34:35.457 回答
25

我的三个建议:

  • 编写单元测试。他们将帮助您在进行时将适合您问题的设计归零。比(仅仅)依靠预先冥想好得多。
  • 从第一天开始安装并运行内存泄漏检测器(那里有各种各样的库)。一旦程序/测试退出,让这个库打印出所有泄漏。这将使您在引入泄漏后立即发现泄漏,从而减少修复的痛苦。
  • 用 C 编写 OOP 代码。没那么难。虽然可以模拟方法覆盖,但我建议您从模拟简单对象开始。即使是这个简单的机制也可以给你很大的里程数。

这是一个例子:

typedef struct Vector {
  int size;
  int limit;
  int* ints; 
} Vector;

Vector* Vector_new() {
  Vector* res = (Vector*) malloc(sizeof(Vector));
  res->limit = 10;
  res->size = 0;
  res->ints = (int*) malloc(sizeof(int) * res.limit);

  return res;
}


void Vector_destroy(Vector* v) {
  free(v->ints);
  free(v);
}

void Vector_add(Vector* v, int n) {
  if(v->size == v->limit) {
    v->limit = v->limit * 2 + 10;
    v->ints = realloc(v->ints, v->limit);     
  }

  v->ints[v->size] = n;
  ++v->size;
}

int Vector_get(Vector* v, int index) {
  if(index >= 0 && index < v->size)
    return v->ints[index];

  assert false;
}
于 2010-03-23T05:22:31.930 回答
22

有一本很好的免费在线书籍,名为Object-Oriented Programming With ANSI-C,它涵盖了用 C 编写面向对象代码的主题。谷歌搜索“面向对象的 C”也产生了许多其他好的示例和资源。

如果您的项目对安全至关重要,那么MISRA-C是一套很好的规则。它主要用于嵌入式 c,但在其他领域也很有用。

我认为自己是一个 OO 编码器,并且我使用嵌入式 C 做了很多工作。我能给出的最好建议,尤其是对于大型项目,就是不要过度。在 ANSI C 之上创建一个完整的 OO 框架可能非常诱人,但需要大量时间和精力才能使其正确。你得到的花哨越多,你将花费更多的时间来调试你的框架,而不是在真正的项目上工作。以清晰的头脑和对YAGNI的良好、扎实的把握来完成任务。祝你好运!

于 2010-03-22T13:36:06.110 回答
8

OOP 是一种方法,而不是一种技术。所以我的第一个建议是停止将其视为过程编程。

对于 e.James 的观点,您不想尝试重新创建面向对象的语言或假装您拥有其能力。通过坚持一些简单的原则,你仍然可以做所有正确的事情:

  1. 试驾一切。
  2. 找出变化并封装它。
  3. 设计到接口。
于 2010-03-23T05:08:49.123 回答