1 自顶向下分解软件需求
拿到一个软件需求之后,先不要着急写代码。要把需求吃透,然后对需求进行庖丁解牛式地分解。把大需求分解为中等需求,再把中等需求分解为小需求。
![](https://i-blog.csdnimg.cn/blog_migrate/d49562932815bd3f5e5b14c2212c4bd6.png)
以ECU软件刷新为例,画出需求分解图,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/a3d330d66c240ffef30e93e34a440bd2.png)
2 画出状态机和时序图
软件的状态是有限的,软件在不同的状态下,收到的消息会做出不同的响应。所以,要画出状态机图,以及在每个状态机下收到不同的消息做出什么响应,这些都应该在写代码之前落实到文档里。
我们以TCP的状态机为例进行说明。
![](https://i-blog.csdnimg.cn/blog_migrate/4f304ec11587e70adf5beed9ce7b2ef4.png)
比如TCP客户端发送SYN报文之后,进行SYN-SEND状态,等待对端的SYN+ACK报文。处于SYN-SEND状态的客户端收到服务器端发过来的SYN+ACK报文,应答ACK报文,这时客户端进入ESTABLISHED状态,然后可以进行数据传输了。
3 本着高内聚低耦合的原则编写代码
将软件系统划分模块时,遵循高内聚、低耦合的原则,提高模块和函数的独立性,为设计高质量的软件结构奠定坚实的基础。
内聚就是一个模块或者函数内各个元素彼此结合的紧密程度。
耦合是多个模块组成的系统中各个模块或者函数之间的关联关系,指软件系统结构中各模块间相互联系紧密程度的一种度量。耦合度的高低取决于模块间接口的复杂性、调用的方式及传递的信息。
模块独立性指每个模块只完成系统要求的独立子功能,并且与其他模块的联系最少、接口简单。
高内聚是说模块内部要高度聚合,低耦合是说模块与模块之间的藕合度要尽量低。
函数有效行数控制在80行以下,不要有大函数,函数功能要单纯,不要设计多用途的函数,减少函数复杂度。因为单用途的函数,可能在其他地方可以得以调用。如果超过这个限制(超过80行),函数内部逻辑一般可以拆分。如果试图超过这个标准,请你列出理由。
4 编程的优先原则排序
编程时首先达到正确性,其次考虑效率。编程首先考虑的是满足正确性、健壮性、可维护性、可移植性等质量因素,最后才考虑程序的效率和资源占用。
if (a&&b&&c)
…
else:
…
系统判断a的值为False后,就不再判断b和c的逻辑值,直接执行else语句。所以我们预测a的值大概率为False时,就把a放在前面。
循环的优化:当有多个if elif条件判断时,可以把最有可能先发生的条件放到前面,这样可以减少程序判断的次数,提高运行效率。
5 添加合理注释,禁用魔鬼数字
函数头和类头要添加注释,关键步骤要添加注释。注释有助于理解代码,有效的注释是指在代码的功能、意图层次上进行注释,提供有用、额外的信息,而不是代码表面意义的简单重复。一般情况下,源程序有效注释量必须在20%以上。
不要出现魔鬼数字。魔鬼数字的定义:在代码中没有具体含义的数字、字符串。主要影响了代码可读性,读者看到的数字无法理解其含义,从而难以理解程序的意图。解决方法:用常量定义魔鬼数字。
6 强可维可测性
在同一个项目组或产品组内,调测打印出的信息串要有统一的格式。信息串中应当包含所在的模块名(或源文件名)、函数名、行号等信息、告警等级。在编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码(如打印函数等)。
在编写代码时,在关键函数流程中加上打印信息(打印到log文件里),以便追踪代码流程是否正常。当某函数有入参时,把函数入参值打印出来(打印到log文件里),出现异常时,可以追踪到是入参有问题,还是本函数处理流程有问题。可以在打印处加上开关(全局变量),当代码稳定了,可以通过设置此全局变量,把一些打印关掉。
在for或者while循环中,尽量少打印。如果确实需要打印,建议只打印error级别的错误信息,调试或者跟踪级别的信息就不要打印了。
7 自底向上进行测试与验证
理解自底向上的执行思维:模块化集成。对各个单元进行测试与验证,直至系统各部分以组装的思路都经过测试和验证。
8 时间分配
分解需求、画状态机、画时序图,占40%时间。
编写代码,占40%时间。
调试代码,占20%时间。
总之,编写程序,写类,写变量,写函数。做到:
注释清楚.
间隔整齐.
可读性高.
可维护性好.
可扩展性好.