组织多个scala相互关联的sbt&git项目 - 最佳实践建议

mat*_*ter 11 git scala sbt sbt-native-packager

随着scala使用sbt的构建和git版本控制,这将是组织你的团队的代码时,它会跨出是单个项目的好方法?在某些时候,您开始考虑将代码分离到单独的库或项目中,并根据需要在它们之间进行导入.你会如何为此组织事情?或者你会避免诱惑,只管理同一个sbt和git单一"项目"下的所有包裹?

兴趣点是:(随意改变)

  • 避免发明过度设计想象力的新"头痛".
  • 仍然能够在你想要的时候轻松地构建所有东西,在给定的开发机器上或者CI server.
  • 生产包装:能够用来SbtNativePackager包装您的产品,而不会产生太多的痛苦.
  • 轻松控制您在给定开发机器上使用的每个库的哪个版本,并能够无缝地在它们之间切换.
  • 避免git操作变得比它通常更糟糕.

此外,您是否会使用某种"本地sbt/maven团队存储库"以及可能需要做些什么才能实现这一目标?希望这不是必要的.

谢谢!

lmm*_*lmm 13

我在沙子中使用以下几行:

  • 最终进入不同可部署的代码在同一个存储库中的不同文件夹中,在一个伞形项目下 - SBT称为多项目构建(我使用maven而不是SBT,但概念非常相似).它将被构建/部署到不同的罐子.

在制作有意义的划分时,我会尝试考虑最终的可展开性.例如,如果我的系统foosys具有foosys-frontendfoosys-backenddeployables,在那里foosys-frontend做HTML模板和foosys-backend谈判,以数据库和通过REST API 2通信,那么我就会有这些作为单独的项目,以及foosys-core对公共代码项目.foosys-core不允许依赖于html模板库(因为foosys-backend不希望这样),也不允许依赖于ORM库(因为foosys-frontend不希望这样).但我不担心分离,与从"芯域对象"的REST库工作的代码,因为这两个foosys-frontendfoosys-backend使用REST代码.

现在我要添加一个新的foosys-reports可部署的,它可以访问数据库来做一些报告.然后,我可能会创建一个foosys-database项目,视foosys-core,保持双方使用的共享代码foosys-backendfoosys-reports.由于foosys-reports不使用REST库,我可能也应该foosys-rest从中分离出来foosys-core.所以我最终得到了一个foosys-core库,两个依赖于它的库项目(foosys-databasefoosys-rest),以及三个可部署的项目(foosys-reports取决于foosys-database,foosys-frontend取决于foosys-rest,foosys-backend取决于两者).

您会注意到,这意味着可以使用该代码的每个可部署组合都有一个代码项目.所有三个可部署的代码都进入了foosys-core.只有一个可部署的代码可以部署在该可部署的项目中.三个可部署中的两个中的代码进入foosys-restfoosys-database.如果我们想有一些代码,是部分foosys-frontendfoosys-reportsdeployables,但不是foosys-backend部署,我们必须创建代码另一个项目.从理论上讲,这意味着随着我们添加更多可部署项目,项目数量呈指数级增长.在实践中我发现它并没有太大的问题 - 大多数理论上可能的组合实际上没有意义,所以只要我们只有在我们实际有代码放入它们时才创建新项目就可以了.如果我们最终得到的几个类foosys-core实际上并没有在每个可部署中使用,那么它不是世界末日.

在此视图中,测试最好被理解为另一种可部署的.所以我会有一个单独的foosys-test项目,包含用于测试所有三个可部署项目(取决于foosys-core)的公共代码,也许还有一个foosys-database-test项目(取决于foosys-testfoosys-database)用于测试助手代码(例如数据库集成测试设置代码)foosys-backendfoosys-reports.最终,我们最终可能会得到完整的并行-test项目层次结构.

  • 只有在具有不同的发布生命周期时,才将项目移动到单独的git存储库(同时,将整个构建分开).

不同存储库中的代码必须独立编辑,因此在某种意义上,这是一个空洞的定义.但我认为你应该继续分开git存储库,只有当你需要时(类似于这篇文章:当数据太大而不能使用任何更友好的东西时,你应该只使用Hadoop).一旦你的代码在多个git存储库中,你必须手动更新它们之间的依赖关系(在开发机器上,你可以使用-SNAPSHOT依赖关系和IDE支持工作,就好像版本仍然同步,但你必须手动更新它每次与master重新同步时,都会增加开发的摩擦力.由于您正在进行发布并异步更新依赖关系,因此您必须采用并执行类似语义版本控制的操作,以便人们知道何时更新依赖关系foocorp-utils以及何时更新依赖关系是安全的.您必须发布更改日志,并具有预警CI构建和更全面的代码审查过程.所有这一切都是因为反馈周期要长得多; 如果你在下游项目中打破了某些东西,你将不会知道这一点,直到他们更新他们的依赖性foocorp-utils,几个月甚至几年后(是的,几年 - 我见过这个,在一个80人的创业公司,而不是一个巨型公司) .所以你需要进程来防止这种情况,而且一切都变得相对不那么灵活.

这样做的有效理由包括:

  • 完整的项目构建花费的时间太长,减慢了您正在处理的代码的集成速度 - 尽管首先尝试加快它的速度.
  • 部署所有可部署的内容耗时太长 - 尽管如此,请尝试自动执行此操作并加快速度.保持一切同步是一个真正的优势,你不想放弃,直到你绝对必须.
  • 单独的团队需要处理代码.如果你不是彼此不断沟通,那么无论如何你都需要进程开销(语义版本控制等),所以你也可以获得更快的构建时间.(要明确的是,我认为每个git存储库都应该拥有一个拥有并负责的团队,当团队分裂时,他们应该拆分存储库.我对发布过程和职责有进一步的想法,但这个答案已经很长了) .

我会使用团队maven存储库,可能是Nexus.实际上我甚至在你进入多项目阶段之前就推荐这个.它非常容易运行(只是一个Java应用程序),您可以通过它代理外部依赖项,这意味着您有一个可靠的依赖项源代码,即使您的某个上游依赖项消失,您的构建也将是可重现的.

我打算将我的团队工作方式写成博客文章,但与此同时,我很乐意回答任何进一步的问题.