避免修改构造函数输入参数引起的 breaking change

简介: 避免修改构造函数输入参数引起的 breaking change

本文记录我在工作中的一次失误。


如下图所示,我在构造函数里注入了一个新的依赖:


protected checkoutService: CheckoutService

c704e19e382143e7a8eb8a14e128484f.png

当下列情况同时满足时,客户就会遇到编译错误:


(1) 客户升级到了新的 minor 版本,即我引入该新的依赖的版本。

(2) 客户之前扩展了 CheckoutDeliveryService

(3) 客户在自己的扩展类的构造函数里,调用了 super 即父类的构造函数。


因为客户是从旧版本升级上来的,所以构造函数里没有传递我这个新版本引入的 checkoutService 输入参数,所以会遇到语法错误。


正确的做法如下图所示:


7576b226f0bd48d78d770c6fbc70c9ef.png

export class CheckoutDeliveryService implements CheckoutDeliveryFacade {
  constructor(
    protected checkoutStore: Store<StateWithCheckout>,
    protected processStateStore: Store<StateWithProcess<void>>,
    protected activeCartService: ActiveCartService,
    protected userIdService: UserIdService,
    @Optional() protected checkoutService?: CheckoutService
  ) {}

使用 @Optional 来修饰这个新引入的构造函数输入参数。

同时,在代码里的逻辑也需要改变,需要同时处理 checkoutService 为空或者不为空的情况。

  protected isCheckoutDetailsLoading$: Observable<boolean> = this
    .checkoutService
    ? this.checkoutService.isLoading()
    : this.checkoutStore.pipe(select(CheckoutSelectors.getCheckoutLoading));

如果 checkoutService 不为空,则使用 checkoutService.isLoading 返回的 Observable;否则,就为旧版本的情况,使用旧版本的实现,从 checkoutStore 里取出 checkout loading 的读取状态。


修改了服务代码之后,也会影响到对应的单元测试代码。


如今的 isSetDeliveryModeBusy 标志位,决定其值的输入条件之二,从 checkoutService.isLoading, 更改成了 isCheckoutDetailsLoading.


208f2e6b49314fe0b0b7e30c6c0b8c8c.png


因此,在单元测试代码里,我们需要创建一个全局的 isCheckoutLoading$ Observable 对象:


c13e33dd7d33467c873b338a1c1a5da4.png


然后创建一个 mockCheckoutService 类,内部返回这个全局的 isCheckoutLoading$ Observable 对象。


1c9eafab15b24ee7adf8d69469bd5fd7.png


这样,在任何时候我们需要修改 CheckoutService.isLoading 的返回值时,通过调用 isCheckoutLoading$ 的 next 方法即可灵活控制。


fd06057ae0cc457dbe04484a7f2c4418.png


需要强调的是,在大型 API 中保持稳定性是一项挑战。 如果您要更改 API 库,请考虑更改的广泛后果,并尝试预测可能出现的任何问题。

相关文章
解决办法:对lzma_stream_decoder/lzma_code/lzma_end未定义的引用
解决办法:对lzma_stream_decoder/lzma_code/lzma_end未定义的引用
161 0
|
测试技术 API
避免修改构造函数输入参数引起的 breaking change
避免修改构造函数输入参数引起的 breaking change
82 0
避免修改构造函数输入参数引起的 breaking change
成功解决 cl: 命令行 error D8021 :无效的数值参数“/Wno-cpp” 和 cl: 命令行 error D8021 :无效的数值参数“/Wno-unused-function”
成功解决 cl: 命令行 error D8021 :无效的数值参数“/Wno-cpp” 和 cl: 命令行 error D8021 :无效的数值参数“/Wno-unused-function”
成功解决 cl: 命令行 error D8021 :无效的数值参数“/Wno-cpp” 和 cl: 命令行 error D8021 :无效的数值参数“/Wno-unused-function”
|
C++
Effective C++学习笔记之copy构造函数和default函数和copy赋值函数(operator=)
Effective C++学习笔记之copy构造函数和default函数和copy赋值函数(operator=)
116 0
在SAP Spartacus的convertor函数里,直接修改输入参数target的值,会有什么问题
在SAP Spartacus的convertor函数里,直接修改输入参数target的值,会有什么问题
122 0
在SAP Spartacus的convertor函数里,直接修改输入参数target的值,会有什么问题
VS2017报错:严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C4996 'strcpy': This function or variable may be unsafe. Consid
VS2017报错:严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C4996 'strcpy': This function or variable may be unsafe. Consid
550 0
修改sequenc number
create or replace procedure CHANGE_SEQ_NUMBER( PI_SEQ_OWNER VARCHAR2 , PI_SEQNAME VARCHAR2 , PI_LAST_NUMBER NUMBER) IS V_LastValue integer; V_incr...
655 0
重构——47以明确函数取代参数(Replace Parameter with Explicit Methods)
以明确函数取代参数(Replace Parameter with Explicit Methods):你有一个函数,其中完全取决于参数值而采取不同的行为;针对该参数的每一个可用值,建立一个独立函数
1821 0
重构——50引入参数对象(Introduce Parameter Object)
引入参数对象(Introduce Parameter Object):Range模式;某些参数总是很自然的同时出现;以一个对象取代这些参数
1697 0