如何模块化(大型)Java 应用程序?
我手头有一个相当大的(几个 MLOC)应用程序,我想将其拆分为更易于维护的单独部分。 目前该产品由大约 40 个 Eclipse 项目组成,其中许多项目具有相互依赖性。 仅此一点就使得连续构建系统变得不可行,因为每次签入都必须进行大量重建。
是否有一种“最佳实践”方法来
- 识别可以立即分离的部分
- 文档相互依赖性直观
- 现有代码
- 地理清我们需要应用于库的 句柄“补丁”(当前通过将它们放在实际库之前的类路径中来处理) )
如果有(免费/开放)工具支持这一点,我将不胜感激。
尽管我没有任何使用 Maven 的经验,但它似乎强制采用了非常模块化的设计。 我现在想知道这是否可以迭代地进行改造,或者使用它的项目是否必须从一开始就考虑到模块化的布局。
编辑于 2009-07-10
我们正在使用 Apache Ant 拆分一些核心模块/常春藤。 真正有用且设计良好的工具,不像 Maven 那样强加给你那么多。
我在我的博客上写下了一些关于我们为什么这样做的更一般的细节和个人意见 - 太长了,无法在这里发布,而且可能不是每个人都感兴趣,所以请自行决定遵循:www.danielschneller.com
I have a rather large (several MLOC) application at hand that I'd like to split up into more maintainable separate parts. Currently the product is comprised of about 40 Eclipse projects, many of them having inter-dependencies. This alone makes a continuous build system unfeasible, because it would have to rebuild very much with each checkin.
Is there a "best practice" way of how to
- identify parts that can immediately be separated
- document inter-dependencies visually
- untangle the existing code
- handle "patches" we need to apply to libraries (currently handled by putting them in the classpath before the actual library)
If there are (free/open) tools to support this, I'd appreciate pointers.
Even though I do not have any experience with Maven it seems like it forces a very modular design. I wonder now whether this is something that can be retrofitted iteratively or if a project that was to use it would have to be layouted with modularity in mind right from the start.
Edit 2009-07-10
We are in the process of splitting out some core modules using Apache Ant/Ivy. Really helpful and well designed tool, not imposing as much on you as maven does.
I wrote down some more general details and personal opinion about why we are doing that on my blog - too long to post here and maybe not interesting to everyone, so follow at your own discretion: www.danielschneller.com
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
第一:祝你好运& 好咖啡。 你两者都需要。
我曾经遇到过类似的问题。 遗留代码具有可怕的循环依赖关系,甚至在来自不同包的类之间(例如 org.example.pkg1.A)也依赖于 org.example.pk2.B , 反之亦然。
我从 Maven2 和新的 Eclipse 项目开始。 首先,我尝试确定最常见的功能(日志记录层、通用接口、通用服务)并创建 Maven 项目。 每次我对某个部件感到满意时,我都会将该库部署到中央 Nexus 存储库,以便它几乎可以立即用于其他项目。
所以我慢慢地逐层进行。 maven2 处理依赖关系,m2eclipse 插件提供了有用的依赖关系视图。 顺便说一句 - 将 Eclipse 项目转换为 Maven 项目通常并不太困难。 m2eclipse 可以为您做到这一点,您只需创建一些新文件夹(如 src/main/java)并调整源文件夹的构建路径。 只需要一两分钟。 但是,如果您的项目是 Eclipse 插件或 RCP 应用程序,并且您希望 Maven 不仅可以管理工件,还可以构建和部署应用程序,那么预计会遇到更多困难。
就我看来,eclipse、maven 和 nexus(或任何其他 Maven 存储库管理器)是一个很好的起点。 如果您有系统架构的良好文档并且该架构确实得到了实现,那么您很幸运;)
First: good luck & good coffee. You'll need both.
I once had a similiar problem. Legacy code with awful circular dependencies, even between classes from different packages like org.example.pkg1.A depends on org.example.pk2.B and vice versa.
I started with maven2 and fresh eclipse projects. First I tried to identify the most common functionalities (logging layer, common interfaces, common services) and created maven projects. Each time I was happy with a part, I deployed the library to the central nexus repository so that it was almost immediately available for other projects.
So I slowly worked up through the layers. maven2 handled the dependencies and the m2eclipse plugin provided a helpful dependency view. BTW - it's usually not too difficult to convert an eclipse project into a maven project. m2eclipse can do it for you and you just have to create a few new folders (like src/main/java) and adjust the build path for source folders. Takes just a minute or two. But expect more difficulties, if your project is an eclipse plugin or rcp application and you want maven not only to manage artifacts but also to build and deploy the application.
To opinion, eclipse, maven and nexus (or any other maven repository manager) are a good basis to start. You're lucky, if you have a good documentation of the system architecture and this architecture is really implemented ;)
我在小型代码库(40 kloc)中也有过类似的经历。 没有“规则”:
在使用 Maven 的 CI 过程中
非常好的有向图)
与您的产品一起编译(有时这很容易有时非常
困难)
还检查依赖分析器:
(来源:javalobby.org< /a>)
Netbeans:
(来源:zimmer428.net< /a>)
I had a similar experience in a small code base (40 kloc). There are no °rules":
in your CI process
very nice directed graph)
compile with your products (sometimes this is very easy sometimes it is very
difficult)
Check also Dependency Analyzer:
(source: javalobby.org)
Netbeans:
(source: zimmer428.net)
对于现有系统来说,迁移到 Maven 是很痛苦的。 然而,它可以毫无困难地应对 100 多个模块项目。
Maven is painful to migrate to for an existing system. However it can cope with 100+ module projects without much difficulty.
您需要决定的第一件事是您将迁移到哪种基础设施。 它应该是许多独立维护的模块(转化为单独的 Eclipse 项目),还是您会认为它是作为一个整体进行版本控制和部署的单个代码块。 第一个非常适合迁移到类似 Maven 的构建环境 - 后者可以一次性包含所有源代码。
无论如何,您都需要一个运行的持续集成系统。 您的第一个任务是自动构建代码库,这样您就可以让 CI 系统监视您的源存储库并在您更改内容时重建它。 我决定在这里采用非 Maven 方法,并且我们专注于拥有一个简单的 Eclipse 环境,因此我使用 ant4eclipse 和 Team ProjectSet 文件(我们无论如何都使用它)创建了一个构建环境。
下一步将是消除循环依赖 - 这将使您的构建更简单,消除 Eclipse 警告,并最终允许您进入“签出、编译一次、运行”阶段。 这可能需要一段时间:-(当您迁移方法和类时,不要移动它们,而是提取或委托它们并保留它们的旧名称并将它们标记为已弃用。这会将您的整理与重构分开,并允许代码“在您的项目之外,仍然可以使用项目内部的代码。
您将受益于允许移动文件和保留历史记录的源代码存储库。CVS 在这方面非常薄弱。
The first thing you need to decide is what infra-structure you will move to. Should it be a lot of independently maintained modules (which translates to individual Eclipse projects) or will you consider it a single chunk of code which is versioned and deployed as a whole. The first is well suited for migrating to a Maven like build environment - the latter for having all the source code in at once.
In any case you WILL need a continuous integration system running. Your first task is to make the code base build automatically, so you can let your CI system watch over your source repository and rebuild it whenyou change things. I decided for a non-Maven approach here, and we focus on having an easy Eclipse environment so I created a build enviornment using ant4eclipse and Team ProjectSet files (which we use anyway).
The next step would be getting rid of the circular dependencies - this will make your build simpler, get rid of Eclipse warnings, and eventually allow you to get to the "checkout, compile once, run" stage. This might take a while :-( When you migrate methods and classes, do not MOVE them, but extract or delegate them and leave their old name lying around and mark them deprecated. This will separate your untangeling with your refactoring, and allow code "outside" your project to still work with the code inside your project.
You WILL benefit from a source repository which allows for moving files, and keeping history. CVS is very weak in this regard.
我不会推荐 Maven 作为遗留源代码库。 仅仅尝试调整所有内容来配合它可能会给您带来很多麻烦。
我想你需要的是对你的项目进行架构布局。 工具可能会有所帮助,但最重要的部分是组织模块的逻辑视图。
I wouldn't recommend Maven for a legacy source code base. It could give you many headaches just trying to adapt everything to work with it.
I suppose what you need is to do an architectural layout of your project. A tool might help, but the most important part is to organize a logical view of the modules.
它不是免费的,但 Structure101 将为您提供尽可能好的击球工具支持你所有的要点。 但郑重声明,我有偏见,所以您可能也想看看 SonarJ 和 Lattix。 ;-)
It's not free but Structure101 will give you as good as you will get in terms of tool support for hitting all your bullet points. But for the record I'm biased, so you might want to check out SonarJ and Lattix too. ;-)
使用 OSGi 可能很适合您。 它将允许在应用程序之外创建模块。 您还可以以更好的方式组织依赖关系。 如果您正确定义了不同模块之间的接口,那么您可以使用持续集成,因为您只需重建在签入时受影响的模块。
OSGi 提供的机制将帮助您理清现有代码。 由于类加载的工作方式,它还可以帮助您以更简单的方式处理补丁。
OSGi 的一些概念似乎很适合您,如维基百科所示:
框架从概念上讲,它分为以下几个区域:
Using OSGi could be a good fit for you. It would allow to create modules out of the application. You can also organize dependencies in a better way. If you define your interfaces between the different modules correctly, then you can use continuous integration as you only have to rebuild the module that you affected on check-in.
The mechanisms provided by OSGi will help you untangle the existing code. Because of the way the classloading works, it also helps you handle the patches in an easier way.
Some concepts of OSGi that seem to be a good match for you, as shown from wikipedia:
The framework is conceptually divided into the following areas: