Наша обіцянка про зворотну сумісність
Дата оновлення перекладу 2024-05-09
Наша обіцянка про зворотну сумісність
Гарантування плавного оновлення ваших проектів є нашим головним пріоритетом. Тому ми обіцяємо вам зворотну сумісність (ЗС) для всіх молодших релізів Symfony. Ви скоріше за все знаєте цю стратегію, як Семантичне версіонування. Коротше кажучи, семантичне версіонування означає, що тільки старші релізи (на кшталт 5.0, 6.0 і т.д.) можуть порушувати зворотну сумісність. Молодші релізи (на кшталт 5.1, 5.2 і т.д.) можуть надавати нові функції, але повинні робити це не порушуючи існуючий API цієї гілки релізу (у попередньому прикладі - 5.x).
Ми також надаємо повідомлення про старіння, викликане у базовому коді, щоб допомогти вам з процесом міграції на новий старший реліз.
Однак, зворотна сумісність має безліч різних форм. Насправді, майже кожна зміна, яку ми робимо у фреймворку, може потенційно зламати додаток. Наприклад, якщо ми додамо новий метод у клас, це зламає додаток, який розширював цей клас та додавав той же метод, але з іншим підписом методу.
Також, не кожне порушення ЗС має однаковий вплив на код додатку. У той час як деякі порушення ЗС вимагають суттєвих змін у ваших класах або архітектурі, інші виправляються простою зміною імені методу.
Тому ми створили цю сторінку для вас. Розділ "Використання коду Symfony" розповість вам про те, як ви можете гарантувати, що ваш додаток не зламається повністю при оновленні до новішої версії однієї гілки старшого релізу.
Другий розділ "Робота над кодом Symfony", направлена на вкладників Symfony. Цей розділ перераховує детальні правила, яких має дотримуватися кожний вкладник, щоб гарантувати плавні оновлення для наших користувачів.
Caution
Експериментальні функції і код, маркований
тегами @internal
, виключаються з нашої обіцянки про зворотну сумісність.
Також відмітьте, що поррушення зворотної сумісності вибачаються, якщо вони необхідні для виправлення проблеми безпеки.
Використання коду Symfony
Якщо ви використовуєте Symfony у ваших проектах, то наступні правила допоможуть вам гарантувати плавні оновлення до всіх молодших релізів вашої версії Symfony.
Використання наших інтерфейсів
Всі інтерфейси, що постачаються з Symfony, можуть бути використані у підказках. Ви також можете викликати будь-який з заявлених ними методів. Ми гарантуємо, що це не зламає код, який дотримується цих правил.
Caution
Виключенням з цього правила є інтерфейси, теговані @internal
. Такі інтерфейси
не повинні бути використані або реалізовані.
Якщо ви реалізуєте інтерфейс, ми обіцяємо, що ніколи не зламаємо ваш код.
Наступна таблиця детально пояснює, які випадки використання охоплюються нашою обіцянкою про зворотну сумісність:
??????? ???????????? | ???????? ?????????? |
---|---|
???? ??... | ?? ?? ?????????? ??... |
?????????????? ???????? ? ?????????? | ??? |
?????????? ????? | ??? [10] |
???? ?? ?????????? ????????? ?... | ?? ?? ?????????? ??... |
?????????? ????? | ??? |
??????? ???????? ? ???????????? ????? | ??? |
??????? ???????? ?? ????????????? ? ???????? | ??? |
??????? ????????? ??? ? ????????????? ????? | ??? |
Використання наших класів
Всі класи, надані Symfony можуть бути інстанційовані та доступні через їх публічні методи та властивості.
Caution
Класи, властивості та методи, які зберігають тег @internal
, а також класи, розташовані
у різноманітних просторах імен *\Tests\
є виключенням з цього правила. Вони призначені
лише для внутрішнього використання і не повинні бути доступнні з вашого власного коду.
Щоб перестрахуватися, перегляньте наступну таблицю, щоб знати, які випадки використання охоплюються нашою обіцянкою про зворотну сумісність:
??????? ???????????? | ???????? ?????????? |
---|---|
???? ??... | ?? ?? ?????????? ??... |
?????????????? ???????? ? ????? | ??? |
????????? ????? ????????? | ??? |
?????????? ???? | ??? |
????????? ?????? ?? ????????? ??????????? | ??? |
?????????? ????????? ????? | ??? [10] |
???? ?? ?????????? ???? ?... | ?? ?? ?????????? ??... |
????????? ?????? ?? ????????? ??????????? | ??? |
?????????? ????????? ????? | ??? [10] |
?????????????? ???????? ??????????? | ??? |
?????????????? ???????? ??????????? | ??? |
?????????????? ????????? ????? | ??? |
?????????????? ????????? ????? | ??? |
??????? ???? ??????????? | ?? |
??????? ????? ????? | ?? |
??????? ???????? ?? ????????????? ?????? | ??? |
??????? ?? ????????? ???????? ?? ????????????? | ??? |
?????????? ????????? ????? (????? Reflection) | ?? |
????????? ?????? ?? ????????? ??????????? (????? Reflection) | ?? |
Використання наших рис
Всі риси, надані Symfony, можуть бути використані у ваших класах.
Caution
Виключенням з цього правила є риси, теговані @internal
. Такі риси не
мають бути використані.
Щоб бути у безпеці, перегляньте наступну таблицю, щоб знати, які випадки користування охоплюються нашою обіцянкою про зворотну сумісність:
??????? ???????????? | ???????? ?????????? |
---|---|
???? ??... | ?? ?? ?????????? ??... |
?????????????? ???? | ??? |
???? ?? ?????????????? ???? ?... | ?? ?? ?????????? ??... |
?????????????? ?? ??? ?????????? ?????????? | ??? |
?????????????? ?? ??? ?????????? ???????????? ?????? | ??? |
?????????????? ?? ??? ?????????? ????????????? ????? | ??? |
?????????????? ?? ??? ?????????? ???????????? ????? | ??? |
?????????????? ????????, ???????? ??? ???????? ??????????? | ??? |
?????????????? ?????????, ????????? ??? ????????? ????? | ??? |
Робота над кодом Symfony
Ви хочете допомогти нам покращити Symfony? Це чудово! Однак, будь ласка, дотримуйтесь правил, зазначених нижче, щоб гарантувати плавні оновлення для наших користувачів.
Зміна інтерфейсів
Ця таблиця повідомляє вам, які зміни вам можна робити при роботі з інтерфейсами Symfony:
??? ????? | ????? ????????? | ???????? |
---|---|---|
???????? ???????? | ?? | |
??????? ???? ??? ??????? ???? | ?? | |
?????? ???????????? ????????? | ??? | [2] |
???????? ???????????? ????????? | ?? | |
?????? | ||
?????? ????? | ?? | |
???????? ????? | ?? | |
??????? ???? | ?? | |
??????????? ???????????? ????????? | ??? | |
?????? ???????? ??? ???????? ?? ????????????? | ?? | |
?????? ???????? ?? ????????? ?? ????????????? | ?? | |
???????? ???????? | ?? | [3] |
?????? ???????? ?? ????????????? ?? ????????? | ?? | |
???????? ???????? ?? ????????????? ? ????????? | ?? | |
?????? ???????? ?? ????????? | ?? | |
???????? ???????? ????????? | ?? | |
??????? ??? ????????? | ?? | |
?????? ????????? ??? | ?? | |
???????? ????????? ??? | ?? | [9] |
??????? ????????? ??? | ?? | |
???????? ?????? | ||
??????????? ??????????? ?? ????????? | ?? | |
??????????? ????????? ?? ??????????? | ?? | |
????????? | ||
?????? ????????? | ??? | |
???????? ????????? | ?? | |
??????? ???????? ????????? | ??? | [1] [5] |
Примітки
[1] Варто уникати. Якщо ж зміну зроблено, вона має бути задокументована у файлі UPGRADE.
[2] Доданий батьківський інтерфейс не повинен представляти ніяких нових методів, які не існують в інтерфейсі раніше.
[3] Лише останній(і) аргумент(и) методу можуть бути видалені, так як PHP не хвилюють додаткові аргументи, які ви передаєте методу.
[4] При зміні батьківського класу, початковий батьківський клас повинен залишатися попередником класу.
[5] Значення константи може бути змінено лише коли константи не використовують у конфігурації (наприклад, у файлах Yaml і XML), так як вони не підтримують константи і повинні жорстко кодувати значення. Наприклад, константи імен подій не можуть змінювати значення без порушення ЗС. Окрім того, якщо константа буде скоріше за все використана у серіалізованих обʼєктах, значення константи не повинно бути змінено.
[6] Дозволено використання анотації @final
.
[7] Дозволено, якщо клас фінальний. Класи, що отримали анотацію @final
після свого релізу вважаються фінальними у наступній старшій версії. Зміна типу
аргументу можлива лише з батьківським типом. Зміна зворотного типу можлива лише
з дочірнім типом.
[8] Дозволено, якщо метод фінальний. Метод, що отримав @final
після
свого першого релізу, вважається фінальним у наступній старшій версії. Зміна
типу аргументу можлива лише з батьківським типом. Зміна зворотного типу можлива
лише з дочірним типом.
[9] Дозволено для зворотного типу void
.
[10] Імена параметрів охоплююьтся обіцянкою про зворотну сумісність лише для конструкторів класів атрибуту. Використання PHP-іменованих аргументів може порушити ваш код при оновленні до новіших вресій Symfony.
Внесення змін до коду зі зворотною сумісністю
Як ви читали вище, багато змін не дозволено, оскільки вони можуть призвести до порушення зворотної сумісності. Однак, ми хочемо мати можливість покращувати код та його можливості з часом, і це можна зробити завдяки деяким стратегіям, які дозволяють робити деякі недозволені зміни у декілька етапів, що забезпечує зворотну сумісність та плавний шлях оновлення. Деякі з них описані у наступних розділах.
Додавання аргументу до публічного методу
Додавання нового аргументу до публічного методу можливе лише в тому випадку, якщо це останній аргумент методу.
Якщо це так, то ось як це правильно зробити у молодшій версії:
Додайте аргумент як коментар у підпис:
1 2 3 4 5 6 7 8 9
// новий аргумент може бути опціональним public function say(string $text, /* bool $stripWithespace = true */): void { } // або обовʼязковим public function say(string $text, /* bool $stripWithespace */): void { }
Задокументуйте новий аргумент в PHPDoc:
1 2 3
/** * @param bool $stripWithespace */
Використайте
func_num_args
таfunc_get_arg
, щоб отримати аргумент в методі:1
$stripWithespace = 2 <= \func_num_args() ? func_get_arg(1) : false;
Відмітьте, що значення за замовчуванням -
false
для того, щоб залишити поточну поведінку.Якщо аргумент має значення за замовчуванням, яке зміниться у поточній поведінці, попередьте користувача:
1
trigger_deprecation('symfony/COMPONENT', 'X.Y', 'Відсутність ясної передачі аргументу "bool $stripWithespace" застаріла, значення за замовчуванням зміниться на X в Z.0.');
Якщо аргумент не має значення за замовчуванням, попередьте користувача, що воно буде обовʼязковим у наступній старшій версії:
1 2 3 4 5 6 7
if (\func_num_args() < 2) { trigger_deprecation('symfony/COMPONENT', 'X.Y', 'Метод "%s()" матиме новий аргумент "bool $stripWithespace" у версії Z.0, відсутність визначення застаріла.', __METHOD__); $stripWithespace = false; } else { $stripWithespace = func_get_arg(1); }
- У наступній старшій версії (
X.0
), розкоментуйте аргумент, відаліть PHPDoc, якщо немає потреби в описі, та видаліть кодfunc_get_arg
і попередження, якщо воно є.