JavaRush /Курси /Claude code /Дослідження на основі changelog для міграції

Дослідження на основі changelog для міграції

Claude code
Рівень 28 , Лекція 2
Відкрита

1. Памʼять ШІ в міграції — поганий штурман

Коли ви працюєте зі звичайною задачею у знайомому коді, памʼять ШІ часто виручає: нагадає синтаксис, підкине шаблон тесту. Міграція — інша територія: важливі не загальні патерни, а точні зміни між конкретними версіями. І тут памʼять стає не джерелом істини, а джерелом спокуси.

Проблема в тому, що модель памʼятає усереднену картину: змішає поради для Spring Boot 3.0, 3.1 і 3.3 в одну гарну розповідь, видасть правдоподібне «зазвичай це вирішується так» — а ваш проєкт саме той випадок, де «зазвичай» не працює. Вона не має злих намірів. Просто дуже добрий співрозмовник, а не офіційний changelog.

Тому в міграції діє жорстке правило: памʼять ШІ — це старт гіпотези, а не доказ. Claude каже «у Boot 3 треба замінити javax на jakarta» — не готова робота, а привід відкрити migration guide і перевірити, де проєкт потрапляє під зміну.

Порівняйте два запити. Перший зручний, але небезпечний:

Розкажи, що ламається в Spring Boot 3,
і як нам швидко полагодити проєкт.

Другий схожий на інженерне формулювання задачі:

Порівняй наш поточний стек Boot 2.7.18 + Java 8
з цільовим стеком Boot 3.x + Java 21.
Використовуй лише official migration guide і release notes.
Для кожного висновку вкажи docs section і file path у repo.
Непідтверджені місця позначай як Unknown.

У другому варіанті ви не просите модель «бути розумною» — ви просите її працювати як аналітик. Це зовсім інший режим. І саме він потрібен нам у CashFlow Dashboard, де ціна помилки — не лише червона збірка, а й тихо зламаний розрахунок підписок.

2. Авторитетне джерело, а не підказка

Фраза authoritative source звучить солідно, а сенс у неї простий: джерело, якому довіряють насамперед. Не єдине — насамперед. Технологія належить вендору — його guide, release notes і changelog стоять вище за блоги, форуми та чужі перекази.

Для міграції CashFlow цього особливо не можна забувати, тому що змінюється одразу кілька шарів: Spring Boot, Java, Gradle, база даних. Один блог-пост не замінить чотири незалежні журнали змін.

Джерело На яке запитання відповідає Як використовувати
Файли проєкту і Migration Current State Що ми маємо зараз Це точка старту: версії, конфіги, API, CI, кастомні адаптери
Official migration guide Що вендор вважає обовʼязковими змінами Читаємо як карту переходу між версіями
Release notes / changelog Що саме змінювалося від релізу до релізу Потрібні, щоб не пропустити накопичені зміни між minor-версіями
Build/test output Що реально ламається у вашому проєкті Це остаточний практичний суддя, але не на сьогоднішньому етапі
Блоги, форуми, відповіді на StackOverflow Як інші люди пояснюють проблему Корисні лише після офіційної документації, як вторинний шар

Зверніть увагу на одну деталь. Сьогодні ми ще не запускаємо цільову збірку і не збираємо runtime evidence. І навіть ідеальний guide не доведе сумісність вашого кастомного JsonAdapter або старого UserType: документація показує, де шукати ризик, але не обіцяє, що проєкт поводитиметься за підручником. Проєкти взагалі рідко читають підручники. Документація відповідає на «що має змінитися за правилами технології», код — на «де це нас зачепить»; корисне дослідження дають обидві відповіді.

3. Як виглядає нормальний changelog-driven research

Почувши «читайте release notes», ви можете сприйняти це як покарання за минулі гріхи. Але в правильному порядку вони з бюрократії перетворюються на робочий інструмент: не читати все підряд, а йти від поточного стану до цільового стеку.

Нормальний цикл виглядає так:

flowchart TD
    A[Поточний стан міграції] --> B[Official migration guide]
    B --> C[Release notes і changelog]
    C --> D[Співставлення з репозиторієм]
    D --> E[Статуси: confirmed / assumption / unknown]
    E --> F[Нотатки дослідження щодо міграції]

Спочатку ви берете вже зібраний Migration Current State і фіксуєте, звідки та куди йдете: для нас це Boot 2.7.18 → Boot 3.x і Java 8 → Java 21. Відкриваєте guide саме для цього переходу. Читаєте release notes проміжних релізів — зміни розмазано по ланцюжку 3.0 → 3.1 → 3.2 → 3.3, а не зібрано на одній сторінці.

Лише потім починається співставлення з кодом. Не навпаки. Спочатку розуміння, що саме ви шукаєте, інакше grep видасть класику: двадцять імпортів, десять конфігів, пʼять тривожних місць і нуль розуміння, які з них важливі.

Запит тут потрібен не креативний, а дисциплінований:

Використовуй official migration guide і release notes
для Boot 3.x і Java 21.
Порівняй їх із файлами build.gradle, application.yml,
gradle-wrapper.properties і src/main/java.
Поверни лише релевантні breaking changes,
файли, яких це стосується, та місця для ручної перевірки.
Для кожного пункту вкажи docs section і file path.
Не пропонуй правки коду і не запускай build.

Зверніть увагу на дві речі: ви обмежили набір файлів і заборонили ранні дії — інакше дослідження зʼїде в «я вже все зрозумів, давайте одразу лагодити». Ні, не давайте. Сьогодні ми збираємо докази. Код ще встигне постраждати без нас.

4. Привʼязка breaking changes до коду CashFlow

Ось де починається справжня інженерна робота: побудувати міст між зовнішнім джерелом і кодом CashFlow. Поки ви не показали пальцем — «цей пункт guide стосується ось цього файла» — документація залишається гарною пачкою слів.

Починати зручно з формальних місць — з build.gradle:

plugins {
    id 'org.springframework.boot' version '2.7.18'
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
}

Це маленький фрагмент, але він уже багато що говорить: ці два рядки фіксують стартовий майданчик. Guide вимагає Java 17+ — ви вже знаєте, де перша пряма невідповідність.

Далі — кодові сигнали. Класичний маркер міграції на сучасний Spring — старі javax.* імпорти:

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Subscription {
    @Id
    private Long id;
}

Є в документації розділ про перехід на jakarta.* — і цей код стає підтвердженою точкою дотику guide та проєкту. Не гіпотеза. Факт: зміна стосується цього файла.

Так само працює старий security-конфіг:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }
}

Навіть якщо ви ще не знаєте нового стилю конфігурації, ризик ви вже бачите. Не тому, що «Claude десь чув», а тому, що guide говорить про зміни в Spring Security, а код використовує застарілий підхід.

Такі відповідності зручно тримати в компактній таблиці:

Що знайшли в офіційних docs Що шукаємо в проєкті Де це видно в CashFlow
Перехід javax.*jakarta.* Імпорти javax.persistence, javax.validation Файли: Subscription.java, BillingHistory.java
Новий baseline Java sourceCompatibility, CI-образ, toolchain Файли: build.gradle, CI workflow
Зміни в Spring Security WebSecurityConfigurerAdapter, старі DSL-ланцюжки Файл: SecurityConfig.java
Конфігураційні зміни Старі ключі в application.yml Файл: src/main/resources/application.yml
Можливі проблеми з кастомними типами Самописні адаптери та ORM-розширення Типи: JsonAdapter, MoneyUserType

Останній рядок особливо цікавий. Він показує, що не все в дослідженні зобовʼязане одразу стати підтвердженим фактом. Кастомний MoneyUserType може не мати прямого опису в guide. Отже, він не перетворюється магічно на «все буде добре». Він переходить у зону Unknown і чекає ручної перевірки. Це якраз зріла поведінка, а не слабкість. Слабкість — це закрити його фразою «мабуть, сумісно».

5. Accelerators: docs lookup без режиму оракула

Коли дослідження стає довгим, зʼявляється природне бажання прискоритися. І це нормальне бажання. Зрештою, ми прийшли на курс по Claude Code не для того, щоб вручну гортати сто сторінок документації, зображаючи монаха-схоласта. Але прискорення має бути керованим. Інакше ви просто заміните сліпу віру в памʼять ШІ сліпою вірою в гарний інструмент.

Хороший docs lookup працює як хороший бібліотекар: швидко приносить потрібну полицю. Поганий — як знайомий, що влітає з криком: «Я все зрозумів, давайте терміново переписувати!» У міграції другий тип особливо небезпечний.

Якщо в команди є read-only MCP-сервер для пошуку по документації, його конфіг може виглядати приблизно так:

mcpServers:
  spring-docs:
    command: npx
    args: ["-y", "@example/spring-docs-mcp"]
    permissions: read-only

Важлива не марка пакета — імʼя сервера, плагіна або утиліти у вас може бути іншим. Стабільний принцип один: доступ лише на читання. Інструмент шукає і цитує, а не змінює код, запускає recipe і «завершує міграцію за вас».

Добре, якщо межі зафіксовано і в CLAUDE.md migration-сесії:

## Режим дослідження міграції
- джерело істини: official docs + repo files
- кожен висновок = docs section + file path
- непідтверджене позначати Unknown
- не пропонувати edit, build і version bump без запиту

Це дуже корисна маленька дисципліна: вона не дає сесії поплисти в «ну я і так уже все зрозумів» — попливе вона рівно тоді, коли ви розслабилися і вирішили, що перевіряти більше не потрібно.

Якщо у вас є Context7-like workflow, docs plugin або власний migration-assistant із Workflow Kit — ставтеся до них так само. Вони прискорюють шлях до розділу, збирають вичавку, підсвічують файли. Але вердикт «це confirmed» ви виносите лише тоді, коли бачите docs section і file path поруч, в одному кадрі. Решта — гарні розповіді.

6. Фіксація висновків: confirmed, assumption, unknown

Найдоросліше сьогодні — навіть не джерела, а мова, якою ви фіксуєте результат. Немає цієї мови — команда плутає факт, здогад і надію. А в міграції надія — поганий dependency manager.

Тому зручно використовувати три статуси:

Статус Що означає Як із ним поводитися
confirmed Є підтвердження і в docs, і в repo Можна включати у робочі рішення
assumption Є сильна гіпотеза, але бракує частини доказів Не можна вважати завершеним висновком
unknown Ні docs, ні код не дають чесної відповіді без перевірки Явно виноситься в ручну верифікацію

Тут важливо не змішувати цей словник зі словником COMPATIBILITY_MATRIX.md. confirmed / assumption / unknown описують якість знання на етапі research notes. Трохи далі зʼявляться статуси рішень на кшталт needs code changes або needs manual validation. Якщо assumption або unknown так і не отримали підтвердження, вони не зникають: у матриці стають needs manual validation, а в плані доживають до Open risks.

Це не бюрократія, а спосіб не брехати самому собі. Наприклад, так може виглядати робочий фрагмент нотаток усередині документа дослідження:

## Міграція Jakarta
- confirmed: `javax.persistence` використовується в `Subscription.java`
  і `BillingHistory.java`; див. розділ migration guide про Jakarta.
- assumption: автоматична масова заміна імпортів не зачепить
  кастомні анотації в модулі billing.
- unknown: сумісність `MoneyUserType` з новим стеком ORM.

Тут усе влаштовано правильно: третій пункт не можна «закрити оптимізмом» — він чесно висить незавершеним питанням. І це добре: Unknown не ознака слабкості, а ознака того, що ви ще не почали грати в рулетку.

Якщо винесете з лекції одну звичку — нехай буде ця: не заповнювати прогалини впевненим тоном. У міграції тон голосу не доводить нічого; доводять офіційна документація, конкретний файл у репозиторії та чесна позначка, де знання закінчується. У той момент, коли ви спокійно пишете Unknown замість «мабуть, нормально», дослідження перестає бути ворожінням і стає інженерною роботою.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ