代码整洁之道——坏味道

《clean code》中对一些代码中坏味道(bad smell)的总结,在编写代码的过程中应该多注意不要出现列表中的问题,使代码具有更高的可读性。

欢迎大家来我的个人博客玩耍~
https://xuchang-x.github.io/

转载请注明出处:https://blog.youkuaiyun.com/weixin_37587973/article/details/110137123

环境

  1. 需要多步才能做到的环境
    • 构建系统应该可以用单个命令运行,其本身应该是单步的小操作,但不应该依赖一系列指令或环境依赖脚本,不应该到处寻找额外的jar、xml等。
  2. 需要多步才能做到的测试
    • 测试应该可以快速运行

JAVA

  1. 不要继承常量,而应该使用静态导入。在某个接口中放置了常量,在深层级继承类中使用会很困惑这些常量的来源。
  2. 减少常量的使用,更多的使用枚举类。

函数

  1. 过多的参数
  2. 输出参数违反直觉,与函数命名不符
  3. 标识函数,通过布尔值在函数中做多个功能,这类函数违反单一权责原则
  4. 死函数(永远不会被调用的函数)

名称

  1. 采用描述性名称
  2. 名称应与抽象层级相符
  3. 尽可能使用标准命名法。如采用装饰器模式,就该以Decorator结尾
  4. 使用没有歧义的名称
  5. 为较大作用范围选用较长的名称。如for循环中for(i),如果循环体中逻辑复杂,应该选用有意义的命名
  6. 避免编码。不应在名称中包括类型或作用范围信息。
  7. 名称应说明带来的副作用。也就是应该准确的描述其实现的所有功能。

注释

  1. 不恰当的信息,如作者、修改历史等信息
  2. 废弃的注释
  3. 冗余注释,用解释一段可以充分自我解释的代码,那么注释就是多余的
  4. 糟糕的注释,注释应该足够简洁,甄字酌句。
  5. 注释掉的代码

一般性问题

  1. 一个源文件中存在多种语言。如java中包括XML、HTML、YAML等。
  2. 理应被实现的行为未被实现。如将日期翻译成该日期的枚举类,我们希望Monday可以翻译,也希望缩写可以翻译,同时还希望忽略大小写。如果以上的功能没能实现,用户就需要阅读代码细节而不是依靠对函数名的直觉。
  3. 不正确的边界行为。不要依赖直觉,未各种边界条件编写测试,确定函数确实符合预期。
  4. 忽视安全。不要关闭测试然后告诉自己过后处理。
  5. 重复。DRY原则(Don’t Repeat Yourself,别重复自己)。
  6. 在错误的抽象层级上的代码,如细节实现有关的常量、变量或工具函数不应在基类中出现。这个原则对源文件、组件和模块也适用,不同层级对概念应该分离到不同的容器中。
  7. 基类依赖与派生类。基类概念不应该依赖较底层派生类的概念。
  8. 信息过多。一个类中的方法越少越好,一个函数知道的变量越少越好。
  9. 死代码(不执行的代码)。
  10. 垂直分隔。 变量和函数应该在靠近被使用的地方定义。
  11. 前后不一致。
  12. 混淆视听。比如没有用的变量、从不调用的函数、没有用的注释和一切应该移除的代码。
  13. 人为耦合。不相互依赖的东西不该耦合,一般人为耦合的根源是将变量、常量或函数不恰当地放在临时方便的位置。
  14. 特性依赖。类的方法应该只对其所属类的变量和函数感兴趣感兴趣,不应该访问其他类中的变量和函数。
  15. 选择算子参数。不要在函数中使用标识位(布尔、枚举、整数等等)。
  16. 晦涩的意图。代码应该尽可能具有表达力。
  17. 位置错误的权责。仔细考虑代码应该放在哪里,深入思考类、函数和变量的命名,避免误解。
  18. 不恰当的静态方法。通常应倾向于选用非静态方法,如果拿不准应该使用哪一种,那么就选用非静态方法。
  19. 使用解释性变量。让程序可读的最有力的方式之一就是将计算过程打散,并通过有意义的单词命名中间值。
  20. 函数名称应该表达其行为。如果必须通过查看实现或文档才能知道函数是做什么的,那就应该换个更好的函数名。
  21. 理解算法。在实现某个函数前应该深入理解它工作的方式,通过全部测试只是最低要求,应该用优雅的方式实现,而不是if-else的堆砌。
  22. 把逻辑依赖改为物理依赖。如果某个模块依赖另一个模块,那就应该通过调用该模块方法的方式查询相关信息,而不是直接调用该模块中的某些数据结构。
  23. 用多态替代If/Else和Switch/Case
  24. 遵循标准约定。如团队中的标准。
  25. 用命名常量替代魔术数(难以理解的符号)。
  26. 准确。比如第一次匹配不等于唯一匹配、浮点数不能直接用在货币计算上、某些行为应该使用事务等等,编写代码应该在恰当的位置使用准确的方式。
  27. 结构强于约定。比如用到良好命名的Switch/Case要若愚拥有抽象方法的基类。没人强迫每次一同样的方式实现Switch/Case,但实现类中必须实现基类中的方法。
  28. 封装条件。如布尔条件难以理解,应该把解释了条件意图的函数抽离出来。
  29. 避免否定性条件。尽可能将条件表达式表示为肯定形式。
  30. 函数只该做一件事
  31. 掩蔽时序耦合。需要按序调用的函数应该让调用次序显而易见,每个函数都传出下一个函数所需的结果,这样一来就没理由不按顺序调用了。
  32. 别随意。代码的组织和构建(如方法应该放在哪个类中)需要理由,不要随意堆砌。
  33. 封装边界条件。边界条件难以追踪,把边界条件的代码集中到一处,不要散落在代码中。
  34. 函数应该只在一个抽象层级上。函数中的语句应该在同一抽象层级上,不要混淆层级。
  35. 在较高层级放置可配置数据
  36. 避免传递浏览。模块应该只了解其直接协作者,而不是整个系统的游览图。

测试

  1. 避免测试不足
  2. 使用覆盖率工具
  3. 不要略过小测试
  4. 被忽略的测试就是对不确定事务的疑问
  5. 全面测试边界条件
  6. 全面测试相近的缺陷。缺陷趋向于扎堆,在某个函数中发现一个缺陷时,最好全面测试那个函数。
  7. 测试应该快速

最后再次期待大家来我的个人博客玩耍呀~
https://xuchang-x.github.io/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值