《代码整洁之道》笔记(7-9章节)

2022-06-28 20:42:36 浏览数 (1)

本文最后更新于 388 天前,其中的信息可能已经有所发展或是发生改变。

错误处理

使用异常而非返回码

多个条件分支记录错误信息,可以封装进一个方法,在记录异常信息的地方抛出异常,并给出相应信息。在该方法外部捕获,记录异常信息。异常处理和正常业务流程隔离。

缩小异常类型,反例:全部使用Excception。

使用未检异常

代价:违反开闭原则。该方法调用链路上的方法签名都得修改。

给出异常发生的环境说明

应创建信息充分的错误信息,并和异常一起传递出去。

依调用者需要定义异常类

当一个被调用的方法会抛出多种异常时,可以封装下,只抛出一个自定义异常,之前的异常信息传递到自定义异常里。

定义常规流程

代码语言:javascript复制
try{
    MealExpense e=expenseReportDAO.getMeals(x);
    total =e.getTotal;
}catch(MealExpenseNotFound e){
    total =getMealPerDiem());
}

修改为

  1. 定义一个特例类:PerDiemMealExpenses,继承于MealExpense,并重写getTotal方法。
  2. 在GetMeals方法里不抛异常,而是返回特例类。这样就不用catch了。

当存在特殊情况时,由被调用方处理特殊情况,调用方只需使用常规流程即可。 特例模式:创建一个类或者配置一个对象,用来处理特例。

别返回null值

多处调用者需要做判空处理,这些是可以封装到被调用的方法里。例如:没有查询到数据时,就返回空列表。

别传递null值

如果禁止参数为null,如果为null,就抛出异常。此时可以使用更优雅的断言

小结

整洁代码时可读的,但也是强固的。可读与强固并不冲突。

例如返回空列表。

边界

使用第三方代码

第三方代码追求普适性,而使用者可能会有不同的定制化要求,这是矛盾的。为防止第三方提供的数据被随意修改,可将数据封装起来,提供操作数据的方法。例如以前提供一个Map,数据可能会被修改。现在将Map封装到类里,并提供可控的,有限的操作数据的方法,保证数据的安全。

另外还可提升扩展性,当存储数据的数据结构发生变动,不再是Map,此时只需修改操作数据的方法即可,不影响调用者。

不建议使用Map传参,这样传参,参数包含的数据是不可预知的。必要时可以封装下。

浏览和学习边界

通过编写测试来浏览和理解第三方代码。——学习性测试

学习性测试的好处不只是免费

编写学习性测试很容易了解第三方代码,并且当第三方代码更新时,我们可以运行学习性测试,看看程序的行为是否有变化。

使用尚不存在的代码

在开发过程中,需要与第三方交互,但是还没有定义相关接口。这种情况可以自己拟定接口,从而不影响自己的开发进度。在真正的接口定义好时,通过编写适配器,在我们自己拟定的接口和真正的接口中间转换下。

整洁的边界

如果有良好的软件设计,则无需巨大投入和重写即可进行修改。在使用我们控制不了的代码时,必须加倍小心保护资产,确保未来的修改不至于代价太大。 依靠你能控制的东西,好过依靠你控制不了的东西,免得日后受他控制。

单元测试

TDD三定律

第一定律:在编写不能通过的单元测试前,不可变械生产代码。 第二定律:只可编写刚好不可通过的单元测试,不能编译也算不通过。 第三定律:只可编写刚好足以通过当前失败测试的生产代码。

保持测试的整洁

测试代码和生产代码一样重要。

单元测试是敢于重构代码的底气。

整洁的测试

在单元测试中,可读性甚至比在生产代码中还重要。

测试方法中不要违背单一职责原则。构建数据,执行测试目标方法,校验结果,这些该抽取就抽取,要让测试代码易读。

权衡优雅和性能。

每个测试一个断言

这样会造成重复代码,可通过模板模式来解决,共性放在基类,特性放到派生类。还可以单独一个测试类,共性放到@Before里。

视情况而定,没有绝对的规定,需要权衡,把握那个度。

单元测试中的断言数量应该最小化。

每个测试一个概念,符合单一职责原则,使其在一个抽象层面。

FIRST

  • Fast:快速,测试应该快速运行。
  • Independent:独立,测试应该相互独立,不因有依赖关系。
  • Repeatable:可重复。
  • Self-Validating:自足验证,测试可以自己检查是否通过,不应依靠他人。例如输出结果,人为检查是否正确。
  • Timely:及时,单元测试应在生产代码前编写。

Post Views: 322

0 人点赞