代码生成工具也是一个重点,像 Lombok
和 MapStruct
可以显著减少样板代码,提高开发效率。工具选型在我看来主打一个减少程序员劳动的性价比,应遵循“效率 > 维护 > 扩展”的优先级原则,首先应该以解决问题为主,提升软件开发效率;在解决问题之上再考虑后期维护成本,毕竟很多项目都是一次性
项目;在维护基础上考虑增加不定或者扩展。作为一个Java程序员,可以在这里提供一些选型控制开发成本的建议,包括 构建工具、代码生成工具、单元测试工具、持续集成工具、性能分析工具、依赖管理工具、云服务/微服务成本控制、代码质量管理工具。
Gradle成本优化配置示例
// build.gradle 关键优化项
tasks.withType(JavaCompile) {
// 避免反射性能损耗
options.compilerArgs += ["-parameters"]
// 启用增量编译
options.incremental = true
}
configurations.all {
// 动态依赖实时更新
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
指标 | Maven | Gradle |
---|---|---|
构建速度 | 慢(XML解析) | 快(增量编译+缓存) |
配置复杂度 | 简单(约定优于配置) | 灵活(Groovy/Kotlin) |
维护成本 | 低 | 中(需学习DSL) |
结论:中小型微服务项目选Maven,大型微服务选Gradle。
代码生成工具,对于每一位开发者来说应该不陌生,本次推荐两款代码生成工具:Lombok 和 MapStruct。
用途:实体自动生成方法
介绍:Java其实是一门很棒的语言(作为Java的软件开发者的我是这么认为),但是对于我们必须在代码中完成的常见任务或遵守一些框架实践,它有时会变得过于冗长、繁杂。这通常不会给我们程序的业务方面带来任何真正的价值,这就是Lombok解决问题后让我们更有效率的地方。例如我们的业务实体对象中的获取方法、设置方法、参数构造函数、对象转字符串等等。而使用代码生成工具可以使每个实体类成本减少80%代码量。
@Data // 自动生成getter/setter/toString
@Builder // 自动生成建造者模式
public class User {
private Long id;
private String name;
private Integer age;
}
用途:对象DTO转换自动化。
介绍:从官方提供的介绍来看MapStruct,Mapstruct是一个代码生成器,它极大地简化了基于约定优于配置方法的Javabean类型之间映射的实现,生成的映射代码使用普通方法调用,因此快速、类型安全且易于理解。减少手工转换代码,也能提升软件开发者的开发效率。
@Mapper
public interface UserConverter {
UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);
@Mapping(source = "birthDate", target = "age", qualifiedByName = "calculateAge")
UserDTO toDTO(User user);
@Named("calculateAge")
default int calculateAge(LocalDate birthDate) {
return Period.between(birthDate, LocalDate.now()).getYears();
}
}
JUnit 是一个很不错的单元测试工具,很多博主都写了相关博文来详细介绍,这里就提一嘴就好了。
Mockito 是一个java模拟库。Mockito的Mocked构建特性是对模拟框架的强大补充,允许开发人员模拟新对象的构建。此特性在方法在执行期间创建新对象的场景中特别有用,并且需要在测试期间控制该对象的行为。
成本控制点:
@ExtendWith(MockitoExtension.class)
class PaymentServiceTest {
@Mock
private RiskControlClient riskControlClient;
@InjectMocks
private PaymentService paymentService;
@ParameterizedTest
@CsvSource({"100, true", "1000000, false"})
void testPayAmount(long amount, boolean expected) {
when(riskControlClient.check(any())).thenReturn(new RiskResponse(200, "OK"));
assertThat(paymentService.pay(amount)).isEqualTo(expected);
}
}
持续集成工具不得不说的一个软件那就是Jenkins,它拥有很多官方提供的插件和第三方插件,这让他为自动化降本提供了有力的帮助。持续集成是一种软件开发实践,团队成员经常集成他们的工作(至少每天一次,尽管通常会进行多次日常集成)。
在持续集成和持续交付(CI/CD)实践中,Jenkins 和 Pipeline 一起使用可制定标准化流程,通过定义Pipeline模板,可以确保所有项目遵循相同的构建、测试和部署流程,减少人为错误。在预定义模板下,新项目的CI/CD设置变得非常简单,只需少量配置即可开始工作,大大缩短了项目上线准备时间。下面是一个示例:
pipeline {
agent any
stages {
stage('Build') {
steps {
sh './gradlew clean build -x test' // 跳过测试加快构建
}
}
stage('Parallel Test') {
parallel {
stage('Unit Test') {
steps {
sh './gradlew test'
}
}
stage('Integration Test') {
steps {
sh './gradlew integrationTest'
}
}
}
}
stage('Docker Build') {
steps {
script {
docker.build("myapp:${env.BUILD_ID}")
}
}
}
}
}
为什么需要性能分析,在性能分析中,可以借助工具帮助开发者识别瓶颈、监控资源使用情况、理解系统行为等,通过分析热点方法、内存使用情况等,针对性地进行代码优化,确保其高效稳定运行,让程序更加符合业务应用。
使用VisualVM可以快速定位性能瓶颈。例如静态变量的生命周期与应用程序相同,如果向静态集合中添加对象而不移除它们,这些对象将永远不会被垃圾回收,导致内存泄漏。
案例一
// 典型内存泄漏模式
public class CacheManager {
// 业务中的定义的静态集合,
// 此处也没有适当的策略来限制缓存大小或者清除过期数据,
// 缓存可能会无限增长,导致内存不足。
private static final Map<String, Object> CACHE = new HashMap<>();
public void add(String key, Object value) {
// 未设置淘汰策略,那么这个变量则不会背GC回收。
CACHE.put(key, value);
}
}
案例二
// 典型的未关闭的I/O流、数据库连接等资源会占用系统资源
public class ResourceLeakExample {
public void readFile() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("example.txt");
// 忘记关闭fis,并且这些对象通常持有大量内存,此时可调用 fis.close();
}
}
可以利用工具诊断步骤:
备注⚠️:一些性能问题优化小窍门,例如 及时清理不再使用的对象
、 使用try-with-resources语句
、弱引用(WeakReference)或软引用(SoftReference)
、 定期审查代码
。
Async Profiler 是一款高效、低开销的性能分析工具,特别适用于对Java应用程序进行CPU和内存剖析。
下面是一个产生火焰图精准定位CPU热点方法(其他方式方法或者用法可以参考官方提供资料)。
./profiler.sh -d 30 -f flamegraph.html <PID>
代码的质量直接影响到软件的可维护性、稳定性和长期发展,那么如果选择代码质量检查工具也是一个至关重要的事情。而SonarQube来自动化检查代码规范也成为了我在技术层面的选择之一。
SonarQube减少技术债务积累、降低后期维护成本、发现潜在问题、分享知识、确保代码符合团队标准,可选择的配置如下:
# sonar-project.properties
sonar.qualitygate.wait=true
sonar.qualitygate.timeout=600
# 质量阈值
sonar.qualitygate=
reliability_rating < 3;
security_rating < 3;
coverage >= 80%;
其他的码审查工具如 GitHub Pull Requests、GitLab Merge Requests,在提交代码时每次提交只包含一个小功能或修复,并说明改动的原因和背景,也可以降低后期维护成本。
Checkstyle是一种开发工具,可以帮助程序员编写符合编码标准的Java代码。它自动化了检查Java代码的过程,以使人类免于这项无聊(但重要)的任务。这使得它成为想要强制执行编码标准的项目的理想选择。
Checkstyle的配置比较简单,搜索并下载配置,导入进去即可。
其实,本篇主要借助前几期的互选题经验来组织,例如
第42期-版本控制与协作
第43期-高质量单元测试技巧
第46期-容器化与微服务的通用架构与优化
第47期-敏捷开发中的自动化测试
第49期-代码与数据传输安全
第50期-接口设计与性能优化
第54期-用最少的代码搞定最多的事!
第59期-代码审查(Code Review)
第61期-自动化部署与CI/CD
第63期-深入理解并发编程
第64期-微服务调试与监控实战
无论是是一个环节,都需要维持三大核心原则,即:
前几期的博文写作的最终目的都是为了能通过工具选型来提高协助效率,控制开发成本,降低企业成本。
好了,就总结到这里了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。