发布在即!企业 AIGC 应用程度测评,3 步定制专属评估报告。抢首批测评权益>>> 了解详情
写点什么

程序员开发大型应用程序的技巧

  • 2012-04-24
  • 本文字数:4245 字

    阅读完需:约 14 分钟

假如你是一名 Java 开发者,正在开发和维护包含 2000 个类并使用了很多框架的应用程序。你要如何理解这些代码呢?在典型的 Java 企业项目小组中,大部分能够帮你的高级工程师看起来都很忙,文档也很少。你需要尽快交付成果,并向项目组证明自己的能力。你会如何处理这种状况呢?这篇文章为开始开发新项目的 Java 开发者提供了一些建议。

1. 不要试图一下子搞懂整个项目

仔细考虑一下,为什么你会想要先理解项目代码呢?大部分情况是有人要求你修复一个 bug,或者增强系统已有功能。你要做的第一件事情不是理解整个项目的架构。当对项目进行维护时,这样做(理解整个项目架构)可能会对你造成巨大的压力。

即便是有 10 年编程经验的 Java 开发者,也无法理解项目的核心工作机制,尽管他们可能已经在这个项目工作超过一年(假设他们并非最初的开发人员)。比如,对于认证机制或事务管理机制还是缺乏确切的认识。

他们是怎么做的呢?他们对于自己负责的部分非常了解,并且能够交付价值给小组。每天的交付价值远比了解一些以后还不确定有没有的东西重要的多。

2. 关注于尽快交付价值

那我是要打消你对于理解项目架构的热情吗?完全不是。我只是要求你尽早地交付价值,一旦你开始一个项目,搭建了开发环境,你就不应该花一两周时间才交付内容,无论它的规模大小如何。假如你是一位有经验的程序员,却两周都没有任何交付,你的经理怎么会知道你是真的在工作,还是在看新闻呢?。

所以交付能够将事情变得简单。不要认为在做有价值的交付前,你必须理解整个项目。这是完全错误的。加一段 javascript 的验证代码对业务就很有价值,经理能够通过你的交付对你更加信任。这样能够向上级领导证明你的贡献以及员工价值。

日复一日,在不断修复 bug 及增强功能之后,你就能够慢慢开始理解项目架构。不要低估对系统方方面面理解时需要花费的时间。花 3 到 4 天理解认证机制,2 到 3 天理解事务管理。这些都是依靠之前的相似项目的经历,但关键还是要花时间才能透彻的理解。要在日常工作中挤出时间,不要向经理要求特定的时间来做这些。

找找项目是否有一些有效维护的单元测试用例。有效的单元测试用例是理解大型项目代码很好的途径。单元测试能够帮助你理解代码片段,包括一个单元的外部接口(单元如何被调用以及返回内容)及其内部实现(调试单元测试比调试整个实际用例简单许多)。

你如果能够很好的理解一些内容,那么就写些笔记,或者画些类图、时序图、数据模型图等,以便你或日后其他的开发者可以进行维护。

3. 维护大型项目所必须的技能

你能从事当前的工作,必然已经具有良好的 java 技术。我们来谈谈能够让你在新项目中良好表现的其他技能。大部分时间里,你在项目中的任务是修复 bug 和增强功能。

有两项很重要的技能能够在你维护大型项目代码起到帮助。

3.1 能够迅速发现需要的类

在任何维护活动中,无论是修复 bug 或增强功能,第一件事情就是识别出当前修复或增强的用例中调用的类。当你定位到需要修复或增强的类 / 方法,就已经完工了一半。

3.2 能够分析变更的影响

当你在完成必要的修改或增强工作后,最重要的就是要确认你的修改没有破坏代码的其他部分。你要用你的 java 技术及对其他框架的理解找出变更可能影响的部分。下面两个简单的例子详细描述了最后提及的情况:

  • 当类 A 的 equals() 方法变更后,调用保存 A 实例的 List 的 contains() 方法时就会受到影响。若 Java 知识不够,就很难考虑到这样的影响。
  • 在 web 项目中,我们假设“user id”保存在 session 中。新加入的程序员可能在“user id”中加入一些信息来修复 bug,但是却不知道那会影响到 与“user id”关联的用例。

因此,既要深入了解 Java 语言,又要深入了解你在应用中使用的框架,这样才能分析出一个改变的影响。

当你提高了如上两个技能,尽管你对项目不是非常了解,但大部分的维护任务会变得简单很多。如果你想要修复一个 bug,就会定位并修复这个 bug,并且保证变更不会破坏项目的其他部分。如果你想要增强或加入特性,基本上你只需要模仿现有的特性,使用类似的设计。

在一个在线银行项目中,为什么“查看账户摘要”和“查看交易历史”的设计要有巨大的差别呢?如果你理解了“查看账户摘要”的设计,完全可以模仿开发出“查看交易历史”的功能。

就修复 bug 和增强来说,你不必完全理解所有 2000 个类的工作内容和代码驱动系统运行的原理。只要有上面的技能,你就能很快定位需要修改的代码,使用良好的 java 和框架技能修复,保证变更不会破坏项目的其他部分,然后交付,尽管你可能只知道一小部分项目的设计。

4. 使用工具找到所需变更内容以及变更产生的影响

继续我们尽快交付的主题,你应该寻找工具作为辅助,只需要对项目又很少理解,就能帮助你尽快实施交付。

4.1 迅速发现所需变更内容的工具

无论是修复 bug 还是增强系统,首先你都要找到该用例调用且需要修改的类及方法。基本上有两种方式理解用例的工作方式,静态代码分析和运行时分析。

源码分析统计会扫描所有代码并且展现类之间的关系。市场上有很多工具。比如:Architexa、AgileJ、UModel、Poseidon 等。

所有静态代码分析工具的缺点在于,它们无法确切展现 用例中类或方法的运行时调用情况。因此 Java 新加入了一些特性,如回调机制(callback patterns)。比方说,静态分析工具无法推断出当前页面提交按钮被点击时,会调用哪个 Servlet。

运行时分析工具能够展现类和方法在用例运行时的状态。这样的工具包括:MaintainJ、Diver、jSonde、Java Call Tracer 等。这些工具可以捕获运行时的堆栈状态,并以此为用例生成序列图和类图。

序列图会展现该用例在运行时所有调用的方法。如果你在修复 bug,那么这个 bug 很可能就是这些被调用的方法之一。

如果你在增强已有功能,可能是新增验证,修改 DAO 等,那么就可以利用序列图理解调用流程然后再修改。

如果你在新增功能,那么就可以找到一些相似的特性,利用序列图理解调用流程,然后模仿开发新功能。

要仔细地挑选运行时分析工具。信息过多是这类工具的主要问题。选择一些工具,能够提供简单的信息,过滤掉无效信息,并能够方便的查看各种视图。

4.2 发现变更产生影响的工具

若单元测试有效,你就可以通过运行单元测试发现变更有没有破坏其他测试用例。有效维护并且覆盖大型企业应用的单元测试还是比较少的。下面有一些针对该情况的工具。

在此,仍然是有两种技术——静态代码分析和运行时分析——可以使用。市场中有很多静态代码分析工具可用。如:Lattix、Structure101、Coverity、nWire 和 IntelliJ’s DSM。

对于变更后的类,上述工具均可识别对该类存在依赖的类的集合。开发者需要根据这些信息“猜测”可能产生影响的用例,因为这些工具无法展示运行时类之间的调用关系。

市场上可以用于运行时影响分析的工具并不多,可能只有 MaintainJ。MaintainJ 先会捕获在用例中调用的所有类和方法。当所有用例的上述信息都被捕获之后,就很容易发现类的变更对用例的影响。MaintainJ 能够有效工作的前提条件就是项目的所有用例都应当先运行一遍,以便能够获得运行时的依赖关系。

总之,目前你在迅速准确分析变更影响方面,还是可以从工具中获得有限的帮助。首先根据需要实施一些影响分析,然后根据自己或小组其他高级成员评审来判断变更的影响。你可能需要使用上述工具对你的判断进行反复确认。

5. 对上述内容的两个忠告

5.1 不要降低代码质量

为了快速交付,可以不全盘理解架构,但绝不能以降低代码质量为条件。下面是一些你可能因为只考虑快速交付而引发的代码质量问题。

因为修改代码涉及到很多的依赖关系,所以新增代码相对而言风险较小。例如,有五个用例都调用了某个方法。为了改进某个用例,你需要修改这个方法的实现。最简单的做法就是复制这个方法,重命名,然后在改进的用例中调用新方法。千万不要这么做。代码冗余绝对是非常有害的。你要尝试对方法进行包装或者重写,甚至是直接修改,然后重新测试所有用例,通常停下来想一想,然后亲手去实施,是一种不错的方式。

另一个例子是将“private”方法改为“public”,让别的类也可以调用。尽量不要将非必须的部分暴露出来。假如是为了更好的设计而需要重构,那么就应当着手去做。

大部分应用都有确定的结构和模式来实施。修复或增强程序时,你要确保不会偏离这样的模式。如果对规约不确定,那么就请其他高级开发者来审核你的变更。如果你必须做一些违背规约的动作,那么就尽量放置于规模较小的类中(一个 200 行代码的类中的私有函数应当不会影响应用的整体设计)

5.2 不要停止深入理解项目架构

按照文章列出的方式,假设你能够在对项目了解较少的情况下进行交付,并持续这样下去,可能就会停止对项目架构的深入了解。这从长远角度来说对你的职业生涯没有帮助。当你的经验增加时,就会承担比较大的模块任务。如构建一个完整的新特性,或者修改项目的一些基础设计等较大的改进。当能够做这些改进时,你对项目的整体架构应该相当了解。文中列举的方法只是让你在最短的时间内提升自己,而不是阻止你完整理解整个项目。

6. 结论

整篇文章的重点在于,对项目进行必要了解,然后进行快速交付。你可以在不降低代码质量的前提下做到这一点。

如果要修复 bug,那么迅速定位并修复。可以在必要的时候使用运行时分析工具。如果要新增特性,那么就可以寻找类似特性,理解流程(在必要的时候使用工具)并编写。

或许这些听起来很简单,但是实用吗?当然。前提是你有良好的 java 技术,以及对框架足够了解,然后才能先修改代码,再分析变更所产生的影响。分析变更所产生的影响比实施变需要更多技巧。你可能需要高级开发人员协助你分析变更影响。

大约有 50% 的 IT 可操作预算用于简单的 bug 修复和功能增强。文中的建议对于在维护活动中节省经费应当还是很有帮助的。

作者 Choudary Kothapalli 也是 MaintainJ 项目的创立者。

关于作者

Choudary Kothapalli MaintainJ Inc. 创始人。该公司提供的工具用于在维护大型 Java 项目时节省开支。作者在开发和维护企业级 Java 应用方面已经有 15 年的经验,并且具有 Sun 认证的企业架构师与 Java 开发者资格。他目前和妻子以及 2 个儿子居住在加拿大多伦多。

关于译者

陈晨, 长期从事互联网信息收集分析领域架构研究。对海量数据处理,NoSQL 等处理运用有丰富经验,关注过程方法及其自动化。他的新浪微博:一酌散千忧


感谢侯伯薇对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2012-04-24 00:0011162

评论

发布
暂无评论
发现更多内容

写博客的感想

为自己带盐

28天写作 12月日更

跟着动画学 Go 数据结构之Go 实现栈

宇宙之一粟

Go 语言 12月日更

Docker Rootless 在非特权模式下运行 Docker

Se7en

大公司生存的几把斧

圣迪

人才 组织 战略 大公司 技术委员会

介绍一些拉新的具体方案

石云升

AARRR 28天写作 产品增长 12月日更

Dubbo 框架学习笔记十三

风翱

dubbo 12月日更

如何命名指标和标签

耳东@Erdong

Prometheus label Metric Naming

.NET6新东西---TryGetNonEnumeratedCount

喵叔

28天写作 12月日更

前端开发:自定义时间轴的使用

三掌柜

28t 28天写作 12月日更

画饼,是领导者的基本技能

搬砖的周狮傅

管理 管理经

HarmonyOS(鸿蒙)——滑动事件

李子捌

28天写作 21天挑战 12月日更

GraphQL与REST:两种API架构

devpoint

graphql REST API 12月日更

我在《Effective STL》中的找到的知识点

SkyFire

c++ stl

重载(overload) 和重写(override) 的区别?重载的方法能否根据返回类型进行区分?

海拥(haiyong.site)

28天写作 12月日更

追热点

张老蔫

28天写作

25《重学JAVA》--多线程(二)

杨鹏Geek

Java25周年 28天写作 12月日更

盘点 2021|海军的 2021年终总结, 跳槽后,我收获了什么

程序员海军

年终总结 2021年度技术盘点与展望

结束了(26/28)

赵新龙

28天写作

前端开发:基于移动端的Vue项目的Loading使用

三掌柜

28t 28天写作 12月日更

【CSS 学习总结】第六篇 - CSS 布局概述

Brave

CSS 12月日更

架构实战营模块七作业

spark99

架构实战营

架构实战训练营-模块4-作业

温安适

「架构实战营」

人生的意义要不断探索实现

mtfelix

28天写作

利用 Github Pages 和 Hugo 快速搭建免费的个人网站

xcbeyond

GitHub Pages Hugo 28天写作 12月日更

没事-2022继续做梦

将军-技术演讲力教练

Springboot国际化消息和源码解读

DoneSpeak

Java spring springboot

56 K8S之Kubernetes监控

穿过生命散发芬芳

k8s 28天写作 12月日更

代码实验01:main 方法可以继承吗?

Seven的代码实验室

阿里二面 main方法

Timsort - 混合、稳定、高效的排序算法

ue4

算法 排序 插入排序 归并排序 Timosrt

模块三作业

浮生若梦

「架构实战营」

发射、加速与着陆:一群科学家的奥林帕斯探索之旅

脑极体

程序员开发大型应用程序的技巧_Java_Choudary Kothapalli_InfoQ精选文章