我在沙子中使用以下几行:
-
最终进入不同可部署项目的代码进入同一个存储库的不同文件夹中,在一个伞式项目下 - SBT 称之为 multi-project build(我使用 maven 而不是 SBT,但这些概念非常相似的)。它将被构建/部署到不同的 jars。
在进行有意义的划分时,我会尝试考虑最终的可部署项。例如,如果我的系统 foosys 有 foosys-frontend 和 foosys-backend 可部署项,其中 foosys-frontend 执行 HTML 模板,foosys-backend 与数据库通信,两者通过 REST API 进行通信,那么我会将它们作为单独的项目,以及用于公共代码的foosys-core 项目。不允许 foosys-core 依赖于 html 模板库(因为 foosys-backend 不想要那个),也不允许依赖于 ORM 库(因为 foosys-frontend 不想要那个)。但我不担心将与 REST 库一起使用的代码与“核心域对象”分开,因为 foosys-frontend 和 foosys-backend 都使用 REST 代码。
现在假设我添加了一个新的foosys-reports deployable,它访问数据库来做一些报告。然后我可能会根据foosys-core 创建一个foosys-database 项目来保存foosys-backend 和foosys-reports 使用的共享代码。而且由于foosys-reports 不使用REST 库,我可能还应该从foosys-core 中分离出foosys-rest。所以我最终得到了一个 foosys-core 库,另外两个依赖它的库项目(foosys-database 和 foosys-rest),以及三个可部署项目(foosys-reports 取决于 foosys-database,foosys-frontend 取决于 @ 987654349@ 和 foosys-backend 取决于两者)。
您会注意到,这意味着对于可能使用该代码的每个组合 可部署项都有一个代码项目。所有三个可部署的代码都在foosys-core 中。仅包含在一个可部署项目中的代码将进入该可部署项目的项目。三个可部署的两个中的代码进入foosys-rest 或foosys-database。如果我们想要一些代码是 foosys-frontend 和 foosys-reports 可部署的一部分,但不是 foosys-backend 可部署的,我们必须为该代码创建另一个项目。从理论上讲,这意味着随着我们添加更多可部署项目,项目数量会呈指数级增长。在实践中,我发现这并没有太大问题 - 大多数理论上可能的组合实际上没有意义,所以只要我们只在实际有代码可以放入新项目时创建新项目就可以了。如果我们最终在 foosys-core 中有几个类实际上并没有用于每个可部署的类,那也不是世界末日。
在此视图中最好将测试理解为另一种可部署的。所以我会有一个单独的 foosys-test 项目,其中包含用于测试所有三个可部署项目的通用代码(取决于 foosys-core),也许还有一个 foosys-database-test 项目(取决于 foosys-test 和 foosys-database)在foosys-backend 和foosys-reports 之间通用的测试助手代码(例如数据库集成测试设置代码)。最终,我们可能会得到一个完全并行的 -test 项目层次结构。
- 只有在项目具有不同的发布生命周期时,才将项目移动到单独的 git 存储库(同时,将整体构建单独)。
不同存储库中的代码必须独立进行版本控制,因此在某种意义上这是一个空洞的定义。但我认为只有在必要时才应该继续使用单独的 git 存储库(类似于this post:只有当数据太大而无法使用更友好的东西时才应该使用 Hadoop)。一旦您的代码位于多个 git 存储库中,您必须手动更新它们之间的依赖关系(在开发机器上,您可以使用 -SNAPSHOT 依赖关系和 IDE 支持来工作,就好像版本仍然同步一样,但您必须手动更新它每次与 master 重新同步时,都会增加开发摩擦)。由于您正在异步发布和更新依赖项,因此您必须采用并强制执行语义版本控制之类的东西,以便人们知道何时更新foocorp-utils 上的依赖项是安全的,何时不安全。您必须发布变更日志,并进行早期预警 CI 构建,以及更彻底的代码审查流程。这一切都是因为反馈周期要长得多;如果你在下游项目中破坏了某些东西,你不会知道这一点,直到他们更新他们对 foocorp-utils 的依赖,几个月甚至几年后(是的,几年 - 我见证了这一点,在一个 80 人的创业公司中,不是大型公司)。因此,您需要流程来防止这种情况发生,而一切都会相应地变得不那么敏捷。
这样做的正当理由包括:
- 项目的完整构建花费的时间太长,这会减慢您正在处理的代码的集成速度 - 但请先尝试加快速度。
- 部署所有可部署项目的时间太长 - 不过,请再次尝试自动化并加快速度。让所有内容保持同步有一个真正的优势,你不想放弃它,直到你绝对必须这样做。
- 需要单独的团队处理代码。如果您彼此之间没有持续的沟通,那么无论如何您都需要进程开销(语义版本控制等),因此您最好获得更快的构建时间。 (要明确一点,我认为每个 git 存储库都应该有一个单独的团队来拥有并负责它,并且当团队拆分时,他们应该拆分存储库。我对发布过程和职责有进一步的想法,但是这个答案已经很长了) .
我会使用团队 maven 存储库,可能是 Nexus。实际上,即使在您进入多项目阶段之前,我也会推荐这个。它非常容易运行(只是一个 Java 应用程序),您可以通过它proxy your external dependencies,这意味着您有一个可靠的依赖 jar 源,即使您的上游依赖项之一消失,您的构建也将是可重现的。
我打算将我的团队合作方式写成一篇博文,但同时我很乐意回答任何进一步的问题。