Виняток - твій друг

  image
У середині дев'яностих, коли я переходив з програмування під DOS на Windows, мій наставник познайомив мене з механізмом винятків.
З тих пір в моїй свідомості вкоренилася думка: програма, падаюча з виключенням — погана програма. Усі винятки треба обробляти і завершувати роботу програми в разі нештатної ситуації самостійно.
І це цілком актуально для звичайного застосування під Windows. Адже в разі падіння програми користувач отримує невиразне повідомлення про помилку і, як результат, негативне сприйняття нестабільно працюючого програми.
Моя думка почало змінюватися після знайомства з інструментами автоматичної обробки виключень (таких як EurekaLog і аналогів).
І остаточно змінилося після знайомства з системою звітів Google Play.
Цей пост — крик душі проти тих тисяч прикладів, які вчать нас пхати в свій код необдумані перевірки.
 
Приводом для написання даного поста став діалог з товаришем, який просив ради з реалізації взаємодії NDK з Java-кодом. Мені були показані вихідні коди, написані на основі цього мануала .
Код, що викликає питання:
 
jmethodID method = env->GetStaticMethodID(interfaceClass, "callBack", "(Ljava/lang/String;)V");
    if(!method) {
        LOGE("callback_handler: failed to get method ID");
        return;
    }
    env->CallStaticVoidMethod(interfaceClass, method, js);

Це класичний приклад коду, який виглядає правильно, але насправді тільки створює нові проблеми.
Перевірка тут потрібна тільки в одному випадку — якщо метод callBack не зобов'язаний існувати і може бути відсутнім у штатному режимі додатки.
Перевірки потрібні коли ми перевіряємо результат роботи мережевих модулів або коли ми працюємо з зовнішніми файлами і т.п.
Тобто, коли помилка може виникати з вини зовнішніх факторів. У цьому випадку перевірка на помилки — наш прямий обов'язок.
Ситуація повністю змінюється, коли помилка генерується нашим кодом і не залежить від зовнішніх факторів.
Якщо callBack описаний нами і повинен бути присутнім в коді, перевірка не потрібна.
 
 
Перевірка лише замаскує помилку.
Дуже важливо розуміти, що маскування помилок — це погано. Набагато гірше, ніж падіння додатки з виключенням.
Ви можете сказати, що повідомлення виводиться в лог і спливає під час тестування.
Ну, відмінно, якщо спливає. А якщо не спливе? Якщо користувачеві піде непрацюючий код, який буде просто мовчки ігнорувати виклик callBack?
Ваші користувачі будуть працювати з програмою, яка не виконує задуманий функціонал. Добре, якщо це якась дрібниця, що не впливає серйозно на роботу програми. Але що, якщо там ховається важлива частина коду, через якого все результати роботи користувача виявляються некоректними?
Приберіть перевірку і перший користувач, який зіткнувся з викликом callBack, отримає падіння додаток. А Ви — звіт про помилку з заповненим call stack. Як мінімум, це зверне Вашу увагу на проблему. Так, користувач буде незадоволений. Але Ви вже через п'ять годин заллєте на Google Play нову версію і тисячі користувачів навіть не дізнаються про цю проблему.
Це набагато краще, ніж величезна клієнтська база, що працює з додатком з міною сповільненої дії.
 
Перевірки на помилки — це важлива частина роботи програми. Помилки самого різного роду виникають постійно. Не буває жодного запуску скільки-небудь складного додатка, який би стався без виникнення кількох помилок. Але треба відокремлювати штатні помилки від нештатних. Штатні помилки — ті помилки, які допустимі і вліяеніе яких передбачувано. Ці помилки потрібно обробляти всередині програми і міняти логіку роботи залежно від ситуації. Позаштатні помилки ні в якому разі не можна обробляти стандартними перевірками. Не можна просто взяти і засунути блок коду в if c перевіркою на NULL. Ви завжди повинні чітко розуміти, чому об'єкт став NULL і чим це загрожує в роботі вашої програми.
 
 
Так що ж робити з перевірками?
Можна не робити нічого. Просто прибрати перевірку. У наведеному прикладі ми точно знаємо, що у разі отсутсвия методу буде викликано виключення на наступному кроці.
Цей варіант прийнятний, але не дуже хороший, тому що виклик виключення знаходиться за межами нашого коду і ми не можемо гарантувати, що виключення буде викликано.
Тому, в ідеальному випадку, перевірка потрібна, але не з записом помилки в лог, а з порушенням винятку, щоб гарантувати зупинку виконання коду і відправку звіту про помилку.
 
Звичайно, я не відкрив Америку для професіоналів, які на власному досвіді знають, наскільки шкідлива маскування помилок.
Цей текст націлений на новачків, які вивчають програмування за прикладами з інтернету… А приклади, тим часом, рясніють безглуздими і нещадними перевірками…
  
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.