Название: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 18, 2014, 11:17 Привет!
Об этой стратегии обработки ошибок пользователя я прочитал в книге Professional C++ (2nd Edition) (http://www.amazon.com/Professional-C-Marc-Gregoire/dp/0470932449) Скачать книгу (99МБ)+код к книге (464КБ) одним архивом (90МБ): https://yadi.sk/d/VCvsky11c6wtP Подробное описание создания собственных классов исключений находится здесь: "Chapter 10. Handling Errors" -> "Exceptions and Polymorphism" -> "Writing Your Own Exception Classes" Проверка: непустой ли входной аргумент Функция printArray принимает массив и выбрасывает исключение EmptyError, если входной аргумент пуст: Output: Цитировать Error: empty argument in the function printArray() main.cpp Код
freeFunctions.h Код
freeFunctions.cpp Код
EmptyArgument.h Код
LogicError.h Код
Проверки: открыт ли файл, удачна ли запись, удачно ли чтение Если файл не открывается, то выбрасывается исключение FileOpenError с текстом, к примеру: Цитировать Error: unable to open the file "input.txt" in the "readData()" Если из файла невозможно прочитать, то - FileReadError с тектом: Цитировать Error: unable to read the file "input.txt" in the "readData()" Если диск переполнен и невозможно записать, то - FileWriteError с текстом: Цитировать Error: unable to write to the file "input.txt" in the "readData()" Все выше перечисленные исключения наследуются от FileError, поэтому мы можем все три исключения отлавливать так: Код
Исключение EmptyArgument выбрасывается, когда входные данные пустые и наследуется от LogicError Следующий пример читает имена и фамилии из файла, заполняет массив объектов типа Person и выводит имена на экран: main.cpp Код
Person.h Код
freeFunctions.h Код
freeFunctions.cpp Код
FileError.h Код
FileOpenError.h Код
FileReadError.h Код
FileWriteError.h Код
EmptyArgument.h Код
LogicError.h Код
Проверка деления на ноль и выхода из диапазона В моём примере есть функция divide(a, b), где a и b должны быть в диапазоне [-1000, 1000]. Если один из параметров превысил этот диапазон, то функция выбросит исключение с текстом: Цитировать Error: values must be from the range [-1000, 1000] in the function Calculator::divide() Допустим в моём проекте 10 классов, и в каждой по несколько функций, которые должны следить за диапазоном своих аргументов. Мне при написании этих функций достаточно выбросить после проверки исключение: Код
main.cpp Код
Calculator.h Код
DivideByZero.h Код
OutOfRange.h Код
LogicError.h Код
Интересные ссылки: Правило 8: Не позволяйте исключениям покидать деструкторы (http://www.e-reading.me/chapter.php/1002058/28/Mayers_-_Effektivnoe_ispolzovanie_CPP.html) Правило 25: Подумайте о поддержке функции swap, не возбуждающей исключений (http://www.e-reading.me/chapter.php/1002058/64/Mayers_-_Effektivnoe_ispolzovanie_CPP.html) Правило 29: Стремитесь, чтобы программа была безопасна относительно исключений (http://www.e-reading.me/chapter.php/1002058/73/Mayers_-_Effektivnoe_ispolzovanie_CPP.html) Exception Safety | QtDoc 5.3 (http://qt-project.org/doc/qt-5/exceptionsafety.html) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 18, 2014, 12:00 Пару дней назад был такой случай: приложение виснет при испускании exception. Поставил печать в catch - до нее дело не доходит. Как такое может быть?
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 18, 2014, 12:07 Пару дней назад был такой случай: приложение виснет при испускании exception. Поставил печать в catch - до нее дело не доходит. Как такое может быть? Я лишь показал стратегию. Если есть предложения, замечания и т.д., то я могу внести исправления. Ваш вопрос не относится к теме. Создавайте свою. Если относится, то не говорите загадками, а опишите проблему в моём примере, если она естьНазвание: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 18, 2014, 12:28 Я лишь показал стратегию. А может Вам лучше сначала набраться практического опыта, а потом уж пописывать статейки и "показывать стратегию"? :) А то первый же простейший вопрос ставит "стратега" в тупик :) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 18, 2014, 13:02 Я не придумывал эту стратегию, а перетранслировал из книги. Использую её на практике. Написал здесь, чтобы услышать конструктивную критику и исправить недочёты в демо-примере
Цитировать приложение виснет Почему виснет, а не рушится?Цитировать А может Вам лучше сначала набраться практического опыта, а потом уж пописывать статейки и "показывать стратегию"? Я так не считаю. Эта статья будет расти вместе со мной. И если кто-то решит воспользоваться этой версией подхода и столкнётся с проблемой, то сообщит в комментариях и я внесу соответсвующие изменения/дополненияНазвание: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 18, 2014, 13:39 Почему виснет, а не рушится? Ну так приложение не вылетает, ошибки краша нет. Останавливаюсь в отладчике - вижу какие-то потроха ntcore.dll (или др системного модуля - не суть), и это все. Откуда это взялось из моего кода - хз. Вот я и говорю "виснет".Вот допустим читал, читал и читал, (кстати вчера молодой человек наглядно показал знакомство с теми ссылками что выше). И тут хирак - вот такая ситуевина. Ну наверное если столько прочел, да еще и статью накатал - разрулит в момент! А иначе зачем читать, да еще и писать? :) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: kambala от Октябрь 18, 2014, 14:50 Я не придумывал эту стратегию, а перетранслировал из книги. таким вещам место в уютненьком [бложике]Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 18, 2014, 18:50 Я не придумывал эту стратегию, а перетранслировал из книги. таким вещам место в уютненьком [бложике]Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 18, 2014, 19:14 Это даже близко не статья. Просто сообщение.
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 18, 2014, 20:09 Статья в коде
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Nidxogg от Октябрь 18, 2014, 20:44 Цитировать Я развил идею из книги. Каким образом?Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 18, 2014, 21:16 Тут нет развития. Тут нет даже пояснения. тут имеются ссылки на учебники и код... Печаль.
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 19, 2014, 10:21 Ладно, попробуем вникнуть в "перетранслированное"
Код Я ненавижу такой код. Он создает дутый объем и впечатление "вумности", но реально за ним ничего нет. Откуда я возьму значения диапазона? Чего они вбиты как константы? Если мне надо поделить напр 2000 на 5, я что, уже не могу это сделать и всегда получу исключение? Какой вообще смысл в проверке делимого? И почему делитель проверяется на "слишком большое число" - что это за ошибка такая? Как всегда в таких случаях насованы template, c претензией на общность. Но (как не всегда, но часто) общность эта липовая. Для чисел с точкой логика совсем другая. Ах да, ну это же все "для примера". Мы же говорим о "стратегии", общем подходе. Так это тоже неверно, причем принципиально. Операции типа "деление на ноль" слишком мелки чтобы размазывать их в ф-цию, тем более они критичны по скорости (не надо парить про "преждевременную оптимизацию"). Правильно контролировать их прямо в коде, напр Код а часто и обходиться без исключений, особенно для чисел с точкой, напр Код Вот кстати типовая задача: есть ф-ция/метод нормализация вектора. Должна ли она бросать исключение? Ладно, вернемся к нашему юному графоману :) 8Observer8, у Вас есть свое видение проблемы, свой взгляд на вещи, основанный на личном опыте, которым Вы бы хотели поделиться? Я его в упор не вижу, Вы даже списываете совершенно бездарно. Если на Вас книга произвела неизгладимое впечатление - просто дайте ссылку на нее, не надо никаких статей. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 19, 2014, 16:41 Цитировать Откуда я возьму значения диапазона? Вы сами определяете диапазон и передаёте его исключению OutOfRange. Суть в том, что текст, который будет выводиться находится в OutOfRange. Это намного лучше того, если бы мы в каждой разрабатываемой функции кидали std::out_of_range( " Error: values must be from the range ... " ). Было бы дублирование текста. А свои классы исключений гибкие. Можно задавать параметры. Один из очень удобных параметров - это имя функции. И ещё раз отмечу централизованное управление выводимым текстом. Теперь можно писать свои классы исключений и наследовать их от LogicError. По-моему, очень даже удобноНазвание: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 19, 2014, 17:18 Вы сами определяете диапазон и передаёте его исключению OutOfRange. Каким образом я его определю ??? Вот есть операцияКод Какие значения "а" можно делить на "b" а какие нельзя? Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 19, 2014, 23:09 В моём примере есть функция divide(a, b), где a и b должны быть в диапазоне [-1000, 1000]. Если один из параметров превысил этот диапазон, то функция выбросит исключение с текстом:
Цитировать Error: values must be from the range [-1000, 1000] in the function Calculator::divide() Допустим в моём проекте 10 классов, и в каждой по несколько функций, которые должны следить за диапазоном своих аргументов. Мне при написании этих функций достаточно выбросить после проверки исключение: Код
Я могу так же легко написать любое исключение. Мне достаточно будет унаследовать его от LogicError. К примеру, могу написать исключение EmptyError, которое будет содержать текст, что входной аргумент пуст. Допустим, я разрабатываю функцию printArray, которая принимает массив и выбрасывает исключение EmptyError, если входной аргумент пуст: Output: Цитировать Error: empty argument in the function printArray() main.cpp Код
freeFunctions.h Код
freeFunctions.cpp Код
EmptyArgument.h Код
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 20, 2014, 08:13 Статья увеличилась. Следующий раздел будет называться: Проверки: открыт ли файл, удачна ли запись, удачно ли чтение
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 20, 2014, 08:49 В моём примере есть функция divide(a, b), где a и b должны быть в диапазоне [-1000, 1000]. Где Вы видели такую задачу? Значит 1000 можно делить на что-то, а 1001 уже нельзя - это с какой стати? Если стратегия/концепция (что Вы хотели показать) нуждается в столь синтетических примерах - грош ей цена.Допустим в моём проекте 10 классов, и в каждой по несколько функций, которые должны следить за диапазоном своих аргументов. Мне при написании этих функций достаточно выбросить после проверки исключение: Вероятно имелось ввиду что черновая работа (печать строки ошибки и.т.п.) собрана в классе исключения, и ее не придется писать 10 раз. Так нормальный программист решил бы это без всяких книжек (с завлекательным названием "профессионал") просто-напросто создав ф-цию, напрКод
Код Чего не хватает? Зачем выдумывать классы раздувая текст на ровном месте? Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 20, 2014, 09:18 Цитировать Где Вы видели такую задачу? Значит 1000 можно делить на что-то, а 1001 уже нельзя - это с какой стати? Если стратегия/концепция (что Вы хотели показать) нуждается в столь синтетических примерах - грош ей цена. Пока не придумал подходящего примераНазвание: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 20, 2014, 09:49 Давайте пока забудем про OutOfRange. Я может пока вообще удалю этот пример до лучших времён. В книге был пример с проверками файла на открытие чтение и т.д. А OutOfRange это я уже развил, а пример оказался неудачный
Теперь о файлах и собственных классах исключений Если файл не открывается, то выбрасывается исключение FileOpenError с текстом, к примеру: Цитировать Error: unable to open the file "input.txt" in the "readData()" Если из файла невозможно прочитать, то - FileReadError с тектом: Цитировать Error: unable to read the file "input.txt" in the "readData()" Если диск переполнен и невозможно записать, то - FileWriteError с текстом: Цитировать Error: unable to write to the file "input.txt" in the "readData()" Все выше перечисленные исключения наследуются от FileError, поэтому мы можем все три исключения отлавливать так: Код
Исключение EmptyArgument выбрасывается, когда входные данные пустые и наследуется от LogicError Следующий пример читает имена и фамилии из файла, заполняет массив объектов типа Person и выводит имена на экран: main.cpp Код
Person.h Код
freeFunctions.h Код
freeFunctions.cpp Код
FileError.h Код
FileOpenError.h Код
FileReadError.h Код
FileWriteError.h Код
EmptyArgument.h Код
LogicError.h Код
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 20, 2014, 10:00 Посмотрите сейчас на мою статью. Она стала лучше
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 20, 2014, 11:36 Огроооомный минус перебивающий все плюсы - что за ересь у вас в архиве с исходниками?
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 20, 2014, 15:11 То что в проекте становится побольше классов, после введения этой концепции, так это не проблема, а преимущество. Разделяй и властвуй!
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 20, 2014, 15:35 Я про то, что у вас в архиве лежит хренова туча хрен знает какого кода с пустыми папками и без пояснений...
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 20, 2014, 22:07 Значит это не мой архив, так как я никаких архивов, в этой теме, не прикреплял
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: m_ax от Октябрь 20, 2014, 22:19 Это даже близко не статья..(
В статье самое главное - это Заключение (Conclusions) (поскольку, по большому счёту, только его и читают) А заключение должно быть, как женское нижнее бельё - Короткое, прозрачное и возбуждающее) А здесь этим даже и не пахнет) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: gil9red от Октябрь 20, 2014, 23:12 Значит это не мой архив, так как я никаких архивов, в этой теме, не прикреплял Первое сообщение темы имеет ссылку на архив на яндексе Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 21, 2014, 07:01 Бгг... вот это человек... У него в статье прячется вражеский архив, а он и не знает :D
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 21, 2014, 08:54 Спасибо за замечания! Над заключением подумаю
По поводу архива, то там всё нормально. Я этот код скачал отсюда: ссылка (http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449,descCd-DOWNLOAD.html) Число в названии папки означает номер главы. В некоторых главах книги нет примеров с кодом, поэтому и написано "empty". Вот содержимое папки: (http://img.pixs.ru/storage/0/2/1/400png_6183298_14364021.png) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: qate от Октябрь 21, 2014, 09:39 Функция printArray принимает массив и выбрасывает исключение EmptyError, если входной аргумент пуст: низа чтобы не стал пользоваться такой функцией в концепции qt исключения получаются как лишними - везде ходят события и отложенный результат Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 21, 2014, 09:52 У меня аж руки опускаются. У него архив с примерами по какому то учебнику и без нормальных названий и он выставляет его с подобием своей статьи, как свои примеры... Что творится в этом человеке?
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 21, 2014, 11:17 То что в проекте становится побольше классов, после введения этой концепции, так это не проблема, а преимущество. Разделяй и властвуй! Все упирается в то что у Вас нет никакого практического опыта. На абстрактных примерах успешно доказывается любая концепция (в том числе и противоположные). На деле все не так- много классов - уже плохо (грубо говоря). Вы их сами писали, причем недавно, все помните. Но поставьте себя на место "желающего воспользоваться". Он-то ведь без понятия, ему нужно хотя бы просмотреть каждый класс, запомнить имя класса чтобы его юзать. Это совсем непросто в чужом коде. - что делают эти многочисленные классы? Печатают ошибки. Это место весьма уязвимо. Нужна или печать в юникоде, или в национальном алфавите или вообще "другая". Напр Вы сочли разумным сообщать имя ф-ции. Но др разработчик может так не считать, напр зачем в месяге для юзера имя ф-ции? И что тогда? Лезть и переделывать весь Ваш дизайн? Стандартный подход: код ошибки + доп данные (часто имя файла) + строка ошибки по умолчанию. И обработчик исключений уже решит что показывать юзверю: то ли сам напечатает, то ли Ваше или вообще ничего Ну и вообще, как-то вяло, неинтересно. Что Вы хотели показать? Что можно организовывать исключения так и сяк, иногда переиспускать. Ну можно конечно, с этим никто не спорит. Но что здесь такого что надо специально изучать, читать статьи и.т.п.? По моему это и так понятно :) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 21, 2014, 12:02 У меня аж руки опускаются. У него архив с примерами по какому то учебнику и без нормальных названий и он выставляет его с подобием своей статьи, как свои примеры... Что творится в этом человеке? Я подправил, чтобы было ясно: Цитировать Об этой стратегии обработки ошибок пользователя я прочитал в книге Professional C++ (2nd Edition) (http://www.amazon.com/Professional-C-Marc-Gregoire/dp/0470932449) Скачать книгу (99МБ)+код к книге (464КБ) одним архивом (90МБ): https://yadi.sk/d/VCvsky11c6wtP Подробное описание создания собственных классов исключений находится здесь: "Chapter 10. Handling Errors" -> "Exceptions and Polymorphism" -> "Writing Your Own Exception Classes" Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 22, 2014, 13:44 Функция printArray принимает массив и выбрасывает исключение EmptyError, если входной аргумент пуст: низа чтобы не стал пользоваться такой функциейв концепции qt исключения получаются как лишними - везде ходят события и отложенный результат Есть конечно и другой способ без исключений. Это проверять параметры перед тем как отдавать их STL функциям, которые могут выбросить исключение. Просто когда есть свои классы исключений, то лично мне удобно, что текст ошибок находится в классах и не дублируется. Единообразный способ обработки, а не нужно придумывать через что возвращать код ошибки: Цитата из моей темы: http://www.prog.org.ru/topic_26723_0.html 1) Функция возвращает 0 при отсутствии ошибок и -1 в случае ошибки. Посмотреть код ошибки можно с помощью глобальной переменной errno (глобальной для потока). Значение функции возвращаем через ссылку-параметр функции. 2) Функция возвращает 0 в случае ошибки, так как 0 в C и C++ - это false. Функцию, тогда можно вызывать так: if ( func( ) ). Посмотреть код ошибки можно с помощью глобальной переменной errno. Значение функции возвращаем через ссылку-параметр функции. 3) Функция возвращает, как значение, так и код ошибки через структуру, либо класс, либо std::pair, либо std::tuple 4) Слышал, есть ещё способ с nullptr. Но так пример и не нашёл. 5) Ещё я слышал есть механизм setjmp()/longjmp(). Но его в C++ нельзя использовать, там какая-то замута с конструкторами, деструкторами и стеком. Да и в C его не используют (или не рекомендуют) 6) Функция возвращает 0 при отсутствии ошибок и код ошибки (errno не используется). Значение функции возвращаем через ссылку-параметр функции (можно сделать наоборот, что функция будет возвращать значение, а код ошибки через ссылку-параметр). Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 22, 2014, 14:21 Есть конечно и другой способ без исключений. Это проверять параметры перед тем как отдавать их STL функциям, которые могут выбросить исключение. Просто когда есть свои классы исключений, то лично мне удобно, что текст ошибок находится в классах и не дублируется. Единообразный способ обработки, а не нужно придумывать через что возвращать код ошибки: Вы прекрасный образец негибкого, догматического мЫшления :) Заучим правило и будем ему неуклонно следовать! С исключениями лучше чем без них! В действительности все зависит от конкретной ситуации. Исключения могут быть очень хороши или очень плохи (как впрочем и все другое). В каждом конкретном случае выбор способа обработки ошибок требует интуиции, и, опять-таки, того самого опыта.Вот Вы рассказываете как хороши классы исключений. Давайте зарядим на каждый случай свой класс! В действительности это достаточно спорно/проблематично. Напр я (и полагаю - не только) совсем не горю желанием иметь батарею catch'ей. Ну если где-то в одном месте - ладно, потерплю. Но если во многих - это так загадит код что он станет невыносимым. Не надо спешить с выводами (тем более в виде статей) всего лишь прочитав книжку (пусть самую хорошую). Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: vulko от Октябрь 22, 2014, 14:27 В каждом конкретном случае выбор способа обработки ошибок требует интуиции Фраза века! В каждом конкретном случае говнокодинг и говнофиксинг требует интуиции. Потому что если анализировать и думать, то наговнокодить сложнее. А тут интуитивно понатыкал говнокода, а вдруг пофиксится!)) Индусы именно так и работают))) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 22, 2014, 14:47 Vulko а вот тут вы неправы. Igors дело говорит. А уж Observer для меня стал нарицательным именем :D
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: vulko от Октябрь 22, 2014, 15:04 Vulko а вот тут вы неправы. Igors дело говорит. А уж Observer для меня стал нарицательным именем :D Насчет того что не везде нужна обработка исключений я не спорю, по делу сказал. Но вот про интуицию это конечно ппц))) Вопрос заключается в том нужны ли они для разработчика/юзера или не нужны. И ответ зависит лишь от того, возможны ли потенциальные ошибки в рантайме. Например юзер ввел неверно что-то. Программист вышел за пределы массива. И т.п. Причем ошибки юзера можно свести на нет проверками, исключения не особо нужны. Остаются разработчики. Если для разработчика АПИ будет скрыто, неплохо бы добавить исключения. А если для разработчика оно открыто, то не обязательно. Какая нафик интуиция вообще?! Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 22, 2014, 15:09 Цитировать Напр я (и полагаю - не только) совсем не горю желанием иметь батарею catch'ей Их можно все унаследовать от одного класса, например, пусть он называется LogicError:Код
Опять же повторюсь, что это способ завершить программу без креша, и с максимально полной информацией. Конечно же, если команда конкретной фирмы за это, то здорово! А когда один работаешь, то ещё лучше. Мне лично пока такая схема очень нравится. Пока не вижу в ней недостатков, так как не видел конкретных ситуаций, примеров. На мой взляд, такая схема завершения без креша намного лучше, чем придумывать свою схему возвращения кодов ошибок. О вкусах не спорят Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 22, 2014, 15:26 Qt возвращает коды ошибок - прекрасно! Можно написать обёртку, которая выкидывает исключение. Но я далеко не всегда так делаю. Просто показываю сообщение QMessageBox. Ошибки нужно обрабатывать всегда, но комбинировать намного лучше, чем следовать одной догме. В одном месте программы мне удобно показать QMessageBox с текстом "Некорректны ввод. Введите снова" без всяких исключений. А вот в другом месте программы я вызываю метод своего объекта. Я знаю, что он выбрасывает исключения унаследованные от класса LogicError. Я пишу вызов метода в блоке try{}. Показал текст, который выбросило исключение в QMessageBox (сохранил в лог), завершил приложение
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 22, 2014, 15:27 Их можно все унаследовать от одного класса, например, пусть он называется LogicError: А тогда чего городились многочисленные классы? Типа - захочет, пусть разбирается с каждым в своем catch, а нет - вывел общую ошибку (как здесь) и все. Не так ли ? :) Но это неудачно (или просто неверно), если интересно объясню почему.Код
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 22, 2014, 15:40 Цитировать А тогда чего городились многочисленные классы? Классы городились, потому что там текст разный и параметры конструкторы могут разные принимать. И для удобства различия по имени. Наследуются от одного или от разных классов по связи, чтобы catch'ев много не писать. Вот у меня в проекте есть базовый класс FileError, а от него наследуются: FileOpenError, FileWriteError, FileReadError, которые содержат просто разный текст и в качестве параметра конструкторам передаётся имя функции, которое выбросило исключение. Текст показали, завершили приложениеНазвание: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 22, 2014, 17:19 Классы городились, потому что там текст разный .. Это плохое, поверхностное решениеНазвание: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 22, 2014, 18:34 to Vulko:
Именно интуиция разработчика позволяет создать универсальное и легковесное решение :D Разработчику без интуиции очень сложно, я бы сказал невозможно жить :) PS почитайте что такое интуиция и с удивлением поймёте, что интуиция есть результат осмысления опыта :) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Old от Октябрь 22, 2014, 21:26 Вот про что я говрил в теме "Мать и матика". Очередная тема в которой вы совсем не разбираетесь, но пытетесь делать заключения и даже давать рекомендации.
Но это неудачно (или просто неверно), если интересно объясню почему. Конечно, будьте любезны обьяснить свои фантазии.Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: vulko от Октябрь 23, 2014, 08:01 to Vulko: Именно интуиция разработчика позволяет создать универсальное и легковесное решение :D Разработчику без интуиции очень сложно, я бы сказал невозможно жить :) PS почитайте что такое интуиция и с удивлением поймёте, что интуиция есть результат осмысления опыта :) Результатом осмысления опыта, является осмысленный опыт, позволяющий осознанно принимать решения. А интуиция это нечто совершенно другое. Есть автоматизм, который приходит с опытом и тренировками, а есть интуиция. Это только у википедиков интуиция есть результат осмысления опыта. В жизни все по другому. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: vulko от Октябрь 23, 2014, 08:04 Вот про что я говрил в теме "Мать и матика". Очередная тема в которой вы совсем не разбираетесь, но пытетесь делать заключения и даже давать рекомендации. Но это неудачно (или просто неверно), если интересно объясню почему. Конечно, будьте любезны обьяснить свои фантазии.Да... этот профессиАнал в каждой тебе путает людей своими "познаниями". Банить имхо таких надо. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 23, 2014, 08:37 Интуиция это и есть наш опыт в неявной форме. Профессиональный строитель забьёт гвоздь 1 ударом. Профессиональный портной сделает закройку парой движений. Профессиональный инженер даже без уровня заценит размер помещения с точностью до 20 см и увидит кривизну. А профессиональный программист при просмотре кода зацепится за несоответствие и закроет баг, не дожидаясь слива в интернете.
Закроем тему интуиции. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: vulko от Октябрь 23, 2014, 09:23 Интуиция это и есть наш опыт в неявной форме. Профессиональный строитель забьёт гвоздь 1 ударом. Профессиональный портной сделает закройку парой движений. Профессиональный инженер даже без уровня заценит размер помещения с точностью до 20 см и увидит кривизну. А профессиональный программист при просмотре кода зацепится за несоответствие и закроет баг, не дожидаясь слива в интернете. Закроем тему интуиции. Интуиция, это когда программист не увидев кода скажет где несоответсвие и баг. А то что ты описал, это опыт. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Bepec от Октябрь 23, 2014, 10:02 Не спорю далее я с вами,
Не мне вас в этом убеждать. Когда нибудь поймёте сами, Где интуицию вам взять :D Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: vulko от Октябрь 23, 2014, 10:10 Не спорю далее я с вами, Не мне вас в этом убеждать. Когда нибудь поймёте сами, Где интуицию вам взять :D Так аргументов у тебя просто нет, потому и не споришь. Слив засчитан. Такой же балабол как игорс, видимо. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 23, 2014, 11:45 Конечно, будьте любезны обьяснить свои фантазии. Какой-то Вы неумелый провокатор :) Если, по-Вашему, я не разбираюсь, то зачем же Вам слушать мои объяснения? Я могу удобно соскочить: "если Вы такой умный - Вы и объясните". Ну да ладно, попробую поддержать конструктив, но будете еще фыркать - перестану отвечатьПлохо здесь то что классов наворочено много, а толку никакого. Каждый класс посвящен печати - а это 10 раз поменяется в том же проекте. А про повторное использование и говорить нечего. Правильно планировать так чтобы было удобно обработчику который поймал catch и общается с юзверем. Напр чтение/запись файла. Какие случаи меня интересуют? 1) Файл отсутствует 2) открыт по записи др приложением 3) диск переполнен Все остальное - какая-то "общая ошибка", все равно мне нечего предпринять. От "испустившего" мне нужен КОД ОШИБКИ, а разбираться с ним я буду сам. Напр в случае "3" возможно "Try Again" (юзер почистит trash и нажмет). Зачем было городить класс на каждый случай - хз. Тот клаcc все равно ничего путного не сделает, т.к. он не знает что нужно - это знает "ловящий" Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Akon от Октябрь 23, 2014, 11:57 Observer: по моему скромному опыту могу сказать следующее (сам адепт исключений):
1. Qt их "не всегда" поддерживает, в том смысле, что когда код Qt работает после вашего (например, вы перекрыли виртуальный метод Qt-класса), он не ожидает исключения. Также яркий пример - исключения их слотов (не допустимы). 2. Стоит разделять ошибки программиста и ошибки пользователя. Для первых предназначен assert, для вторых подходят исключения. В этом свете std::logic_error вообще не нужен, если его назначением считать сигнализацию о логической ошибке (ошибке программиста). 3. Тонкая дифференциация ошибки посредством внушительной иерархии классов исключений, конечно, хорошо, но на практике обычно требуется проверка 2-3 вариантов. В подавляющем большинстве случаев в рамках приложения достаточно std::runtime_error c соответствующим сообщением ошибки для пользователя. Если же вы пишете библиотеку, то хорошим тоном будет использование своего класса исключения для специфичных опреаций вашей библиотеки, с тем чтобы иметь возможность отслеживания источника ошибки. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Old от Октябрь 23, 2014, 13:03 Плохо здесь то что классов наворочено много, а толку никакого. Каждый класс посвящен печати - а это 10 раз поменяется в том же проекте. А про повторное использование и говорить нечего. Это потому, что ТС не смог объяснить для чего же нужны деревья разных исключений, а вы их начали воспринимать в меру своих знаний.Я уже писал, что C++ это промышленный язык, для разработки больших систем, поэтому когда мы разрабатываем подсистему, мы хотим сделать ее максимально универсальной, что бы было возможно использовать ее без переделки и дублирования во многих местах системы. Поэтому, мы должны учесть и сообщать исключениями о совершенно разных событиях, которые могут произойти при работе. Мы не знаем, где, когда, кто и как эти события будет обрабатывать. В одном месте системы при использовании подсистемы Storage мне хватит одной общей ошибки StorageError, в другом месте системы, мне понадобиться детально разобраться, а что же происходит с хранилищем и принять меры. Причем, у меня разные исключения могут обрабатываться не то, что в одной функции (или в методах одного класса), а на разных логических уровнях. Какие-то я обработаю в самом низу (нет хранилища - ничего, попробую другое из доступных), какие-то будут обрабатываться уровнем выше (нет данных в хранилище - я попробую обойтись значениями по умолчанию, если получиться), а если хранилища разрушены - то мне ничего не остается, как завершить процесс с выводом диагностики оператору в функции main. Мне нужны развесистые деревья исключений (да и не только мне), поэтому не стоит рассказывать, что это какие-то ошибки и нормальные программисты так не сделают. Кто тут у нас решает кто нормальный программист, а кто нет? Тем более не нужно отвечать за всю отрасль, как вы любите говорить: "Обычно делают так". Вы понятия не имеете как это делается на самом деле. Честнее писать "Что так делаете именно вы", ну собственно как все на форуме и делают. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: vulko от Октябрь 23, 2014, 15:15 Это потому, что ТС не смог объяснить для чего же нужны деревья разных исключений, а вы их начали воспринимать в меру своих знаний. ... Мне нужны развесистые деревья исключений (да и не только мне), поэтому не стоит рассказывать, что это какие-то ошибки и нормальные программисты так не сделают. Кто тут у нас решает кто нормальный программист, а кто нет? Тем более не нужно отвечать за всю отрасль, как вы любите говорить: "Обычно делают так". Вы понятия не имеете как это делается на самом деле. Честнее писать "Что так делаете именно вы", ну собственно как все на форуме и делают. А зачем объяснять. Достаточно взять для примера жабу. Наличие четкой и понятной иерархии Exception'ов позволяет понять причину ошибки даже на этапе разработки сразу при её возникновении в 99% случаев без запуска дебага. Профит. п.с. Кстати в соседней ветке "эксперт" игорс предлагал игнорировать мои советы не плодить ненужные классы в низкоуровневом скрытом апи, и всячески поддерживал эту идею. А тут, где они действительно нужны, совершенно по другому пишет. Просто фрилансер-недоучка набивает посты...)) Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Igors от Октябрь 23, 2014, 19:14 .. а вы их начали воспринимать в меру своих знаний. Ну почему из Вас постоянно прет заносчивость и спесь? Так Вы ничего не достигаете и никого не убеждаете, только себе вредите....не стоит рассказывать, ..Кто тут у нас решает кто нормальный программист, а кто нет? .. Вы понятия не имеете как это делается на самом деле. Мне нужны развесистые деревья исключений (да и не только мне), Практически это вся аргументация. "Я так делаю", а кто делает иначе - неграмотный, понятия не имеет... :) Вот давайте сделаем на каждый чих класс исключения, и тогда нам будет гораздо легче поддерживать сложную систему. Да с какой стати? Каждый новый шаг разработки создает новые ситуации - значит новые классы. У меня впечатление что Вы просто злоупотребляете исключениями - тогда да, без "ветвистости" не обойтись. Ладно, раз пошел переход на личности - тема себя исчерпала (впрочем и была дохленькая). Умолкаю Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Old от Октябрь 23, 2014, 19:26 Ну почему из Вас постоянно прет заносчивость и спесь? Нее, спесь прет из вас, если вас не одергивать, вы переходите не то что на личности, на открытые оскорбления.Так Вы ничего не достигаете и никого не убеждаете, только себе вредите. Это потому, что мне не нужно здесь ничего достигать. В отличие от вас. :)Практически это вся аргументация. Аргументация была выше. Резюмируя, для того, что бы иметь возможность обрабатывать разные ситуации в разных местах, мне нужны отдельные классы для каждой ситуации. Внимание! Не один класс с кодом ситуации, а именно разные классы.Ладно, раз пошел переход на личности - тема себя исчерпала (впрочем и была дохленькая). Умолкаю Ну что, хорошо. Я надеюсь и на личности больше переходить не будете. :)Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 24, 2014, 09:18 Observer: по моему скромному опыту могу сказать следующее (сам адепт исключений): Очень важный момент. Хотелось бы не упустить. Давайте не сразу всё, а немного уточним до этого момента: "вы перекрыли виртуальный метод Qt-класса". Что значит: "Qt работает после вашего исключения"? После моего обработанного исключения? Или необработанного? Вроде после необработанного исключения приложение падает. Не всегда? Я думаю, что в стандарте C++ должен быть ответ, но врядли я найду. Прошу прощения, но Qt и C++ я изучаю (по-настоящему и серьёзно) меньше года и сейчас с боем прорываюсь всеми методами, в том числе и провакационными темами и вопросами. На войне лучше всего узнаёшь людей. Кто действительно дело говорит, а кто самоутверждается за счёт унижения других1. Qt их "не всегда" поддерживает, в том смысле, что когда код Qt работает после вашего (например, вы перекрыли виртуальный метод Qt-класса), он не ожидает исключения. Также яркий пример - исключения их слотов (не допустимы). "Qt работает после вашего отловленного исключения". Я готов предположить, что имеется ввиду ситуация, когда я перебрасываю исключение на уровень выше. Просто уточните: да или нет. Я обязательно напишу пример. Только помогите разобраться или натолкните на мысль "Также яркий пример - исключения их слотов (не допустимы). " Если можно, то чуть подробнее Покажу, какой я сделал класс "Receiver". А вы напишите, хорош ли он с точки зрения обработки ошибок и в какой ситуации он может быть плох. И какие меры предпринять, чтобы убрать эту "плохость", если она есть. У этого класса есть метод "run()", который запускаем приём данных от COM-порта. Если посылка пришла, то высылается сигнал с данными QByteArray. Этот метод "run()" выбрасывает исключение моего типа "PortError": Код
Вот таким образом я вызываю метод "run()" Код
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 24, 2014, 09:23 Вот класс "Receiver" целиком:
Receiver.h Код
Receiver.cpp Код
PortError.h Код
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 24, 2014, 13:01 Я придумал отличный пример из жизни вокруг которого можно построить статью. Займусь переделкой статьи позже. А пока изложу суть
Задача отправлять данные в COM-порт. COM-порт может быть закрыт. Либо он может быть отрыт, но данные в него нельзя отправить Класс Sender имеет два метода: - open() - для открытия порта - void send( const QByteArray &data ) - для отправки данных в порт Пользователь класса Sender открывает порт так: Код
Метод open выбрасывает исключение PortOpenError с текстом: (http://i9.pixs.ru/storage/9/7/9/412png_7451163_14410979.png) Метод send выбрасывает два исключения PortOpenError, PortSendDataError. Второе исключение с текстом: Error: unable to send data to the port "COM7" in the fucntion "Sender::send()" Оба исключения наследуются от базового класса PortError, поэтому пользотелю класса Sender достаточно написать один catch для PortError, а второй catch( ... ) (для всех исключений), на всякий случай: Код
(http://i9.pixs.ru/storage/1/9/5/413png_2177121_14411195.png) (http://pixs.ru/showimage/413png_2177121_14411195.png) Sender.h Код
Sender.cpp Код
PortOpenError.h Код
PortSendDataError.h Код
PortError.h Код
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 24, 2014, 13:06 Я немного работал с Java и C#, там примерно такая же схема
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 28, 2014, 20:55 Интересное мнение по поводу исключений: (http://www.cyberforum.ru/cpp-beginners/thread1286683.html#post6780007)
Цитата: Во-первых, сделать проверку на ошибку ничуть не проще, если ее надо протащить на неизвестное количество уровней выше. Код возврата надо тащить с уровня на уровень вручную. Исключение тащить никуда не надо - оно само летит. Во-вторых, что более важно: throw бросает наверх не какой-то жалкий код ошибки, а целый объект пользовательского типа любого размера. В этот объект вы можете запихать любое количество информации, которое будут аккуратно перенесено с самого низу наверх, к обработчику исключения. Пока исключение летит снизу вверх, его можно перехватывать на полпути, дополнять контекстной информацией и посылать дальше вверх. В-третьих, механизм перехвата исключения позволяет фильтровать исключения по типу брошенного объекта. Т.е. на любом уровне вы можете перехватывать те типы исключений, которые вас интересуют и игнорировать остальные (которые будут спокойно пролетать вверх). И т.д. и т.п. А здесь про Qt и исключения: (http://qt-project.org/forums/viewthread/1150) Цитата: When Qt was started exceptions were not available for all the compilers that needed to be supported by Qt. Today we are trying to keep the APIs consistent, so modules that have a history of not using exceptions will generally not get new code using exceptions added. You will notice exceptions are used in some of the new modules of Qt. Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: gil9red от Октябрь 28, 2014, 21:07 Интересное мнение по поводу исключений: (http://www.cyberforum.ru/cpp-beginners/thread1286683.html#post6780007) Цитата: When Qt was started exceptions were not available for all the compilers that needed to be supported by Qt. Today we are trying to keep the APIs consistent, so modules that have a history of not using exceptions will generally not get new code using exceptions added. You will notice exceptions are used in some of the new modules of Qt. А про какие новые модули говорится? Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Октябрь 28, 2014, 21:18 Может быть это: http://qt-project.org/doc/qt-5/qexception.html
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: Akon от Октябрь 31, 2014, 10:08 8Observer8: К сожалению, у меня нет достаточно времени, чтобы вникать в ваши довольно объемные посты и код. ИМХО, лучший путь глубоко изучить Qt (как и любой другой тоолкит) - это изучить исходники. Запустите отладчик и пройдитесь по коду вызова слота, в котором генерируется исключение.
Название: Re: Стратегия обработки ошибок пользователя с помощью собственных классов исключений Отправлено: 8Observer8 от Ноябрь 06, 2014, 16:28 Цитировать Запустите отладчик и пройдитесь по коду вызова слота, в котором генерируется исключение Спасибо, что обратили внимание. Как будет время - посмотрю. Как я понял из ваших слов - применение исключений в слотах что-то нарушает в работе Qt механизма сигнал\слот |