如何将大型Java项目划分为更小的组件

时间:2008-11-15 20:17:59

标签: java refactoring

我们试图将大代码库分成逻辑模块。我想要一些工具建议以及你可能遇到的任何经验。

该应用程序由服务器WAR和分布在JAR中的多个富客户端组成。麻烦的是,它只是一个庞大的代码库,一个源代码树> 2k档战争。每个JAR都有一个带有main方法的专用类,但依赖关系的纠结很快就会陷入困境。这并不是那么糟糕,一贯遵循良好实践,并且有一些具有特定任务的组件。它只是需要一些改进来帮助我们的团队随着它的发展而扩展。

每个模块都在一个maven项目中,由父POM构建。这个过程已经开始将每个JAR / WAR移动到它自己的项目中,但很明显,这只会刮开表面:每个应用程序JAR中的一些类和一个庞大的“遗留”项目。此外,已经有一些单元和集成测试。

无论如何,我对工具,技术和一般建议感兴趣,它们将过大且纠缠不清的代码库分解为更易于管理的东西。首选免费/开源。

6 个答案:

答案 0 :(得分:8)

看看Structure 101。它可视化依赖关系,并显示依赖关系,以便在通往更清洁的结构的过程中中断。

答案 1 :(得分:6)

我们最近完成了一项类似的任务,即一个由>组成的项目。 1k源文件,包含两个必须拆分的主类。我们最终得到了四个独立的项目,一个用于基础实用程序类,一个用于客户端数据库,一个用于服务器(项目是rmi-server-client应用程序),另一个用于客户端gui。我们的项目必须分开,因为其他应用程序只使用客户端作为命令行,如果你偶然使用任何gui类,你就会遇到只在无头部署服务器上启动时出现的无头异常。

从我们的经验中要记住一些事项:

  • 使用整个sprint 来分离项目(不要让其他任务干扰拆分,因为你需要整个sprint的时间)
  • 使用版本控制
  • 在移动任何其他功能
  • 之前编写单元测试
  • 使用持续集成系统(无论家庭成长还是开箱即用)
  • 最大限度地减少当前变更集中的文件数量(当您必须撤消某些更改时,您将节省大量工作)
  • 使用依赖性分析工具之前移动课程(我们已经使用DependencyFinder获得了良好的体验)
  • 花点时间将包重组为合理的每个项目包集
  • 不要害怕更改接口,但要在工作区中包含所有依赖项目,以便获得所有编译错误

答案 2 :(得分:2)

两个建议:您需要的第一件事是测试套件。第二个建议是小步骤。

如果你有一个强大的测试套件,那么你就处于有利位置。否则,我会进行一些很好的高级测试(又称:系统测试)。

高水平测试的主要优点是相对少量的测试可以为您提供很好的覆盖率。它们不会帮助你指出一个错误,但你不会真的需要它:如果你在小步骤中工作,并确保在每次更改后运行测试,你将能够快速检测(意外引入)错误:自上次运行测试以来,错误的根源位于代码的一小部分中。

答案 3 :(得分:1)

我会从你需要完成的各种任务开始。

我最近遇到了一个类似的任务,考虑到一个15岁的代码库是由一系列开发人员制作的,他们之间没有任何沟通(一个人在项目上工作,剩下的,然后是另一个人雇用等,没有串扰)。结果是风格和质量完全不同的混搭。

为了使它工作,我们必须隔离必要的功能,不同于装饰性绒毛,使其全部工作。例如,那里有很多不同的字符串类,一个人花了大量的时间在COleDateTimeconst char*之间进行2k行转换,然后再回来;这是一个松散的代码,用于解决主要目标的辅助任务(将数据输入和输出数据库)。

我们最终要做的是确定此代码完成的一个大目标,然后为此编写基本逻辑。当我们需要完成一项我们知道之前完成的任务时,我们找到它并将其包装在库调用中,以便它可以独立存在。例如,一个代码块激活USB设备驱动程序以创建映像;该代码不受当前项目的影响,但必要时通过库调用调用。另一个代码块用于安全加密狗,另一个代码块用于查询远程服务器的数据。这是可以封装的所有必要代码。然而,绘图代码已经建立了超过15年,这样一个疯狂的大厦,在一个月内重写OpenGL是一个更好的时间使用,而不是试图弄清楚别人做了什么,然后如何添加它。

我在这里有点手工,因为我们的项目是MFC C ++到.NET C#,但基本原则适用:

  1. 找到主要目标
  2. 确定使主要目标成为可能的所有小目标
  3. 隔离已封装的代码部分(如果有),以用作库调用
  4. 找出将它们拼凑在一起的逻辑。
  5. 我希望有帮助...

答案 4 :(得分:1)

为了继续Itay的回答,我建议阅读Michael Feathers' "Working Effectively With Legacy Code"(pdf)。他还建议每一步都要有测试支持。还有A book-length version

答案 5 :(得分:1)

Maven允许您将小项目设置为较大项目的子项。如果您想将项目的一部分提取为其他项目的单独库,那么maven也允许您这样做。

话虽如此,你肯定需要记录你的任务,每个小项目将完成什么,然后(如此处已多次说明)测试,测试,测试。您需要在整个项目中运行的测试,然后进行与项目的各个部分一起使用的测试,这些部分将作为子项目结束。

当您开始提取功能时,您需要进行额外的测试以确保您的功能一致,并且您可以模拟输入到各种子项目中。