Эволюция ПСР
Объем и цели
PSR часто состоит из текста и кода, как правило, интерфейсов. Эти интерфейсы представляют собой фрагменты кода, которые выпускаются и помечаются в определенный момент времени. Однако язык PHP не стоит на месте; он развивается со временем.
Это означает, что эти интерфейсы должны обеспечивать стабильный контракт, а также развиваться, чтобы использовать новые языковые функции, которые могут помочь лучше реализовать поведение, описанное в самом PSR.
В то же время PSR не может быть изменен после его выпуска (с этого момента допускаются только опечатки), чтобы защитить пакет, объявленный совместимым, от фактической несовместимости.
Этот документ определяет процесс, которому необходимо следовать при обновлении интерфейсов PSR таким образом, чтобы не нарушать поведение конечных пользователей и с соответствующим путем обновления для потребителей.
Определения
- Потребитель — библиотеки и проекты, использующие один или несколько интерфейсов из кода, выпущенного как часть рассматриваемого PSR.
- Реализатор — библиотеки и проекты, реализующие один или несколько интерфейсов из кода, выпущенного как часть рассматриваемого PSR.
- Кросс-совместимость — возможность для потребителя или разработчика поддерживать более одной версии кода PSR в одном собственном выпуске.
Новые релизы
Новый второстепенный выпуск пакета PHP-FIG, содержащий интерфейсы для PSR, ДОЛЖЕН соответствовать следующим правилам: * новый выпуск ДОЛЖЕН следовать правилам Semantic Versioning; * поведение PSR НЕ ДОЛЖНО изменяться; * потребители или разработчики этих интерфейсов НЕ ДОЛЖНЫ подвергаться критическим изменениям; * ограничение версии PHP пакета PHP-FIG МОЖЕТ быть увеличено, чтобы использовать новые языковые функции, особенно те, которые будут способствовать кросс-совместимости потребителей и разработчиков со старой и новой версиями; * ограничение версии PHP пакета PHP-FIG НЕ ДОЛЖНО изменяться для использования новых языковых функций, которые могут создать проблемы кросс-совместимости.
Новый основной выпуск пакета PHP-FIG, содержащий интерфейсы для PSR, ДОЛЖЕН следовать тем же правилам, за одним исключением: * новая основная версия пакета МОЖЕТ содержать критические изменения, если реализующие пакеты имеют разумный путь обновления, например, возможность выпуска кросс-совместимой реализации с предыдущими выпусками; * новая основная версия пакета МОЖЕТ ссылаться на новый, заменяющий PSR.
Обратите внимание, что если путь обновления заставляет потребителей или разработчиков поддерживать несколько версий своих библиотек параллельно только для поддержки нескольких версий одного и того же PSR, путь обновления следует считать слишком крутым.
Рабочий процесс
Поскольку выпуск новых версий интерфейсов НЕ ДОЛЖЕН изменять поведение PSR, за эти выпуски можно проголосовать с помощью того же процесса, что и изменения опечаток. Новые выпуски ДОЛЖНЫ быть объявлены и включены с кратким пояснением и ссылкой в документе PSR, как в следующем примере:
interface ContainerInterface
{
> // code snippet here
}
Начиная с версии psr/container 1.1, приведенный выше интерфейс был обновлен для добавления подсказок типа аргумента.
В приведенном выше примере последняя строка указывает, что следует добавить в спецификацию.
Метадокумент ДОЛЖЕН быть дополнен информацией, подробно описывающей путь обновления потребителя и/или исполнителя.
Практический пример
Распространенным случаем обновления интерфейсов является добавление типов для параметров и возвращаемых значений, поскольку они представляют собой новые языковые функции, представленные в PHP 7, а многие интерфейсы PSR предшествуют этому выпуску. Мы будем использовать метод из PSR-11 в качестве примера того, как можно обновить интерфейс PSR.
ПСР-11: интерфейс
PSR-11 выпущен с пакетом psr/container
и содержит ContainerInterface
, который имеет этот метод:
/**
* @param string $id Identifier of the entry to look for.
*
* @return bool
*/
public function has($id);
Этот метод может быть обновлен новым второстепенным выпуском, который добавляет тип аргумента для $id
:
public function has(string $id);
Это изменение технически было бы критическим изменением, но благодаря ограниченной контравариантности, возможной в PHP 7.2 мы можем этого избежать. Это означает, что просто потребовав "php": "^7.2"
в psr/container
composer.json
, мы могли бы пометить это изменение как второстепенный выпуск, и все потребители и разработчики будут автоматически кросс-совместимы, при условии, что они объявляют "psr/container": "^1.0"
(или эквивалент) в качестве ограничения.
После этого промежуточного шага можно было бы выпустить новую основную версию, добавив подсказку типа возвращаемого значения:
public function has(string $id): bool;
Это должно быть выпущено как новая основная версия psr/container
(2.0); любой пакет, реализующий это, сможет объявить "psr/container": "^1.1 || ^2.0"
, поскольку обратная совместимость с первым выпуском будет невозможна из-за суммы правил ковариантности и контравариантности.
PSR-11: реализация
С другой стороны, разработчики смогут выполнить цикл выпуска противоположным образом. Первый выпуск выглядит так:
public function has($id);
Во втором выпуске будет добавлен возвращаемый тип, сохраняя совместимость с исходным интерфейсом:
public function has($id): bool;
В третьем выпуске также будет добавлена подсказка типа аргумента:
public function has(string $id): bool;