你没看错就是这个题目即使是Java系统也会变成遗留系统每当我们想起遗留系统时我们就会想起那些存储着大量文件数据并只能用COBOL访问的嘎吱嘎吱作响的大型主机但事实是Java已经是一门具有年历史的开发语言用Java写就的成千上万的系统已经成功运行了十年甚至更久
因此考虑到许多读者都会工作在某个遗留的Java系统上我根据自己的经验特地攒了这八个技巧来帮助团队更新和激活他们的遗留Java应用
技巧使用分析器
分析器提供了任何其他工具无法提供的功能从而能够深入检查你的应用如果你的应用已经有一年多时间没有被分析过了那么它肯定会有大块大块的低效代码潜伏在某个黑暗的角落市面上有许多不同的或免费或商业的分析器对于CPU分析我最喜欢的是JProfiler因为它足够强大能分析出大多数问题同时易于设置尤其当你使用它内建的设置向导的时候而诊断内存问题时我最亲睐的工具是Eclipse Memory Analyzer因为它使用的是记录在磁盘上的索引而不是把整个堆的快照放到内存中
通常来说隐藏着的易耗尽CPU的代码包括低效的hashCode()或者equals()方法(在卷动JTable时以及使用Java collection类时它们会被调用上百万次)以及一些出人意料的出自Sun之手的低效类比如SimpleDateFormat
分析器可能会明显地让你的应用变得很慢所以你一定要在测试环境中使用它
技巧监控数据库使用状况
分析器除了可以显示你的应用过度占用CPU时钟的细节它们也可以对你的应用在哪些地方长时间做了数据库的操作给出提示但更好的用来监控数据使用的工具是像Proactive DBA或者HP Diagnostics或者任何其他来自于你的数据库产品厂商的工具这些工具可以告诉你哪些代码做了长时间的SQL调用以及哪些代码在短时间内对同一行做了多次调用来自数据库厂商的工具还可以帮助发现那些阻塞了其他调用的查询虽然在我的经验里这样的阻塞问题基本不过是些简单的低效的SQL用法
我写了一个新的工具叫做jdbcGrabber它可以让你以可视化的形式描述出哪些代码正在访问哪些数据表通过这种可视化呈现你可以很容易发现那些多次访问数据库中不同部分信息的代码从而将其调整为一次合并的请求
技巧构建和部署自动化
许多遗留系统缺乏一种完全自动化的方式来构建它们的代码更不用说自动部署了自动化构建和部署对于提高遗留系统开发者的效率来说是一种简单直接而又低风险的方式而且通常不需要修改代码
没有自动化的构建和部署过程新的开发者不得不重新发明轮子跟那些前辈们早就斗争过的同样问题重新来斗而且每次重复的部署问题发生开发者都会发明出不同的解决方案
虽然Maven是一款卓越的而且使用广泛的构建工具但它对你的源码树结构以及库依赖有着固执的要求所以把它用在遗留应用中会有点困难但足够优秀的Ant应该更易于使用因为它处理起遗留代码结构更加灵活也更容易部分采用而不是全盘采用
技巧自动化你的操作并使用JMX
另外一种提高遗留应用的效率但不会带来修改代码的风险的方式是改善它的运维许多内部开发的企业系统一般都需要大量出人意料的手把手指导和维护即使这样是不应该的
既有的Java功能可以通过使用JMX很容易地暴露给负责运营的人们而不会带来负面影响许多开发者对JMX比较熟悉是因为他们用JMX来跟JBoss和WebLogic这样的应用服务器进行交互但他们不清楚把JMX用在他们自己的应用中是多么方便任何Java class都可以通过JMX暴露出来几乎没什么负面效果也没有什么风险
比如如果你的应用有一个本地的静态HashMap作为cache你就可以通过JMX来暴露功能从而很容易地清除那个cache
一旦应用通过JMX暴露运维团队或者开发者就可以以良好的方式来操作应用无需直接访问运行着应用的机器
技巧创建单元测试
一旦你对遗留系统的修改破坏了某个功能你所面临的最大障碍之一就来到了一些工具宣称能对代码进行反向工程并为其创建单元测试但我对这些工具没有太多的信心要想有足够的信心你的单元测试的确覆盖了你期望它们覆盖的代码你就不得不亲自创建它们
很幸运为遗留代码创建单元测试并没有一开始感觉上的那样困难我使用了Michale Feathers在Working Effectively with Legacy Code一书中讲解的遗留代码修改算法
确认修改点
找出测试点
打破依赖
编写测试
修改并重构
有效使用这个算法的窍门在于第点打破依赖有很多技术可以用来干这个但其中大多数都是关于移除静态引用以及在接口和facade下隐藏外部引用和复杂代码一旦你具有这样打破依赖的感觉了接触遗留代码就不会是一件让你提心吊胆的事情了
技巧杀死无用代码
虽然无用代码可能看起来无害但它们实际上往往会是无声的杀手原因在于只要无用代码还在代码库中负责维护的程序员就不会非常确信代码是真的无用还是只是看起来无用感受过前几次修改所带来的痛苦的维护者都知道即使是静态代码分析也不能证明代码是真的无用了比如十年前一些聪明的程序员可能会通过数据库中的字符串值来驱动Java reflection调用业务逻辑(别笑我不止一次看到过这样)
因此杀死无用代码应用是第一优先级的任务虽然Emma通常被认为是一种单元测试覆盖工具但它可以用来侦测无用代码当你把Emma注入到JVM中它就可以追蹤到哪些代码执行了哪些没有在你的开发环境中把Emma和一个完整的测试周期相结合使用你就会知道哪些代码活着还是死了
技巧采用一种顺从方式构建代码
遗留应用不可能一次清理完毕在现实中开发团队必须利用任何一次机会来改善遗留代码但许多团队对目前代码的情况都倍感失望而无法考虑他们究竟该怎么做代码实在太糟糕了开发者说
冷漠是最大的错误遗留应用之所以还存活着是因为它们依然有用而且和所有有用的应用一样他们的用户会继续想要修改它们如果团队抓住机会定义一个可以达到的愿景希望应用会是什么样子然后做出逐步增量的改变他们就会离距离最终的愿景更进一步
没有这样的愿景团队的每个成员就会做出任何他/她所认为最正确的事情一个人会使用Spring JdbcTemplate而另一个人会开始使用iBATIS/MyBatis虽然每个人都真正期望改善这个应用但事实上他们会让事情变得更糟因为他们是在不同的方向上使力使已经复杂的结构更加混乱
技巧升级你的JRE
当我告诉一些团队Sun(现在是Oracle)早在年月就已经宣称不在继续对JDK 的支持时他们仍然觉得惊讶不已这不仅仅是立刻要升级JRE到的事情那些历经磨难的团队还记得从升级到或者升级到时所发生的一切他们可能对这样的升级还感到犹豫但我的经验是这样的升级会很平滑而且会给应用带来一次显着的免费的性能飞跃另外JDK 还带来许多有用的免费的运维和分析工具来帮助诊断那些你这些年一直备受困扰的垃圾回收问题
八个技巧之外
上面精心挑选出来的每个技巧基本都是易于采用并风险相对要低但还有很多其他的方式来改善遗留应用让应用改善后看起来就像是新的一样
首先现在的开放源代码库生态系统给过去大部分的遗留Java系统带来了生机许多遗留系统会有土生土长完全自定义的各种子系统工作流引擎规则引擎模板引擎用户接口框架以及对象关系映射层等等这些土生土长的组件中的任意一个都可以被一个免费的开放源代码库替换掉而且更加智能并足够强壮这样一对一的替换可以很大程度上消除一次全部替换所带来的维护上的困难
其次是时候好好看看你自己的遗留应用的设计问题了虽然改变设计远比仅仅升级JRE要复杂得多但它也会给你的投资带来更大的回报对于大量逻辑都存储在数据库存储过程中的应用可以考虑把那些逻辑提高到应用层从而可以受益于集群服务器并更容易进行单元测试如果一个设计把表示层跟业务逻辑层绑定得太紧那你就可以把它们分开这样增加新潮的iPhone界面也会很容易实现在各个子系统之间的同步调用也可以转换成异步基于消息的调用这在弹性和性能上都会是重要的改善
最后为了让你从Java遗留应用中多活两到四年我建议你雇佣一个对这样系统有经验的专家就像一个外科医生做精妙的大脑手术一样有经验的专家通常可以为遗留系统中的问题找到更好的解决方案从而带来更多的好处以及低风险