anonymous@RULINUX.NET~# Last login: 2024-12-26 00:02:14
Регистрация Вход Новости | Разметка | Пользователи | Галерея | Форум | Статьи | Неподтвержденное | Трекер | Правила форума | F.A.Q. | Ссылки | Поиск
[#] [Добавить метку] [Редактировать]
Скрыть

Exception

Как вы обрабатываете исключения?

Я не люблю передавать исключения дальше по вызову. Сначала я делал так (для примера):

java

/**
 * Возвращает имя объекта.
 * В случае ошибки возвращает null.
 */

public static String getName(ObjectWithName arg) {
    try {
        if (arg.name != null && !arg.name.isEmpty()) {
            return arg.name; //OK_EXIT
        } else {
            return generateNewName(arg); // OK_EXIT
        }
    } catch (Exception e) {
        System.out.println("[ERROR] Не удалось получить имя");
        e.printStackTrace();
        return null; //ERROR_EXIT
    }
}
 


А метод, который вызывает этот метод, проверяет результат на null и сам думает, что делать. Первое время меня это устраивало, так как на моем компьютере у меня исключений никогда не было или они были некритичными для меня.

Однако у пользователей исключения случаются часто и они критичные. Так как я фронт-энд разработчик, то я сделал специальное диалоговое окно, которое выскакивает при исключениях. Содержит извинения и адрес на локальном диске, где собран подробный отчет об ошибке. В отчет входит:

  •   Тематическое пояснение к исключению
  •   Распечатка стека вызовов
  •   Скриншот всего основного монитора на момент исключения
  •   Фрагмент декомпилированного кода, в котором возникло исключение (класс задается явно, так как может интересовать не фронтовой относительно исключения класс, а второй или третий эшелон). Фрагмент включает плюс-минус 30 строчек вокруг строки с ошибкой, с указанием номеров строк и меткой у строки с ошибкой.
  •   Список полей и их значений у некоторых объектов


Сейчас я думаю добавить в диалог галочку, чтобы в отчет добавлялся снимок кучи. Также думаю копировать все отчеты на шару. Ожидаю в день по 100 отчетов.

java

/**
 * Возвращает имя объекта.
 * В случае ошибки создает отчет.
 */

public static String getName(ObjectWithName arg) {
    try {
        if (arg.name != null && !arg.name.isEmpty()) {
            return arg.name; //OK_EXIT
        } else {
            return generateNewName(arg); // OK_EXIT
        }
    } catch (Exception e) {
        Errors.DisplayReport(
            "Исключение при получении имени для ObjectWithName", // тематический комментарий
            e, // Откуда извлечь стек вызовов
            ObjectWithName.getClass().getName(), // фрагмент кода какого класса показать
            arg  // объект для анализа значений полей
        );
        throw new RunTimeException("Так жить больше нельзя");
    }
}
 

AMUR-WOLF(*) (2018-03-17 04:34:05)
Отредактировано AMUR-WOLF по причине "не указана"
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0

[Ответить на это сообщение]
[#] [Добавить метку] [Редактировать] Ответ на: Exception от AMUR-WOLF 2018-03-17 04:34:05
avatar
Скрыть

Re:Exception

Всё, что отправляется в консоль, сохраняется в логах. Логи тоже копируются в отчет

AMUR-WOLF(*)(2018-03-17 04:45:05)

Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0
[#] [Добавить метку] [Редактировать] Ответ на: Exception от AMUR-WOLF 2018-03-17 04:34:05
avatar
Скрыть

Re:Exception

>сделал специальное диалоговое окно
Я, как пользователь джава приложений, всегда с трудом находил что то полезное в месиве портянкок которые они выдают.

Но в целом да, явное лучше неявного.



p.s. А как разгребать сотни отчетов об ошибках?

Dr.uid(*)(2018-03-17 10:35:51)
Отредактировано Dr.uid по причине "не указана"
Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0
[#] [Добавить метку] [Редактировать] Ответ на: Exception от AMUR-WOLF 2018-03-17 04:34:05
avatar
Скрыть

Re:Exception

Поясните для Си-нациста, что отлавливает данная конструкция, если проверка на не-NULL и пустую строку происходит явно?

> try {...} catch


> я сделал специальное диалоговое окно, которое выскакивает при исключениях
Такой подход был в 90-х. Выскакивающие посреди работы надоедливые окна никто не читает.

anonymous(*)(2018-03-17 12:01:15)
Отредактировано anonymous по причине "не указана"
[#] [Добавить метку] [Редактировать] Ответ на: Exception от AMUR-WOLF 2018-03-17 04:34:05
avatar
Скрыть

Re:Exception

Пиздец Амур, ты же вроде как тут нам показывал системные подходы в проживании своей жизни))) И поэтому я собственно удивлен, что ты так и не прочитал, что же такое исключения и для чего они нужны)))

Попробую объяснить кратенько. Функция возвращающая имя, не должна возвращать NULL, если ты используешь исключения. Представь себе, у тебя сложное действие из нескольких сложенных шагов (вызовов функций). Например посчитать сколько в группе Васей. То есть "Счет Васей" << "Получение списка имен" << "Получение конкретного имени". И смотри что, на 13 студенте у тебя случилось что-то плохое и ты вернул NULL. Дальше уже продолжать нет смысла, гарантировано Васей ты уже не пересчитаешь. Что ты будешь делать в своем случае? Как минимум будешь проверять всех на != NULL, потом что список у тебя без NULL. Верно? А представь у тебя более глубокая вложенность кода и "список Вась" это лишь малая часть, но без валидного этого списка, все действия надо отменить. Ты утрахаешься все эти проверки делать.

Но если ты не ловишь исключение до места воззврата результата. В данном примере до места возврата количества Вась, серьезно упростишь весть код. Догоняеешь?))

Именно для таких случаем, умные дядки, не помню в каком языке впервые, но запелили эти самые - исключения.

anonymous(*)(2018-03-17 15:07:48)

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36
[#] [Добавить метку] [Редактировать] Ответ на: Re:Exception от anonymous 2018-03-17 12:01:15
avatar
Скрыть

Re:Exception

> Поясните для Си-нациста, что отлавливает данная конструкция, если проверка на не-NULL и пустую строку происходит явно?



Блок отлавливает любой выброс Exception методом generateNewName() или любым методом, который вызывается внутри метода generateNewName(). А если заменить

java

try {
    //...
} catch (Exception e) {
    //...
}
 


на

java

try {
    //...
} catch (Throwable t) {
    //...
}
 


то отлавливаться будут еще и такие вещи, как истощение свободного места в куче, с чем я столкнулся впервые в прошлую пятницу вечером и сейчас читаю статьи, почему в java сборщик мусора не всегда вычищает объекты, которые мне больше не нужны. Блин, накосячил я... Но у нас все думают, что сборщик мусора умен и всё чистит, а профилировщиками никто не пользуется и дампы никогда не делает.

AMUR-WOLF(*)(2018-03-17 15:10:43)

Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0
[#] [Добавить метку] [Редактировать] Ответ на: Re:Exception от anonymous 2018-03-17 12:01:15
avatar
Скрыть

Re:Exception

> Поясните для Си-нациста, что отлавливает данная конструкция, если проверка на не-NULL и пустую строку происходит явно?

Видимо метод generateNewName() валится при недостатке вычислительных ресурсов для генерации имени :)

anonymous(*)(2018-03-17 15:17:28)

Mozilla/5.0 (X11; Fedora; Linux i686; rv:58.0) Gecko/20100101 Firefox/58.0
[#] [Добавить метку] [Редактировать] Ответ на: Re:Exception от anonymous 2018-03-17 15:07:48
avatar
Скрыть

Re:Exception

> И смотри что, на 13 студенте у тебя случилось что-то плохое и ты вернул NULL. Дальше уже продолжать нет смысла, гарантировано Васей ты уже не пересчитаешь. Что ты будешь делать в своем случае? Как минимум будешь проверять всех на != NULL, потом что список у тебя без NULL. Верно?



Нет не верно

java

static public ArrayList<ObjectWithName> getVasyas() {
    ArrayList<ObjectWithName> students = getStudents();
    if (students == null) {
        System.out.println("[ERROR] Не удалось получить список студентов");
        return null; //ERROR_EXIT
    }

    ArrayList<ObjectWithName> result = new ArrayList<>();
    for (ObjectWithName student : students) {
        String name = student.getName();
        if (name == null) {
            System.out.println("[ERROR] Не удалось получить имя студента");
            return null; //ERROR_EXIT
        }

        if (name.equals("Vasia")) {
            result.add(student);
        }
    }
   
    return result;
}
 


И не надо мне проверять весь список по завершению его заполнения. То есть чуть что, я возвращаю null из любого места в методе, если в этом месте можно возбудить exception.

AMUR-WOLF(*)(2018-03-17 15:23:03)
Отредактировано AMUR-WOLF по причине "не указана"
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0
[#] [Добавить метку] [Редактировать] Ответ на: Re:Exception от AMUR-WOLF 2018-03-17 15:10:43
avatar
Скрыть

Re:Exception

> А если заменить catch (Exception e) на catch (Throwable t)

Кстати, интересно. Я раньше как-то не обращал внимания на этот нюанс.

> отлавливаться будут еще и такие вещи, как истощение свободного места в куче

А в настоящем времени на чем оно валится и ты ожидаешь по сотне репортов в день?

anonymous(*)(2018-03-17 15:26:43)

Mozilla/5.0 (X11; Fedora; Linux i686; rv:58.0) Gecko/20100101 Firefox/58.0
[#] [Добавить метку] [Редактировать] Ответ на: Re:Exception от Dr.uid 2018-03-17 10:35:51
avatar
Скрыть

Re:Exception

> А как разгребать сотни отчетов об ошибках?

grep'ом. Да и в джаво обычно получается достаточно наглядный трейс чтобы сразу понять что там пошло поперёк борозды.

anonymous(*)(2018-03-17 15:32:02)

Mozilla/5.0 (X11; Fedora; Linux i686; rv:58.0) Gecko/20100101 Firefox/58.0
[#] [Добавить метку] [Редактировать] Ответ на: Re:Exception от anonymous 2018-03-17 15:26:43
avatar
Скрыть

Re:Exception

> А в настоящем времени на чем оно валится и ты ожидаешь по сотне репортов в день?



Обычно я что-то не проверил на нуль или возбудился фирменный Exception из библиотечных классов. Еще бывает попытка изменить состояние в компонетах GUI из параллельных потоков.

AMUR-WOLF(*)(2018-03-17 15:35:59)
Отредактировано AMUR-WOLF по причине "не указана"
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0
[#] [Добавить метку] [Редактировать] Ответ на: Re:Exception от AMUR-WOLF 2018-03-17 15:23:03
avatar
Скрыть

Re:Exception

Как минимум семь строчек кода в твоем примере лишние, если бы ты понимал зачем нужны исключения))) Лано, бывает))

anonymous(*)(2018-03-17 19:29:26)

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36
[#] [Добавить метку] [Редактировать] Ответ на: Exception от AMUR-WOLF 2018-03-17 04:34:05
avatar
Скрыть

Re:Exception

handler-bind, restart-case все дела

Vasily(*)(2018-03-19 08:54:19)

Mozilla/5.0 (X11; FreeBSD) AppleWebKit/602.1 (KHTML, like Gecko) QupZilla/1.8.9 Version/9.0 Safari/602.1
[#] [Добавить метку] [Редактировать] Ответ на: Exception от AMUR-WOLF 2018-03-17 04:34:05
avatar
Скрыть

Re:Exception

Заменять exception на NULL -- явно неудачная идея.

Вот как я отлавливаю ошибки в своем загрузчике картинок с голыми девками с борд:

lisp

(defun download-images% (uri directory)
  "Download images from a thread (without error handling)"
  (with-simple-restart (thread-skip "Skip downloading this thread")
    (let* ((thread (make-thread uri))
           (pathname (get-directory-pathname directory (directory-name thread))))
      (let ((files (remove-extensions (image-sources thread) *ignored-extensions*)))
        (ensure-directories-exist pathname)
        (format t "Downloading total of ~d images~%" (length files))
        (mapc (lambda (file)
                (format t ".")
                (force-output)
                (destructuring-bind (uri . name) file
                  (let ((file-path (merge-pathnames name pathname)))
                    (tagbody retry
                       (restart-case
                           (if (not (open file-path :direction :probe))
                               (let ((data (make-request uri)))
                                 (with-open-file (output file-path
                                                         :direction :output
                                                         :if-does-not-exist :create
                                                         :element-type '(unsigned-byte 8))
                                   (write-sequence data output))))
                         (file-skip ()
                           :report "Skip downloading file" ())
                         (file-retry ()
                           :report "Retry downloading file" (go retry)))))))
              files))))
  (format t "~%")
  t)

(defun try-restarts (restarts)
  "Invoke the first available restart from list"
  (mapc (lambda (restart)
          (if (find-restart restart)
              (invoke-restart restart)))
        restarts))

(defun handle-conditions (condition)
  "Handle conditions automatically or fall back to the debugger"
  (princ condition *error-output*)
  (terpri *error-output*)
  (force-output *error-output*)
  (typecase condition
    (unknown-resource
     ;; Skip the thread and continue with a new one
     (invoke-restart 'thread-skip))
    ((or bad-response-code usocket:timeout-error)
     ;; Try to skip a file first
     (try-restarts '(file-skip thread-skip)))))

(defun download-images (uri directory)
  "Download images from a thread. URI is a desired resource WWW address.
 All files will be saved to DIRECTORY + some guessed name, based on the
 name of the thread or URI."

  (handler-bind
      (((or file-error usocket:socket-error
            image-downloader-error)
        #'handle-conditions))
    (download-images% uri directory)))
 


Ошибки возникают внутри make-request (тут не показано) при невозможности скачать картинку. Далее, даунлоадер предоставляет стратегии исправления ошибок (пропуск треда, пропуск файла, повтор попытки). handle-conditions выбирает нужную стратегию в зависимости от ошибки (выбрать один из рестартов или вывалиться в интерактивный отладчик), а также печатает какую-либо осмысленную инфу об ошибке. Наконец, в download-images мы связываем обработчик ошибок handle-conditions с функцией скачивания.

Если заменять condition на простое значение (NULL), теряется весь смысл какого-то особого мехазизма обработки ошибок. Получается что-то в роде C с кодами ошибок

Vasily(*)(2018-03-19 09:10:33)

Mozilla/5.0 (X11; FreeBSD) AppleWebKit/602.1 (KHTML, like Gecko) QupZilla/1.8.9 Version/9.0 Safari/602.1
Этот тред читают 2 пользователя:
Анонимных: 2
Зарегистрированных: 0




(c) 2010-2020 LOR-NG Developers Group
Powered by TimeMachine

Valid HTML 4.01 Transitional Правильный CSS!