Дизайн по контракту с использованием утверждений или исключений? [закрыто]

В подобном экземпляре я не мог ждать в блоке catch. Тем не менее, я смог установить флаг и использовать флаг в инструкции if (код ниже)

--------------------- ------------------...

boolean exceptionFlag = false; 

try 
{ 
do your thing 
} 
catch 
{ 
exceptionFlag = true; 
} 

if(exceptionFlag == true){ 
do what you wanted to do in the catch block 
}
119
задан Community 23 May 2017 в 12:34
поделиться

13 ответов

Отключение утверждает в сборках конечных версий, похож на высказывание, "У меня никогда не будет проблем вообще в сборке конечных версий", которая часто является не случаем. Поэтому утверждайте, не должен быть отключен в сборке конечных версий. Но Вы не хотите катастрофический отказ сборки конечных версий каждый раз, когда ошибки происходят также, не так ли?

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

39
ответ дан Adam Bellaire 23 May 2017 в 22:34
поделиться

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

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

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

#ifdef DEBUG
#define RETURN_IF_FAIL(expr)      do {                      \
 if (!(expr))                                           \
 {                                                      \
     fprintf(stderr,                                        \
        "file %s: line %d (%s): precondition `%s' failed.", \
        __FILE__,                                           \
        __LINE__,                                           \
        __PRETTY_FUNCTION__,                                \
        #expr);                                             \
     ::print_stack_trace(2);                                \
     return;                                                \
 };               } while(0)
#define RETURN_VAL_IF_FAIL(expr, val)  do {                         \
 if (!(expr))                                                   \
 {                                                              \
    fprintf(stderr,                                             \
        "file %s: line %d (%s): precondition `%s' failed.",     \
        __FILE__,                                               \
        __LINE__,                                               \
        __PRETTY_FUNCTION__,                                    \
        #expr);                                                 \
     ::print_stack_trace(2);                                    \
     return val;                                                \
 };               } while(0)
#else
#define RETURN_IF_FAIL(expr)
#define RETURN_VAL_IF_FAIL(expr, val)
#endif

, Если бы мне была нужна проверка во время выполнения аргументов, я сделал бы это:

char *doSomething(char *ptr)
{
    RETURN_VAL_IF_FAIL(ptr != NULL, NULL);  // same as assert(ptr != NULL), but returns NULL if it fails.
                                            // Goes away when debug off.

    if( ptr != NULL )
    {
       ...
    }

    return ptr;
}
0
ответ дан indiv 23 May 2017 в 22:34
поделиться

См. также этот вопрос :

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

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

я обычно выдаю исключение в операторе "if" для взятия на себя роли по утверждению в случае, если они отключены

assert(value>0);
if(value<=0) throw new ArgumentOutOfRangeException("value");
//do stuff
0
ответ дан Community 23 May 2017 в 22:34
поделиться

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

, Если Вы думаете, нарушение того предварительного условия вероятно, сохраните его как исключение или осуществите рефакторинг предварительное условие далеко.

0
ответ дан Mike Elkins 23 May 2017 в 22:34
поделиться

Было огромное поток относительно включения/отключения утверждений в сборках конечных версий на comp.lang.c ++. модерируемый, который, если у Вас есть несколько недель, Вы видите, как варьировался, мнения об этом. :)

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

  1. Умирают с некоторым отказом типа ОС, приводящим к вызову для прерывания. (Без утверждают)
  2. , Умирают через прямой вызов аварийного прекращения работы. (С утверждают)

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

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

Лично, однако, я не уверен, что пошел бы за исключениями для этого случая также. Исключения лучше подходят туда, где подходящая форма восстановления может произойти. Например, может случиться так, что Вы пытаетесь выделить память. Когда Вы ловите 'станд.:: bad_alloc' исключение это могло бы быть возможно к свободному память и попробовать еще раз.

2
ответ дан Community 23 May 2017 в 22:34
поделиться

Я предпочитаю второй. В то время как Ваши тесты, возможно, хорошо работали, , Murphy говорит, что что-то неожиданное пойдет не так, как надо. Так, вместо того, чтобы получить исключение в фактическом ошибочном вызове метода, Вы заканчиваете тем, что проследили NullPointerException (или эквивалентный) 10 стековых фреймов глубже.

0
ответ дан jdmichal 23 May 2017 в 22:34
поделиться

Утверждает для ловли чего-то, что разработчик сделал неправильно (не только самостоятельно - другой разработчик в Вашей команде также). Если разумно, что пользовательская ошибка могла создать это условие, то это должно быть исключение.

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

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

6
ответ дан DJClayworth 23 May 2017 в 22:34
поделиться

Принцип, за которым я следую, является этим: Если ситуации можно реалистично избежать путем кодирования, затем используют утверждение. Иначе используйте исключение.

Утверждения для обеспечения, что Контракт придерживается к. Контракт должен быть справедливым, так, чтобы клиент имел возможность удостоверяться, что он соответствует. Например, можно заявить в контракте, что URL должен быть допустимым, потому что правила о том, что и не является допустимым URL, известны и последовательны.

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

я хотел бы добавить, что Утверждение / различие Исключения не является действительно лучшим способом думать об этом. То, о чем Вы действительно хотите думать, является контрактом и как он может быть осуществлен. В моем примере URL выше той лучшей вещи сделать, имеют класс, который инкапсулирует URL и является или Пустым указателем или допустимым URL. Это - преобразование строки в URL, который осуществляет контракт, и исключение выдается, если это недопустимо. Метод с параметром URL является намного более четким, что метод со Строковым параметром и утверждением, которое указывает URL.

22
ответ дан Ged Byrne 23 May 2017 в 22:34
поделиться

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

194
ответ дан Dima 23 May 2017 в 22:34
поделиться

Вы спрашиваете о различии между временем проектирования и ошибками времени выполнения.

утверждает, 'эй программист, это повреждается' уведомления, они там для напоминания Вам об ошибках, которые Вы не заметили бы, когда они произошли.

исключениями является 'эй пользователь, somethings, которые уводят неправильно' уведомления (очевидно, можно кодировать для ловли их так, пользователю никогда не говорят), но они разработаны для появления во время выполнения, когда пользователь Joe использует приложение.

Так, если Вы думаете, что можно вывести все ошибки, используйте исключения только. Если Вы думаете, что не можете..... использовать исключения. Можно все еще использовать отладку, утверждает для создания количества исключений меньше, конечно.

не забывают, что многие предварительные условия будут предоставленными пользователями данными, таким образом, Вам будет нужен хороший способ сообщить пользователю, что его данные были бесполезны. Чтобы сделать это, необходимо будет часто возвращать ошибочные данные вниз стек вызовов к битам, с которыми он взаимодействует. Утверждает не будет полезно затем - вдвойне поэтому, если Ваше приложение будет n-tier.

Наконец, я не использовал бы ни одного - коды ошибок намного выше к ошибкам, Вы думаете, будет регулярно происходить. :)

1
ответ дан gbjbaanb 23 May 2017 в 22:34
поделиться

Это не точно верно, что "утверждают сбои только в режиме отладки".

В Разработка объектно-ориентированного программного обеспечения, 2-й Выпуск Bertrand Meyer, автор оставляет дверь открытой для проверки предварительных условий в режиме выпуска. В этом случае, что происходит, когда утверждение перестало работать, то, что... исключение нарушения утверждения повышено! В этом случае нет никакого восстановления после ситуации: что-то полезное могло быть сделано, хотя, и оно должно автоматически генерировать сообщение об ошибке и, в некоторых случаях, для перезапуска приложения.

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

необходимо ли всегда уезжать, проверки предварительного условия включили? Это зависит.Ваш решать. Нет никакого универсального ответа. При создании программного обеспечения для банка могло бы быть лучше прервать выполнение аварийным сообщением, чем передать 1 000 000$ вместо 1 000$. Но что, если Вы программируете игру? Возможно, Вам нужна вся скорость, которую можно получить, и если кто-то понимает 1 000 мыслей вместо 10 из-за ошибки, которую предварительные условия не поймали (потому что им не включают), жесткая удача.

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

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

См. также: , Когда утверждения должны остаться в производственном коде?

5
ответ дан Community 23 May 2017 в 22:34
поделиться

Я обрисовал в общих чертах свое представление о состоянии вещества здесь: , Как, Вы проверяете object' s внутреннее состояние? . Обычно утверждайте свои требования и бросок для нарушения другими. Поскольку отключение утверждает в сборках конечных версий, можно сделать:

  • Отключают, утверждает для дорогих проверок (как проверка, заказан ли диапазон)
  • , Сохраняют тривиальные проверки включенными (как проверка нулевого указателя или булево значение)

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

2
ответ дан Community 23 May 2017 в 22:34
поделиться

Я попытался синтезировать здесь несколько других ответов с моими собственными представлениями.

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

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

По аргументу, что легче отлаживать утверждения: трассировку стека из правильно названного исключения так же легко прочитать, как и утверждения. Хороший код должен улавливать только определенные типы исключений, поэтому исключения не должны оставаться незамеченными из-за того, что они были пойманы. Однако я думаю, что Java иногда заставляет вас ловить все исключения.

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

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

0
ответ дан 24 November 2019 в 01:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: