Странный шаблон: все функции / методы возвращают код ошибки, используя один и тот же тип в C ++ - PullRequest
2 голосов
/ 21 ноября 2010

В моих последних двух проектах я видел странное руководство: «Все методы / функции должны возвращать код ошибки, используя некоторый распространенный тип ERROR_CODE». В обоих проектах ERROR_CODE является int typedef.

Есть ли веская причина делать это в C ++? Некоторое требование MISRA или что-то в этом роде?

Я вижу только недостатки:

  • Если функция должна возвращать значение, это делается с помощью ссылки на аргумент. e.g.:

    строка с; ERROR_CODE err = getString (s);

  • Важность функции не очевидна. Все выглядит одинаково. Список ошибок содержит сотни ошибок от ошибок низкого уровня до некоторых ошибок, специфичных для домена.

Испытывали ли вы этот стиль программирования? Есть ли веские аргументы против или за это?

Ответы [ 5 ]

3 голосов
/ 21 ноября 2010

Я думаю, что это очень плохой стиль по нескольким причинам.

  1. Как вы уже сказали, он заставляет вас передавать указатели / ссылки для хранения фактического результата функции.
  2. Как вы сказали, унифицированный код ошибки уродлив, потому что он пытается объединить все виды ошибок из всех типов доменов.
  3. Он создает искусственную зависимость всех модулей программы от системы кодов ошибок, что затрудняет повторное использование одного модуля или небольшого подмножества модулей в других программах.
  4. Кроме того, поскольку некоторые коды ошибок зависят от домена, фактически вводятся зависимости между несвязанными типами / модулями объектов, поскольку онивсе зависят от компонента, который зависит от объединения всех их возможных типов ошибок.

Я считаю, что любая функция / метод, который имеет более чем небольшое количество управляемых способов, может потерпеть неудачулибо слишком сложен, либо плохо учтен, вероятно, оба варианта.

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

  1. Простой способ: отбросить всю абстракцию кода ошибки и просто использовать int с несколькими универсальными классами ошибок.
  2. Тяжелый объектно-ориентированный способ: предоставить указатель на внутренний «объект ошибки», где базовый класс является очень абстрактным и может совместно использоваться всеми компонентами без какой-либо зависимости, и где каждый компонент определяет свой собственный компонент-специфическийобъекты ошибок, если это необходимо.

Лучший подход, если вы используете C ++, вероятно, будет использовать исключения ...

1 голос
/ 21 ноября 2010

Я видел аргумент, что при связывании с библиотекой C ++, скомпилированной другим компилятором, который используется для компиляции ваших двоичных файлов, исключения могут не работать. Хотя этот нерабочий режим может быть полностью правдивым, на самом деле даже процесс связывания не обязательно должен работать (хотя каждый может придерживаться стандартов), поэтому теоретически этот аргумент является недействительным. На практике, однако, может быть (у меня нет опыта здесь, извините), что конфликты искажения имен возникают редко, конфликты выравнивания редко возникают, и, ну, в общем, все другие специфические для реализации вещи широко согласованы , кроме исключений.

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

В моем типичном C ++ я использую микс. Я использую более медленные исключения для вещей, которые на самом деле не ожидаем, чтобы происходить часто, или кодовых путей, которые измеряются, чтобы быть выполненными редко, но возвращают коды для вещей, которые с большей вероятностью сломаются и, вероятно, будут вызываться часто. Бросать исключения в узкий цикл, потому что в каждой итерации выполняется какое-то забавное условие, недешево (при условии, что тело цикла обрабатывает его).

1 голос
/ 21 ноября 2010

Эта идиома довольно распространена, особенно в мире Си.

Несмотря на то, что я не пользуюсь им сам и думаю, что это приносит больше вреда, чем пользы (подробнее об этом в других ответах), я нахожу его преимущество: последовательный способ сообщать о неожиданных ошибках на сайт вызова , Что-то вроде переменной errno, но проще в использовании.

Например, рассмотрим набор функций:

int a();
std::string b();
double c();
std::list<long> d();

Каждая из вышеперечисленных функций будет указывать сбой по-разному: a () может возвращать -1, b () пустую строку, c () a 0.0 и d () пустой список. Это противоречиво и не совсем интуитивно понятно. Теперь представьте функцию, диапазон которой охватывает весь возможный диапазон возвращаемого типа. Это еще хуже.

Некоторые API также делают:

int x(bool* ok);

Но это также загрязняет каждую функцию дополнительным аргументом.

В C не так много возможностей сделать это хорошим способом, к сожалению, если вам действительно нужно разработать такой API, который бы указывал на различные типы сбоев. Однако в мире C ++ вы можете просто использовать исключения.

1 голос
/ 21 ноября 2010

Для команд не является чем-то необычным договориться о распространенных способах возврата ошибок, поскольку это помогает создать общий «внешний вид» кода проекта, как и любое другое соглашение о кодировании для всей команды.Это может помочь новым членам команды быстрее понять общую картину и сделать обслуживание в команде кода других людей более интуитивным.

Мне удивительно, что проект C ++ объединяется за ошибками, а не за исключениями, тем не мение.Здесь обсуждаются плюсы и минусы использования исключений против кодов ошибок здесь .

Полагаю, один аргумент в пользу обработки кода ошибки - если вы используете API в стиле C, который ведет вас к этому подходу (кашель ... Win32 ... кашель).

1 голос
/ 21 ноября 2010

Я видел это.

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

Это не звучит как хорошая идея, но и не все так плохоодного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...