C++项目惯例
这里没有标新立异,对于老项目务必做到和历史代码风格统一,对于新项目做到和团队风格统一,对于没有明确要求或个人的项目做到前后风格一致。
我的风格
这里推荐一个Google 开源项目风格指南,比较全面;至少微软的指南我没找到有这个全面的。
这里不介绍具体规则,简要提一下整个项目可以考虑遵循的一些建议:
-
对于一万行(非精确)以内的可执行程序项目,使用命名空间与否、拆分为
include
和src
文件夹与否不重要,这种规模的软件这样做不会带来更大收益,反而会增加复杂性。但是当代码数量超过这个量级,尽量这样做以确保持续增长的代码不会导致冲突。
注意,需要提前预估项目代码是否会维持在一万行以内,如果有可能超出,则最好提前做好管理,否则修改等于重构。
-
对于所有的库项目,使用命名空间、拆分为
include
和src
文件夹进行管理。你需要考虑库被大型项目使用所可能造成的命名冲突问题;同时为了方便其他项目源码形式引入库,需要将对外提供的接口头文件放入
include
文件夹,无关头文件不可放入该文件夹,避免暴露细节被误用。
补充
以上内容均为建议,在可以执行的时候推荐执行,否则如开头所说优先遵循现有风格。
正如谷歌风格指南所说:
我们认为风格指南当前的目标如下:
风格规则应该有影响力
一条风格规则应该具备足够大的好处, 以至于值得所有工程师铭记. 所谓好处是相对于当前代码库的状态而言的, 所以即使某一习惯十分恶劣, 如果人们很少使用, 那么禁止这一习惯的好处依然很小. 这样可以解释为什么我们没有写下某些规则. 例如, goto 语句违背了许多原则, 但是现在已经很少出现, 所以风格指南不会讨论它. 为读者优化, 而非为作者优化 我们的代码库 (以及其中的每个组件) 应该会存在很长时间. 因此, 我们读代码的时间比写代码的时间更长. 我们明确地选择优化平均水平的软件工程师阅读、维护和调试代码的体验, 而非编写代码的舒适度. “为读者留下线索” 是这一理念的一个方面. 如果代码中有特殊的情况 (例如指针所有权转移), 在此处给读者留下的文字提示很有价值 (在代码中使用 std::unique_ptr 就明确地表达了所有权转移).
和现有代码保持一致
我们让代码库的风格保持整体一致, 就能聚焦在其他 (更有价值的) 问题上. 一致性也会帮助自动化: 那些格式化代码或者调整 #include 顺序的工具, 只能在你的代码符合预期时才能正常工作. 很多时候, 那些用于 “保持一致” 的规则本质上就是 “任选其一并停止内耗”; 在这些问题上, 争论的成本超过了提供自由度的价值. 不过, 一致性原则也有局限性. 在没有清晰的技术性论据和长远方向时, 这才是很好的打破平局的方式. 这一原则适合局部使用 (一个文件内, 或者一组关联性强的接口). 不应该为了一致性而采用旧风格, 忽视新风格的好处. 应该考虑到代码库会随时间推移而过渡到新风格.
恰当时与广大 C++ 社区保持一致
与其他组织保持一致性是有价值的, 这和我们保持内部一致性的原因一样. 如果 C++ 标准中的特性解决了某个问题, 或者某一范式被广泛采用, 这就是采纳它们的依据. 不过, 有时标准的特性和范式有缺陷, 或者在设计上没有考虑我们代码库的需求. 此时 (正如下文所描述的) 应该限制或者禁止这些标准特性. 有时, 相较于 C++ 标准库, 我们偏向于自研库或某些第三方库. 一般这是因为我们所选择的库具有优越性, 或者迁移到标准库的价值不值得那些工作量.
避免使用奇特或危险的语法结构
有些 C++ 的特性比表面上更加奇特或危险. 风格指南中的一些限制就是为了防止掉入这些陷阱. 你需要达到很高的标准才能豁免这些限制, 因为忽略这些规则就很可能直接引起程序错误.
避免使用那些正常水平的 C++ 程序员认为棘手或难以维护的语法结构
有些 C++ 特性会给代码带来复杂性, 因此通常不适合使用. 在用途广泛的代码中, 我们可以接受更巧妙的语法结构. 这是因为复杂的实现方式所带来的收益会被众多使用者放大, 而且在编写新代码时, 也不需要重新解读这些复杂的语法. 如有疑问, 可以请求项目主管豁免这些规则. 这对我们的代码库至关重要, 因为代码负责人和团队成员会变化: 即使所有现在修改这段代码的人都理解代码, 几年后人们就不一定还能理解了.
需要注意我们的规模
我们有上亿行代码和成千上万的工程师, 因此一位工程师的失误或者投机取巧的行为会成为很多人的负担. 举例来说, 一定要避免污染全局命名空间 (global namespace): 如果所有人都往全局命名空间里塞东西, 就很难避免上亿行代码之间的符号冲突 (name collision), 也难以修复冲突.
在必要时为优化让路
即使性能优化的手段会和此文档的其他理念冲突, 有时这些手段也是必要且恰当的.
此文档的目的是提供最大程度的指导和合理限制. 和往常一样, 你应该追随常理和正常审美. 这里我们特指整个谷歌 C++ 社区所建立的规范, 而不是你个人或者所在团队的偏好. 应该对巧妙或奇特的语法结构保持怀疑和犹豫的态度: 并不是 “法无禁止即可为”. 运用你的判断力. 如有疑惑, 请不要犹豫, 随时向项目主管咨询意见.