【问题标题】:Best way to handle dependencies between components of a PHP framework using Git and Composer使用 Git 和 Composer 处理 PHP 框架组件之间依赖关系的最佳方法
【发布时间】:2017-06-20 18:52:33
【问题描述】:

背景

我正在用 PHP 开发一个框架。我首先分别制作每个组件,以便可以独立于框架使用它。

创建四个库ABCD后:

  • A没有依赖关系

  • BC 需要 A

  • D 需要 ABC

现在我在发布一个库的新版本时遇到了一些问题,我可能不得不更改其他库的依赖项,并且必须为它们发布新版本。例如:A的新版本表示BCD的新版本。

我查看了 SymfonyLaravel 等其他框架如何解决这个问题。我了解到他们正在使用 Git 的 subtree 功能和 Composer 的 replace 功能。它的工作原理如下:

  • 每个组件都在一个只读存储库中,有自己的composer.json

  • 每个组件都可以需要其他组件,但replace 不需要。

  • 框架存储库使用subtrees 包含所有组件。所以不需要使用作曲家require他们。但它应该 require 他们所有的依赖项(因为 Compser 不再处理它)。

  • 框架replaces 的所有组件。

我也注意到了

  • 组件存储库仅包含源代码(没有单元测试!)

  • Laravel 制作组件 Contracts 只是为了存储所有组件的所有接口,每个组件都需要它。

问题

  1. 我对 Laravel 和 Symfony 如何解决问题的解释正确吗?

  2. 我真的必须从组件存储库中删除测试并将它们放入框架一吗?

  3. 如果是,只想使用单个组件的人如何确保它通过测试,而不管整个框架是否通过了 wole 测试?

  4. 我是否必须确保所有组件依赖项都兼容并在框架中手动要求它们composer.json

  5. 拥有一个接口组件有什么意义?这无论如何都不能单独使用!

  6. 有没有更好的方法来解决这个问题?

P.S:这里是ABCD的链接

【问题讨论】:

    标签: php git frameworks dependencies composer-php


    【解决方案1】:

    现在我在发布一个库的新版本时遇到了一些问题,我可能不得不更改其他库的依赖项并必须为它们发布新版本。例如:A 的新版本表示 B、C 和 D 的新版本。

    • 您有一个多仓库方法。
    • A 的编辑 => A 的新版本 => B、C 和 D 中需要的版本提升。

    我认为最重要的是不要使用dev-master 并正确地对组件进行版本化,一旦它们稳定并准备好脱离开发阶段。然后,您可以使用 Composers 范围运算符 (caret ^ & tilde ~) 自动更新到某个major.minor 版本范围内的最新发布版本。这有很大帮助,让您无需再进行繁琐的手动版本更新工作。

    1. 我对 Laravel 和 Symfony 如何解决问题的解释正确吗?
    • 这是不正确的。软件包的基本开发概念、发布和使用方式与您所描述的有所不同。
    • 他们使用整体式回购开发风格。它是一个单一的存储库,其中包含一组包的代码。 mono-repo 的对立面是 many-repo 方法。替代方案是git submodules
    • 框架的所有模块/包和框架核心/内核都在一个存储库中!对于 Laravel,它是 https://github.com/laravel/framework/tree/5.4/src/Illuminate
    • 每个模块/包文件夹包含一个composer.json,框架本身包含一个composer.json
    • 这允许将模块文件夹“拆分”成独立的只读存储库。使用自定义 git 助手,例如git subsplit publish 喜欢 Laravel 使用 https://github.com/laravel/framework/blob/636020a96a082b80fa87eed07d45c74fa7a4ba70/build/illuminate-split-full.shsplitsh https://github.com/splitsh/lite,喜欢 Symfony 使用
    • 开发发生在主存储库中。
    • 最后,从用户/消费者的角度(在您的 CMS/应用程序的 composer.json 中),您只需要来自“独立只读存储库”源的模块/捆绑包。这是多存储库,因为您的应用依赖于许多存储库。

    当您使用 Composer 更新依赖项时,Composer 会将您的包替换为更新的版本。

    1. 我真的必须从组件存储库中删除测试并将它们放入框架一吗?

    没有。您也可以将测试留在/moduleA/tests 文件夹中并调整您的单元测试收集器。

    1. 如果是,只想使用单个组件的人如何确保它通过测试,而不管整个框架是否通过了整个测试?

    两件事。被测对象是:

    • (a) 组件,理想情况下是可独立测试的,并且
    • (b) 框架,它使用许多组件并测试功能,这些功能依赖于来自多个组件(例如核心/内核)的功能。一旦内核稳定并且可以独立测试,您也可以将其拆分出来。 (例如您的组件 D)
    1. 我是否必须确保所有组件依赖项都兼容并在框架 composer.json 中手动要求它们?

    monorepo 开发者视角: 当所有组件的所有单元测试和框架本身的所有单元测试都通过时,框架的开发者/维护者才能发布一个新版本,对吧?然后他可以启动子树拆分并自动对新组件进行版本化。

    应用开发者视角: 是的。作为 monorep 组件的用户,您只是在使用独立依赖项(来自只读存储库)。这意味着您必须手动或自动维护composer.json 中所需组件的版本。

    1. 拥有一个接口组件有什么意义?这无论如何都不能独立使用!

    好问题!

    • 也许开发人员想要以不同的方式做事并“保持有序”

    • 或者,他们有一个糟糕的优化想法:

    有人可能会争辩说,接口只是开发合同。 当所有组件都针对接口编写时,您可以简单地在测试之后和进行生产发布之前拔掉它们的插头。 换句话说:您可以离开接口存储库 并在您发布生产时运行接口删除。

    离开接口 repo 会导致“未找到接口 X”致命错误。然后你对其余的类运行“优化器传递”并删除所有“实现 interfaceX”字符串。要包含的文件更少。需要解析的代码更少。更少的 IO。现在我可能会在评论部分中提出这个建议而被杀:) 不,Laravel 或 Symfony 没有这样做。

    1. 有没有更好的方法来解决这个问题?

    我建议执行以下操作:对于具有 5 个组件,请转到 monorepo。

    一般来说,解决这个问题的选择并不多:

    1. git 子模块
    2. 单一回购
    3. 多仓库

    每种方法都有优缺点。

    • 更新 git 子模块也就是 git 版本碰撞和子模块更新会导致 git 疯狂,因为它会不断被破坏。和 git 的疯狂导致了黑暗的一面。 :)
    • Mono-repo 易于维护和发布。它为开发人员提供了轻松的维护服务,并为消费者提供了多仓库。您可以一次跨所有模块/组件替换/重命名/重构。
    • 当您拥有大量组件时,多存储库很难维护。

    另见:

    【讨论】:

      猜你喜欢
      • 2012-09-02
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      • 2015-07-15
      • 2021-02-16
      • 2021-03-12
      • 1970-01-01
      • 2013-03-08
      相关资源
      最近更新 更多