文档章节

第2章 编写高质量代码

UncleHao
 UncleHao
发布于 2017/01/21 13:51
字数 2957
阅读 2
收藏 0


2.1 良好的编程实践

    1. 看:阅读优秀的代码,学习别人的代码。
    2. 问:https://github.com/seajs/seajs/issues/545如何向开源社区提问题
    3. 练:亲自动手编写代码,实践、实践、再实践。

软件开发的工程思维

image

 

 

 

   

 

 

 

 

 

 

 

模块化程序设计

基本思想:将一个大的程序按功能产分成一系列小模块。

如何进行模块划分?

image

 

基于易变与稳定:认识和识别变与不变的部分,并将之科学的分离开。

image

基于单一职责:类或函数应该只做一件事,并且做好这件事情。

    1. 单一职责 ≠ 单一功能
    2. 单一职责:只有一个引起变化的原因

模块化设计的好处:思路清晰、易于测试、适应未来可能的变化。

面向抽象编程

  1. 在模块化设计的基础上,我们可以设计出各个模块的“骨架”,或者说对各个模块进行“抽象”,定义他们之间的接口。
  2. 定义各个模块互相之间关联的部分,这些部分在未来开发中不应该发生改变。
  3. 接口不一定要显示的定义出来,也可以是开发人员之间的一种约定。

异常处理

  1. 细化具体的异常类型,更有针对的处理
  2. 减少try/catch中代码量
  3. 在关键部分应该检查代码的合法性,包括类型、取值范围等,避免“雪球效应”

2.2 代码静态检查

hb-zhanghao 标记: 代码静态检查代码质量软件工程

代码评审技术

代码审查(Code Review)是一种用来确认方案设计和代码实现的质量保证机制,它通过阅读代码来检查源代码与编写规范的符合性以及代码的质量。

代码审查的作用:

  1. 检查设计的合理性
  2. 互为BackUp
  3. 分享知识、设计、技术
  4. 增加代码的可读性
  5. 处理代码中的“地雷区”

缺陷检查表

编程规范 面向对象设计
  1. 按照具体编程语言的编码规范进行检查,包括命名规则、程序注释、缩进排版、声明与初始化、语句格式等。
  1. 类的设计和抽象是否合适
  2. 是否符合面向接口编程的思想
  3. 是否使用合适的设计模式
性能方面 资源释放处理
  1. 在出现海量数据时,队列、表、文件在传输、上载等方面是否会出现问题,是否控制如分配的内存块大小、队列长度等
  2. 对 Hashtable、Vector 等集合类数据结构的选择和设置是否合适
  3. 有无滥用 String 对象的现象
  4. 是否采用通用的线程池、对象池等高速缓存技术以提高性能
  5. 类的接口是否定义良好,如参数类型等应避免内部转换
  6. 是否采用内存或硬盘缓冲机制以提高效率? • 并发访问时的应对策略
  7. I/O 方面是否使用了合适的类或采用良好的方法以提高性能(如减少序列化、使用 buffer 类封装流等)
  8. 同步方法的使用是否得当,是否过度使用? • 递归方法中的迭代次数是否合适(应保证在合理的栈空间范围内)
  9. 如果调用了阻塞方法,是否考虑了保证性能的措施
  10. 避免过度优化,对性能要求高的代码是否使用profile工具

 

  1. 分配的内存是否释放,尤其在错误处理路径上(如 C/C++)
  2. 错误发生时是否所有对象被释放,如数据库连接、Socket、文件等
  3. 是否同一个对象被释放多次(如 C/C++)
  4. 代码是否保存准确的对象引用计数
程序流程 数据库处理(续)
  1. 循环结束条件是否准确
  2. 是否避免了死循环的产生
  3. 对循环的处理是否合适,应考虑到性能方面的影响
  1. 数据库设计或SQL语句是否便于移植(注意与性能会存在冲突)
  2. 数据库资源是否正常关闭和释放数据库访问模块是否正确封装,便于管理和提高性能
  3. 是否采用合适的事务隔离级别
  4. 是否采用存储过程以提高性能
  5. 是否采用 PreparedStatement 以提高性能
线程安全 通讯方面
  1. 代码中所有的全局变量是否是线程安全的
  2. 需要被多个线程访问的对象是否线程安全,检查有无通过同步方法保护
  3. 同步对象上的锁是否按相同的顺序获得和释放以避免死锁,注意错误处理代码
  4. 是否存在可能的死锁或是竞争,当用到多个锁时,避免出现类似情况:线程A获得锁1,然后锁2,线程B获得锁2,然后锁1
  5. 在保证线程安全的同时,注意避免过度使用同步,导致性能降低
  1. Socket 通讯是否存在长期阻塞问题
  2. 发送接收的数据流是否采用缓冲机制
  3. Socket 超时处理和异常处理
  4. 数据传输的流量控制问题
JAVA对象处理 异常处理
  1. 对象生命周期的处理,是否对象引用已失效可设置 null 并被回收
  2. 在对象传值和传参方面有无问题,对象的 clone 方法使用是否过度
  3. 是否大量经常地创建临时对象
  4. 是否尽量使用局部对象(堆栈对象)
  5. 在只需要对象引用的地方是否创建了新的对象实例
  1. 每次当方法返回时是否正确处理了异常,如最简单的处理是记录日志到日志文件中
  2. 是否对数据的值和范围是否合法进行校验,包括使用断言
  3. 在出错路径上是否所有的资源和内存都已经释放
  4. 所有抛出的异常是否都得到正确的处理,特别是对子方法抛出的异常,在整个调用栈中必须能够被捕捉并处理
  5. 当调用导致错误发生时,方法的调用者应该得到一个通知
  6. 不要忘了对错误处理部分的代码进行测试,很多代码在正常情况下执行良好,而一旦出错整个系统就崩溃了?
方法(函数) 安全方面
  1. 方法的参数是否都做了校验
  2. 数组类结构是否做了边界校验
  3. 变量在使用前是否做了初始化
  4. 返回堆对象的引用,不要返回栈对象的引用
  5. 方法的 API 是否被良好定义,即是否尽量面向接口编程,以便于维护和重构
  1. 对命令行执行的代码,需要详细检查命令行参数
  2. WEB 类程序检查是否对访问参数进行合法性验证
  3. 重要信息的保存是否选用合适的加密算法
  4. 通讯时考虑是否选用安全的通讯方式

其他

  1. 日志是否正常输出和控制
  2. 配置信息如何获得,是否有硬编码

 

 


2.3 代码性能分析

代码性能优化

优化是对代码进行等价变换,使得变换后的代码运行结果与变换前的代码运行结果相同,但执行速度加快或存储开销减少。

程序性能:

  1. 时间复杂性
  2. 空间复杂性

代码性能优化是一门复杂的学问。

根据 80/20 原则,实现程序的重构、优化、扩展以及文档相关的事情通常需要消耗 80% 的工作量。

优化的前提条件:

  1. 在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率
  2. 以提高程序的全局效率为主,提高局部效率为辅 • 在优化程序效率时,应先找出限制效率的“瓶颈”
  3. 先优化数据结构和算法,再优化执行代码
  4. 时间效率和空间效率可能是对立的,应当分析哪一个因素更重要,再做出适当的折衷
  5. 从一开始就要考虑程序性能,不要期待在开发结束后再做一些快速调整
  6. 正确的代码要比速度快的代码重要,任何优化都不能破坏代码的正确性
  7. 认真选择测试数据,使其能够代表实际的使用状况
  8. 永远不要在没有执行前后性能评估的情况下尝试对代码进行优化

image

 

改进算法,选择合适的数据结构

  1. 良好的算法对性能起到关键作用,因此性能改进的首要点是对算法改进
  2. 算法时间复杂性的排序依次是

image

 

 

   3.   对成员的查找访问等操作,字典(dictionary)要比列表(list)更快

   4.   集合(set)的并、交、差的操作比列表(list)的迭代要快

一些关于优化的建议:

    1. 循环优化的基本原则:尽量减少循环过程中的计算量,在多重循环的时候,尽量将内层的计算提到上一层。
    2. 字符串的优化: Python的字符串对象是不可改变的。字符串连接的使用尽量使用 join() 而不是 +。当对字符串可以使用正则表达式或者内置函数处理时,选择内置函数。
    3. 使用列表解析和生成器表达式:列表解析要比在循环中重新构建一个新的 list 更为高效,因此可以利用这一特性来提高运行的效率。

结对编程

结对编程是由两名程序员在同一台电脑上结对编写解决同一问题的代码。

驾驶员:负责用键盘编写程序

领航员:起到领航、提醒的作用。

两个人轮流驾驶,角色互换。

    1. 结对编程不仅意味着编程活动,也包括分析、设计、测试等全程活动。
    2. 结对编程有助于按时完成项目,并且保证高质量的代码。
    3. 结对编程的基础是会话和讨论,不是一个人自得其乐。
    4. 口渴指数是核实伙伴交流程度的一个考核标准。
    5. 驾驶员不要连续工作超过1个小时,每1个小时休息10分钟
    6. 给驾驶员一点时间去发现和找到错误,别让伙伴觉得你很烦
    7. 常用的资料和规范(可以打印出来)以及书籍等应该放在手边
    8. 结对开始之前要协调沟通,彼此互相通告希望对方关注些什么,自己喜欢做什么
    9. 主动参与,任何一个任务都是共同的责任,只有“我们的代码
    10. 坚持代码标准和流程规范
    11. 注意听取伙伴的意见
    12. 结对编程是一个相互学习、相互磨合的渐进过程,实施时需要团队成员克服个性冲突和习惯差异。
    13. 结对编程应该自由选择和灵活运用,它不应是强制性的,也不要教条地运行,最好由两位程序员自己决定合适的方式。

下面一些情况不适合结对编程:

  1. 处于探索阶段的项目
  2. 后期维护的技术含量不高
  3. 验证测试需要运行很长时间
  4. 团队的人员要在多个项目中工作
  5. 领航的用处不大

另外,也不是所有的人都适合结对编程。

© 著作权归作者所有

UncleHao
粉丝 0
博文 1
码字总数 2957
作品 0
武汉
程序员
私信 提问
找到一本不错的Linux电子书,附《Linux就该这么学》章节目录。

此书是由全国多名红帽架构师(RHCA)基于RHEL7系统共同编写的高质量Linux技术自学书籍,各章节知识点从实践出发且具有较强连贯性,极其适合Linux初学者或用作Linux相关辅助教材,专注于Linux...

mialuz
2017/05/29
0
0
ThinkPHP 5.0开发微信小程序商场实现全栈项目架构

第1章 前言:不同的时代,不同的Web 我们说,做一个产品,真的只是做一个产品吗?恐怕不是。现代的Web产品是一个产品矩阵,需要有良好的服务器端架构来支撑整个产品体系。本小节,我们将对现...

15543555749
2018/05/19
0
0
《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》笔记

这本书很早有了解过,评价都不错,但最近才终于把这本书看完,整本书介绍了很多个提高Objective-C的方法,都是平时用得很多但是没有注意使用的,下面对这些方法做一些小总结。 第1章 熟悉Objec...

TouchMing
2018/01/15
0
0
‘PostgreSQL用户会’携手‘机工社华章公司’发起以下赠书活动

活动参与方式: QQ空间分享此帖:并将分享截图发布到此帖下面,即有机会获赠精美图书; 活动时间:11.12—11.19 活动奖品: 《PostgreSQL服务器编程》,总10本。结束后,由机工社华章公司统一...

YuanyuanL
2014/11/12
0
2
《Clean Code》一书回顾

《Clean Code》一书从翻开至今,已经差不多两个月的时间了,尽管刨去其中的假期,算下来实在是读得有点慢。阅读期间,断断续续的做了不少笔记。之前,每每在读完了一本技术书籍之后,其中的诸...

Peter87
2015/04/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

怎么升级phpstudy中的php版本

http://www.php.cn/jishu/php/413274.html php官网 下载php版本 https://windows.php.net/

15834278076
2分钟前
0
0
文件已删除但句柄没有释放导致磁盘空间用完

有时候会发现linux文件系统分区已经快满了,但又找不到到底是什么文件占用了磁盘空间,就有可能是已删除的文件的句柄没有释放,还占着空间 检查命令: lsof | grep deleted 如果发现很多del...

果树啊
6分钟前
0
0
mysql5.7 [Err] 1118 - Row size too large (> 8126).

mysql [Err] 1118 - Row size too large (> 8126). 问题 mysql5.7 在执行创建表或者增加字段时,发现row size长度过长,导致出现以下错误。 [Err] 1118 - Row size too large (> 8126). C......

GritTan
7分钟前
0
0
[mybatis]一级缓存与二级缓存配置(mybatis3.4.0)

二级缓存 添加<cache />即可 日志: 2019-05-20 16:28:16.525 [http-nio-8830-exec-2] DEBUG com.asiainfo.mysql.MysqlMapper -Cache Hit Ratio [com.asiainfo.mysql.MysqlMapper]: 0.......

Danni3
18分钟前
0
0
Kafka两级调度实现分布式协调任务分配Golang版

背景 基于Kafka消息队列的两级协调调度架构 Kafka内部为了协调内部的consumer和kafka connector的工作实现了一个复制协议, 主要工作分为两个步骤: 通过worker(consumer或connect)获取自身的...

8小时
25分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部