一、高质量代码
1、什么是软件?什么又是程序?区别与联系。
(1)软件=程序+文档=数据结构+算法+文档
(2)软件是包含程序的有机集合体,程序是软件的必要元素。任何软件都有可运行的程序,至少一个。比如:操作系统给的工具软件,很多都只有一个可运行程序。而Office是一个办公软件包,却包含了很多可运行程序,软件是程序以及开发、使用和维护所需要的所有文档的总称,而程序是软件的一部分。
2、高质量代码的标准
(1)简洁(2)可维护(3)可靠(4)可测试(5)高效(6)移植
3、几个原则
(1)设计。良好的设计
(2)编码。DRY原则、童子军规则、Clean Code
(3)过程。细心、不赶进度、缺陷预防、持续的重构
良好的设计:简单的设计,模块内部高内聚,模块间低耦合,以空调为例子理解这个设计模式。
编码原则:
单一原则,我们的设计不能像瑞士军刀一样,各种功能集成到一起。
开放封闭原则,用空调接电压不同国家的电压值不一样,空调内部电源不一样,但是只预留给外部一个插头。
接口隔离原则,理解空调的插头和内部隔离出来,抽象
依赖倒置原则。
DRY原则,Don’t Repeat Yourself,我们需要的不是 拷贝+粘贴,我们需要在此后加上重构即拷贝+粘贴+重构使我们的原则。
童子军原则,理解破窗理论,Leave the code cleaner than you found it.
Clean Code,从三个方面来命名,函数,注释。函数有几个指标得注意,圈复杂度和嵌套层数,注释注意准守WHY原则,not HOW or WHAT
4、优秀代码的八个特征
(1)命名精确表达功能含义
(2)函数的圈复杂度
(3)嵌套层数
(4)有效的注释比例
(5)函数有效代码行数
(6)函数的参数个数
(7)函数的局部变量个数
(8)非结构化语句的数量
5、代码的坏味道
(1)重复代码
(2)大函数
(3)过多的函数参数
(4)数据泥团
(5)长switch语句
(6)过度耦合
(7)复杂表达式
(8)过多的函数调用层次
6、解决办法:重构
(1)“软件可察行为”
(2)“3.0版本” 效应
(3)核心思想:测试保证,小步前进,立即测试
(4)重构的手法:
可以直接降低圈复杂度的9种重构技术(针对结构化编程):
Composing Methods(重新组织你的函数)
Extract Method(提炼函数)
Substitute Algorithm(替换你的算法)
Simplifying Conditional Expressions(简化条件表达式)
Decompose Conditional(分解条件式)
Consolidate Conditional Expression(合并条件式)
Consolidate Duplicate Conditional Fragments(合并重复的条件片断)
Remove Control Flag(移除控制标记)
Making Method Calls Simpler(简化函数调用)
Separate Query from Modifier(将查询函数和修改函数分离)
Parameterize Method(令函数携带参数)
Replace Parameter with Explicit Methods(以明确函数取代参数)
— Refactoring: Improving the Design of Existing Code
针对面向对象编程:
Replace Conditional with Polymorphism(以多态取代条件式)
二、优化代码性能
1、优化代码三个层次:系统层次,算法层次,代码层次
2、优化代码-代码层次进行优化
(1)以空间换性能。例子:CRC32(x)=x^32+x^26+x^23+…+x^1+1,先计算好放到内存中,后续只需要访问内存,最常用的方法是进行查表法则
(2)使用模板赋值
(3)减少压栈成本。函数->宏/内联
(4)改变判断顺序、if…else if…else将前后顺序按照概率的大小进行排序
(5)改进遍历查表,使用一些优秀的查找算法进行优化
3、优化改进点(要找好优化的热点,进行有的放矢的优化)
(1)循环体内工作量最小化
(2)避免重复运算
(3)避免不必要的内存拷贝
(4)使用指针传递函数的入口参数
(5)把最有可能性的判断放在最前面
(6)根据需要申请和释放资源
(7)日志必须按照合适的级别分级打印
(8)文件IO操作使用缓冲
三、代码可靠性案例
1、内存和消息包的使用
(1)指针使用不当导致死机问题
函数不能改变指针所指向的地址。通过指针的指针改善代码。
函数可以改变指针指向的内容。
使用指针前判断指针是否有效,是否为NULL,函数的入参需要判断是否为空。
(2)局部变量使用不当导致流量异常。
函数局部变量地址不能返回。
(3)消息包释放不当导致流程中断。
2、强制转换的使用
(1)小变量地址传递给大变量地址,导致越界,如果对内存进行写操作则会发生后果;大变量地址传递给小变量地址。
(2)取决cpu字节序,如果写程序进行cpu小端和大端的判断。
(3)看似长度相同的内存强制转化为结构,遵循字节对齐原则。
3、循环变量的使用
(1)cpu过载,功能超时,循环变量初始化
(2)死机,断链。
4、定义,结构使用
(1)单板复位(重启),使用了超大局部数组,华为内部规定,局部变量<1K,总局部变量<4K
(2)防止堆栈互相被踩
5、运算符号的使用
(1)转换BCD码
M>>&0x0F + 0×30 ;
M&0x0F + 0×30 ;
错误原因:”+”优先级高于”&”
(2)加减乘除可能导致溢出