设计模式之美
王争
前 Google 工程师,《数据结构与算法之美》专栏作者
123425 人已学习
新⼈⾸单¥98
登录后,你可以任选6讲全文学习
课程目录
已完结/共 113 讲
设计模式与范式:行为型 (18讲)
设计模式之美
15
15
1.0x
00:00/00:00
登录|注册

37 | 实战二(下):重构ID生成器项目中各函数的异常处理代码

总结重点
重构代码示例
参数处理
重构代码示例
参数处理
重构代码示例
异常处理方式
重构代码示例
返回值处理
课堂讨论
重点回顾
重构之后的RandomIdGenerator代码
重构generateRandomAlphameric()函数
重构getLastSubstrSplittedByDot()函数
重构getLastFieldOfHostName()函数
重构generate()函数
重构ID生成器项目中各函数的异常处理代码

该思维导图由 AI 生成,仅供参考

平时进行软件设计开发的时候,我们除了要保证正常情况下的逻辑运行正确之外,还需要编写大量额外的代码,来处理有可能出现的异常情况,以保证代码在任何情况下,都在我们的掌控之内,不会出现非预期的运行结果。程序的 bug 往往都出现在一些边界条件和异常情况下,所以说,异常处理得好坏直接影响了代码的健壮性。全面、合理地处理各种异常能有效减少代码 bug,也是保证代码质量的一个重要手段。
在上一节课中,我们讲解了几种异常情况的处理方式,比如返回错误码、NULL 值、空对象、异常对象。针对最常用的异常对象,我们还重点讲解了两种异常类型的应用场景,以及针对函数抛出的异常的三种处理方式:直接吞掉、原封不动地抛出和包裹成新的异常抛出。
除此之外,在上一节课的开头,我们还针对 ID 生成器的代码,提出了 4 个有关异常处理的问题。今天,我们就用一节课的时间,结合上一节课讲到的理论知识,来逐一解答一下这几个问题。
话不多说,让我们正式开始今天的内容吧!

重构 generate() 函数

首先,我们来看,对于 generate() 函数,如果本机名获取失败,函数返回什么?这样的返回值是否合理?
public String generate() {
String substrOfHostName = getLastFieldOfHostName();
long currentTimeMillis = System.currentTimeMillis();
String randomString = generateRandomAlphameric(8);
String id = String.format("%s-%d-%s",
substrOfHostName, currentTimeMillis, randomString);
return id;
}
ID 由三部分构成:本机名、时间戳和随机数。时间戳和随机数的生成函数不会出错,唯独主机名有可能获取失败。在目前的代码实现中,如果主机名获取失败,substrOfHostName 为 NULL,那 generate() 函数会返回类似“null-16723733647-83Ab3uK6”这样的数据。如果主机名获取失败,substrOfHostName 为空字符串,那 generate() 函数会返回类似“-16723733647-83Ab3uK6”这样的数据。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

重构ID生成器项目中的异常处理代码是本文的核心内容。文章首先讨论了generate()函数中主机名获取失败时返回NULL值的合理性,并提出了抛出受检异常的重构方案。其次,对getLastFieldOfHostName()函数和getLastSubstrSplittedByDot()函数进行了重构,加入了对异常情况的处理逻辑。通过这些重构,文章强调了全面、合理地处理各种异常能有效减少代码bug,提高代码的健壮性。重构后的RandomIdGenerator代码展示了对各个函数异常情况处理代码的重构,提供了实际的重构思路和方法。读者可以从中学习到更高层的软件设计和开发思想,以及对代码优化的追求。通过对一个简单的ID生成器代码的多次迭代重构,读者可以领悟到代码优化的重要性和价值。整体而言,本文通过具体的代码示例和分析,为读者提供了实际的重构思路和方法,有助于读者在实际开发中更好地处理异常情况,提高代码质量。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《设计模式之美》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(89)

  • 最新
  • 精选
  • Jxin
    还学到什么: 1.一下子想搞个例子讲这些真的太难了,拍着脑子想demo。栏主这个demo背景简单,也将要讲的内容串起来了,实属不易,幸苦栏主了。 个人见解: 1.按我的习惯,我会尽量把入参和中间不可靠变量的异常校验都放在public方法,所有私有方法都以契约的方式不再做参数校验。也就是说 public方法干 1.参数校验 2. 系统一级流程编排 3.统一异常处理 这三件事。所以对private方法的提炼会和栏主有点出入。 2.如果这个id生成器还要带有业务key,比如分表路由key之类的东西。那么这个实现就还得大动干戈。但凡这种涉及持久数据的玩意,很可能需要考虑新老版本兼容的问题,也就是如何平滑过度老数据。所以需要在id生成算法上引入版本或者类型的标记,把标记打在持久化的数据上,以备平滑过度老数据。

    作者回复: 我觉得你懂我~

    2020-01-27
    13
    212
  • 高源
    希望老师每节课举的代码有下载的地方,自己下载下来结合老师讲解的,自己理解体会其中的解决问题

    作者回复: 好的,等我俩月,我整理好,一块放到github上: https://github.com/wangzheng0822

    2020-01-27
    6
    10
  • 田园牧歌
    看了争哥专栏,受益匪浅,了解了如何评判一个项目、一段代码的好烂,如何写出高质量代码。但我有一个疑问,就是像这种基于接口而非实现的编程方式,在实际的业务项目中如何分包和模块呢?如果是静态方法的小算法我可以放到util包中,比如命名为IdGeneratorUtil.java

    作者回复: 划分模块跟划分类的方法一样,做到高内聚低耦合,职责单一。你可以参考面向对象设计的4个步骤来做模块的定义和划分。

    2020-06-24
    3
  • Kelly.W
    开发能用的代码可能会很快也比较简单。但想要开发出优秀的代码,就需要投入比较多的精力,一轮轮来优化。 能用的代码和优质代码之间最大的区别就在于细节,像这节课中讲到的异常抛出,特殊值处理等等都是细节。 这就是60分和100分的差别。

    作者回复: 嗯嗯

    2020-11-26
    2
  • Clear
    王老师好,我有一个问题: 根据函数是否关心异常类型,来判断异常是否需要转换抛出,会不会导致需要新增很多异常的类呢。

    作者回复: 会,但为了清晰、易于理解,多几个异常也未尝不可啊

    2020-06-21
    1
  • 空白昵称
    我觉得抛异常这件事,有点像开发经理的职责。下级有问题(异常)要反馈,然后自己能处理则处理(吞掉异常)。如果自己不能处理的,要向上级汇报,那么汇报的时候就要考虑,如果上级不关心底层研发问题,则上报自己汇总的问题(re-throw新的异常)。如果上级领导也是技术控,对底层很了解,那么可适当直接上报(直接re-throw下级反馈的异常)。
    2020-03-13
    7
    160
  • undefined
    个人见解:如果 id 生成器需要应用到生产环境,类似 hostname 获取失败的问题,需要由生成器本身给出降级方案。一来为了 id 格式统一,二来假若抛给业务,业务对于这种系统底层的失败,也没有什么好的解决方法。
    2020-02-01
    9
    58
  • Geek_kobe
    果然还是看技术文章能让恐慌的心静下来
    2020-01-27
    1
    26
  • Harvey
    设计之所以难是因为没有标准答案,很多权衡是依赖于具体业务的。这就是DDD的思想所在,要先想清楚问题域是什么在思考解决方案。很多开发讨论问题的时候没有层次,上来就陷入技术细节,这就叫缺乏抽象。下游系统要想清楚哪些是上游系统给你提供的服务?哪些是人家的内部技术实现?比如ID生成,作为上游系统,ID生成服务提供的是有小概率重复的随机ID服务,至于随机算法,下游系统不必关心,这是上游系统的内部实现,这样上游系统才有空间更换算法而不影响下游系统。
    2020-01-27
    3
    24
  • xk_
    很多小伙伴说,generate方法不需要抛出异常。 对,如果这个业务是仅仅只是作为唯一id,那么不管怎么样一定要生成一个随机数的。 那么,放开来想这个业务并非是一个id生成器,而是生成一个id业务码,这个id后面会用个主机名,对流量进行识别。争哥这么抛出异常,我觉得是可行的。还是要看具体的业务 再说一句,主机名还是一个很重要的东西,hadoop集群获取不到主机名,是一个很严重的问题。
    2020-03-16
    1
    13
收起评论
显示
设置
留言
89
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部