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

标签 git scala sbt sbt-native-packager

scala , 使用 sbt用于构建和 git对于版本控制,当团队代码不再是单个项目时,组织团队代码的好方法是什么?在某个时候,您开始考虑将您的代码分成单独的库或项目,并根据需要在它们之间导入。你会如何组织事情呢?或者你会避免诱惑而只是在同一个 sbt 和 git 单个“项目”下管理所有包?

兴趣点是:(随意更改)

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

  • 此外,您是否会使用某种“本地 sbt/maven 团队存储库”,并且可能需要做些什么来完成它?希望这不是必需的。

    谢谢!

    最佳答案

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

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

  • 在进行有意义的划分时,我会尝试考虑最终的可部署性。例如,如果我的系统 foosys 有 foosys-frontendfoosys-backend可部署,其中 foosys-frontend做 HTML 模板和 foosys-backend与数据库对话,两者通过 REST API 进行通信,然后我会将它们作为单独的项目,还有一个 foosys-core公共(public)代码项目。 foosys-core不允许依赖于 html 模板库(因为 foosys-backend 不想要那个),也不依赖于 ORM 库(因为 foosys-frontend 不想要那个)。但是我不担心将与 REST 库一起使用的代码与“核心域对象”分开,因为 foosys-frontendfoosys-backend使用 REST 代码。

    现在假设我添加了一个新的 foosys-reports可部署的,它访问数据库做一些报告。然后我可能会创建一个 foosys-database项目,取决于 foosys-core , 保存 foosys-backend 使用的共享代码和 foosys-reports .从 foosys-reports不使用 REST 库,我可能也应该拆分 foosys-rest来自 foosys-core .所以我最终得到了 foosys-core库,另外两个依赖它的库项目( foosys-databasefoosys-rest ),以及三个可部署的项目( foosys-reports 取决于 foosys-databasefoosys-frontend 取决于 foosys-rest 5 和 7两个都)。

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

    在这种情况下,最好将测试理解为另一种可部署的。所以我会有一个单独的 foosys-core项目包含用于测试所有三个可部署项目的公共(public)代码(取决于 foosys-test),也许还有一个 foosys-core项目(取决于 foosys-database-testfoosys-test )用于在 foosys-database 之间通用的测试帮助程序代码(例如数据库集成测试设置代码)和 foosys-backend .最终我们可能会得到一个完整的并行层次结构 foosys-reports项目。
  • 仅当项目具有不同的发布生命周期时,才将项目移动到单独的 git 存储库(同时,单独的整体构建)。

  • 不同存储库中的代码必须独立进行版本控制,因此从某种意义上说,这是一个空洞的定义。但我认为您应该仅在必要时才继续分离 git 存储库(与 this post 类似:您应该只在您的数据太大而无法使用任何更友好的东西时才使用 Hadoop)。一旦您的代码位于多个 git 存储库中,您必须手动更新它们之间的依赖项(在开发机器上,您可以使用 -SNAPSHOT 依赖项和 IDE 支持来工作,就好像版本仍然同步,但您必须手动更新它每次与 master 重新同步时,都会增加开发的摩擦)。由于您正在异步发布和更新依赖项,因此您必须采用并强制执行诸如语义版本控制之类的操作,以便人们知道何时可以安全地更新 -test 上的依赖项。当它不是。你必须发布变更日志,并有一个早期预警 CI 构建,以及更彻底的代码审查过程。这一切都是因为反馈周期要长得多;如果你在下游项目中破坏了某些东西,除非他们更新对 foocorp-utils 的依赖,否则你不会知道这件事。 ,数月甚至数年后(是的,数年 - 我亲眼目睹了这一点,并且在一个 80 人的初创公司中,而不是大型企业)。因此,您需要流程来防止这种情况发生,而一切都相应地变得不那么敏捷。

    这样做的正当理由包括:
  • 项目的完整构建花费的时间太长,这会减慢您正在处理的代码的集成速度 - 尽管首先尝试加快速度。
  • 部署所有可部署的东西花费的时间太长了——尽管再次尝试自动化并加快速度。保持一切同步有一个真正的优势,你不想放弃,直到你绝对不得不放弃。
  • 不同的团队需要处理代码。如果您没有保持相互之间的持续通信,那么无论如何您都需要处理开销(语义版本控制等),因此您也可以获得更快的构建时间。 (明确地说,我认为每个 git 存储库都应该有一个拥有并负责它的团队,当团队拆分时,他们应该拆分存储库。我对发布流程和责任有进一步的想法,但这个答案已经很长了) .

  • 我会使用团队 Maven 存储库,可能是 Nexus .实际上,我什至在您进入多项目阶段之前就建议这样做。它很容易运行(只是一个 Java 应用程序),您可以 proxy your external dependencies通过它,这意味着您有一个可靠的依赖 jar 来源,即使您的上游依赖项之一消失,您的构建也将是可重现的。

    我打算将我的团队工作方式写成一篇博文,但同时我很乐意回答任何其他问题。

    关于git - 组织多个 Scala 相互关联的 sbt 和 git 项目 - 最佳实践建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26486339/

    相关文章:

    git - 致命的 : unable to access cannot resolve host gitlab error when using HTTPS git repository

    json - 从 JSON 中提取字段

    java - 如何在 Play 2.5.x (Scala) 中禁用弱密码和客户端重新协商

    scala - 如何在 Scala 列表中找到元素的最后一次出现?

    scala - 如何发布带有校验和(MD5、SHA1)的工件?

    sbt - 可以禁用 sbt 1.x 服务器吗?

    scala - Intellij中如何运行指定的子模块播放应用

    linux - 克隆到 Samba 共享时 Git 速度很慢

    git 缺少工作树

    ruby-on-rails - 无法在 Windows 10 中删除 Ubuntu 中的文件夹