我有一个中等规模但复杂的C项目(总共大约200,000行),其中包含大约100个.h文件和几乎同样多的.c文件。
许多.h文件对应于等效的.c文件,但有一个特别的.h文件,让我们称之为project_common. h,它包含许多其他.h文件,并包含大约2000行主要是struct和enum定义等。许多结构都是嵌套的,因此它们的顺序非常重要。
该文件的结构大致如下:
#include guard
#include <assert.h>
#include <stdint.h>
/* etc */
#include "project_aaa.h"
#include "project_bbb.h"
/* Then another 30 or so lines like this. These are in alphabetical
order and a certain amount of effort has been made that they can be
included in any order. */
/* Then about 2000 lines of struct, enums, function definitions etc. */
字符串
我的任务是移动2000行中的大部分或全部,为它们创建新的.h文件,或者将它们粘贴到现有的.h文件中。一个规则是每个标头必须能够独立于所有其他标头被包括。换句话说,每个标头必须不需要在其之前包括其他标头。经过一番努力,我很快意识到,即使作为一个有25年以上经验的高级软件工程师,这也不是一件容易的事情,因为结构定义的复杂性和层次性。
我的问题尤其是:
1.将所有这些头文件都包含在project_common. h中是不好的做法,而且也没有必要将其全部拆分。
1.很难将所有这些拆分成这样一种方式,即结果头可以以任何组合包含在给定的C文件中。
所以我想问的是,有没有什么工具可以帮助将所有.h文件重构为更优化的配置,和/或有没有一种公认的方法比试错法更好?
到目前为止,我已经尝试过移动结构体定义,但是进展非常缓慢和乏味,尽管我已经将project_common. h的大小减少了近一半,但我创建的新头文件只有在它们以正确的顺序包含时才能工作。
1条答案
按热度按时间7y4bm7vi1#
我的任务是移动2000行中的大部分或全部,为它们创建新的.h文件,或者将它们粘贴到现有的.h文件中。
我不知道重构工具是什么,但作为一个突出的代码风格问题,我认为每个头文件和常规源文件X本身都应该
#include
每个其他直接声明X定义或直接引用的任何函数或变量的头文件,以及每个定义X直接使用的宏的头文件,并且仅这些。这适用于#include
的系统和第三方头文件,就像适用于项目的内部头文件一样。您可能已经在这个方向上走了很长的路,以支持可以单独
#include
任何头部的目标。然而,很明显,当你说你不能完全坚持这一原则时,你不能完全坚持这一原则。我创建的新头文件只有在它们以正确的顺序包含时才能工作。
如果每个header
#include
都为所有其他header提供了它自己需要的声明,并且还提供了有效的保护措施来防止多重包含,那么出现#include
顺序问题的唯一方法就是存在依赖循环。如果在开始重构时还没有一个循环,那么就没有什么特别的理由来说明为什么重构应该产生一个。如果你的重构确实产生了一个头,那么这意味着在那个循环中头的部分或全部内容应该合并到同一个头中。此外,这可能是显而易见的,在选择将现有声明移动到哪里时,我建议将重点放在语义关系上,而不是简单的代码依赖关系上。通常一起使用的东西可能会选择在同一个头中共存,但不会有太多的东西碰巧在一些相同的依赖链中。
我想有可能当你说...
一个规则是每个标头必须能够独立于所有其他标头被包括。
...你的意思不仅仅是人们可以挑选和选择标题来包含而不考虑顺序和依赖关系,而且 * 还 * 不允许任何标题包含任何其他标题。如果是这样,那么这是一个人为的和难以维持的规定。它意味着,例如,无论你有一个结构或联合类型,它嵌入(而不仅仅是指向)项目的其他内部类型之一的对象,这两个类型必须在同一个头中声明。如果你碰巧被这样的事情所困扰,那么你现在的任务就为你提供了一个很好的背景来对抗它。
最后,作为一个实际问题,我会从文件的顶部开始,然后从那里向下工作。通过这种方式,您将首先处理具有最少依赖项的声明。您甚至可能会发现将其视为一系列小的重构而不是一个巨大的重构是有用的。