Clean Code总结

为什么看这本书?

  • 如这本书的名字意思,写出整洁的代码。整洁的代码,对以后的自己维护之前写的代码更加方便。代码混乱会导致难以维护,bug越修越多。

个人认为整洁的代码,就是别人没有改进的余地。
具体来说就是:

  1. 能够通过所有的测试
  2. 没有重复代码
  3. 体现系统中的全部设计理念
  4. 包括尽量少的实体,比如类、方法、函数等

整洁代码

有意义的命名

  • 名副其实(有意义的命名,比如魔术数字)
  • 避免误导(相似长名变量)
  • 区分有意义的命名(意思相近的名称,比如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)

测试

  • 测试不足(测到所有可能失败的东西)
  • 使用测试覆盖率
  • 别略过小测试(小测试易与编写,文档价值高于编写成本
  • 被忽略的测试就是对不确定事物的疑问(需求不明确)
  • 测试边界条件
  • 全面测试相近的缺陷(某个函数有一个缺陷,那个函数可能还有另外的缺陷)
  • 测试失败的模式有启发性(看到测试失败,啊哈)
  • 测试覆盖率的模式有启发性
  • 测试应该快速

总结

上面的那一系列清单大致很难说是完备的了,但是你遵循这些原则不应该是目标,清单是列不完的,它背后的那一套价值体系才是自己需要学习的,自己需要自我驱动

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值