Українська
Стратегія обробки помилок
Вибір способу повідомлення про помилку
Виняток доречний, коли звичайний результат не можна отримати, а обробник розташований вище в стеку. Expected доречний, коли відмова є видимою частиною типу результату і викликач повинен вирішити її локально. Optional доречний, коли відсутність значення не потребує діагностичної причини.
Не стверджуйте, що один підхід завжди швидший. Вартість залежить від частоти відмов, розмірів типів, компілятора та організації коду. Вимірювати потрібно конкретний сценарій, а не порожню функцію, яка не відображає програму.
На межі бібліотеки або модуля правила потрібно документувати: які винятки можуть вийти, які коди помилок повертаються, що залишається незмінним після невдачі. Не перетворюйте будь-який виняток на довільний нуль, якщо нуль є коректним результатом.
Контракти C++26 описують передумови, післяумови та перевірки тверджень через механізми на зразок pre, post і contract_assert. Це огляд розвитку мови, а не підтвердження підтримки MSVC. У цьому курсі для поточного набору засобів використовуються явні перевірки і assert; контрактний синтаксис не входить до обов’язкових програм.
Послідовний пошук причини дефекту
У великій програмі неправильний результат може з’явитися далеко від місця, де дані були зіпсовані. Тому ставити точку зупинки лише на останньому println часто недостатньо. Визначте етапи: читання, розбір, перевірка, обчислення, збереження, оформлення. На межі кожного етапу порівняйте стан з очікуваним. Перша межа, де стан неправильний, звужує ділянку пошуку.
Наприклад, підсумковий середній бал 0 може мати кілька причин:не прочитано жодного запису, сума обнуляється в циклі, ціле ділення відкинуло дріб або друкується інша змінна. Перевірка лише фінального значення не розрізняє цих причин. Спочатку подивіться розмір колекції, потім суму, потім тип ділення й лише потім формат рядка.
Під час експерименту змінюйте одну гіпотезу. Якщо одночасно замінити тип, формулу і тест, успішний результат не пояснить, яка зміна усунула дефект. Після виправлення поверніться до початкового відтворюваного тесту й перевірте сусідні граничні випадки. Саме початковий тест стає регресійним доказом виправлення.
Debug і Release як різні спостереження
У Debug локальна змінна може залишатися доступною для перегляду довше, ніж у оптимізованій збірці. Компілятор Release може зберігати значення в регістрі, об’єднати обчислення або вилучити непотрібну змінну. Повідомлення налагоджувача про недоступне значення не означає, що сама змінна була неініціалізованою. Це потрібно відрізняти від справжнього дефекту часу життя.
Якщо поведінка змінюється між конфігураціями, не робіть висновок «оптимізатор зламав коректний код» без доказів. Спершу перевірте вихід за межі, висячі посилання, знакове переповнення і побічні ефекти в assert. Це поширені причини того, що одна конфігурація лише приховує помилку іншої.
Дизайн повідомлень про відмову
Повідомлення повинне допомогти користувачеві виправити вхід, а розробникові – знайти причину. Для парсера дати корисні категорія помилки, позиція та очікуваний формат. Для недостатнього балансу – запитана сума і доступний залишок. Водночас текст не повинен містити випадкові секрети або повний пароль лише тому, що він був аргументом функції.
Код помилки та текст мають різні ролі. Програма може приймати рішення за Error::range, а користувач бачити українське пояснення. Не аналізуйте рядок what() як стабільний машинний протокол: його формулювання може змінитися. Тип або enum краще виражає категорію для подальшої логіки.
Власний виняток потрібний, коли викликач повинен розрізняти спеціальну ситуацію або отримати додаткові поля. Простий похідний тип від runtime_error дозволяє зберегти стандартний what() і водночас мати окремий catch. Не створюйте новий клас для кожного тексту, якщо реакція на всі випадки однакова.
Загальний catch на верхньому рівні може перетворити необроблену відмову на контрольований код завершення. Але він не повинен продовжувати операції з частково зміненим станом, якщо інваріанти не гарантовано. «Перехопив» не означає «відновив».