При розробці великих систем (наприклад, корпоративних додатків, спільних програмних пакетів, бібліотек, ...), де багато рівнів і розробників взаємодіють один з одним, виникає проблема, як управляти випуском нових версій коду.
Розглянемо приклад ситуації, коли ми хочемо розробити спільний пакет Composer для спільноти розробників.
Перш ніж вирішувати проблему зворотної та прямої сумісності, потрібно з'ясувати, як відстежувати зміни в програмному забезпеченні. Наразі (2022 рік) найкращим способом версіонування всіх змін є Git. Доступ до репозиторію програмного забезпечення можна отримати, наприклад, через GitHub або GitLab. Кожна зміна програмного забезпечення має унікальний ідентифікатор, який ідентифікує кожну фіксацію та описує, що насправді відбулося.
Наступна стратегія добре спрацювала для мене при розвитку бібліотек:
На початку розробки створюється початкова фіксація в гілці master
(або main
), де фіксується основна файлова структура.
Для кожного нового запиту створюється окрема гілка з master, в якій ведеться робота. Коли зміна готова, майстру надсилається запит на злиття у вигляді "Pull request". Над запитом виконується перевірка коду, і якщо все гаразд, то зміна зливається в майстер.
Якщо гілка містить зворотньо несумісну зміну (BC break, від Back Compatibility Break
), це повинно бути відповідним чином позначено. Метод позначення розривів БК обговорюється в наступних розділах.
Виробнича версія бібліотеки тегується за допомогою тегів, які мають наступну структуру (на основі Semantic Versioning 2.0.0):
Номер версії записуємо у форматі MAJOR.MINOR.PATCH
. Нарощування номерів версій здійснюється наступним чином:
MAJOR
- коли відбувається зміна, яка не має зворотної сумісності з іншими (API)MINOR
- коли додається функціональність зі збереженням зворотної сумісностіВикористовуючи пре-релізи та додаючи метадані, можна уточнити інформацію. Наприклад: 1.0.0-альфа
, 1.0.1-beta+2
.
Детальніше про семантичну версифікацію можна прочитати на офіційному сайті: https://semver.org.
При розробці програмного забезпечення завжди слід думати про зворотну сумісність (нові функції та зміни повинні бути сумісними зі старим кодом), а в деяких випадках і про перспективну сумісність (поточні функції повинні бути сумісними з майбутніми змінами інтерфейсу).
Виконання обох завдань є дуже складним завданням. Не завжди є можливість внести зміни без порушення сумісності.
При внесенні змін завжди необхідно діяти поетапно і надавати користувачам достатньо часу для реакції на зміни.
У наступних розділах описано, як про це думати.
Основним типом загрози сумісності є видалення або перейменування функції, яка існувала в минулому. Найчастіше це пов'язано з тим, що змінилися аргументи, які приймає функція, або це стара логіка, яку по-новому потрібно обробляти.
На першому етапі старі частини кодексу мають бути позначені як застарілі, але жодним чином не змінені.
У PHP для цього є анотація @deprecated
, яку слід писати безпосередньо над методами, функціями, властивостями, змінними, константами і взагалі всім застарілим кодом.
Також гарною практикою є написання причини, чому та чи інша річ амортизується, і як це буде змінено в майбутньому. Наприклад, дати назву новій функції або способу використання.
Реальний приклад маркування застарілого коду: Константи будуть прибрані, краще використовувати вбудований Enum (перерва в БК у зв'язку з переходом на новішу версію PHP):
class OrderNotification{/** @застаріло з 2022-05-24, використовуйте enum OrderNotificationType*/ /** @застаріло з 2022-05-24, використовуйте enum OrderNotificationType */public constTYPE_EMAIL = 'електронна пошта',TYPE_SMS = 'текст';
Анотація @deprecated
викличе лише мовчазне попередження для IDE (засобу розробки) та засобів компіляції. Він нічого не ламає.
На другому етапі ми замінюємо стару реалізацію на нову, але використовуємо новий метод у старій реалізації. Це допоможе зберегти сумісність інтерфейсу непомітно для користувача.
Приклад: метод застарілий, оскільки замість нього створено новий статичний сервіс. Оскільки хтось може ним користуватися, то він просто позначає його як застарілий і внутрішньо називає нову реалізацію. Розробник в цілому може припустити, що в майбутньому цей метод буде повністю вилучений.
/** @застаріло з 2021-09-11 замість цього використовуйте Ip::get(). */public static function userIp(): string{return Ip::get();}
Якщо ви використовуєте статичний аналіз, такий як PhpStan (настійно рекомендується!), Буде гарною ідеєю спочатку переписати анотації PHPDoc, перш ніж фактично змінювати типи даних. Статичний аналіз повідомить користувача про те, що щось зламано, але час виконання залишиться недоторканим.
На четвертій фазі викликається новий метод, і одночасно викидається помилка рівня "примітка". Додаток продовжує працювати, просто починає поступово накопичувати в системному журналі інформацію про те, що та чи інша функція застаріла і буде змінена або видалена. Відтепер ми будемо активно інформувати про подібні зміни. Розробник побачить помилки під час розробки або компіляції.
/** @застаріло з 2021-05-01, замість нього використовуйте UserMetaManager. */public function getMeta(int $userId, string $key): ?string{trigger_error(__METHOD__ . ': Цей метод застарілий, використовуйте замість нього UserMetaManager.');return $this->userMetaManager->get($userId, $key);}
Я рекомендую викинути один з фатальних винятків, перш ніж повністю видалити метод. Це особливо важливо, тому що робота програми буде повністю зупинена і помилку не можна буде проігнорувати. На відміну від повного видалення коду, користувач буде повідомлений про те, що насправді сталося, і зможе легко виправити помилку.
На останньому етапі буде повністю видалено старий код. Якщо будь-який користувач не виправив залежності, його додаток буде перервано.
Серйозні порушення БК у чутливих сферах завжди повинні бути зроблені в наступному "ВЕЛИКОМУ" випуску і на них слід вказувати принаймні в одному "ВЕЛИКОМУ" випуску раніше шляхом розміщення відповідного повідомлення. Якщо цього не зробити, оновлення бібліотеки буде вкрай складним.
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu:
Články píše Jan Barášek © 2009-2024 | Kontakt | Mapa webu
Status | Aktualizováno: ... | uk