如何开发一个高质量的公共组件

我们在开发过程中为了 避免造轮子,往往会开发一些公共组件,将大家都用到的、重复性的代码封装到公共组件中。优秀的公共组件确实可以大大提高代码的重用率,节省开发时间,提高开发效率,但是在实际开发中,却经常听到抱怨:为什么引入你的组件服务无法启动;无法对你的组件二次开发;想要禁用组件的某些功能。本文将深入探讨如何开发一款优秀的公共组件,并分享一些关键步骤和最佳实践。

易用性

作为JAVA应用开发的同学对SpringBoot应该再了解不过了,它提供了自动化配置和约定大于配置的方式可以让我们快速开发;自动化配置功能可以让开发人员不需要编写大量的XML配置文件,减少了配置的复杂性和出错的可能性。同时,SpringBoot也提供了许多默认的配置选项,使得开发人员可以很方便地配置和管理应用程序的各个方面。

自动装配

SpringBoot在启动的时候提供了SPI机制,在服务启动的时候会扫描resource/META-INF文件夹下的spring.factories文件,该类必须是一个配置类@Configuration,以该类作为切入点,开始加载其他组件。

image-20240303094054118

我们在加载Bean的时候要遵循最少依赖的原理和自适应加载。比如很多开发同学在配置Spring扫包的时候直接配置了根目录,这样会导致项目中大量的不需要甚至根本不会执行的Bean加载到了容器中,给JVM更加了负担。

自适应激活

我们来思考一下,如果我引用了你的Starter,但是又不想使用其功能,或者在某个调试的时候希望关闭这个功能,难道还需要在maven中将该依赖移除?SpringBoot的自适应装配,可以根据依赖的环境或者其他配置来决定是否加载该配置。我们来看下Redis提供的Starter,只有配置了Redis连接等信息的时候才会加载Redis配置,这样使用其他更灵活。

image-20240303095116334

灵活控制

Spring 的 @ConditionalXXX可以帮我们灵活的控制Bean的加载:

  • @Conditional:用来标识一个 Spring Bean 或者 Configuration 配置文件,当满足指定的条件才开启配置。
  • @ConditionalOnBean:组合 @Conditional 注解,当容器中有指定的 Bean 才开启配置。
  • @ConditionalOnMissingBean:组合 @Conditional 注解,和 @ConditionalOnBean 注解相反,当容器中没有指定的 Bean 才开启配置。
  • @ConditionalOnClass:组合 @Conditional 注解,当容器中有指定的 Class 才开启配置。
  • @ConditionalOnMissingClass:组合 @Conditional 注解,和 @ConditionalOnMissingClass 注解相反,当容器中没有指定的 Class 才开启配置。
  • @ConditionalOnWebApplication:组合 @Conditional 注解,当前项目类型是 WEB 项目才开启配置。

有了@ConditionalXXX我们可以在组件底层提供一个默认的Bean加载,如果底层提供的Bean不符合我们的要求,我们可以自定义一个Bean,这样组件中默认的Bean会自动失效,以此来达到定制化开发的目的。

image-20240303101344506

默认配置、集中管理

我们在项目中会多或少的会引用一些配置,然后这些配置通过@Value注入到项目中。我在项目中看到比较多的是在一个Bean(如Service或者Controller)中使用@Value将某个变量加载进来,如果这个变量值是可以动态刷新的,还会在Bean上加上@RefreshScope,在绝大多数场景下,这样使用代码是能正常运行的,但是如果你知道它的运行原理,你可能就会对这种用法产生怀疑。

@RefreshScope是将这个类做了一层代理,当监听到环境变量改变时,会将这个Bean注销掉,然后重新注册Bean,那么你的Service或Controller就会在容器中频繁的创建销毁你觉得合理么?

另外,我们代码中@Value随处可见,会导致我们的项目有多少配置就连开发者自己也不清楚,所以我们应该将同一类配置抽到一个XXXProperties类中,比如在RedisProperties中,我们很清晰的就知道了Redis客户端为我们提供了哪些配置。

image-20240303105152227

单元测试

我们在提供一个公共组件,要确保这个组件质量是可靠的,就要经过详细的测试,针对SDK的测试,通过完善的单元测试来保证交付的可靠性。单元测试有如下指标:

  1. 测试覆盖率
    • 语句覆盖率:每个语句是否至少被执行了一次。
    • 分支覆盖率:每个可能的代码分支是否都被执行了。
    • 条件覆盖率:每个布尔子表达式的每个可能结果是否都出现过。
    • 路径覆盖率:所有可能的执行路径是否都被执行了。这个指标通常很难达到100%,因为随着代码复杂性的增加,可能的路径数量会急剧增加。
    • 函数覆盖率:每个函数或方法是否都被调用了至少一次。
  2. 断言密度
    断言是单元测试中的检查点,用于验证代码的行为。断言密度是指测试用例中断言的数量与测试用例代码量的比例。较高的断言密度通常意味着更严格的测试。
  3. 测试运行时间
    单元测试的执行速度是一个重要指标。理想情况下,单元测试应该运行得足够快,以便开发人员可以频繁地运行它们而不会中断工作流程。
  4. 测试独立性
    单元测试应该是相互独立的,一个测试的失败不应该影响其他测试的执行或结果。测试的独立性有助于准确地定位问题。
  5. 代码质量指标
    单元测试的代码本身也应该遵循良好的编码实践,包括可读性、可维护性和可扩展性。有时候,代码质量工具(如SonarQube)可以用于评估测试代码的质量。
  6. 测试可重复性
    单元测试应该是可重复的,意味着在任何环境下运行都应该产生相同的结果。这确保了测试的可靠性和一致性。

总结

优秀公共组件是软件开发过程中的重要资产,它们能够提高开发效率、保证软件质量和降低维护成本。为了实现这些目标,开发者应关注组件的可复用性、可扩展性、可维护性、性能优化和兼容性等关键特性,并在实践中遵循设计原则、编写文档、测试覆盖、版本管理和社区支持等最佳实践。通过不断地完善和优化公共组件,我们可以为软件开发项目提供稳定、高效和可持续的基础支持。

、编写文档、测试覆盖、版本管理和社区支持等最佳实践。通过不断地完善和优化公共组件,我们可以为软件开发项目提供稳定、高效和可持续的基础支持。

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值