Плохо ли смешивать логические и рет-коды?

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

Вид, в котором 0 (первое значение перечисления) означает успех, а 1 — отказ. В некоторых случаях у меня есть собственные вспомогательные функции, которые возвращают логическое значение, указывающее на ошибку, в других случаях я поднимаю перечисление ошибок. К сожалению, иногда я путаю одно с другим, и все терпит неудачу.

Чтобы вы посоветовали? Я пропускаю некоторые предупреждения о gcc, которые будут предупреждать в этих случаях?

P.S. мне кажется странным возвращать код ошибки, который совершенно не связан с моим кодом, хотя я думаю, что мог бы вернуть -1 или какое-то другое недопустимое значение.


person Roman A. Taycher    schedule 13.06.2011    source источник


Ответы (5)


Это плохая идея? Нет, вы должны делать то, что имеет смысл, а не следовать какому-то абстрактному правилу (которое почти никогда не подходит для всех ситуаций, с которыми вы все равно столкнетесь).

Один из способов избежать проблем — убедиться, что все функции, возвращающие логические значения, читаются как на правильном английском языке, например, isEmpty(), userFlaggedExit() или hasContent(). Это отличается от моих обычных конструкций глагол-существительное, таких как updateTables(), deleteAccount() или crashProgram().

Для функции, которая возвращает логическое значение, указывающее на успех или неудачу функции, которая обычно следует за этой конструкцией глагол-существительное, я обычно использую что-то вроде deleteAccountWorked() или successfulTableUpdate().

Во всех случаях, когда возвращаются логические значения, я могу создать легко читаемый оператор if:

if (isEmpty (list)) ...
if (deleteAccountWorked (user)) ...

И так далее.

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


Но имейте в виду, что это моё решение. Это может или не может работать для других людей.

person paxdiablo    schedule 13.06.2011

Я бы сказал, что в тех частях приложения, которыми вы управляете, и в частях, составляющих ваш внешний API, выберите один тип обработки ошибок и придерживайтесь его. Какой тип менее важен, но будьте последовательны. В противном случае люди, работающие над вашим кодом, не будут знать, чего ожидать, и даже вы сами будете чесать голову, когда вернетесь к коду через год или около того;)

person inquam    schedule 13.06.2011

Если стандартизировать схему с нулевой == ошибкой, вы можете смешивать и сопоставлять как enum, так и bool, если вы построите свои тесты следующим образом:

ошибка = некоторые_функции(); если !ошибся...

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

Однако, как правило, лучше возвращать целое число (или перечисление), так как это позволяет расширить возвращаемые коды ошибок без модификации вызывающего кода.

person Pete    schedule 13.06.2011
comment
Разве это не было бы нулевой ошибкой !=? Потому что для перечисления имеет смысл иметь 1 код ok и n кодов ошибок, а не наоборот. - person Lundin; 13.06.2011
comment
Ну нет, операция имеет 0 как успех (на самом деле довольно часто), так что !err ... сделать некоторые вещи работает как задумано. - person Pete; 13.06.2011
comment
очень распространено, так как перечисления начинаются с 0 по умолчанию. - person Roman A. Taycher; 14.06.2011
comment
больше похоже на код возврата != успех, но иногда я мог бы сделать на самом деле_a_bool != значение_успеха_которое_равно_нулю. Называть переменную var_bool так уродливо. - person Roman A. Taycher; 14.06.2011

Я бы не сказал, что это плохая практика.

Нет необходимости создавать тонны enum, если вам просто нужно вернуть true/false, и у вас нет других вариантов (и true и false достаточно пояснены).

Кроме того, если ваши функции названы OK, у вас будет меньше «ошибок».

Например - IsBlaBla - ожидает возврата true. Если у вас [Do|On]Reload, перезагрузка может завершиться неудачей по многим причинам, поэтому следует ожидать enum. То же самое для IsConnected и Connect и т. д.

person Kiril Kirov    schedule 13.06.2011
comment
Перечисление — это перечисление ошибок из внешних библиотек. - person Roman A. Taycher; 13.06.2011
comment
Ах, я вижу, я пропустил эту часть. - person Kiril Kirov; 13.06.2011

ИМХО, здесь помогает именование функций.

Например. для функций, возвращающих логическое значение, is_foo_bar(...) или для функций, возвращающих код успеха или ошибки, do_foo_bar(...).

person janneb    schedule 13.06.2011
comment
Обратите внимание, что они подразумевают другое поведение. do_xyz() обычно означает, что функция имеет побочные эффекты, а is_xyz() обычно используется для предикатов, которые не вызывают (наблюдаемых) изменений состояния. - person efotinis; 13.06.2011
comment
@efotinis: Да, и это тоже. Так совпало, что почти все мои функции, возвращающие логическое значение, являются функциями без побочных эффектов. Часто, когда функция имеет побочные эффекты, существует несколько способов сбоя, и, следовательно, код ошибки является лучшим выбором, чем логическое значение. В любом случае, кажется, ответ paxdiablo более подробно изложил мои мысли. - person janneb; 13.06.2011