Квест → Как хакнуть форму
Прошли: 77
Монолитные репозитории предоставляют множество преимуществ. Я создал прототип Fiddler - дополнение для Composer, добавляющее управление зависимостями для монолитных репозиториев в PHP.
Спасибо Александру за обсуждение этой темы со мной, а также за рассмотрение моего проекта и этого поста.
С широким распространением Git и Composer в проектах с открытым кодом и в компаниях, монолитные репозитории, содержащие несколько проектов, стали несколько плохой практикой. Такая практика, как и монолитные приложения, существует вне моды. А последняя тенденция - это всякие фишки, связанные с микросервисами и Docker'ом.
Composer сделал возможным создавать множество маленьких пакетов и с лёгкостью распространять их через Packagist. Это очень улучшило экосистему php путем увеличения использования повторного кода и предоставления доступа к нему извне.
Но важно учесть распространение пакетов и разработку каждого из них отдельно друг от друга. Развитие менеджера пакетов связано с продуктивностью при управлении версиями зависимостей, так как Composer, NPM, Bower вынуждают использовать ровно один репозиторий для одного пакета, чтобы выгодно распространять или повторно использовать этот пакет.
В этом посте я сравниваю монолитные хранилища с одним репозиторием с пакетными, сосредоточившись на внутренних проектах компаний и организаций. В следующем посте обсудим проекты с открытым исходным кодом.
Движение в сторону меньших репозиториев вызывает сомнение, если обратить внимание на три чрезвычайно продуктивных организации, работающих в невероятных масштабах.
Во всех этих компаниях очень огромное количество разработчиков, переиспользование кода, крупномасштабный рефакторинг для выбора такого подхода. Facebook даже упоминает, как их инфраструктура разработки сосредоточена на сохранении рабочего процесса.
Недостатком работы с более мелкими хранилищами может быть огромная нагрузка для разработчиков. Я видел подобное в таких проектах с открытым исходным кодом, как Doctrine и в нескольких клиентских проектах:
Одно важное замечание: монолитные репозитории не значит монолитный код. ZF2 и Symfony2 хороший пример того, как можно построить отдельные компоненты с графом чистых зависимостей в одном большом репозитории.
В Qafoo мы всегда предпочитали монолитные хранилища, содержащие несколько компонентов поверх множества небольших самостоятельных. Мы советовали этот подход многим клиентам, за исключением особых случаев, когда небольшой репозиторий был экономически более эффективным.
Даже если рассматривать единый репозиторий не в масштабах Facebook и Google, он по-прежнему даёт преимущества:
Вот почему я борюсь с тем, как Packagist и Satis заставляют двигаться в сторону более мелких хранилищ путем технических ограничений "один репозиторий - один файл composer.json". Для многократного использования проектов с открытым исходным кодом это прекрасно, но для проектов компаний этот подход используют чаще, чем надо, что ухудшает производительность разработчиков.
На сегодняшний день я создал прототип сборки системы, дополняющий Composer для управления несколькими раздельными пакетами/проектами для единого репозитория. Я назвал его Fiddler ( скрипач ). Fiddler вводит подход в управлении зависимостями для нескольких проектов в одном репозитории без потери преимуществ, связанных с наличием явных зависимостей для каждого отдельного проекта.
На практике Fiddler позволяет управлять всеми сторонними зависимостями с использованием файла composer.json, с добавлением нового способа управления вашими внутренними зависимостями. Он объединяет как внешние, так и внутренние пакеты в единый пул и позволяет выбрать их в качестве зависимостей для ваших проектов.
Для каждого проекта вы добавляете файл fiddler.json, где указываете и те, и те зависимости. Fiddler позаботится о создании конкретного автозагрузчика для каждого проекта, содержащего только зависимости проекта. Это позволяет вам иметь только один репозиторий, пользуясь явными зависимостями для каждого проекта.
Хранение явных зависимостей для каждого проекта означает, что по-прежнему легко узнать, какие компоненты влияют на изменения для внутренних и сторонних зависимостей.
Допустим, в вашем приложении три пакета: Library_1, Project_A, Project_B. Оба проекта зависят от библиотеки, которая, в свою очередь, зависит от symfony/dependency-injection. Репозиторий будет иметь следующую структуру:
projects ├── components │ ├── Project_A │ │ └── fiddler.json │ ├── Project_B │ │ └── fiddler.json │ └── Library_1 │ └── fiddler.json ├── composer.json
Для Library_1 файл fiddler.json выглядит так:
{ "autoload": {"psr-0": {"Library1\\": "src/"}}, "deps": ["vendor/symfony/dependency-injection"] }
fiddler.json для проектов A и В выглядит похоже:
{ "autoload": {"psr-0": {"ProjectA\\": "src/"}}, "deps": ["components/Library_1"] }
Глобальный composer.json такой:
{ "require": { "symfony/dependency-injection": "~2.6" } }
Как видите, зависимости указаны без ограничений версий и с относительными путями к файлу проекта. Так как всё находится в одном репозитории, весь внутренний код всегда версионирован, тестирован и развернут одновременно. Для сброса необходимо явное версионирование при указании внутренних зависимостей.
С таким подходом вы можете генерировать файлы автозагрузки для каждого пакета, точно так же, как это сделал бы Composer, вызвав:
$ php fiddler.phar build Building fiddler.json projects. [Build] components/Library_1 [Build] components/Project_A [Build] components/Project_B
Теперь в каждом пакете вы можете подключить "vendor/autoload.php". Он подтянет автозагрузчик со всеми зависимостями, указанными для каждого компонента, например, в components/Library_1/index.php
require_once "vendor/autoload.php"; $container = new Symfony\Component\DependencyInjection\ContainerBuilder;
Это все пока предварительно, пожалуйста, попробуйте у себя и пишите ваше мнение. Ценно это или нет и о возможностях расширения. Смотрите README. Код грубый и простой на данный момент, наверняка вы найдёте баги, сообщайте о них, пожалуйста.