美文网首页程序员
《设计模式之美》笔记:规范与重构

《设计模式之美》笔记:规范与重构

作者: Jinglever | 来源:发表于2021-01-02 01:02 被阅读0次

    理解重构

    • 重构是一种对软件内部结构的改善,目的是在不改变软件的可见行为的情况下,使其更易理解,修改成本更低。
    • 在保持功能不变的前提下,利用设计思想、原则、模式、编程规范等理论来优化代码,修改设计上的不足,提高代码质量。
    • 重构是避免过渡设计的有效手段。在我们维护代码的过程中,真正遇到问题的时候,再对代码进行重构,能有效避免前期投入太多时间做过度的设计。
    • 不要等到代码烂到一定程度才去重构,持续重构是一个良好的习惯。

    单元测试

    • 单元测试的测试对象是类或者函数,是代码层级的测试。
    • 代码的可测试性是评判代码质量的一个重要标准。
    • 写单元测试的过程本身就是代码重构的过程。
    • 单元测试用例实际上就是用户用例,反映了代码的功能和如何使用,有助于帮助其他人快速熟悉相关的代码。
    • 写单元测试就是针对代码设计覆盖各种输入、异常、边界条件的测试用例,并将这些测试用例翻译成代码的过程。
    • 依赖注入是实现代码可测试性的最有效的手段。

    常见的Anti-Patterns (即测试性不好的代码)

    • 未决行为:代码的输出是随机或者说不确定的,比如跟时间、随机数有关的代码。
    • 全局变量
    • 静态方法
    • 复杂继承
    • 高耦合代码

    解耦

    • 解耦,是保证代码不至于复杂到无法控制的有效手段。
    • 如何判断代码是否需要解耦?
      • 修改代码是否牵一发而动全身?
      • 把模块间、类间的依赖关系画出来,看看依赖关系图是否过于复杂?
    • 解耦的手段
      • 封装与抽象:可以有效地隐藏实现的复杂性,隔离实现的易变性,给依赖的模块提供稳定且易用的抽象接口。
      • 中间层
      • 模块化:模块化思想的本质就是分而治之。
      • 其他设计思想和原则
        • 单一职责原则
        • 基于接口而非实现变成
        • 依赖注入
        • 多用组合少用继承
        • 迪米特法则

    编码规范

    • 命名
      • 长度:首先要求准确达意,在此基础上越短越好。
      • 利用上下文简化命名。
      • 命名要可读、可搜索。
        • 可读就是,得让人能读出来,比如 eyrie 这种命名,没人知道怎么读。
        • 可搜索就是,整个项目有个命名习惯,比如,统一使用getxxx,不要这里用getxxx,那里用queryxxx。
      • 对接口和抽象类的命名,项目内统一一下,比如:接口类都写成Ixxx。
    • 注释
      • 注释跟命名同等重要。
      • 注释写什么?
        • 目的是为了让代码更容易看懂,应包含三个方面:做什么、为什么、怎么做。
          • 具体情况具体分析,简单易懂的函数,没必要写“为什么、怎么做”,但对于复杂的函数,或者一些类来说,注释起到了总结性作用、文档的作用,可以让阅读代码的人通过注释就能大概了解代码的实现思路,对阅读代码有帮助。
      • 注释是否越多越好?
        • 通常类和函数一定要写注释,且酌情详细些。函数内部的注释相对少一些。
    • 代码风格
      • 类、函数多大才合适?
        • 看感觉。团队项目约定。
      • 一行代码多长合适?
        • 看感觉。团队项目约定。
      • 善用空行分割单元块。
      • 四格缩进还是两格缩进?
        • 团队项目约定。反正,不要用tab,因为不同的IDE下,tab的显示宽度不同。
      • 大括号是否要另起一行?
        • 团队项目约定。
      • 类中成员的排列顺序
        • emmm..在现代IDE的加持下,感觉不太所谓呢,如果追求好看就约定一下吧。(这句我说的)
    • 提高代码可读性的一些编程技巧
      • 把代码分割成更小的单元块。
        • 把大块的复杂逻辑提炼成类或者函数,屏蔽掉细节,让阅读代码的人不至于迷失在细节中。
        • 只有代码逻辑比较复杂的时候才建议提炼。
      • 避免函数参数过多。
        • 处理方法:
          • 考虑函数是否职责单一,能否拆分成多个函数。
          • 将函数的参数封装成对象。
      • 勿用函数参数来控制逻辑。
        • 明显未被单一职责原则和接口隔离原则。
        • (我说的)这个还是具体情况具体分析,没那么绝对。比如要写一个支持筛选获取列表的接口,筛选条件本身就会影响逻辑,但不太适合拆开,不然得写一堆函数。
      • 函数设计要职责单一。
      • 移除过深的嵌套层次。
        • 代码嵌套过审往往是因为if-else、switch-case、for循环过度嵌套导致。
        • 如果嵌套超过两层,就要思考一下能否减少嵌套。嵌套本身就不好理解,嵌套过深,不仅理解起来费劲,也会因为多次缩进影响代码整洁。
        • 常见的解决思路:
          • 去掉多余的if或else。
          • 使用continue、break、return关键字,提前退出嵌套。
          • 调整执行顺序来减少嵌套。
          • 将部分嵌套逻辑封装成函数调用。
      • 学会使用解释性变量。
        • 常量取代魔法数字。比如:定义一个PI,替换代码里的3.1415魔法数字。
        • 使用解释性变量来解释复杂表达式。
    • 统一编码规范(最重要)

    如何发现代码质量问题 - 常规 checklist

    • 目录设置是否合理,模块划分是否清晰,代码结构是否满足“高内聚、松耦合”?
    • 是否遵循经典的设计原则和设计思想(SOLID、DRY、KISS、YAGNI、LOD等)?
    • 设计模式是否应用得当?是否有过度设计?
    • 代码是否容易扩展?如果要添加新功能,是否容易实现?
    • 代码是否可以复用?是否可以复用已有的项目代码或类库?是否有重复造轮子?
    • 代码是否容易测试?单元测试是否全面覆盖各种正常和异常的情况?
    • 代码是否易读?是否符合编码规范(比如命名和注释是否恰当、代码风格是否一致等)?

    如何发现代码质量问题 - 业务需求 checklist

    • 代码是否实现了预期的业务需求?
    • 逻辑是否正确?是否处理了各种异常情况?
    • 日志打印是否得当?是否方便debug排查问题?
    • 接口是否易用?是否支持幂等、事务等?
    • 代码是否存在并发问题?是否线程安全?
    • 性能是否有优化空间,比如,SQL、算法是否可以优化?
    • 是否有安全漏洞?比如,输入输出校验是否全面?

    相关文章

      网友评论

        本文标题:《设计模式之美》笔记:规范与重构

        本文链接:https://www.haomeiwen.com/subject/oswsoktx.html