Ім'я поля не змінилося, але значення змінилося, і низхідний поток тихо зробив помилку: додайте номер версії до результату вилучення

Минулого тижня `amount` представляв «центи», але цього тижня його було змінено на «юань», але назва поля не змінилася. Перевірку типу все одно проходить, але бізнес-результати можуть бути на два порядки гіршими. Найнебезпечнішим оновленням інтерфейсу вилучення часто є не повідомлення про помилку в явному вигляді, а тиха зміна значення.

Ця стаття написана для розробників і груп обробки даних, які підтримують інтерфейси вилучення документів. Після оновлення результатів вилучення назви полів можуть не змінитися, але їхнє значення буде іншим. Наприклад, якщо amount змінено з "fen" на "yuan", перевірка типу все одно пройде, але бізнес-числа можуть відрізнятися на два порядки.

Нижче пояснюється, як використовувати номери версій, очистити функції міграції та записи міграції для вирішення проблеми такого типу. Прочитавши це, ви зможете визначити, для яких оновлень потрібна зміна версії та яку інформацію слід зберегти під час міграції.

У прикладах у цій статті використовуються синтетичні зразки, і код було перевірено прикладами в ізольованому середовищі. Це не є гарантією всіх реальних файлів або ефектів продукту. Перед обробкою важливих документів збережіть оригінали та перегляньте їх відповідно до меж і пунктів прийняття в тексті.

Назва поля не змінилася, але змінилося його значення. Як з цим боротися? Висновок одним реченням

Позначте кожен вихід за допомогою schema_version і використовуйте функції явної міграції для перетворення різних версій даних замість простого позначення нової версії.

ваша ситуаціяРекомендовані практикипричина
Просто додайте поляДодайте нове поле та запишіть версіюДодавання полів – це не те саме, що зміна одиниць вимірювання
Зміна одиниць поля або семантикиВиберіть валідатори та функції міграції за версієюЗначення полів з однаковою назвою тихо зміниться
Старі записи мають невизначені одиниціПрояснити невдачу, зберегти старі дані та додати доказиФункції міграції не повинні бути здогадками
Нижчий потік використав старий інтерфейсЗаплануйте зміну версіїНе можна очікувати, що Downstream буде автоматично виявляти числові семантичні зміни
Звірте переклад із результатами вилученняЗберігати інформацію про версію протоколу для згенерованих полівЗручно перевірити «чому цей час відрізняється від минулого»

Номер версії має відповідати семантиці

Додавання поля – це не те саме, що зміна одиниць вимірювання. Ви можете надати кожному виходу schema_version і вибрати валідатори та функції міграції за версією.

Номери версій самі по собі не захищають систему. Якщо всі версії дотримуються тієї самої недиференційованої логіки аналізу, це лише декоративне поле.

Ключ до розбору версій

  • Виберіть правила аналізу за версією: різні версії використовують власні валідатори.
  • Міграція — це явне перетворення даних: це не пряме позначення старих даних новою версією.
  • Семантичні зміни мають бути відстежуваними: такі правила, як одиниці вимірювання та точність, мають бути доступні для перегляду.

У наведеному нижче прикладі показано, як перетворити ціле число балів на рядок десяткової суми.

Функція міграції, яку можна перевірити

from decimal import Decimal

def migrate(record):
    if record.get("schema_version") != "v1":
        raise ValueError("unexpected input version")
    cents = record.get("amount_cents")
    if type(cents) is not int:
        raise ValueError("integer cents required")
    return {"schema_version": "v2",
            "amount": format(Decimal(cents) / Decimal(100), ".2f"),
            "currency": record["currency"]}

old = {"schema_version": "v1", "amount_cents": 12345, "currency": "USD"}
new = migrate(old)
assert new["amount"] == "123.45"
assert old["amount_cents"] == 12345
assert migrate({**old, "amount_cents": -25})["amount"] == "-0.25"
try:
    migrate({**old, "amount_cents": True})
except ValueError:
    pass
else:
    raise AssertionError("bool is not a monetary integer here")

У цьому прикладі припускається, що вхідна валюта використовує співвідношення одиниць у відсотках, а вихідні дані мають два знаки після коми. Це не універсальний конвертер, який охоплює всі одиниці валюти.

type(cents) is int навмисно виключає логічні значення як цілочисельні підкласи в Python, щоб уникнути прийняття True як пенні.

📊 Основне порівняння: лише номер версії та міграція версій

практикаЕфектобмеження
Додайте лише поле schema_versionВихід позначено версієюЯкщо всі версії все ще дотримуються тієї самої логіки аналізу, номер версії є лише прикрасою
Виберіть валідатори та функції міграції за версієюПоля з однаковою назвою мають чіткі пояснення в різних версіяхНеобхідно записати правила конвертації для кожної версії

Що слід залишити в міграційному записі?

Рекомендується записати наведену нижче інформацію під час міграції, щоб полегшити відстеження та обробку розвантаження.

інформаціївикористовуватиризик втратити
Вхідні та вихідні версіїВиберіть правильне правило тлумаченняЗначення полів з однаковою назвою заплутане
Версія програми міграціїВідтворити результати перетворенняНезрозумілі результати після оновлення
Оригінал записуОтримати джерелоНові та старі дані не збігаються
Причина невдачіВідведення ручної обробкиНекваліфіковані дані заповнюються значеннями за замовчуванням

Не будьте нескінченно сумісними з історичними помилками

Якщо одиниці старого запису самі по собі є невизначеними, функція міграції не повинна вгадувати. Більш прийнятним підходом є повернення явної помилки, збереження старих даних і запит на додаткові докази.

Для подальших користувачів, які вже використовують старий інтерфейс, слід також організувати перемикання версій, замість того, щоб очікувати, що він автоматично виявить, що семантика значення змінилася.

Джерела: Загальні ключові слова схеми JSON

Перевірка після перекладу також вимагає знання версії

Використовуючи витягнуті поля для перевірки перекладів OmniDoc (портал продуктів), ви повинні вказати, за яким протоколом були згенеровані поля. Зміни у вихідних файлах, правилах вилучення чи цільовій мові можуть вплинути на метод порівняння.

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

🎯 Який спосіб вам підходить?

Якщо ви просто додаєте нове поле

Додайте безпосередньо нове поле та запишіть schema_version у вихідні дані.

Якщо ви хочете змінити одиницю виміру або значення поля

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

Якщо одиниця історичних даних незрозуміла

Поясніть, що перенесення не вдалося, збережіть вихідні дані та додайте докази перед обробкою.

❓ Часті запитання (FAQ)

1. Чи достатньо просто додати номер версії до виводу?

недостатньо. Номер версії – це лише мітка, і вона не може захистити бізнес-сенс, якщо всі версії все ще використовують ту саму логіку аналізу.

2. Чому функція міграції виключає логічні значення?

Логічні значення в Python є підкласом цілих чисел, і type(cents) is int запобігає прийняттю True як пенні.

3. Що робити, якщо старий блок запису є невизначеним?

Функції міграції не можна вгадувати. Слід повернути явну помилку, зберегти старі дані та запросити додаткові докази.

4. Яку інформацію потрібно зберігати в міграційних записах?

Включіть як мінімум версії вхідних і вихідних даних, версію програми міграції, вихідний ідентифікатор запису та причину помилки.

📝 Підсумок

Той факт, що назва поля залишається незмінною, не означає, що значення залишається незмінним. Версіонування вихідних даних і обробка семантичних змін за допомогою явних функцій міграції та записів міграції можуть значно зменшити ризик тихих помилок у низхідній частині.

Спробуйте зараз: завантажте документ, щоб розпочати переклад, зберігаючи вихідний макет

Оновлено 2026-11-15