Clean Code
- 为什么看这本书?
如这本书的名字意思,写出整洁的代码。整洁的代码,对以后的自己维护之前写的代码更加方便。代码混乱会导致难以维护,bug越修越多。
个人认为整洁的代码,就是别人没有改进的余地。
具体来说就是:
- 能够通过所有的测试
- 没有重复代码
- 体现系统中的全部设计理念
- 包括尽量少的实体,比如类、方法、函数等
- 整洁代码
- 有意义的命名
- 名副其实(有意义的命名,比如魔术数字)
- 避免误导(相似长名变量)
- 区分有意义的命名(意思相近的名称,比如Manager,Dirver)
- 类名(名称作为类名)
- 方法名(动词作为类名)
- 函数
- 短小
- 只做一件事(一个函数只做一件事,如果它做了二件事,把它拆分成二个函数)
- 每个函数一个抽象层次(你的代码混乱,极大可能是你并没有很好的面向对象(抽象这个对象),函数的层次划分)
- 使用描述性的名称
- 函数参数,参数个数越少越好(0>1>2,超过3个你需要考虑下)
- 无副作用
- 分割指令和询问
- 使用异常返回错误代码(?)
- DRY (消除重复代码)
- 结构化编程 一个入口一个出口 做法:分解函数、修改名称、重复消除。保持测试通过
- 注释
理想情况,你的代码自我注释(即命名好,一看就知道表达的意思和功能,不需要额外的注释)
- 格式
代码格式关乎沟通。只要团队统一格式既可以了。
- 对象和数据结构
避免数据结构和对象的混用
对象暴露行为,隐藏数据
面向对象,添加一个新对象方便,但是添加函数麻烦
面向过程
- 错误处理
使用异常而不是返回码(使用错误代码,会有比较多的if else判断,没有使用异常清楚)
如果异常打断正常业务逻辑,可以使用特例模式
不要返回null值
传递null值,返回异常或者特例模式
- 类
类应该短小
单一职责原则(一个类只有一个需要修改的理由)
内聚()
隔离修改(使用抽象类,依赖倒置原则,依赖于抽象,不依赖于细节)
- 系统
将系统的构造和使用分开()
依赖注入或控制反转(构造和使用分离)
- 启发与味道
- 注释
不恰当的注释。注释只应该与代码又换,设计的技术信息。不该有作者,修改日期
废弃的注释(发现就删除掉)
冗余注释(只描述的东西)
糟糕的注释(注释要好好写,别画蛇添足,保持简洁,语法和拼写正确)
注释掉的代码
- 环境
需要多少步才能实现的构建
需要多少步才能做到的测试
- 函数
过多的参数(0>1>2>3,3个以上要避免)
输出参数(违反直觉,处理:修改对象的状态)
表示参数(输入参数有bool值)
死函数(没有人调用的函数需要删除)
- 一般性问题
- 一个源文件存在多种语言
- 明显的行为未被实现(不考虑大小写等)
- 不正确的边界行为(证明边界的情况, 别依赖直觉,编写测试)
- 忽视安全(关闭编译器警告,关闭失败测试,过后处理)
- 重复(重复(遗漏了抽象),不同模块的相同switch语句,使用多态来解决, 模板方法和策略模式消除算法重复)
- 在错误的抽象层级上的代码
- 基类依赖于派生类(基类对派生类一无所知)
- 信息过多(提供的结构,函数扫,变量少)
- 死代码(不执行的代码,删除)
- 垂直分隔(变量和函数应该在靠近被使用的地方定义)
- 前后不一致(一致性)
- 混淆视听(没有用到的变量,不调用的函数,没有信息量的注释移除)
- 人为耦合(不相互依赖的东西不该耦合,根源是将变量、常量、函数不恰当放在临时方便的位置)
- 特性依恋(视情况而定)
- 旋转算子参数(函数传入bool值, 有选择操作的参数,int,Enum等,使用多个函数,通常要由于向单个函数传递某些代码来选择函数行为)
- 晦涩的意图(联排表达式。匈牙利语标记法。魔术数字)
- 位置错误的权责(PI放在Math?Trigonometry?Circle,最小惊异原则,代码应该放在读者自然而期待它所在的地方,换位置思考)
- 不恰当的静态方法(需要多态,静态函数使用确保没有机会打算让他有多态行为)
- 使用解释性变量
- 函数名称表达行为(day.add(5), 添加5天?5星期?5小时?,如果需要看文档知道要做什么,请修改更好的函数名称)
- 理解算法
- 把逻辑依赖改为物理依赖(依赖者模块不应该对被依赖者模块有假定,应当明确查询后者的全部信息)
- 使用多态替代IF else / switch case
- 遵循标准约定
- 用命名常量代替魔术数字
- 准确(明确自己为何要这么做)
- 结构胜于约定(多态vs switch)
- 封装条件
- 避免否定性条件(if (!express))
- 函数只该做一件事
- 遮蔽时序耦合(使用创建序列暴露给时序耦合,每个函数产生下个函数的结果)
- 封装边界条件
- 函数应该只在一个抽象层级上
- 在较高层级放置可配置数据(较低层级并不拥有这些常量值)
- 避免传递浏览(火车失事, 协作者提供全部服务)
- java
通过使用通配符避免过长的导入清单(包导入
不要继承常量
常量 vs 枚举(不用担心越界)
- 名称
采用描述性名称(取名不要太快)
名称和抽象层级相符(不要取沟通实现的名称,取反映类或函数抽象层级的名称model(dial, disconnect) )
尽可能使用标准命名法(装饰者模式, decorator)
无歧义的名称
较大作用范围选用较长名称(较小范围可以很短名称)
名称应该说明副作用(getOos ,如果不存在,创建一个, =》createOrReturnOos)
- 测试
测试不足(测到所有可能失败的东西)
使用测试覆盖率
别略过小测试(小测试易与编写,文档价值高于编写成本
被忽略的测试就是对不确定事物的疑问(需求不明确)
测试边界条件
全面测试相近的缺陷(某个函数有一个缺陷,那个函数可能还有另外的缺陷)
测试失败的模式有启发性(看到测试失败,啊哈)
测试覆盖率的模式有启发性
测试应该快速
- 总结
上面的那一系列清单大致很难说是完备的了,但是你遵循这些原则不应该是目标,清单是列不完的,它背后的那一套价值体系才是自己需要学习的,自己需要自我驱动
————————————————
版权声明:本文为CSDN博主「y z x」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a352614834/article/details/89420266