【问题标题】:Radical modularity in Java [closed]Java中的激进模块化[关闭]
【发布时间】:2014-06-18 06:55:12
【问题描述】:

我所在的开发团队编写并仍然维护着一个纯 Java 意大利面条代码的代码库。其中大部分是在我加入这个团队之前实施的。

我的背景是 Python/Django 开发,而 Django 社区非常强调“可插拔性”——Django“应用程序”(模块)的一个特性,主要意味着“一件事和一件事好”、可重用性、松散耦合,以及一个干净、有意识的 API。一旦我曾经工作过的 Django 团队开始“理解它”,我们几乎可以零问题地处理凌乱、紧密耦合的大量单体代码。

我们的实践涉及在我们打算使用该应用程序的 Django 项目之外开发 Django 应用程序(根据我收集的信息,这是 Django 开发人员的一种常见做法)每个人甚至都生活在一个独立于整体的 Git 存储库中Django 项目。

现在,我们有机会重构大部分意大利面条式代码,在我看来,我从 Django 社区学到的一些东西应该在这里应用。简而言之,我希望看到我们的新代码库开发为一系列“可插拔”模块,每个模块都是在假设它无法访问其他模块(除了它应该合理依赖的模块之外)的情况下编写的。我相信这应该可以很好地将正确的软件设计的基本原则推广到整个团队。

所以,我提倡的是在我们的新(Spring)项目中为每个我们想要的“功能”拥有一个单独的存储库。每个都有自己独立的构建过程,结果将是一个 .jar 。我们还有一个项目级事物(JSP、静态文件等)的存储库,它的构建过程会产生一个 .war 。 .jar 不会放在 .war 中,而是被视为 Gradle 依赖项(与第三方依赖项相同。)

现在我必须把它卖给老板。他被要求提供该计划的先例示例。显而易见的地方是开源项目,但如果一个项目被拆分为多个存储库,它很可能是多个项目。所以,也许我正在寻找某种套件。作为一个例子,Spring 本身看起来很有希望,但我找不到很多其他的。

我的问题是(对于冗长的背景故事感到抱歉):

  • 有没有这样的先例?
  • 有哪些例子?
  • 是否有任何文档(即使只是一篇博文也会有所帮助)提倡这样的事情?
  • 对实施此有什么建议吗?
  • 这是个好主意吗?

提前致谢!

编辑:是否重构不是问题。我们已经决定对我们的大部分代码进行一些大刀阔斧的修改——事实上,主要不是为了“让它更干净”。我的问题是我们计划的项目结构是否合理,以及如何向决策者证明其合理性。

【问题讨论】:

  • 不要重构,继续支持意大利面的东西;)任何人都可以重构,意大利面只适合真正的男人。
  • 是否重构目前尚无定论。已经决定了。我们新项目的目标之一是消除对旧版本 Struts 的依赖,并根据需要转换所有代码以改用 Spring。
  • 这在语义上所说的是重写。您使用的术语 refactoring 与您所描述的不同。不理解语义的人被卖了一座桥,当它严重失败时会生气,这是这些事情结束的唯一方式。
  • 从头开始实施一个新项目来替换现有项目也是重写。那些失败的更惨,谷歌“大改写”并阅读了这一点。 无论哪种方式,这个问题大多是题外话,太宽泛,太自以为是答案证明了这一点,包括我的!
  • JSF 不是答案,唯一推动 JSF 的人是顾问,他们希望将他们的客户锁定在一个昂贵而复杂的解决方案中,他们需要不断的帮助,哦,我多么希望我能拒绝 cmets !

标签: java


【解决方案1】:

以下问题比将代码放在磁盘或工件中的哪个位置更重要:

如果你不明白这一点,你就已经失败了。

你描述的不是重构,是改用一个更好听的名字:

除非您已经在单元测试中覆盖了 100% 的代码;当(而不是如果)这种努力失败时,有人会因此而被解雇,可能是多次失败!

即使有很棒的单元测试,也有人会错过一些东西,当它最终在生产中被发现时,有人会摔倒,通常是在数月的默默破坏数据之后。

语义很重要:

删除 Struts 并用 Spring 替换不是重构,顾名思义是重写。重构将从 Struts 1.1 转移到 2.0,替换 Struts 意味着用其他东西替换所有 Struts 代码,根据定义,重写不是重构。

工作软件有多种伪装:

企业总是认为他们拥有的东西是工作

错过最后期限,引入错误(无论多么小),丢失功能(无论多么小),错误解释未记录的流程并更改一些东西,无论多么小,甚至变得更好。他们只是在寻找任何问题弱点或潜在的麻烦来传播 FUD,并确保您的努力是失败的,至少在大多数情况下是这样。

所有这些事情都会让你和你的团队付出政治资本,有人会为这些事情而失败,无论被认为是多么无辜或毫无价值!

预计结果:

很可能是您和/或其他“非 Java”开发人员,而不是创建这个工作系统的核心 Java 人员,您“非 Java”人员重构(在本例中为重写的代码字)并按时交付不完整或未按时交付或根本未交付。

【讨论】:

  • 他们提到了struts,意思是过于复杂,纠缠不清!两者都是我在事后处理的专长。移除 struts 是 NOT 重构,它是 重写,完全不同的任务和成功结果的可能性。
  • 在这种情况下删除我的评论:P 因为我几乎不使用 java(仅在绝对必要时)
  • 我什至不确定我是否理解您的回答。当 what 严重失败时,有人会因为 what 而被解雇吗?重构计划(同样,这是没有问题的)会严重失败吗?我们提议的特定建议存储库结构?或者你是说修改大部分代码的简单行为会引入错误?
  • 另外,你提到的“核心 Java 人”(他们自己承认)进入原始项目时几乎没有 Java 和/或编程经验或培训,并且“工作系统”的正常运行时间非常令人尴尬记录。此外,任何“非 Java”开发人员(顺便说一下,他们的 Java 经验与“核心 Java”类似人”)还没有。
  • 对目前工作的业务而言,即使是最小的问题(细微的错误、感知的性能问题、错过最后期限)也会对团队会像滚雪球一样为某人带来灾难,而且不会是管理,永远不会!
【解决方案2】:

我认为可以在 Java 和 Python 中找到好的和坏的实现示例。

春天确实是一个很好的开始。它强调良好的分层、界面设计等。我强烈推荐它。

Spring 的分层是“水平的”。如果“模块”对您来说意味着“业务功能”,那么给定层中将存在多个模块。

Plugable 建议采用更垂直的方法。

也许另一种攻击方式是将系统分解为一组独立的 REST Web 服务。将功能与界面完全解耦。通过这种方式,服务可以由网络、移动设备或任何其他出现的客户端共享。

这需要严格隔离服务和数据源的所有权。单个 Web 服务将拥有/管理大量数据。

我建议您查看 Michael Feathers 的书 "Working Effectively With Legacy Code"。它已有十年历史,但在亚马逊上仍然备受推崇。

我喜欢 REST Web 服务方法的一点是,您可以隔离功能并在时间和预算允许的情况下执行它们。创建和测试服务,让客户使用它,然后继续其余的工作。如果事情不是太耦合,您可以通过这种方式浏览应用程序。

【讨论】:

    【解决方案3】:

    每个组件都在自己的 jar 中,但 jar 不包含在 war 中?那应该如何工作?甚至第三方库也包括在战争中。容器提供的除外。关于jsp的东西:Can I serve JSPs from inside a JAR in lib, or is there a workaround?

    【讨论】:

      【解决方案4】:

      我推荐观看领域驱动设计创始人 Eric Evans 的“处理遗留代码的四种策略”:http://dddcommunity.org/library/evans_2011_2/

      它可能无法完全回答您的问题,但它提供的论据和策略可能有助于您的努力。

      【讨论】:

        【解决方案5】:

        重构整个应用程序并不是一件容易的事,特别是如果代码是硬连线的,如您所描述的。如果 Pluggablity 是一个重要的目标,我会推荐 Grails/Groovy。

        如果您能以某种方式识别视图、控制器和业务逻辑,或者更好的服务。您也许可以重用一些现有代码。 grails/groovy 的好处是您可以将 JSP/JAVA 与 GSP/GROOVY 结合起来。

        同样,这真的很难卖,而 grails 可能是一个很好的框架来缓解重构的痛苦。

        【讨论】:

        • 爆炸。所有这些答案都表明我没有正确传达我的问题的重点......我最好编辑它。
        猜你喜欢
        • 1970-01-01
        • 2020-04-14
        • 1970-01-01
        • 2014-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多