前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >开发实战|Java程序员如何通过工具选型控制开发成本

开发实战|Java程序员如何通过工具选型控制开发成本

原创
作者头像
六月暴雪飞梨花
修改2025-03-09 19:23:32
修改2025-03-09 19:23:32
6020
代码可运行
举报
运行总次数:0
代码可运行

引言

代码生成工具也是一个重点,像 LombokMapStruct 可以显著减少样板代码,提高开发效率。工具选型在我看来主打一个减少程序员劳动的性价比,应遵循“效率 > 维护 > 扩展”的优先级原则,首先应该以解决问题为主,提升软件开发效率;在解决问题之上再考虑后期维护成本,毕竟很多项目都是一次性项目;在维护基础上考虑增加不定或者扩展。作为一个Java程序员,可以在这里提供一些选型控制开发成本的建议,包括 构建工具、代码生成工具、单元测试工具、持续集成工具、性能分析工具、依赖管理工具、云服务/微服务成本控制、代码质量管理工具。

(图来自AI工具生成)
(图来自AI工具生成)

1 构建工具选型之效率

Maven vs Gradle 成本对比

  • 构建时间成本:在构建时间上,可以选择一个项目为蓝本,然后记录首次构建(冷启动)以及后续构建(热启动)的时间。
  • 增量构建成本:Maven 和 Gradle都支持增量构建,但Gradle在这方面可能更先进一些。可以尝试修改部分源代码后重新构建项目,并观察是否仅重新编译了必要的部分。
  • 内存与CPU资源消耗成本:使用系统监控工具来跟踪构建过程中内存和CPU的使用情况。了解哪一个工具对资源的需求更低,可以帮助在资源受限的环境中做出更好的选择。
  • 并行任务执行速度:Gradle默认支持并行任务执行,可以通过配置进一步优化性能;而Maven虽然也支持并行构建,但其灵活性和效果可能不如Gradle显著。
  • 文件配置复杂度:两者都有丰富的插件库,但是Gradle由于其基于Groovy或Kotlin DSL的脚本语言,提供了更高的自定义能力,检查你需要使用的特定插件在这两个平台上的可用性和成熟度。
  • 维护成本:maven使用较广泛,维护起来可能更简洁方便;相比之下,我对Gradle不是很熟悉,但是对Groovy语言还比较好,尤其是ivy语言的构建。
  • 版本统一:如果使用了构建工具,还需要统一版本号,减少依赖冲突排查时间。
(图来自AI工具生成)
(图来自AI工具生成)

Gradle成本优化配置示例

代码语言:javascript
代码运行次数:0
复制
// build.gradle 关键优化项  
tasks.withType(JavaCompile) {  
    // 避免反射性能损耗  
    options.compilerArgs += ["-parameters"] 
    // 启用增量编译  
    options.incremental = true             
}  

configurations.all {  
    // 动态依赖实时更新  
    resolutionStrategy.cacheChangingModulesFor 0, 'seconds' 
}

Maven vs Gradle 对比总结

指标

Maven

Gradle

构建速度

慢(XML解析)

快(增量编译+缓存)

配置复杂度

简单(约定优于配置)

灵活(Groovy/Kotlin)

维护成本

中(需学习DSL)

结论:中小型微服务项目选Maven,大型微服务选Gradle。

2 代码生成工具选型

代码生成工具,对于每一位开发者来说应该不陌生,本次推荐两款代码生成工具:Lombok 和 MapStruct。

Lombok

用途:实体自动生成方法

介绍:Java其实是一门很棒的语言(作为Java的软件开发者的我是这么认为),但是对于我们必须在代码中完成的常见任务或遵守一些框架实践,它有时会变得过于冗长、繁杂。这通常不会给我们程序的业务方面带来任何真正的价值,这就是Lombok解决问题后让我们更有效率的地方。例如我们的业务实体对象中的获取方法、设置方法、参数构造函数、对象转字符串等等。而使用代码生成工具可以使每个实体类成本减少80%代码量。

代码语言:javascript
代码运行次数:0
复制
@Data // 自动生成getter/setter/toString  
@Builder // 自动生成建造者模式  
public class User {  
    private Long id;  
    private String name;  
    private Integer age;  
}

MapStruct

用途:对象DTO转换自动化。

介绍:从官方提供的介绍来看MapStruct,Mapstruct是一个代码生成器,它极大地简化了基于约定优于配置方法的Javabean类型之间映射的实现,生成的映射代码使用普通方法调用,因此快速、类型安全且易于理解。减少手工转换代码,也能提升软件开发者的开发效率。

代码语言:javascript
代码运行次数:0
复制
@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();  
    }  
}

3 单元测试工具

JUnit 单元测试

JUnit 是一个很不错的单元测试工具,很多博主都写了相关博文来详细介绍,这里就提一嘴就好了。

(官网图)
(官网图)

Mockito 模拟库

Mockito 是一个java模拟库。Mockito的Mocked构建特性是对模拟框架的强大补充,允许开发人员模拟新对象的构建。此特性在方法在执行期间创建新对象的场景中特别有用,并且需要在测试期间控制该对象的行为。

(官网图)
(官网图)

JUnit 5 + Mockito最佳实践

成本控制点:

  • 参数化测试减少用例代码量
  • 合理Mock外部依赖,避免过度Mock导致测试脆弱
代码语言:javascript
代码运行次数:0
复制
@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);  
    }  
}

4 持续集成工具

Jenkins

持续集成工具不得不说的一个软件那就是Jenkins,它拥有很多官方提供的插件和第三方插件,这让他为自动化降本提供了有力的帮助。持续集成是一种软件开发实践,团队成员经常集成他们的工作(至少每天一次,尽管通常会进行多次日常集成)。

Jenkins + Pipeline模板优化

在持续集成和持续交付(CI/CD)实践中,Jenkins 和 Pipeline 一起使用可制定标准化流程,通过定义Pipeline模板,可以确保所有项目遵循相同的构建、测试和部署流程,减少人为错误。在预定义模板下,新项目的CI/CD设置变得非常简单,只需少量配置即可开始工作,大大缩短了项目上线准备时间。下面是一个示例:

代码语言:javascript
代码运行次数:0
复制
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}")  
                }  
            }  
        }  
    }  
}

5 性能分析工具

为什么需要性能分析,在性能分析中,可以借助工具帮助开发者识别瓶颈、监控资源使用情况、理解系统行为等,通过分析热点方法、内存使用情况等,针对性地进行代码优化,确保其高效稳定运行,让程序更加符合业务应用。

VisualVM

使用VisualVM可以快速定位性能瓶颈。例如静态变量的生命周期与应用程序相同,如果向静态集合中添加对象而不移除它们,这些对象将永远不会被垃圾回收,导致内存泄漏。

案例一

代码语言:javascript
代码运行次数:0
复制
// 典型内存泄漏模式  
public class CacheManager {  
    
    // 业务中的定义的静态集合,
    // 此处也没有适当的策略来限制缓存大小或者清除过期数据,
    // 缓存可能会无限增长,导致内存不足。
    private static final Map<String, Object> CACHE = new HashMap<>();  

    public void add(String key, Object value) {  
        // 未设置淘汰策略,那么这个变量则不会背GC回收。 
        CACHE.put(key, value); 
    }  
}

案例二

代码语言:javascript
代码运行次数:0
复制
// 典型的未关闭的I/O流、数据库连接等资源会占用系统资源
public class ResourceLeakExample {
    public void readFile() throws FileNotFoundException {
        FileInputStream fis = new FileInputStream("example.txt");
        // 忘记关闭fis,并且这些对象通常持有大量内存,此时可调用 fis.close();
    }
}

可以利用工具诊断步骤:

  1. 抓取Heap Dump
  2. 分析Dominator Tree
  3. 定位到CacheManager的HashMap

备注⚠️:一些性能问题优化小窍门,例如 及时清理不再使用的对象使用try-with-resources语句 弱引用(WeakReference)或软引用(SoftReference) 定期审查代码

Async Profiler CPU

Async Profiler 是一款高效、低开销的性能分析工具,特别适用于对Java应用程序进行CPU和内存剖析。

下面是一个产生火焰图精准定位CPU热点方法(其他方式方法或者用法可以参考官方提供资料)。

代码语言:javascript
代码运行次数:0
复制
./profiler.sh -d 30 -f flamegraph.html <PID>  

6 代码质量管理

代码的质量直接影响到软件的可维护性、稳定性和长期发展,那么如果选择代码质量检查工具也是一个至关重要的事情。而SonarQube来自动化检查代码规范也成为了我在技术层面的选择之一。

SonarQube

SonarQube减少技术债务积累、降低后期维护成本、发现潜在问题、分享知识、确保代码符合团队标准,可选择的配置如下:

代码语言:javascript
代码运行次数:0
复制
# 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

Checkstyle是一种开发工具,可以帮助程序员编写符合编码标准的Java代码。它自动化了检查Java代码的过程,以使人类免于这项无聊(但重要)的任务。这使得它成为想要强制执行编码标准的项目的理想选择。

Checkstyle的配置比较简单,搜索并下载配置,导入进去即可。

总结

其实,本篇主要借助前几期的互选题经验来组织,例如

第42期-版本控制与协作

第43期-高质量单元测试技巧

第46期-容器化与微服务的通用架构与优化

第47期-敏捷开发中的自动化测试

第49期-代码与数据传输安全

第50期-接口设计与性能优化

第54期-用最少的代码搞定最多的事!

第59期-代码审查(Code Review)

第61期-自动化部署与CI/CD

第63期-深入理解并发编程

第64期-微服务调试与监控实战

无论是是一个环节,都需要维持三大核心原则,即:

  1. 适配性:不求最先进,但求最适合团队现状;
  2. 可观测:所有工具必须支持Metrics导出;
  3. 可替代:避免供应商锁定,优先选开源方案;

前几期的博文写作的最终目的都是为了能通过工具选型来提高协助效率,控制开发成本,降低企业成本。

好了,就总结到这里了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 1 构建工具选型之效率
    • Maven vs Gradle 成本对比
    • Maven vs Gradle 对比总结
  • 2 代码生成工具选型
    • Lombok
    • MapStruct
  • 3 单元测试工具
    • JUnit 单元测试
    • Mockito 模拟库
    • JUnit 5 + Mockito最佳实践
  • 4 持续集成工具
    • Jenkins
    • Jenkins + Pipeline模板优化
  • 5 性能分析工具
    • VisualVM
    • Async Profiler CPU
  • 6 代码质量管理
    • SonarQube
    • Checkstyle
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档