代码整洁之道
2021-07-08 19:21:15 2 举报
AI智能生成
代码整洁之道
作者其他创作
大纲/内容
类
组织
变量列表
public static ...
private static ...
private ...
公共函数
随后
调用的私有函数
短小
单一职责原则
类和模块有且只有一个修改的理由
内聚
为修改而组织
隔离修改
依赖倒置:接口或抽象
适配模式
错误处理
使用异常而非错误码
先写try-catch-finally
使用RuntimeException
环境说明
定义常规流程
能走业务逻辑,不用异常逻辑
特例模式
null值
别返回,别传递
对象
数据抽象
隐藏其实现
乱加get/set方法
反对称性
过程式
暴露数据,无操作
不改动数据结构,添加新函数
面向对象
隐藏数据,暴露操作
不改动既有函数,添加新类
模块不应了解它所操作对象的内部情形
eg.
火车失事
建议
作为数据结构
ctxt.options.scratchDir.absolutePath;
混淆
一半对象,一半数据结构
隐藏结构
Bad.
Good.
数据传送对象
DTO(Data Transfer Objects)
Active Record
解决
Active Record 单纯数据结构
创建包含业务规则,隐藏内部数据的独立对象
单元测试
TDD 三定律
在编写失败用例前,不能编写生产代码
只可编写刚好无法通过的测试用例
只可编写刚好通过当前失败用例的生产代码
保持测试代码整洁
测试代码不整洁,就会出现脏测试,无法全覆盖
测试代码和生产代码一样重要,迭代同时更新
测试的好处
预知测试缺陷
预知代码结构设计和架构的整洁
整洁的测试
可读性
构造参数
操作测试数据
业务逻辑
校验数据
eg. 断言assertEquals()
面向特定领域的语言
提供一个API 或第三方包,需要提供单元测试
双重标准
不强制要求测试代码标准
每个测试一个断言
如果因为分解代码,导致重复代码,应该放在基类
F.I.R.S.T原则
快速(Fast)
应该能快速运行
独立(Independent)
测试应该相互独立
可重复(Repeatable)
测试应当在每个环境都能通过
自足校验(Self-Validating)
每个校验都应该用boolean 判断
及时(Timely)
生产的代码应该在编写测试代码之后
整洁代码
法则:稍后等于永不(Later equals never)
简单代码规则
通过所有测试
没有重复代码
体现系统中的全部设计理念
尽量小的实体(类、方法、函数等)
代码读写比
10:1
军规:让营地比你来时更干净
命名
建议
名副其实
不需要注释即可表达含义
Bad
int d;
List<String> list;
int [] x;
Good
int daysSinceCreation;
List<String> flaggedCells;
int[] cell;
有意义的区分
Good
void copyChars(char source[], char destination[])
Bad
void copyChars(char a1[], char a2[])
a、an、the、info和Data等
getActiveAccount() vs getActiveAccounts() vs getActiveAccountInfo()
容易读
Good
Date generationTimestamp;
Bad
Date genymdhms;
类与方法区分
类名:名词 or 名词短语
方法名:动词 or 动词短语
一个概念一个词
获取: fetch、retrieve、get...?
管理者:controller、manager、driver...?
领域内名称
避免
避免误导
缩写特殊含义
hp、aix、sco等
约定俗成
accountList 真的是List 类型?
相似性
小写I 与1
大写O 与0
避免编码
类型后缀
phoneString
成员前缀
m_desc
避免思维映射
把名称翻译为熟知的名称
别扮可爱
不要使用俚语 or 俗语
whack() VS kill()
eatMyShorts() VS abort()
函数
建议
短小
50行,一层到两层缩进
只做一件事
判断标准:能否再拆一个函数
每个函数一个抽象层级
switch用法
仅出现一次
用于创建多态对象
隐藏在某个继承体系中
描述性名称
长而具有描述性的名称
短而令人费解的名称
厘清模块的设计思路-->改进
一脉相承的命名
参数规范
原则:越少越好
一元函数
转换:T->K
事件:T->Void
标识参数
丑陋不堪
render(boolean isSuite)
拆分
renderForSuite()
renderForSingle()
二元函数
向一元函数改进
writeField(outputStream, name)
outputStream.writeField(name)
自然组合
new Point(0, 0)
三元函数
参数对象
>= 2参数 -->封装为类
参数列表
可变参数
String format(String format, Object... args)
动词与关键词
一元函数
动词/名词对
writeField(name)
参数名称编码成函数名
assertEqual(expected, actual)
assertExpectedEqualsActual(expected, actual)
子主题
操作与查询分离
结构化编程
经典Dijkstra(一个入口、一个出口)
短小函数
return、break或continue
异常替代错误码
避免
副作用
承诺只做一件事,但是还是偷偷做其他事
避免输出参数
void appendFooter(StringBuilder report)
避免重复自己
并发编程
why 需要并发?
并发其实是一种解耦策略
迷思与误解
一定能改进性能?
并发程序无需设计?
采用web容器,并发问题不重要?
正确说法
增加一些开销
正确的并发是复杂的
并发的缺陷总是很难重现
并发 always 涉及策略上根本性修改
挑战
JIT 编译原理
Java内存模型
并发防御原则
单一权责(SPR)原则
尽可能分离并发代码和其他代码
限制数据作用域
严格限制共享数据的访问作用域
使用数据副本
创建副本,低于增加同步执行开销
线程尽可能的独立
尝试将数据分解到可被独立线程中
了解Java库
线程安全的类库(java.util.concurrent)
了解执行模型
限定资源
生产者-消费者模型
线程饥饿
作者-读者模型
如何避免线程饥饿,平衡作者与读者线程
死锁、活锁、互斥
尽可能减小同步区域
测试线程代码
装置试错代码
硬编码
wait()、sleep()
自动化
通过CGLIB或ASM
味道与启发
注释
不恰当的信息
废弃的注释
冗余的注释
糟糕的注释
注释的代码
必须要删除,无任何意义的代码
函数
过多参数
输出参数
避免使用输出参数,如果必须修改,就修改对象的状态
标识参数
避免使用boolean 传参
死函数
不被调用的函数
一般性问题
不正确的边界
忽视安全
消除重复
在错误的抽象层上代码
静态变量在基类
基类依赖于子类
信息过多
接口方法过多
死代码
调用不到的代码必须删除
前后不一致
使用变量名字应该前后保持一致
不恰当地使用静态变量
用多态替代if/else 和 switch/case
用命名常亮代替魔法数值
避免否定条件
难理解
Java
不要继承常量
Enum 代替常量
导入包过多清单,采用通配符
com.alibaba.json.*
名称
采用描述性名称
名称应与抽象层级相符
使用标准命名
使用无歧义名称
避免编码
名称的作用范围越大,名称就该越长越明确
不要用一个动词描述多个动作的函数
测试
测试扎堆
出现bug的地方,剩余bug的几率大
测试应该快速
0 条评论
下一页