среда, 22 декабря 2010 г.

Не вся информация одинаково полезна

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

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

Я очень люблю отладочные сообщения. Они говорят мне значительно больше чем ковыряние в отладчике. Я вообще не люблю отладчики.

Причем наш код уже содержит достаточно много всякого мусора, который давно надо убить. Зачем убить, спросите вы, ведь отладочные сообщения полезны?!? Надо. Опыт подсказывает, что чужие сообщения не несут информации. Очень редко получается так, что посмотрел на чужие сообщения, и понял в чем проблема. Чаще приходится дописывать новые.

Так зачем спрашивается хранить старые, если их в каждом конкретном случае все равно приходится менять??? Эти отладочные сообщения заполонили весь код, у нас их столько, что за ними содержательных не видно!!!

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

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

Какого черта вот она в fastDB падает:
assert(currId != 0);
Может это и правильно с ее точки зрения, но не несет мне необходимой информации. Может быть исключение в данном случае было бы предпочтительнее? В исключение можно запихнуть значительно больше информации, которая позволит тому, кто пользуется данными методами понять, что же он делает не так.

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

Тему про наглядность ассертов я уже поднимал как-то, с тех пор собственно ничего не изменилось. Ассерты не доносят информацию. Сообщение о том, что 'currId != 0', могло бы что-то полезное сообщить, если я работаю на соседнем уровне, то есть вызываю эту функцию непосредственно. Но теряет всякий смысл, когда я использую все это через три уровня косвенности.

Да, можно определить что она улетела в БД и зарылась где-то там... Зачем зарылась - а кто его знает. Если бы это было бы исключением - его мог бы обработать какой-то из промежуточных уровней и сказать что у него пошло не так. Сказать что-то большее, нежели currId == 0. Чтобы докопаться до причины, в случае ассерта необходимо понять как работают все промежуточные уровни.

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

9 коммент.:

alexp комментирует...

тоже не понимаю в чем полезность ассертов.. в программе как то удобнее записать в лог и/или вернуть нужный exit сode. это гораздо удобнее с точки зрения поддержки пользователейю а так непонятно зачем зашитый в программу юнит-тест получается. хотя в самих юнит тестах - без ассертов - никуда

Andrey Valyaev комментирует...

В юниттестах ассерты не такие. Они не завершают программу аварийно.

alexp комментирует...

да, да не такие, просто для примера привел, что этот инструмент удобнее использовать именно для юнит-тестирования. поэтому assert.h не использую. и непонимаю почему дебажная версия третьестороннего подгружаемого модуля должна стопать мою программу, если ей что-то не понравилось. верни исключение, или екзит-код, но стопать то зачем? хотя может это и есть unix-way :)

Tier комментирует...

assert'ы - зло. IMHO, конечно. Это чисто сишный пережиток.
А shared_ptr ведёт себя так по той же причине, по которой std::vector::operator[] не кидает исключения - оптимизация.
На мой взгляд вместо assert'ов лучше исключения, кидаемые в DEBUG сборке.

Andrey Valyaev комментирует...

Да, это верно подмечено, оптимизация...

ассерты ничего не стоят в релизной версии.

Просто в С++ видимо нужно написать специальные макросы, которые не стопают программу а делают что-то другое.

в BOOST можно определить свой assert handler. Но это к сожалению никак не повлияет на сторонние библиотеки... :)

Tier комментирует...

>ассерты ничего не стоят в релизной версии.

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

afunix комментирует...

Я иногда использую assert-ы, потому что можно запустить программу в gdb, заставить сработать assert(), затем посмотреть backtrace в gdb. Порой бывает очень полезно

Andrey Valyaev комментирует...

2Tier: Чтобы сказать, что ассерты не нужны - нужно быть уверенным что ты в отладочной версии все эти ветви проверил, все возможные ситуации. Очень редко кто сможет за это поручиться, я таких людей не знаю. :)

2afunix: Дык это получается ровно то же, что и отладочные сообщения, свои - хорошо.. чужие - вечно не в тему :)

Tier комментирует...

Так я тоже таких людей не знаю :) Но ведь всё равно assert'ы в релизе не работают :)