Ім'я поля не змінилося, але значення змінилося, і низхідний поток тихо зробив помилку: додайте номер версії до результату вилучення
Минулого тижня `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. Яку інформацію потрібно зберігати в міграційних записах?
Включіть як мінімум версії вхідних і вихідних даних, версію програми міграції, вихідний ідентифікатор запису та причину помилки.
📝 Підсумок
Той факт, що назва поля залишається незмінною, не означає, що значення залишається незмінним. Версіонування вихідних даних і обробка семантичних змін за допомогою явних функцій міграції та записів міграції можуть значно зменшити ризик тихих помилок у низхідній частині.
Спробуйте зараз: завантажте документ, щоб розпочати переклад, зберігаючи вихідний макет


