C++ 代码整洁之道

这篇具有很好参考价值的文章主要介绍了C++ 代码整洁之道。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

NOTICE: 这篇文章的框架条目来自《C++代码整洁之道:C++17可持续软件开发模式实践》,作者: [德] 斯提芬·罗特。书籍原名"Clean C++: Sustainable Software Development Patterns and Best Practices with C++ 17"。

NOTICE:未经作者允许禁止转载!

1. 编码基本原则

保持简单和直接原则(KISS)

Keep It Simple and Stupid.尽可能地采取简短、明了和直观的设计或编码方案,以避免过度工程化和不必要的复杂性。

不需要原则(YAGNI)

You Aren’t Gonna Need It. 这个原则的核心观点是:不要浪费时间在你可能永远不需要的特性上。在确定真的有必要的时候再写代码,那时再重构也来得及。

避免重复原则(DRY)

Don’t Repeat Yourself。应该尽量避免重复代码和冗余数据的出现,而应该采用抽象化、封装和代码重用等方式来避免重复。
遵循DRY原则可以带来以下几个好处:

a. 提高代码的可维护性、可读性和可重用性:通过避免重复代码和数据,可以使代码更具有模块化和可重用性,从而降低开发和维护成本,并且使代码更易于理解和修改。
b. 减少潜在的错误:重复代码很容易导致错误和不一致性,因为如果需要更新某个行为或者修复一个问题,需改的地方就会增加,这样可能会导致不必要的错误。
c. 优化性能:使用代码重用技术可以避免不必要的计算,因为不需要执行重复的代码,可以提高程序的性能。

为了遵循DRY原则,开发人员应该注意以下几点:

a. 提取共同的行为:在编写代码时,应该寻找可以被多次使用的代码块,并将它们提取出来作为公共函数或类库。
b. 采用抽象化和封装:通过对代码进行抽象化和封装,可以降低代码耦合性,并且可以避免重复代码的出现。
c. 避免分散数据:在编写代码时,应该避免将同一数据保存在多个地方,尽可能地将所有相关的数据都保存在一个地方,这样可以避免数据的不一致性。

信息隐藏原则

一段代码调用了另外一段代码,那么调用者不应该知道被调用者的内部实现。

a. 封装实现细节:每个组件应该将自己的实现细节尽可能地封装起来,以减少对外暴露的内容。这样可以有效地控制系统的复杂度,并降低修改组件时的风险。
b. 限制接口暴露:每个组件应该仅向外部暴露必要的接口,并尽可能地减少对外暴露的内容。这不仅可以提高组件间的独立性,还可以使系统更加灵活、可重用和易于维护。

高内聚原则

高内聚原则是指一个模块或类应该尽可能地将自己的功能和数据集中在一起,形成一个独立的单元,并且各个单元之间应该相互独立。高内聚的目的是将一个大模块分解为更小、更容易理解和维护的部分。

松耦合原则

不同的模块或组件之间应该尽量减少相互依赖。松耦合原则包括以下几个关键点:

a.接口稳定:模块之间的通信应该通过稳定的接口进行,接口的设计应该简单、清晰,并且能够满足各种场景的需求。
b. 最小依赖:每个模块或组件应该尽可能地减少对其他模块或组件的依赖,只与必要的组件进行交互,避免与其他模块或组件之间建立过多的耦合关系。
c. 松散耦合:各个模块或组件之间应该尽可能松散地耦合,也就是说它们之间的关系是可插拔、可替换的。这样可以方便地对系统进行扩展或改进,同时也更容易理解和维护。

小心优化原则

小步优化。

最少惊讶原则

保持一致性:在设计软件时,应该尽可能地保持一致的设计风格和交互方式,确保用户可以更容易地理解和使用软件。
满足用户期望:设计的功能和操作应该满足用户的习惯和预期,不应该出现让用户感到惊讶或困惑的行为。
明确反馈:当用户执行操作时,软件应该给予明确的反馈,确保用户可以得知操作的结果和状态。

童子军原则

当发现代码中有需要改进的或者风格不好的代码,应该立刻修改,不管是谁写的代码。

2. C++代码整洁的基本规范

2.1 良好的命名

源代码文件名、命名空间、类、函数、模板、参数、变量、常量等等等等,都应该具有有意义且比较有表现力的名字。

名称应该自注释

  • bad examples
int num;
bool flag;
std::vector<Customer> list;
Product data;
  • good examples
unsigned int number_of_customer;
bool is_changed;
std::vector<Customer> customers;
Product ordered_product;

自注释的命名也不应该过长,如果变量的上下文很清楚,只需要要简短的描述性名称。

避免冗余的名称

  • bad example
class Customer
{
// somde code
private:
    std::string customer_name_;
};

在Customer类中已经有足够的信息能够知道name表示customer的名字了,不必要重复,重复的话违背了"Don’t Repeat Yourself "原则.

std::string string_customer_name;

不要在变量中包含变量类型。

不要用匈牙利命名法

不要在变量前面带类型前缀,在变量里面带上类型前缀,当你更改类型后还需要更改变量名,忘记改还会误导读者,匈牙利命名法在上个世纪没有强大的IDE时可能有用,但是现在提示变量类型的功能在IDE中已经非常普遍。
另外模板类怎么可能提前指定变量类型。

避免晦涩的缩写

Car ctw;	// bad
Car car_to_wash;	// good

Polygon ply1;	// bad
Polygon first_polygon;	// good

const double GOE = 9.80665;	// bad
const double gravitation_acceleration_on_earth = 9.80665; // good

2.2 注释

不要为易懂的代码写注释

customer_index++;
Customer* customer = GetCustomerByIndex(customer_index);
CustomerAccount * account = customer->GetAccount();

像这样的代码完全不需要写注释,不要低估代码阅读者的智商。

不要用注释禁用代码

在代码里面不再需要的代码应该直接删除,有的想用注释的方式把一段代码注释掉,以防后面可能会用到,但是这种情况更应该做的的把代码放入代码版本管理工具中,如果有需要去版本工具中回溯。临时注释某些代码来debug是允许的,但是改完bug后应该删除。

特殊情况的注释

对于某些代码的特殊情况添加注释是很有用的。

2.3 函数

只做一件事

函数应该做一件事。做好这件事。只做这一件事

让函数尽可能小

函数短小的好处:

提高代码可维护性和可读性
提高代码的可复用性
方便调试和测试

如果以行数来计,一般不要超过15行,clean code 中说函数的第一要义是要短小,第二要义是要更短小,20行封顶最佳。

函数命名

函数的命名应该具有表达力和准确性,能够清楚地描述函数的功能和作用。使用动词或动词短语作为函数名,以描述函数执行的操作和结果。例如,getMax、setCount 等。

函数的参数和返回值

函数的参数应该尽可能少,最好没有参数,其次是一个参数,一般不要多于三个输入参数。需要返回的参数直接通过返回值返回。有些人可能会考虑在函数返回时会有临时对象的创建复制等过程,导致程序效率不足,但是现代C++体系发展了move语义,在返回的时候大多数情况下是直接move而不是创建临时对象再赋值,move语义的出现已经很大程度的改变了这种变成模式。

2.4 替换C++中的C风格代码

用string代替char*

string是C++中一个重要的组件,在用到字符串的时候首选string而不要使用c风格的char*。

使用标准容器而不是C风格的数组

C++提供很多标准容器,尽量使用标准容器而不要使用数组。最常用的例如使用vector替代c风格的数组。

使用C++的类型转换代替C的强制类型转换

C++ 中用static_cast(),来做强制类型转换。

float a = 1.0;
int b = (int)a; // c风格的强制类型转换,不推荐
int c = static_cast<int>(a); // C++ 风格的强制类型转换,推荐使用

避免使用宏

宏不利于调试:宏定义是在预处理阶段进行文本替换的,如果使用过多的宏定义,会使代码变得杂乱无章,不易于调试。
宏容易引起错误:宏定义中没有类型检查和作用域限制,这就容易导致一些错误的定义或使用。
宏不易于维护:宏定义的可读性较差,理解复杂的宏定义需要花费较大精力,也不易于修改和维护。

如果是定义常量,可以用 constexpr 来修饰。使用 constexpr 关键字可以优化代码性能,因为编译器可以在编译时将常量表达式计算出来,而无需运行时计算,从而避免了运行时开销。

#define PI 3.141592653 // 不推荐
constexpr long long PI = 3.141592653; //推荐

用一般函数替换宏函数。

2.5 资源管理

智能指针

智能指针是一种 RAII(资源获取即初始化)技术的应用,它自动管理对象的生命周期,解决了动态内存分配和回收的问题。C++11 提供了三种智能指针:std::unique_ptr、std::shared_ptr 和 std::weak_ptr(不推荐使用)。

std::unique_ptr:是一个独占式所有权的智能指针,保证同一时间只有一个指针可以访问其所指向的对象。当 unique_ptr 被销毁时,它所指向的对象也会被销毁。

std::shared_ptr:是一个共享所有权的智能指针,可被多个指针同时访问其所指向的对象,在最后一个 shared_ptr 被销毁时才会销毁所指向的对象。

避免显示的使用new和delete

make_unique 和 make_shared 是 C++11 引入的两个模板函数,用于创建智能指针的对象。它们都遵循 RAII 技术的原则,即对象的生命周期与智能指针的生命周期绑定在一起,从而有效避免了内存泄漏、重复释放等问题。
示例:

auto p = std::make_unique<int>(42);
auto p2 = std::make_shared<int>(42);

3. 面向对象

类的设计原则

让类尽可能的小

像函数一样小的类容易测试,容易理解,容易测试,容易复用。

单一职责原则

一个类应该只有一个单一的职责。

开闭原则

类应该对扩展开放,对修改关闭。

里氏替换原则(LSP)

子类对象应该能够替换掉程序中任何父类对象,并且保证不会产生任何负面影响。也就是说,子类继承父类时不能改变父类已有的行为,而是应该遵循父类的约束。

接口隔离原则(ISP)

“客户端不应该依赖于它不需要的接口”,也就是说,一个类不应该被强迫依赖它不使用的方法。简单来说,一个类对另一个类的依赖性,应该建立在最小化的接口上。

接口隔离原则可以减少系统的耦合度,提高系统的内聚性,从而增加系统的可维护性和可扩展性。

无环依赖原则

依赖倒置原则(DIP)

高层模块不应该依赖于低层模块的实现细节,而是应该依赖于抽象。同时,抽象不应该依赖于具体实现,而具体实现应该依赖于抽象。

不要和陌生人说话(迪米特法则)(LoD)

迪米特法则也被称为最少知道原则(LKP)。一个模块应该对外部模块产生最少依赖关系,即每个模块只应该关注与其密切相关的对象。迪米特法则的目的是为了减少系统中的耦合度,提高系统的可维护性、可扩展性和可测试性。

避免类的静态成员

4. 设计模式和习惯用法

依赖注入模式

Dependency Injection
将组件与其需要的服务分离,这样组件就不必知道这些服务的名称,也不必知道如何获取它们。
例如:日志记录器
C++ 代码整洁之道
常见的注入方式有构造器注入和setter注入。

Adapter模式

把一个类的接口转为期望的另一个接口,让接口不兼容的类可以适配

Strategy模式

定义一组算法,然后封装每个算法,使它们可以相互替换,策略模式允许算法独立于使用它的客户端而变化。
例如:在需要排序的地方定义许多排序算法,快排,堆排,冒泡,希尔排序等等的,在用的时候可以选择。或者在格式化输出的地方,用纯文本、xml、json格式输出文本。

Command模式

常用在client/server架构中

Command处理器模式

Composite模式

将对象组合成树结构来表示“部分-整体”的层次结构。

Observer模式

Factory模式

Strategy模式

Facade模式

Money Class模式

特例用法

参考

[1] https://www.clean-cpp.com/contact/
[2] 《Clean Code》Robert C. Martin
[3] 《C++代码整洁之道:C++17可持续软件开发模式实践》
[4] https://en.cppreference.com
[5] https://refactoringguru.cn/design-patterns/catalog
[6] https://google.github.io/styleguide/文章来源地址https://www.toymoban.com/news/detail-461287.html

到了这里,关于C++ 代码整洁之道的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《架构整洁之道》学习笔记 Part 2 编程范式

    计算机编程发展至今,一共只有三个编程范式: 结构化编程 面向对象编程 函数式编程 结构化编程是各个模块的算法实现基础 多态(面向对象编程)是跨越架构边界的手段 函数式编程是规范和限制数据存放位置与访问权限的手段 软件架构的三大关注重点 : 功能性 、 组建

    2024年02月16日
    浏览(41)
  • Linux C++性能优化秘籍:从编译器到代码,探究高性能C++程序的实现之道

    随着大数据、人工智能等技术的飞速发展,程序性能优化的重要性愈发突出。优化性能可以降低资源消耗、提高系统响应速度,从而在有限的硬件资源下,实现更高的吞吐量和处理能力。此外,性能优化也有助于降低能耗、减少散热问题,延长硬件使用寿命。 Linux操作系统具

    2023年04月09日
    浏览(51)
  • 5分钟说清楚如何让代码更加整洁

    读了两本技术相关的书籍:编程大师Bob大叔的《代码整洁之道》和《代码整洁之道:程序员的职业素养》。 《代码整洁之道》出版于2010年,其内容主要是偏向于技术的\\\"技\\\"。全书都在说一些如何让代码更加整洁的方法和规则。 《代码整洁之道:程序员的职业素养》出版于201

    2024年01月20日
    浏览(32)
  • 关于SpringBoot框架,看这篇就够了。

    目录 是什么 有什么优点、解决了哪些问题 创建第一个以springboot项目 starter 核心配置文件application.yml或properties application中的配置项 springboot的启动流程 自定义banner 整合日志打印 整合druid数据源 处理异常 常用的注解 Configuration Import conditional ConfigruationProperties 基于springboot的

    2024年02月06日
    浏览(50)
  • 【C语言进阶篇】看完这篇结构体文章,我向数据结构又进了一大步!(结构体进阶详解)

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 :《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活!    🌈 hello! 各位宝子们大家好啊,结构体的基本使用和常见错误在上一篇详细讲解过了,不知道大家都学会了没有。    ⛳️ 今天给大家来个硬菜,教点高

    2024年02月15日
    浏览(48)
  • HTTP 框架修炼之道 | 青训营

    Powered by: NEFU AB-IN 走进 HTTP 协议 HTTP 框架的设计与实现 性能修炼之道与企业实践 前后端通过http通信,负责对http请求解析,根据路由选择对应逻辑 超文本 通常包括文本、图像、音频、视频等多种媒体类型,这些内容通过链接与其他相关信息相互连接。最著名的超文本系统之

    2024年02月11日
    浏览(32)
  • C++ 之 一些优质的开源框架和项目代码

    Awesome C++ 一些优质的开源框架和项目代码,学习优秀程序员的代码风格与编程能力

    2024年02月07日
    浏览(38)
  • 【C++系列P1】带上这篇基础小宝典,进发C++!(持续更新ing~)

    前言 大家好吖,欢迎来到 YY 滴 C++系列 ,热烈欢迎! (持续更新ing~) 本章主要内容面向刚刚学完C语言,准备或正在接触C++的老铁。而往往C++奇多的小特性和知识点让铁铁们头晕晕脑涨涨,因而本章收纳了许多C++中零散的知识点,相信这篇基础章会帮助铁铁们更好地入门!主

    2024年02月07日
    浏览(38)
  • idea自动生成代码--看这篇就够了

    目录 1、idea安装插件 2、连接数据库  3、生成代码 打开idea设置,查找mybatisX插件 1. 打开idea右侧database 2. 创建数据库连接 点击database后,弹出database框,点击左上角的“+”号  3. 填写数据库连接信息  填写自定义名称、数据库连接地址、端口号、用户名、密码。第一次配置时

    2024年02月12日
    浏览(50)
  • 【C++】五一假期,我学会了C++类和对象 ( 看完这篇你也能学会 ~ )

      🧑‍🎓 个人主页:简 料   🏆 所属专栏:C++   🏆 个人社区:越努力越幸运社区   🏆 简       介: 简料简料,简单有料~在校大学生一枚,专注C/C++/GO的干货分享,立志成为您的好帮手 ~ C/C++学习路线 (点击解锁) ❤️ C语言 ❤️ 初阶数据结构与算法 ❤️ C++ ❤️

    2024年02月03日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包