OberonCore
https://forum.oberoncore.ru/

Когда применять ASSERT?
https://forum.oberoncore.ru/viewtopic.php?f=27&t=2494
Страница 1 из 2

Автор:  Alexey Veselovsky [ Понедельник, 29 Март, 2010 16:33 ]
Заголовок сообщения:  Когда применять ASSERT?

Предположим у нас некий ЯП, где унас имеется функция ASSERT(cond : Boolean), если cond = False, то она завершает программу выводя некое диагностическое сообщение (допустим номер строки исходника где оно приключилось.

Внимание вопрос -- когда следует использовать ASSERT а когда просто код возврата для диагностики ошибок?

Вот предположим функция:
Код:
GetAt(c : Container, i : Index) : Element

возвращает элемент из некого контейнера. Вопрос -- ставить ли унутре нечто вроде:
ASSERT(InRange(c,i)), или же в случае если InRange вернет False, просто вернуть код ошибки, что мол INVALID_ARGUMENT ?

Автор:  Александр Шостак [ Понедельник, 29 Март, 2010 16:51 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Я ставлю. Так и пишу ASSERT(Alg.InRange(Ind, 0, Count - 1))).
В данном случае, имхо, нужен именно ASSERT. Если при анализе возможного использования функции выясняется, что чаще всего она будет вызываться с корректными данными, то использую ASSERT, а если со слепыми - ошибки. Слепые - это когда удобнее вызвать функцию и обработать результат, а не самому фильтровать параметры. В частности, LexParser, например, может позволять делать GotoLine(x) без строгой проверки на существование строки, иначе код вашего приложения будет захламлён проверками на вызов любой функции LexParser (например, GetCharAtPos, GotoPreviousLine, GotoPos and so on).

То есть если типичный вызов вашей функции будет:
IF GetAt(c, Ind) THEN
....
то нужно возвращать код ошибки, а если

...Elem:=GetAt(c, i)...
То ASSERT. В частности, для списков, массивов, контейнеров я бы использовал только ASSERT-ы, потому как обычно известно кол-во их элементов и ожидается корректное возвращение оных.

Автор:  Иван Кузьмицкий [ Понедельник, 29 Март, 2010 16:57 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

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

Автор:  Alexey Veselovsky [ Понедельник, 29 Март, 2010 17:20 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Иван Кузьмицкий писал(а):
ASSERT'ы нужны, чтобы как можно раньше наступить на все возможные грабли. Тогда будет уверенность в дальнейшей правильной работе.


Во-первых на эти грабли будем наступать не мы, а пользователь этого кода.
Во-вторых ASSERT по сути срабатывает только при тестировании. Т.е. совершенно нет никаких гарантий, что во время тестирования оно вылезет. А во время уже запуска в эксплуатацию программа не имеет права упасть. И тут то становится плохо -- во многих языках ASSERT из релиза убирается. Соответственно имеем возможность некорректной работы приложения (проверку то убрали!), что черевато чем угодно вообще. Если же ASSERT не убрать, то если прилетит не верное значение аргумента функции, то программа упадет => взорвётся ракета, упадет самолет, город останется без связи и т.п. Особенно подобное обидно, если ошибка гнездилась в совершенно некритичным (с т.з. полезности для конечного пользователя -- пассажира самолета например) модуле. Например в каком-нибудь логгере, или чем-то подобном. Т.е. часто лучше пусть эта функция не сработает вообще чем обвалит всю систему.

Автор:  Илья Ермаков [ Понедельник, 29 Март, 2010 17:39 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

viewtopic.php?p=45052#p45052

Либо есть общее обеспечение отказоустойчивости, либо нет.
И тут дело не в ASSERT-ах. Проглоченная ошибка так же может обвалить систему.
Если речь идёт о критических системах, там диагностику и резервирование нужно проектировать централизованно, а не размазыванием вопроса по всей системе "а вот что тут будет".

А по поводу ASSERT - однозначно ставить на предусловия, и неотключаемые. Всюду и в обязательном порядке.

Автор:  Alexey Veselovsky [ Понедельник, 29 Март, 2010 17:51 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Илья Ермаков писал(а):
http://forum.oberoncore.ru/viewtopic.php?p=45052#p45052

Либо есть общее обеспечение отказоустойчивости, либо нет.
И тут дело не в ASSERT-ах. Проглоченная ошибка так же может обвалить систему.
Если речь идёт о критических системах, там диагностику и резервирование нужно проектировать централизованно, а не размазыванием вопроса по всей системе "а вот что тут будет".

А по поводу ASSERT - однозначно ставить на предусловия, и неотключаемые. Всюду и в обязательном порядке.


Ага. Почитал. Значит всё же рекомендуется использовать исключения с Try ... catch в некотором выделенном месте, где достаточно информации для возобновления работы.

Только вот во многих языках ASSERT работает параллельно исключениям (если они там вообще есть), соответственно по срабатыванию ASSERT'a никакой Try не поможет. Программа аварийно завершится без возможности возобновления (только повторный запуск приложения).

Автор:  Валерий Лаптев [ Понедельник, 29 Март, 2010 17:53 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

В других системах (в С++, например) assert предназначен как раз исключительно для отладки. В отличие от КП+ББ.

Автор:  Александр Шостак [ Понедельник, 29 Март, 2010 17:55 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Илья Ермаков писал(а):
Всюду и в обязательном порядке.

При Х-м уровне вложенности функций каждая должна проверять параметры на сложные условия корректности. Процент полезного кода среди таких проверок мал, а сами проверки зачастую ресурсоёмкие. Это первое. Второе: нельзя написать цепочку вызовов:
"IF A AND B AND C", так как все они защищены ASSERT-ами.

Цитата:
Только вот во многих языках ASSERT работает параллельно исключениям

В большинстве языков ASSERT можно переопределить своей функцией.

Цитата:
В других системах (в С++, например) assert предназначен как раз исключительно для отладки

Кем предназначен? ASSERT он один везде и смысл его один.

Автор:  Иван Кузьмицкий [ Понедельник, 29 Март, 2010 17:58 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Alexey Veselovsky писал(а):
Иван Кузьмицкий писал(а):
ASSERT'ы нужны, чтобы как можно раньше наступить на все возможные грабли. Тогда будет уверенность в дальнейшей правильной работе.


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


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

Alexey Veselovsky писал(а):
А во время уже запуска в эксплуатацию программа не имеет права упасть.


Гладко было на бумаге... Это в космических аппаратах нет такого права, а обычная приклада очень даже имеет :) Вон, у меня Опера, вполне себе релиз 10.51, но его регулярно клинит и частенько выскакивает сообщение с предложением отослать разработчикам зафиксированные параметры падения. Про подобные сообщения в Висте вообще молчу - обычное дело.

Ну а если серьёзно - если у Вас есть Много Денег или Много Времени, чтобы довести программу до идеального состояния, то Вам, я считаю, сильно повезло :)

Автор:  Alexey Veselovsky [ Понедельник, 29 Март, 2010 17:59 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Валерий Лаптев писал(а):
В других системах (в С++, например) assert предназначен как раз исключительно для отладки. В отличие от КП+ББ.

Предлагаю таки за все системы не говорить. В java assert банально кидает соответствующее исключение. Ну, собственно в КП видимо как-то подобно должно быть, ибо точился КП именно под jvm.

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

Автор:  Alexey Veselovsky [ Понедельник, 29 Март, 2010 18:10 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Иван Кузьмицкий писал(а):
Ну и пусть наступает. ASSERT в BlackBox не валит всю систему, можно работать дальше. А пользователь может сохранить трап и прислать его по почте, в рамках бета-тестирования.


ASSERT в сишном приложении тоже не валит винду, собственно даже если нет ассерта и оно радостно куда-то нагадило в память, то всё равно имеем Trap и имеем отчет системы который нам могут прислать по почте.

Но Blackbox не важен в данной ситуации, КП не важен, и винда не важна.

Прошу таки соблюдать предусловия данной темы :-)

Предусловия: Имеем ЯП. Он характеризуется наличием ASSERT'а (который аварийно завершает программу с выводом диагностики, без возможности обработки и восстановления после срабатывания оного ASSERT'a), ASSERT может быть убран из релиза программы. Или же мы может возвращать коды ошибок (либо через глобальную переменную, либо через стек, либо через ссылку туда куда скажут).

Задача: Обеспечить хорошую вылавливаемость ошибок во время отладки/тестирования приложения. Не допустить падения всего приложения во время боевого применения. Работать оно должно 24*7*365. По кр. мере это очень желательно. Раз в четыре года 29го февраля профилактика :-)

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

PS. Если бы это был вопрос по КП+ББ, тема появилась бы в соответствующем разделе форума.

Автор:  Илья Ермаков [ Понедельник, 29 Март, 2010 18:17 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Противоречие между тем, что ASSERT надо будет убрать в рабочей системе (т.к. он обваливает систему), но в то же время сохранить возможность обнаружения ошибок.

Я бы ввёл "другой ASSERT", поведение которого можем менять.

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

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

Автор:  Alexey Veselovsky [ Понедельник, 29 Март, 2010 18:21 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Илья Ермаков писал(а):
Противоречие между тем, что ASSERT надо будет убрать в рабочей системе (т.к. он обваливает систему), но в то же время сохранить возможность обнаружения ошибок.


"ASSERT может быть убран из релиза программы"
А может и не быть. Т.е. на выбор.

Но в релизе мы падать не имеем права. Можем только отказывать в некой функциональности. если в реализации её при попытке её задействовать. вылезла ошибка.

Автор:  Alexey Veselovsky [ Понедельник, 29 Март, 2010 18:33 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

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


Кроме того коды ошибок частенько очень хочется проигнорировать :-)

Однако я не очень понял как это будет работать.
Вот в рантайме у нас внезапно случился вызов той самой функции с не правильным индексом. Наш умный рантаймовый ASSERT, проверил предусловие, и понял, что сейчас случится бяка. Соответственно радостно об этом доложил какому-то спец. модулю. Этот модуль, видимо где-то поставил пометочку, что да, произошла ошибка. Будем потом восстанавливаться. Однако что дальше? Ведь если этот умный ASSERT сейчас не вызовет страшный системный ASSERT который погасит приложение нафиг, то управление передастся уже собственно логике этой процедуры, что приведет к не предсказуемым результатам (например случится доступ к не валидному адресу памяти). Как быть?

Автор:  Иван Кузьмицкий [ Понедельник, 29 Март, 2010 18:45 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Alexey Veselovsky писал(а):
Задача: Обеспечить хорошую вылавливаемость ошибок во время отладки/тестирования приложения. Не допустить падения всего приложения во время боевого применения. Работать оно должно 24*7*365. По кр. мере это очень желательно. Раз в четыре года 29го февраля профилактика :-)


У меня это всё уже есть, в рамках КП+ББ (конечно, не 24 часа в сутки, но рабочие дни заполнены с утра до вечера)! Остальное для меня - схоластика :) Переходите на КП+ББ :)

Автор:  Alexey Veselovsky [ Понедельник, 29 Март, 2010 18:49 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Иван Кузьмицкий писал(а):
У меня это всё уже есть, в рамках КП+ББ (конечно, не 24 часа в сутки, но рабочие дни заполнены с утра до вечера)! Остальное для меня - схоластика :)


«Бессмыслица — искать решение, если оно и так есть. Речь идёт о том, как поступить с задачей, которая решения не имеет».

Коль у вас, для вашего частного случая, решение есть, а прочие случаи вам не интересны, то зачем пишете сюда?

Холивор вроде ведется в какой-то соседней теме обсуждения.

PS. А с утра до вечера -- это совсем не то же самое, что 24*7*365. Это СИЛЬНО другое. Ибо максимальный интервал "беспосадочного полёта" программы получается в вашем случае <24 часов, в моем случае -- на несколько порядков больше. Требования к системе совсем другие.

Автор:  Иван Кузьмицкий [ Понедельник, 29 Март, 2010 19:03 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

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

Какого рода систему Вы делаете, если не секрет?

P.S. BlackBox - не падучая вещь. Я более чем уверен, что он способен работать в режиме 24x7x365. Можно спросить у O3 Software.

Автор:  Илья Ермаков [ Понедельник, 29 Март, 2010 19:03 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Alexey Veselovsky писал(а):
Однако что дальше? Ведь если этот умный ASSERT сейчас не вызовет страшный системный ASSERT который погасит приложение нафиг, то управление передастся уже собственно логике этой процедуры, что приведет к не предсказуемым результатам (например случится доступ к не валидному адресу памяти). Как быть?


Тогда давайте конкретно определимся, что у нас в ЯП есть. Исключения? Нет? Но setjmp и подобное должно же быть доступно. Тут явно нужно прерывание нормального хода, с попаданием на какой-то диспетчер, который уже разруливает кашу.

P.S. Класс приложений, видимо, - серверное или коммуникационное ПО?

Автор:  Madzi [ Понедельник, 29 Март, 2010 19:34 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

Нужно разделять два вида исключительных ситуаций:
1. Ситуацию можно предотавратить (деление на нуль -> проверить предварительно делитель)
2. Ситуацию предотвратить нельзя (ошибка чтения с диска).

В первом случае ASSERT необходим (даже в релизе)
Во втором случае следует использовать код возврата из процедуры и обрабатывать этот код.

Автор:  Info21 [ Понедельник, 29 Март, 2010 20:37 ]
Заголовок сообщения:  Re: Когда применять ASSERT?

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

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/