《设计模式之美》实战一(上):通过一段ID生成器代码,学习如何发现代码质量问题

王争《设计模式之美》学习笔记

ID 生成器需求背景介绍

  • “ID”中文翻译为“标识(Identifier)”。
  • ID 常用来表示一些业务信息的唯一标识,比如订单的单号或者数据库中的唯一主键,比如地址表中的 ID 字段(实际上是没有业务含义的,对用户来说是透明的,不需要关注)。
  • 文中举例,ID可用于log_id或者微服务调用链追踪,就是用唯一id来追踪用户一次完成访问轨迹。

一份“能用”的代码实现

  • 文中实现了一个 IdGenerator 类。
  • 类中方法 generate() 实现一个ID的生成,包括三部分:
    1. 本机名的最后一个字段。
    2. 当前时间戳,精确到毫秒。
    3. 8 位的随机字符串,包含大小写字母和数字。
  • 此方法生成的ID有非常低的重复概率,但如果用于日志追踪足够了。

如何发现代码质量问题?

审视代码的几方面

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

关注代码实现是否满足业务本身特有的功能和非功能需求

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

参照以上分析示例代码

审视代码的几方面
  • IdGenerator 的代码比较简单,只有一个类,所以,不涉及目录设置、模块划分、代码结构问题,也不违反基本的 SOLID、DRY、KISS、YAGNI、LOD 等设计原则。
  • 它没有应用设计模式,所以也不存在不合理使用和过度设计的问题。
  • IdGenerator 设计成了实现类而非接口,调用者直接依赖实现而非接口,违反基于接口而非实现编程的设计思想。
    • 将 IdGenerator 设计成实现类,而不定义接口,问题也不大。如果哪天 ID 生成算法改变了,我们只需要直接修改实现类的代码就可以。
    • 如果项目中需要同时存在两种 ID 生成算法,我们就需要将 IdGenerator 定义为接口,并且为不同的生成算法定义不同的实现类。
  • 把 IdGenerator 的 generate() 函数定义为静态函数,会影响使用该函数的代码的可测试性。
  • generate() 函数的代码实现依赖运行环境(本机名)、时间函数、随机函数,所以 generate() 函数本身的可测试性也不好,需要做比较大的重构。
  • 没有编写单元测试代码,我们需要在重构时对其进行补充。
  • 虽然 IdGenerator 只包含一个函数,并且代码行数也不多,但代码的可读性并不好。特别是随机字符串生成的那部分代码:
    • 一方面,代码完全没有注释,生成算法比较难读懂。
    • 另一方面,代码里有很多魔法数,严重影响代码的可读性。
关注代码实现是否满足业务本身特有的功能和非功能需求
  • 获取 hostName 这部分代码逻辑貌似有点问题,并未处理“hostName 为空”的情况。
  • 尽管代码中针对获取不到本机名的情况做了异常处理,但是小王对异常的处理是在 IdGenerator 内部将其吐掉,然后打印一条报警日志,并没有继续往上抛出。(此处遗留思考点,后面章节讲解。)
  • 日志打印得当,日志描述能够准确反应问题,方便 debug,并且没有过多的冗余日志。
  • IdGenerator 只暴露一个 generate() 接口供使用者使用,接口的定义简单明了,不存在不易用问题。
  • generate() 函数代码中没有涉及共享变量,所以代码线程安全,多线程环境下调用 generate() 函数不存在并发问题。
  • 性能方面,ID 的生成不依赖外部存储,在内存中生成,并且日志的打印频率也不会很高,所以在性能方面足以应对目前的营用场景。
  • 每次生成 ID 都需要获取本机名,获取主机名会比较耗时,所以,这部分可以考虑优化一下。
  • randomAscii 的范围是 0~122,但可用数字仅包含三段子区间(09,az,A~Z),极端情况下会随机生成很多三段区间之外的无效数字,需要循环很多次才能生成随机字符串的生成算法也可以优化一下。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值