English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

гість
1 / ?
назад до уроків

Теорія, яка вже існувала

Кожен дефект MOAD мав відоме рішення за десятиліття до системного виявлення у 2026 році. Дефекти не збереглися тому, що ніхто не знав кращого. Вони збереглися тому, що знати — не те саме, що виявляти.

MOAD fester timeline: theory known vs. detected for each of the five defects

MOAD-0001: O(N²) list.contains

Donald Knuth, 1973. The Art of Computer Programming, Volume 3: Sorting and Searching. Хеш-таблиці для O(1) пошуку повністю описані з аналізом у 1973 році. Різниця між O(N) лінійним пошуком і O(1) хеш-пошуком — задокументована, формалізована, широко цитована. Java поставляла HashSet у версії 1.0 (1996). Python додав set як вбудований тип у версії 2.4 (2004). Виправлення існувало за 30 років до того, як стало стандартним ідіомом у кожній екосистемі.

Річард Геммінґ, 1986. Лекції Bell Labs (пізніше опубліковані як The Art of Doing Science and Engineering, 1997). Геммінґ чітко викладав алгоритмічну складність, різницю між коректністю та ефективністю, а також небезпеку створення систем, які працюють у малому масштабі, але не справляються у великому. Він називав це «проєктуванням під проблему, яку ви бачите сьогодні, а не під ту, з якою зіткнетеся завтра».

MOAD-0002: Shared Global State Coupling

Девід Парнас, 1972. «On the Criteria To Be Used in Decomposing Systems into Modules». CACM, грудень 1972. Парнас доводив, що модулі слід декомпозувати за принципом приховування інформації — кожен модуль володіє своїм станом, без спільних змінних глобальних змінних. Це безпосередній теоретичний попередник виправлення Intertangle. Парнас чітко зазначав: глобальний спільний стан створює невидиме зчеплення, яке не виявляється тестуванням.

MOAD-0003: ThreadLocal Identity Leak

Java 1.2, 1998. ThreadLocal з’явився як клас стандартної бібліотеки Java. З моменту одночасного існування пулів потоків і ThreadLocal виникла можливість витоку. Дефект структурний: носій, чий життєвий цикл — потік, а не одиниця роботи. Документація попереджала про це з ранніх етапів життєвого циклу Java EE.

MOAD-0004: Logged Credentials

RFC 1945, 1996. HTTP/1.0 визначив заголовок Authorization. Можливість дефекту логування облікових даних з’явилася в день створення заголовка Authorization. OWASP було засновано у 2001 році, і вже в перших посібниках було задокументовано логування облікових даних як клас вразливостей. Шаблон: Authorization header → логувальний middleware → відкриті облікові дані на диску. Відомо з моменту першої специфікації HTTP-автентифікації.

MOAD-0005: Thundering Herd / Cache Stampede

Ядро Unix, 1993. «Проблема гучного стада» — одночасне пробудження N процесів за спільною подією — з’явилася в обговореннях розробки ядра Unix на початку 1990-х. Робота Дага Шмідта над шаблоном Reactor (1994) та Half-Sync/Half-Async (1995) розв’язувала синхронізацію на рівні інфраструктури. Варіант «штампу кешу» (N потоків обчислюють те саме значення при промаху кешу) задокументовано в літературі з розподілених систем до 2001 року.

---

Теорія: завершена. Інструменти виявлення: відсутні. Розрив між «відомим» і «виявленим» становить від 28 до 54 років залежно від дефекту.

Проблема пізнаваності

Хронологія показує, що для кожного дефекту MOAD відоме рішення існувало принаймні за 28 років до систематичного виявлення. Найкоротший розрив (MOAD-0003) — 28 років. Найдовший (MOAD-0002) — 54 роки.

Це не історія про незнання. Кнут, Парнас, Геммінг — найцитованіші автори в комп’ютерних науках. Їхні праці викладали в університетах. Їхня термінологія (Big O, приховування інформації, алгоритмічна складність) стала стандартною частиною навчальних програм.

Чому знання про ці класи дефектів не запобігло їхній появі? Виберіть один MOAD і простежте конкретний розрив між відомим рішенням і фактичним виявленням.

Чому код гниє: п’ять умов

Дефект не зберігається випадково. П’ять структурних умов, що присутні одночасно, створюють середовище гниття. Видаліть будь-яку з них — і виявлення стає можливим.

П’ять умов для MOAD гниття: причинно-наслідковий DAG від теорії до гниття

Умова 1: Правильний вивід

Список і множина однаково відповідають на запитання про належність. list.contains(x) і set.contains(x) повертають однаковий булевий результат. ThreadLocal, що містить застарілий ідентифікатор, все одно містить якийсь ідентифікатор — просто він належить не тому запиту. Залогінені облікові дані логуються коректно — облікові дані потрапляють у файл логів без помилок. Дефект — не в несправності. Він проявляється лише у вартості чи наслідках для безпеки. Тести, що перевіряють вивід, проходять. Тести, що перевіряють вартість чи наслідки для безпеки: здебільшого не написані.

Умова 2: Відсутність тестів складності в CI

Дейкстра казав: «тестування показує наявність дефектів, а не їхню відсутність». Геммінг розвинув цю думку: дефекти, які ми тестуємо, — це дефекти, які ми знаходимо. CI-пайплайни у 2026 році тестують: коректність, типобезпеку, контракти API, функціональну поведінку. Вони не тестують: алгоритмічну складність на операцію, зростання пам’яті на виклик, очищення заголовка авторизації, життєвий цикл потокового ідентифікатора.

Жоден тест не запускається. Жоден тест не падає. Пайплайн зелений. Дефект невидимий.

Умова 3: Походження з малого N

Код пишеться та переглядається в середовищах розробки. Графи розробки мають 50 вузлів. Навантаження запитів у розробці — 10 одночасних потоків. Частота промахів кешу в розробці низька (теплий кеш, мало ключів). При N=50 вартість O(N²) становить 2 500 операцій. Непомітно. При N=50 000 вартість становить 2 500 000 000 операцій. Збірка триває 17 хвилин замість 1 секунди.

Автор, який написав код, ніколи не бачив N=50 000. Рецензент, який його схвалив, ніколи не бачив N=50 000. Дефект не був помітний у масштабі написання.

Умова 4: Копіювання поширюється без контексту

Правильний алгоритм є повчальним. Підручники навчають на правильних прикладах. Документація демонструє робочий код. Той самий скелет Tarjan SCC — visited = [], внутрішній if n not in visited — з’являється в GHC, Maven, Python pip, Cargo, компіляторі TypeScript, компіляторі Kotlin, компіляторі Scala та javac. Різні команди, різні мови, різні десятиліття. Той самий «скам’янілий» фрагмент. Початкове N=50 автора не поширюється разом із кодом. Поширюється: правильний результат. Залишається позаду: припущення щодо продуктивності.

Умова 5: Масштаб зростає навколо замороженого коду

Код не деградує. Інфраструктура масштабується. Розв’язувач залежностей, написаний у 2003 році для 200 пакетів, працює з 50 000 пакетами у 2024 році. Ніхто його не переписує — він працює. Ніхто його не профілює — CI зелений. N, за якого вартість O(N²) стає катастрофічною, приходить поступово, непомітно, на рівні продакшену. До того часу оригінальний автор уже зник. Код став залежністю. Ніхто не чіпає робочі залежності.

Діагноз: п’ять умов

П’ять умов: правильний результат, відсутність тестів складності, походження з малого N, копіювання без контексту, масштаб зростає навколо замороженого коду.

Усі п’ять умов були присутні для кожного MOAD одночасно. Це не збіг — це структурна сигнатура класу осадових дефектів.

Яка з п’яти умов найважче усувається і чому? Що потрібно, щоб прибрати її з реального пайплайну софтверної організації?

Що сказав Геммінг

Лекції Річарда Геммінга 1986 року в Bell Labs — опубліковані 1997 року як The Art of Doing Science and Engineering — містять застереження, які читаються як прямі описи патерну дефекту MOAD. Він не описував MOAD. Він описував структурну тенденцію інженерних систем закостеніти навколо локально правильних рішень, які стають глобально дорогими.

Геммінг про складність: «Мета обчислень — це розуміння, а не числа. Але у вас має бути правильна складність алгоритму, інакше числа ніколи не з’являться. Алгоритм O(N²), який працює на N=100, не запуститься на N=1 000 000 до вашого виходу на пенсію».

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

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

Hamming про масштаб: «Помилка, яку ви робите на першому році проєкту, — це помилка, яку ви все ще виправляєте на десятому році. Ранні припущення застигають. Навколо них масштабується проєкт. Ніхто не переписує фундамент.»

Розрив між попередженням і операціоналізацією

Попередження Геммінга були правильними. Їх викладали. Їх цитували. Їх включали в навчальні програми. Але попередження — це не детектор. Геммінг описав форму дефекту. Він не створив інструмент, який запускається в CI і позначає гарячі шляхи O(N²), витоки ідентичності ThreadLocal чи логування облікових даних. Розрив між «пізнаваним» і «виявлюваним» — це розрив між теорією та її операціоналізацією як автоматизованої інфраструктури.

MOAD існує тому, що галузь побудувала інфраструктуру коректності, але не побудувала інфраструктуру продуктивності чи безпеки на такому ж рівні. Модульні тести: стандарт з 1970-х. Тести на основі властивостей: стандарт з 1990-х. Бенчмарки алгоритмічної складності в CI: усе ще експериментальні у 2026 році.

Операціоналізація попередження

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

Конвеєр MOAD заповнює цей розрив: сканування → тікет → патч → модульний тест → розкриття → PR → злиття в upstream. Це операціоналізований Геммінг: не лише попередження, а автоматизоване виявлення та конвеєр виправлень.

Геммінг сказав: «те, що ми залишаємо неперевіреним, — те нас і дивує у продакшені». Назвіть одну властивість, яку індустрія програмного забезпечення систематично залишає неперевіреною, і опишіть, як виглядало б автоматизоване виявлення.

Fester Signature

Дефект класу MOAD має впізнаваний signature. Усі п’ять умов присутні одночасно. Усі п’ять можна перевірити ще до написання жодного сканера:

1. Коректний вивід? Запустіть стандартний набір тестів. Якщо він проходить, дефект стосується властивості продуктивності чи безпеки, а не коректності. Це означає, що стандартний CI його не виявить.

2. Немає тесту на складність? Перевірте конфігурацію CI. Чи є етап бенчмарку? Чи порівнює він поведінку алгоритму (а не лише час виконання) з попереднім комітом? Якщо ні: умова присутня.

3. Походження з малого N? Перевірте git blame та початковий коміт. Який був розмір набору даних у першій реалізації? Чи менший цей розмір за поточне виробниче навантаження більше ніж у 100×? Якщо так: умова присутня.

4. Копія поширюється? Шукайте шаблон у всій кодовій базі та в різних екосистемах. Чи з’являється той самий структурний шаблон у N≥3 незалежних кодових базах без спільного походження? Якщо так: скам’янілість поширилася. Кожна копія — нове місце загнивання.

5. Масштаб зростає? Перевірте виробничі метрики. Яке N сьогодні порівняно з N на момент першого розгортання? Чи підтримується темп зростання? За якого N дефект стає критично важливим для експлуатації?

Якщо всі п’ять пунктів перевірено та підтверджено: у вас дефект класу MOAD. Виправлення завжди полягає в заміні одного рядка або одного методу. Складна частина — виявлення. Виправлення — проста частина.

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

Застосуйте сигнатуру

Сигнатура гниття MOAD: правильний результат + відсутність тесту на складність + походження з малого N + поширення копій + зростання масштабу.

Цей сигнатур не обмежується п’ятьма дефектами MOAD. Він описує клас дефектів, які зберігаються в будь-якій системі, де тести на коректність є єдиним автоматизованим бар’єром якості.

Назвіть клас дефектів поза межами п’яти MOAD, що відповідає сигнатурі fester. Покажіть, які з п’яти умов присутні та як виглядатиме автоматизований детектор.