Почему нельзя отключать ASSERT-ы в релизе
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 05.12.05 16:01
Оценка: 13 (2) +1
Почему нельзя отключать ASSERT-ы в релизе

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

Фрагмент из хелпа к BlackBox:

Хорошо известно, что определение ошибки тем более затруднено и дороже обходится, чем позже она обнаруживается, т.е. чем дальше разнесены источник и его эффекты. Это позволяет сформулировать правило:

Позволяйте ошибкам заявлять о себе как можно раньше.

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

Никогда не позволяйте ошибкам проникать сквозь границы компонентов.

К счастью, большинство проверок предусловий недорого и поэтому их отключение при исполнении не имеет смысла. Это важно, поскольку в компонентно-ориентированной системе проверки периода исполнения не могут быть выключены в конечной (готовой) системе, поэтому разрабатываемая и готовая системы не различаются. На практике большинство компонентов уже отлажено в режиме черного ящика ("продукция"), а другие отлаживаются в режиме белого ящика. Готовые компоненты должны взаимодействовать, чтобы доказать приверженность сформулированному выше правилу, которое означает «никогда не отключать проверки периода исполнения».

Перевод на русский язык выполнен здесь.
Re: Почему нельзя отключать ASSERT-ы в релизе
От: McSeem2 США http://www.antigrain.com
Дата: 05.12.05 16:56
Оценка: 21 (4) +11
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Почему нельзя отключать ASSERT-ы в релизе


СГ>В модульных (компонентных) расширяемых системах отключать ASSERT-ы в «релизе» нельзя. Это связано с тем, что для Вас-то, быть может эта система «релизная», а вот для клиента, который пишет для неё (и отлаживает) свои компоненты, она никакая не «релизная».


Я склонен думать, что здесь присутствует терминологическая путаница. ASSERT по определению должен быть отключен в релизе. Иначе он такровым не является — так уж исторически сложилось и менять этот распорядок нехорошо. Если нечто, подобное ассерту должно присутствовать в релизе, то и называться это должно по-другому. Например, VERIFY. И это будет являться штатным механизмом сообщения об ошибках. Весь смысл и заключается в том, что это уже другой механизм, отличный от ASSERT. Тем не менее, встречаются люди, которые даже не могут себе представить, что на свете существуют задачи, в которых наличие ASSERT в релизе категорически недопустмо.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: Почему нельзя отключать ASSERT-ы в релизе
От: GlebZ Россия  
Дата: 05.12.05 17:19
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

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

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Почему нельзя отключать ASSERT-ы в релизе
От: minorlogic Украина  
Дата: 05.12.05 17:27
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Почему нельзя отключать ASSERT-ы в релизе

Догма сомнительная, один термин "компонента" о чем говорит .

Как пример , использую я гдето двусвязанный список объектов ( интрузивный ), и при разработке использую такую функцию как ValidateList, ValidateObject и т.д. которые проверяют список на инварианты.

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

И что , мне эти asserts оставлять в релизе ?
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Почему нельзя отключать ASSERT-ы в релизе
От: Pzz Россия https://github.com/alexpevzner
Дата: 05.12.05 18:43
Оценка: 1 (1)
McSeem2 wrote:
>
> Я склонен думать, что здесь присутствует терминологическая путаница.
> ASSERT по определению должен быть отключен в релизе. Иначе он такровым
> не является — так уж исторически сложилось и менять этот распорядок
> нехорошо. Если нечто, подобное ассерту должно присутствовать в релизе,
> то и называться это должно по-другому. Например, VERIFY. И это будет
> являться штатным механизмом сообщения об ошибках. Весь смысл и

А чем этот VERIFY отличается от ASSERT'а, кроме названия?

> заключается в том, что это уже другой механизм, отличный от ASSERT. Тем

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

И что это за задачи такие?

И кстати, какое ожидается поведение от программы в таких задачах в том
месте, где должен бы сработать ASSERT, но его нету?
Posted via RSDN NNTP Server 2.0
Re[2]: Почему нельзя отключать ASSERT-ы в релизе
От: AVC Россия  
Дата: 05.12.05 23:48
Оценка: 3 (1)
Здравствуйте, McSeem2, Вы писали:

MS>Здравствуйте, Сергей Губанов, Вы писали:


СГ>>Почему нельзя отключать ASSERT-ы в релизе


СГ>>В модульных (компонентных) расширяемых системах отключать ASSERT-ы в «релизе» нельзя. Это связано с тем, что для Вас-то, быть может эта система «релизная», а вот для клиента, который пишет для неё (и отлаживает) свои компоненты, она никакая не «релизная».


MS>Я склонен думать, что здесь присутствует терминологическая путаница. ASSERT по определению должен быть отключен в релизе. Иначе он такровым не является — так уж исторически сложилось и менять этот распорядок нехорошо. Если нечто, подобное ассерту должно присутствовать в релизе, то и называться это должно по-другому. Например, VERIFY. И это будет являться штатным механизмом сообщения об ошибках. Весь смысл и заключается в том, что это уже другой механизм, отличный от ASSERT. Тем не менее, встречаются люди, которые даже не могут себе представить, что на свете существуют задачи, в которых наличие ASSERT в релизе категорически недопустмо.


Сергей говорит о расширяемых (extensible) системах и о применении в них принципа контрактного программирования (Мейер).
В таких системах заранее неизвестно, кто и как будет вызывать наш код. Поэтому отключать проверку предусловий и правда не следует.
Тот ASSERT, о котором говорит Сергей, не приводит к завершению работу программной системы, а только прерывает выполнение текущей команды. Т.е. это разновидность исключения, обрабатываемая системой, "ловушка" (trap).
Вы же говорите, как мне кажется, о другом типе систем.
Поэтому, скорее всего, противоречия нет.
Но у меня возник вопрос: а почему "наличие ASSERT категорически недопустимо"?
Если все предусловия верны, то ASSERT никак себя не проявит. А если где-то предусловие не выполняется, то, не исключено, что генерация исключения — меньшее из зол. (Я не утверждаю, что всегда.)

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[3]: Почему нельзя отключать ASSERT-ы в релизе
От: Павел Кузнецов  
Дата: 06.12.05 00:00
Оценка: +3
AVC,

> Но у меня возник вопрос: а почему "наличие ASSERT категорически недопустимо"?


При достаточно глубоких проверках, ASSERT's могут быть очень дороги. Например, это так в отладочной версии STLport, проверяющей валидность и принадлежность итераторов одному контейнеру и т.п.
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Почему нельзя отключать ASSERT-ы в релизе
От: _FRED_ Черногория
Дата: 06.12.05 00:27
Оценка: 1 (1) +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Почему нельзя отключать ASSERT-ы в релизе


СГ>В модульных (компонентных) расширяемых системах отключать ASSERT-ы в «релизе» нельзя. Это связано с тем, что для Вас-то, быть может эта система «релизная», а вот для клиента, который пишет для неё (и отлаживает) свои компоненты, она никакая не «релизная».


Я, например, не линюсь писать как-то так:

    internal void Fill(TDataSet dataSet) {
      // Объявлена как internal, то есть я могу и должен проконтролировать все вызовы
      // Во время отладки не "замылится", заявит о себе так, что внимания не обратить невозможно…
      Debug.Assert(dataSet != null, "dataSet != null"); 

      // Но если не проконтролировал - чтож, и такое случается  :shuffle: 
      // … а в релизе сообщит об ошибке и программа продолжит работать.
      if(dataSet == null) {
        throw new ArgumentNullException("dataSet"); // Если недосмотрел, то вместо NullReferenceException получу нечно более осмысленное.
      }//if

      // …
    }


Подсмотрел такую практику в каком-то С++ коде, который мне очень понравился и перенял. Да, нелегко приучить себя писать двойные проверки, но зато оправдывает себя.
Help will always be given at Hogwarts to those who ask for it.
Re: Почему нельзя отключать ASSERT-ы в релизе
От: _FRED_ Черногория
Дата: 06.12.05 00:29
Оценка: +2
Здравствуйте, Сергей Губанов, Вы писали:

СГ>… для клиента, который пишет для неё (и отлаживает) свои компоненты, она никакая не «релизная».


Для таких целей можно у разработчиков используемой библиотеки попросить Debug-версии с символами. Майкрософт предоставляет.
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Почему нельзя отключать ASSERT-ы в релизе
От: AVC Россия  
Дата: 06.12.05 00:49
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

>> Но у меня возник вопрос: а почему "наличие ASSERT категорически недопустимо"?


ПК>При достаточно глубоких проверках, ASSERT's могут быть очень дороги. Например, это так в отладочной версии STLport, проверяющей валидность и принадлежность итераторов одному контейнеру и т.п.


Т.е. первый (и самый очевидный) ответ — по причине больших накладных расходов.
Понятно, что в релизной версии предпочитают не сипользовать отладочную версию STLport.
Но, ИМХО, это не означает категорической недопустимости ASSERT в релизе, а является некоторым (разумным) компромиссом между надежностью и эффективностью.
(Предложение реализовать итераторы (STL) таким образом, чтобы необходимые проверки осуществлялись эффективно, я опускаю. Наверное, это выше человеческих сил. )
Но отдельное (stand-alone) приложение с использованием STL мы можем "вылизать", выловив (почти) все ошибки.
А что делать с программным компонентом, который будет использоваться неизвестно кем и неизвестно как?
Например, зловредными индусами, которыми нас тут недавно стращали.
Здесь мы не можем надеяться, что исключили ошибки в использовании компонента. Ведь большинство этих ошибок еще даже не были сделаны, когда мы завершили отладку.
Разумно ли в такой ситуации изымать из кода проверку предусловий?
ИМХО, неразумно.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re: Почему нельзя отключать ASSERT-ы в релизе
От: Дарней Россия  
Дата: 06.12.05 02:54
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

про это еще Страуструп говорил
примененять защитные проверки в debug конфигурации и отключать их в release — это всё равно что плавать на корабле с полным набором спасательных кругов и шлюпок возле берега, и сгружать их на берег перех выходом в открытое море.
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[3]: Почему нельзя отключать ASSERT-ы в релизе
От: Pavel Dvorkin Россия  
Дата: 06.12.05 03:13
Оценка:
Здравствуйте, Pzz, Вы писали:


Pzz>А чем этот VERIFY отличается от ASSERT'а, кроме названия?


#ifdef _DEBUG
#definr VERIFY(f) ASSERT(f)
#else
#define ASSERT(f) ((void)0)
#define VERIFY(f) ((void)f)
#endif

Это вырезка из AFX.H
With best regards
Pavel Dvorkin
Re[5]: Почему нельзя отключать ASSERT-ы в релизе
От: Alex Fedotov США  
Дата: 06.12.05 03:38
Оценка: 15 (3) +14 -2
Здравствуйте, AVC, Вы писали:

AVC>Например, зловредными индусами, которыми нас тут недавно стращали.

AVC>Здесь мы не можем надеяться, что исключили ошибки в использовании компонента. Ведь большинство этих ошибок еще даже не были сделаны, когда мы завершили отладку.
AVC>Разумно ли в такой ситуации изымать из кода проверку предусловий?

Почему-то постоянно кто-то пытается использовать ASSERTs для того, для чего они не предназначены.

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

С другой стороны, если я в release версии своего компонента оставлю все ASSERTs, и в один прекрасный момент вы обнаружите, что срабатывает ASSERT где-то на двенадцатом уровне вызовов, чем вам это поможет?
-- Alex Fedotov
Re: Почему нельзя отключать ASSERT-ы в релизе
От: StanislavK Великобритания  
Дата: 06.12.05 08:46
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Почему нельзя отключать ASSERT-ы в релизе


Лучше использовать настраиваемые логи, тогда вопрос о том, что отключать в релизе, а что нет, просто не будет существовать, т.к. это можно будет сделать в любой момент.
Re[2]: Почему нельзя отключать ASSERT-ы в релизе
От: AVC Россия  
Дата: 06.12.05 09:18
Оценка: :)
Здравствуйте, Дарней, Вы писали:

Д>про это еще Страуструп говорил

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

Да-да, еще Страуструп.
А до Страуструпа — еще Хоар.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[6]: Почему нельзя отключать ASSERT-ы в релизе
От: AVC Россия  
Дата: 06.12.05 09:56
Оценка: 3 (1)
Здравствуйте, Alex Fedotov, Вы писали:

AVC>>Например, зловредными индусами, которыми нас тут недавно стращали.

AVC>>Здесь мы не можем надеяться, что исключили ошибки в использовании компонента. Ведь большинство этих ошибок еще даже не были сделаны, когда мы завершили отладку.
AVC>>Разумно ли в такой ситуации изымать из кода проверку предусловий?

AF>Почему-то постоянно кто-то пытается использовать ASSERTs для того, для чего они не предназначены.


Покажите мне этих негодяев, я им задам!

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


В BlackBox, хелп к которому цитировал Губанов, ASSERT именно этим и занимается.
И как Вы правильно сказали, определенные требования к аргументам являются частью интерфейса компонента.
Поэтому отключать ASSERT в таких условиях нельзя. О чем опять же правильно написано в этом хелпе.
По моему, мы пришли к консенсусу, если только не принимать близко к сердцу лингвистические споры об ASSERT и VERIFY.
По поводу последнего только замечу, что в разных языках существуют разные традиции именования.

AF>С другой стороны, если я в release версии своего компонента оставлю все ASSERTs, и в один прекрасный момент вы обнаружите, что срабатывает ASSERT где-то на двенадцатом уровне вызовов, чем вам это поможет?


В BlackBox (как и в большинстве Оберон-систем) практически нет разницы между release и debug.
Отладочная информация не включается в код, а в случае срабатывания "ловушки" восстанавливается RTS.
Недавно подобный факт открыл для себя VladD2, правда, теоретически — при чтении статьи об одном из способов обработки исключений в Обероне. (Кажется, он думал, что Сергей об этом не знал. )
на Ваш вопрос отвечаем: в результате срабатывания ASSERT на двенадцатом уровне вызовов мы можем восстановить полную информацию о всех 12 подпрограммах, и даже больше. По крайней мере, в BlackBox.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[2]: Причина не внутри модуля, а вне его
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 06.12.05 10:14
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Честно говоря, релизный код не должен содержать ошибок.


Естественно, но дело не в ошибках внутри Вашего модуля (а я говорю именно о модулях — бинарниках). Ошибок внутри релизного модуля быть, конечно, не должно, но и ASSERT-ы в нём не должны быть отключены.

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

Другой разработчик, разрабатывая свои модули взаимодействующие с Вашим (безошибочным) модулем, сам может ошибаться. Так вот, чтобы ошибка из его модуля не пролезла внутрь Вашего — Ваш модуль должен тщательно "обороняться". Оставленные ассерты — это "оборона" Вашего (безошибочного) модуля от ошибок других программистов в других модулях (чтоб ошибки не проникали из одного модуля внутрь другого).
Re[4]: Почему нельзя отключать ASSERT-ы в релизе
От: Pzz Россия https://github.com/alexpevzner
Дата: 06.12.05 10:24
Оценка:
Pavel Dvorkin wrote:
>
> Pzz>А чем этот VERIFY отличается от ASSERT'а, кроме названия?
>
> #ifdef _DEBUG
> #definr VERIFY(f) ASSERT(f)
> #else
> #define ASSERT(f) ((void)0)
> #define VERIFY(f) ((void)f)
> #endif

Т.е., VERIFY, это ASSERT для идиотов, допускает без последствий проверки
с побочными эффектами?
Posted via RSDN NNTP Server 2.0
Re[3]: Почему нельзя отключать ASSERT-ы в релизе
От: Дарней Россия  
Дата: 06.12.05 10:31
Оценка:
Здравствуйте, AVC, Вы писали:

AVC>А до Страуструпа — еще Хоар.


в общем, не знаю, кто это сказал первым. у кого увидел — про того и сказал
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[3]: Причина не внутри модуля, а вне его
От: GlebZ Россия  
Дата: 06.12.05 10:47
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Другой разработчик, разрабатывая свои модули взаимодействующие с Вашим (безошибочным) модулем, сам может ошибаться. Так вот, чтобы ошибка из его модуля не пролезла внутрь Вашего — Ваш модуль должен тщательно "обороняться". Оставленные ассерты — это "оборона" Вашего (безошибочного) модуля от ошибок других программистов в других модулях (чтоб ошибки не проникали из одного модуля внутрь другого).

Давай разведем процесс по ролям. Допустим у нас есть два программиста, при этом один поставил свой модуль и его забрали в армию. И клиенту поставляют вместе с модулем программу написанную вторым программистом.
1. Роль — программист который делает модуль. Для него ассерт как таковой информативен, поскольку несет в себе информацию о месте возникновения ошибки. Имея место, существует надежда что он может локализовать ошибку.
2. Роль — программист-клиент модуля. Для него ассерт по боку. Если он получит ассерт, то единственное что он поймет что где-то что-то у нас порой. Для него нужна более информативная ошибка о неверных параметрах, и каким образом он дошел до такой жизни.
3. Роль — клиент. А вот ему все по фигу. Его не волнует кто ошибся и где ошибся. Он сам может ошибиться. Тогда получается так, ассерт принесенный из модуля, его не волнует. Ошибка принесенная из модуля, тоже ему немного о чем говорит. Подобную ошибку должен выводить программист который написал программу, и в терминах понятных для клиента. То есть, основная информация должна быть выдана программистом основной программы на основе ошибки в модуле. Другое дело, что дополнительно если эта ошибка выходит за пределы бизнес-логики, то программисту нужно получить более подробную информацию. Это делается дополнительными средствами(типа логов, или отправке дампа по почте). Но то что в этой подробной информации написано, клиент вряд-ли разберется.

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

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.