Блог ·
Скрипт перетворення, що пройшовся надто широко
Скрипт типографіки закруглив апостроф усередині цитати виводу програми у статті, якої він ніколи не мав торкатися. Кожна перевірка лишилася зеленою.
Автор: Provibr
Французька й італійська вимагають типографського апострофа, а не прямого, і є тест, що це закріплює. Писати той знак просто до файлу джерела є ненадійним: залежно від того, як файл породжено, оболонка, heredoc чи знаряддя редагування можуть сплющити його назад. Тож ми пишемо прямий знак і запускаємо невеликий скрипт, що згодом його перетворює.
Той скрипт маскує код. Усе всередині зворотних лапок і все всередині огородженого блоку лишають незайманим, бо апостроф усередині фрагмента коду змінив би фрагмент, а порівняння фактів слушно стало б червоним.
Його запустили як шаблон по цілій теці мови. Він перетворив апостроф усередині цитати виводу програми, у статті, написаній іншим раундом, яка випадково сиділа в тій самій теці.
Маскування було правильним, а ціль хибною
Рядком, який він пошкодив, була цитата того, що надрукував наказ, поставлена в лапках-ялинках як суцільна проза, а не розмічена як код. Щось на кшталт Locking administration user's password. Той апостроф належить машині, що його видала, і закруглення його змушує статтю стверджувати, ніби машина сказала те, чого не казала.
Правило маскування є правильним. Зворотні лапки й огороджені блоки є кодом. Цитата виводу програми, набрана як проза, не позначена як код, і її не можна відрізнити від прози, дивлячись на знаки, бо саме нею вона і є: прозою, що цитує машину.
Тож дефект є не в маскуванні. Він є у виборі. Три статті з інших раундів змінив скрипт, написаний, щоб торкнутися чотирьох.
Чому перевірка збірки цього не помітила
Це є тією частиною, що узагальнюється поза межі одного скрипта.
Наші статті породжують. Джерелом є markdown, виводом є породжені файли, збережені в сховищі, і є перевірка, що перебудовує з джерела й вимагає, щоб результат був байт у байт тотожним збереженому. Якщо вони розходяться, вона стає червоною.
Вони не розійшлися. Скрипт змінив джерело, збірку запустили, вивід породили наново зі зміненого джерела, і ці двоє збіглися бездоганно. Перевірка відповідає на питання «чи узгоджений вивід із джерелом», що є справжнім питанням, але не цим. Ніщо в конвеєрі не відповідає на питання «чи змінив цей раунд лише те, що мав змінити».
Не помітив і тест типографіки, з тієї самої причини навпаки: закруглений апостроф у французькій є правильним знаком. Зміна зробила файл більш відповідним, а не менш.
Єдиним, що це показало, був git status на шляхах поза власними файлами раунду. Тепер це є правилом: після запуску будь-якого перетворення перелічіть змінені файли й переконайтеся, що кожен із них є вашим.
Правило, що з цього випливає
Запускайте скрипт перетворення на іменах файлів власного раунду. Ніколи на шаблоні по каталогу.
Записане, це звучить очевидно, а коли це писали, очевидним не було, бо шаблон по теці мови є природним способом висловити «перетвори французькі статті», і скрипт мав правильну властивість безпеки, що додавала відчуття захищеності: він вимагає щонайменше однієї заміни на файл, аби запуск, що тихо не робить нічого, не міг звітувати про успіх. Ця перевірка стосується порожнього успіху. Про обсяг вона не каже нічого.
Перевірка безпеки, що захищає від того, щоб зробити замало, не є перевіркою безпеки від того, щоб зробити забагато. Це є окремими властивостями, і їм потрібні окремі механізми.
Дві менші версії тієї самої проблеми
Раунд, що на це натрапив, натрапив також на дві вади перекладу з тієї самої родини: щось, що мало бути несприйнятливим до редагування, не було так позначене.
Директива кешування зʼявилася в джерелі як гола проза, а не у зворотних лапках. Дві мови її переклали, а це перетворює ключове слово на фразу, і одна з них додатково перетворила тривалість в один рік на множину. Жодного з цих випадків порівняння фактів не ловить, бо те порівняння охоплює те, що є всередині зворотних лапок, і те, що є цифрою, а голе ключове слово не є ні тим, ні тим. Виправленням є позначити його як лексему в усіх девʼяти мовах, після чого порівняння охоплює його назавжди.
Другою була таблиця написів інтерфейсу. Англійська стаття вживала її, щоб показати, що два списки назв розійшлися, і прямо зазначала, що розходження виміряли англійською. Шість із восьми перекладів переклали таблицю. Перекладена пара назв не є мʼякшою версією вимірювання; вона є іншим вимірюванням, якого ніколи не робили. Щоб це скасувати, знадобилося 26 замін.
Обидві вади мають ту саму форму, що й апостроф: шматок тексту, який є даними, а не мовою, що сидить на позиції, де ніщо не позначає його як дані.
Те, на що перевірка відповідає, є вужчим за те, на що вона начебто відповідає
Кожен із трьох механізмів, задіяних тут, є правильним, і кожен відповів на питання, суміжне з тим, що важило.
| Перевірка | Питання, на яке вона відповідає | Питання, на яке не відповідає |
|---|---|---|
| Перевірка збірки вмісту | чи узгоджений породжений вивід із джерелом | чи торкнулася ця зміна лише призначених файлів |
| Тест типографіки | чи вживає цей файл правильних знаків для своєї мови | чи стоять ті знаки на правильних місцях |
| Власна сторожа скрипта | чи дістав цей файл щонайменше одну заміну | чи дістав якийсь файл заміну, якої не мав діставати |
Жоден із них не є погано спроєктованим. Невдачею є припущення, що стіна зелених перевірок становить покриття, тоді як насправді вона становить покриття тих речей, про які хтось подумав.
Найдешевшою протидією цьому є не ще одна перевірка. Нею є перегляд різниці, на рівні імен файлів, перед тим як зберігати будь-що, породжене скриптом.
Що ми б записали
- Обмежуйте обсяг перетворення файлами власного раунду. Шаблон по каталогу не є обсягом, він є категорією.
- Сторожа проти того, щоб зробити замало, не каже нічого про те, щоб зробити забагато. Це є різними властивостями.
- Цитата виводу програми є даними. Позначте її як код, інакше перетворення тексту поставиться до неї як до мови.
- Перевірка узгодженості між джерелом і виводом є сліпою до зміни в обох. Вона відповідає про згоду, а не про намір.
- Зміну, що робить файл правильнішим, помітити найважче, бо кожен сигнал якості йде в потрібний бік.
- Читайте перелік файлів власної різниці. Це є єдиною перевіркою, що відповідає на питання обсягу.
- Усе, що є ключовим словом, належить у джерелі до зворотних лапок, кожною мовою, інакше хтось його перекладе, і жодному тестові до цього не буде діла.
- Перекладене вимірювання є вигаданим вимірюванням. Якщо суть таблиці полягає в тому, що дві речі різняться, таблиця є доказом, а не прозою.
Для ясності про те, чим це є: шкоду відкотили, раунд завершився з перевіркою вмісту на 815 із 815 породжених файлів байт у байт тотожних, набором вебу зеленим на 4546, наборами пакунків, шлюзу та інструментів зеленими на 7236, порівнянням фактів по 1240 абзацах без знахідок, посиланнями на 81 із 81, таблицями на 99 із 99 і скануванням верстки на 108 із 108 на 390 пікселях проти виробничої збірки. Тест типографіки довели червоним із двома посадженими дефектами і зеленим після того. Не доведено: є один читач на переклад, три мови перевірили лише на верстку, типографіку і стан HTTP, а числа, наведені з попередніх раундів, тут не переміряли.
Із платформної роботи над Provibr. Що другий читач знайшов у тих самих восьми статтях, описано в Три вади, яких не міг побачити жоден скрипт, а що девʼять каталогів роблять зі сталим набором елементів керування, описано в Шістнадцять тисяч ключів, девʼять мов.