清除代码异味
今天,Venkat Subramaniam 就关于清除代码异味的话题给我们做了一个非常有趣的演讲。下面就是我记录的一些他的话。
为什么我们需要有质量的代码?
敏捷开发方法是用来应付那些要求代码做大量改动的反馈信息的方法。
如果程序没有用一种好的表达方式来表现,那程序会很难读,难维护,难修改。
什么是代码异味?
代码异味是一种由写的很差的代码引起的一种有臭味的感觉,一种程序什么地方会有问题的感觉
异味更多的是来自一种直觉,而不是一种有据可查的标准,当你看到有味的代码时你就“感觉”到了
如果你不把异味清除,不久之后你就会习惯这种气味,不再对它有察觉
用任何语言都能写出有异味的代码:即使最简单安全的语言,你也能做出天才才能想出的蠢事:)
我们经常会意识不到自己在写很臭的代码,经常需要外人为我们指出这点
边注:如果你不想刻意去批评某人的程序,不要说“太愚蠢了”,要说“哦,这很有意思…。可有一种更好的方法你知道吗”
重复的代码
- 会引起程序里面多个地方相同的错误
- 印度小伙:每两个月我们都会把这相同的错误修改一次
- Venkat:你们去掉了重复的代码了吗?
- 印度小伙:你说的这个方法不错!
不必要的复杂
- 程序员本质上讲高效去处理复杂的问题
- 复杂最恐怖
异常处理
- 问:有什么比一个空的异常捕捉代码更糟糕的?
- try{... } catch (Exception e){}
- 答:一个带有注释的空异常捕捉代码!
- try{... } catch (Exception e){// is this required? }
- Java的异常检查:好还是不好?
- 如果你不想处理一个异常,就把它传递下去
- 如果你想捕捉两个异常,使用两个catch代码,不要只写一个而用If条件处理
- Switch语句& 按类型的条件判断
- Switch语句和按类型的条件判断通常可以用多形性来代替
长方法
- 你不能在一屏上看到整个方法
- 这通常意味着一个方法承担这多重任务
- 难于调试
- 不可测试
- 难于重用-> 导致程序员从方法的其它地方拷贝粘贴出重复的代码
- 复杂的条件语句-> 挑战大脑的逻辑分析能力
- 方法长度:组织归纳水平比控制代码行数更重要
方法组成模式
- 方法里的所有语句都必须处在同一个归纳层次上
无用的注释
- 让代码自我表白
- 标注为什么这样,而不是如何这样
- 对方法表现进行描述等于重复表现
- 这样的注释等于重复写一遍代码
- i += 1 //递增
- 长方法里用来描述这个方法有不同的功用的注释
- 把里面的功能片段提取成小方法& 删除注释
- IDE排泄物:IDE自动产生的注释空白占位符
- 糟糕的注释通常产生于TDD*
- *(TDD:Threat driven development,恐吓驱动开发)——你应该为方法的表象写注释,你应该为长方法写注释,等
- 产品里的注释:
- //上帝保佑,我实在不知道这是什么意思
变量名称
- 使用能表意的名称
- 不要用单个字母做名称
- 也不要使用太长的名称
继承
- 继承更多的是被滥用了
- 组合通常优于继承
- 在一对一关系中使用继承,满足Liskov替换原则
- 不要用继承来实现方法重用
- 重用方法时,委托是个更好的选择
粘手的语言
- 这种语言更容易导致犯错误
最臭的代码
- 冗长的类
- 重复的代码
- 淘汰的方法
- 不必要的塑型(cast)
- 过度使用设计模式
代码除味
- 代码复查!
- 写出之后尽快进行
- 要增量进行
- 要复查测试用例
- 可使用结对编程
- 但要保持结对伙伴的经常变动,否则你会习惯你的气味,不再会有察觉
- 结对伙伴一、两天调换一次
一些设计原则
- 高聚合
- 低耦合
- Demeter定律 [不要告诉我,我会通知你]
- Liskov替换原则
- 先让它跑起来,再让它无误,再让它快速
- 开发/闭合原则
- 反向依赖
- 单一责任原则
一些参考书籍
- 代码整洁之道(Clean Code)
- 代码大全(Code Complete) 2
- 程序员修炼之道(The Pragmatic Programmer)
- 敏捷开发修炼之道(Practices of an Agile Developer)
- Smalltalk Best Practice Patterns
- 实现模式(Implementation Patterns) (from @protoiyer)
问和答
- 关于使用代码检测工具,例如PMD:这样的工具非常的有用,它能让你捕捉到很直接的问题,使你的代码复查工作专注于高层面的设计原则问题
- 关于IDE上附加的工具:不要自己去运行它们。让这些工具在后台自动的运行(或智能化)
- 动态语言里需要重构吗:动态语言里没有太多的自动重构工具,但程序员仍然应该手动的重构
- 关于动态语言的设计模式:每种语言都有自己的模式和特色。例如:smalltalk的execute around method模式
- 关于掌握多种语言
- 你应该知道处理一个问题的多种范式,多种风格和多种方式
- 一种语言中学到的特色方法应用到其它语言里
- 知道各种不同方式的各自风险
- 关于编程语言趋势:对函数性编程,移动设备编程兴趣浓厚
- 关于著书:长时间的思考书中的各项主题,多做这方面话题的讨论,吸取精华。当开始动手去写时,已经胸有成竹,2周内把书写成
- 关于思考文献:思考文献很有用,但你也要多看看批评性的思考性文章,它们是关于你如何去思考的(double loop learning?)
- 关于学习:在用户组里跟其它人合作,交流,讨论。你并不能学到所有的东西,但要努力缩小自己的“你不知道你不知道的东西”,让它成为“你知道你不知道的”
Flock,你知多少?
PHP 中的 flock 函数可以让你的站点挂了,你信吗?不可能,不就是一个锁文件嘛。
我们所使用的是 Discuz! X3.2 版本,其中这个helper_log::writelog 函数中使用了 @flock($fp, 2); 此时如果你的日志目录(data/log/)使用了NFS(网络文件系统),这将在某些情况下是有问题的。