首页 > 酒店新闻 > 公司新闻

AG 真人百家乐试玩平台|Effective Refactoring in C++ (三)

发布时间:2025-10-15 18:02:45    次浏览

王博/通信系统资深架构专家主要关注大型电信级系统软件的设计、开发、重构、自动化测试等领域。曾经主持、或参与过多项大型电信无线通讯设备核心软件的架构设计与重构工作,对于如何使用C++进行大型电信领域嵌入式系统软件的领域建模、演进式设计、重构及自动化测试有很多丰富的实战经验和独到的见解。◆◆◆王博老师作为“2016 C++及系统软件技术大会”的讲师之一,将在10月底和C++之父Bjarne Stroustrup、前Facebook研究科学家Andrei Alexandrescu、ISO C++标准委员会资深权威Mike Spertus等40多位国内外大咖一起做出精彩分享。【文末彩蛋】C++大会完整PPT资料、及更多大咖直播在本文最末领取~高效重构当我们熟练掌握了重构技术后,还不能就此说自己在实践中已经可以安全而高效地实施重构了!因为落到真正的工程实践环境,安全和高效的重构过程还需要好用的IDE工具,成熟的自动化测试套件,快速高效的开发构建环境,以及良好的编码习惯来支撑。本节针对C++语言,总结了一些对实施重构非常有用的工程实践经验。当然其中决大部分也适用于C语言开发。语言相关由于C++的复杂性,导致业界对C++的自动化重构工具支持一直非常不理想。很多重构到目前为止只能手工进行。重构工具对语言的支持的一个难点在于对代码引用点的分析查找。C++中有很多语法会干扰到这一分析,导致难以进行自动化重构。具体会让重构难以进行的语法包含以下: 宏 指针 函数重载 操作符重载 默认参数 类型强转 隐式转换 友元 模板 还有一些不合理的编码规范,也会阻碍到重构的进行,例如 匈牙利命名 函数单一出口 大而全的common头文件 ... 上述语法或者规范不仅会让自动化重构难以进行,也会干扰到手动重构。对于不好的编码规范要及时摒弃!对于会妨碍重构的语言元素要慎重使用,最好保持其影响在一定范围内,缩小重构时查找引用不确定性的范围。当然C++语言中也有一些语法非常有利于重构,例如: const 访问限制修饰符private,protected 匿名namespace 局部变量延迟定义 这些语言元素有些会让代码语义更明确,有些会限制代码元素的可见度,缩小引用查找范围。对于这些语言元素在开发中尽可能多的去使用,可以让重构变得更加容易。最后,保持好的编码习惯,例如一开始就不要将文件/类/函数搞得过大,尽可能多的对外隐藏细节,对复杂语法的使用保持慎重态度,这样每次重构的成本都会小很多。自动化测试由于重构依赖的测试需要快速高效,所以我们往往选择xUnit测试套件,可以对软件进行小模块级别的黑盒测试或者单元测试。目前针对C++,可供选择的xUnit套件有gtest, Testngpp, CppUnit, CXXTest以及Boost Test等。目前最多人使用的应该是gtest,由于使用广泛所以非常成熟,支持跨平台,方便简单容易上手,提供了丰富的断言机制和成熟的用例管理。当然gtest也有其问题,主要是测试注册机制不够优雅导致限制过多,测试用例运行期不能隔离导致互相影响,测试工程的组织不能模块化导致单元测试不能显示化物理依赖,无法低成本完成测试依赖文件的物理替换。经过个人使用,目前功能最强大的C++测试套件应当是Testngpp,它也支持跨平台,测试注册依靠脚本扫描所以限制很少,另外和gtest一样断言丰富,用例管理成熟。它最大的强大之处是支持沙盒模式,测试用例运行期间互相隔离,不会彼此影响。另外,Testngpp支持模块化管理测试工程,对于单元测试可以显示化物理依赖。同时模块化内可以方便的进行测试依赖文件的物理替换,这一特性对于没有虚接口情况下的mock非常实用。但是由于Testngpp的强大,也导致了它某些情况下不如gtest方便使用。在使用xUnit的同时再能结合一款合适的Mock框架,可以大大降低单元测试的成本。对于C++目前最好用Mock框架是Mockcpp,没有之一!用gmock的同学尽快转过来:)!由于Mock经常容易被滥用,导致过多的针对行为进行验证。而且往往对于测试直接打桩进行状态验证成本并不高,所以目前来说我已经很少使用Mock工具了。但是留着它在适合的时候偶尔使用一下也是不错的。最后,我们都知道重构需要自动化测试的支持!但是并不是没有自动化测试,重构就不能开展!有些历史遗留代码,一开始很难加进去测试,必须要先着手修改,才能逐渐添加测试。这时起步需要的就是对安全小步的重构手法的熟练掌握,以及利用原有手工测试进行安全保证。当对软件进行修改从而可以添加自动化测试后,重构慢慢就上轨道了。IDE为了提高重构效率,我们需要一款智能的IDE。它需要支持基本的自动化重构,能够高效准确的搜索到代码的引用点,支持良好的面向对象风格代码浏览,高效流畅地快捷键...本人使用过的一些不错的C++ IDE有: Visual studio C++ 自身的重构工具并不完善,但是加上番茄小助手就很不错了。支持自动重命名,自动提取函数,重命名类还会自动把类的头文件和所有的#include点的文件名都做一修改。最大的缺点是不能跨平台,而且耗费机器资源较多。最新发布的Visual studio 2015据说已经内置了很多重构功能,不过还没有试过。 clion Jetbrains公司出品的跨平台C/C++IDE,号称要做最强大的C++ IDE。目前是收费的,免费的只能试用30天。工程构建只支持CMake,另外只能在64位机器上使用。 Clion内置的自动化重构菜单是最强大(支持rename, inline, extract, Pull member up/down ...)。目前发布了1.0版本,用户还不是特别多,可以持续关注。 eclipse-cdt 个人目前使用最多的C++ IDE。最大的好处是支持跨平台。用eclipse在类的继承引用关系之间跳转非常流畅。支持简单的重命名,提炼函数,提炼常量等自动化重构。从luna版本开始,支持重命名文件或者移动文件的时候,会自动替换所有#include中的路径名。个人目前最满意的C++ IDE。 对于静态类型语言,好的IDE可以在很多地方帮助开发者提高效率。如果你还在使用Source Insight或者其它高级文本编辑器来进行大规模C++代码开发,我建议你试试上面推荐的IDE,总有一款适合你,保证你一旦使用就会离不开它! 如果你还有其它更好的,也请拿出来分享给大家!物理重构物理设计对C/C++程序来说非常重要! 好的物理设计不仅可以减少物理依赖,还会有利于软件的构建和发布,并且还会方便理解和查找代码元素。所以C/C++程序员除了一般的代码元素级别的重构,还需要经常进行物理级别的重构,包括:文件重命名、文件提炼、文件移动,或者目录结构调整等等。对于C/C++来说,物理重构比较繁琐的地方在于经常需要同步修改makefile,或者头文件的#include引用点。以下是一些和物理重构相关的经验技巧(make相关的见下节): 每个文件只包含一个类,并且文件名和类名相同。这样方便重命名类的时候IDE自动对文件进行重命名。 利用IDE提供的自动化重命名,或者移动菜单进行文件/目录的重命名或者移动,以便IDE可以对涉及文件的所有#include引用点进行路径自动替换。 使用IDE提供的自动化头文件添加功能来添加物理依赖,例如在eclipse中是ctrl+shift+n。 配置IDE的头文件模板,让自动生成头文件的Include Guard使用Unique Identifier,避免每次头文件重命名后还得要修改Include Guard(见下)。 (最新的eclipse mars版本中在Windows - Preferences - C/C++ - Code Style - Name Style - Code - Include Guard 中选择 Unique Identifier,较老版本需要在workspace中修改配置文件,可以自行google修改办法。) 编译构建不好的编译构建工程不仅干扰到物理重构,更重要的可能导致编译效率底下从而让重构无法正常开展。没人愿意在每次构建都要几十分钟到数小时的工程上进行频繁重构。大型C/C++工程要对其编译构建过程进行持续地分析优化,不断提高版本的编译构建速度。另一方面,工程需要支持增量编译,以及可以对任意一个指定的子模块或者文件单独进行编译。关于编译构建的一些实践经验如下: makefile中尽可能使用模式规则,自动搜索文件,不要显示使用源文件名,否则每次重命名文件后都得要修改makefile。 makefile中为预编译目标文件设置规则,不仅有利于解决一些宏展开的问题,更重要的可以快速解决一些头文件包含上的编译难题。 makefile采用自底向上组织,保证每个源代码文件单独可编译,每个模块单独可编译。最终产品版本的构建,调用每个模块的makefile生成编译中间产物后进行链接。不要采用自顶向下传递make参数的makefile工程管理模式,否则每次编译任何一个文件或者模块都要全编译所有代码。 尽可能使用并行编译。在Visual Studio下可以使用IncrediBuild分布式编译工具,对于make使用-j选项,并且可以使用distcc来进行分布式编译。另外,可以使用ccache来做缓存加速编译。 将测试工程的编译构建和真实产品版本的构建分离,测试工程的编译构建可以采用更好的工具:例如cmake,rake等。 保证增量编译可用,并且是可靠的。 很多项目虽然有增量编译,但是都不够可靠,尤其是当有头文件删除的时候!另外每次无论是否有依赖变化,makefile都要重新生成加载.d文件,效率也很低下。所以大多数时候增量编译功能是关闭的!《GNU Make项目管理》一书中提供了很多大型工程中make组织的优秀实践,其中有一段对增量编译可靠高效的makefile片段,我将其提炼成了一段make函数,见下面~大家可以使用。 总结我过去几年的工作主要在大型电信系统的软件重构, 这篇文章基本上是自己工作实践的一些心得,包括对《重构》一书的一些精炼和总结。当然关于重构最精华的部分还是在原书的每一处细节中。励志学好重构的同学对于《重构》一书最好能够反复阅读实践。对于再大型的软件重构,无论你的目标架构多么漂亮,最终还必须是一行一行的代码修改。如何安全可靠并且高效地修改代码,必然是落地的基本技能!对于日常开发也是如此, 保持代码符合简单设计是一项日常行为,重构是达成它的唯一方式。对重构的使用应该融入到代码开发的每时每刻,到最后不必强行区分是在开发还是重构,就像《重构》的序言中所说“变得像空气和水一样普通”。希望每个学习重构的同学都能体会到这种感觉。千里之行,始于足下!2016 C++及系统软件技术大会将于2016年10月28日-29日,在上海盛大举行。圈内元祖级大咖都来了——C++之父 / Bjarne Stroustrup前Facebook研究科学家 / Andrei AlexandrescuISO C++标准委员会资深权威 / Mike Spertus《大话西游》《梦幻西游》主要开发者 / 云风两岸著名C++专家 / 侯捷......(共40多位重量级嘉宾)C++谜弟表示要原地炸裂了!戳“阅读原文”即可报名参加【撒福利啦】扫上方二维码关注大会公众号,并回复“C++大会PPT”,即可免费领取大会完整PPT资料!还可进群参加C++系列大咖直播~