Здравствуйте, _FRED_, Вы писали:
_FR>Извини, но ты програмируешь на .NET? Часто нарывался на асерты в сторонних библиотеках? А на ArgumentNullException? Не задумывался, почему для проверки предусловий в стандартных библиотеках используются исключения вместо асертов?
Предусловия по определению не нужно проверять(внутри функции).
Здравствуйте, Юрий Жмеренецкий, Вы писали:
_FR>>Извини, но ты програмируешь на .NET?
Ы?
_FR>>Часто нарывался на асерты в сторонних библиотеках? А на ArgumentNullException? Не задумывался, почему для проверки предусловий в стандартных библиотеках используются исключения вместо асертов?
ЮЖ>Предусловия по определению не нужно проверять(внутри функции).
Чем же тогда объяснить наличие ArgumentException и наследников? Кривостью дизайна .NET Framework?
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>>>Извини, но ты програмируешь на .NET?
В контексте топика это не имеет значения.
ЮЖ>>Предусловия по определению не нужно проверять(внутри функции). _FR>Чем же тогда объяснить наличие ArgumentException и наследников? Кривостью дизайна .NET Framework?
Само наличие еще ни о чем не говорит. А вот использование.. Явная проверка предусловий(это, кстати факт того что предусловия попросту отсутствуют) в функции говорит о том что программа(здесь Framework) не использует design-by-contract(в принципе под определение подвести конечно можно, но это будет притягиванием за уши). Это просто другой подход. В чем-то лучше, в чем-то хуже... Основное отличие в том что если срабатывает assert то программу нужно исправлять, а не выкидывать исключения.
Здравствуйте, _FRED_, Вы писали:
_FR>>>>>Извини, но ты програмируешь на .NET? ЮЖ>>В контексте топика это не имеет значения.
_FR>Ну тогда и говорить не о чем: представь себе библиотеку, которая об ошибках сообщает через асерты. Как с ней работать, имея только релизные сборки?
assert — это не способ обнаружения ошибок. Если есть предусловия, то они должны выполняться, если отсутствуют — то постусловия должны перечилслять все возможные ошибки(исключения). При использовании DbC проверки аргументов никуда не исчезают, они переносятся на уровень выше как предусловия. Чем "глубже" в библиотеку — тем меньше явных проверок, т.к. некоторые предусловия выполняются автоматически будучи уже проверенными(причем один раз) выше.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
_FR>>>>>>Извини, но ты програмируешь на .NET? ЮЖ>>>В контексте топика это не имеет значения. _FR>>Ну тогда и говорить не о чем: представь себе библиотеку, которая об ошибках сообщает через асерты. Как с ней работать, имея только релизные сборки? ЮЖ>assert — это не способ обнаружения ошибок. Если есть предусловия, то они должны выполняться, если отсутствуют — то постусловия должны перечилслять все возможные ошибки(исключения).
Кто должен нести ответственность за соблюдение "предусловий" (если под предусловиями понимать значение передаваемых аргументов, как в рассматриваемом примере
)? Вызывающий. Если мы проверяем предусловия асертом, а у вызывающего только релиз — как он об этом узнает? Получит исключения, как в правильном по моему мнению примере
Программа глухо свёрнётся из-за ошибки доступа по невалидному адресу
Программа будет как-то неправильно работать
Я предпочитаю исключения.
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
ЮЖ>>Если виноват — должен исправить(проверить явно). Иначе это не предусловие.
_FR>Извини, но ты програмируешь на .NET? Часто нарывался на асерты в сторонних библиотеках? А на ArgumentNullException? Не задумывался, почему для проверки предусловий в стандартных библиотеках используются исключения вместо асертов?
Может быть потому что стандартные библиотеки скомпилированы не в дебаге, а в релизе?
Здравствуйте, Lloyd, Вы писали:
ЮЖ>>>Если виноват — должен исправить(проверить явно). Иначе это не предусловие.
_FR>>Извини, но ты програмируешь на .NET? Часто нарывался на асерты в сторонних библиотеках? А на ArgumentNullException? Не задумывался, почему для проверки предусловий в стандартных библиотеках используются исключения вместо асертов?
L>Может быть потому что стандартные библиотеки скомпилированы не в дебаге, а в релизе?
Именно об этом я и говорю. В .NET ещё (или ужЕ) на уровне основной среды разработки (MSVS) не предусмотрено использование разных (конфигураций) сборок в зависимоти от конфигурации проекта, поэтому подавляющее большинство програмистов пишет и отлаживает свой код с релизом чужих сборок. Поэтому, чем более "умная" окажется чужая сборка, чем более удобные и понятные сообщения об ошибках из неё можно получить, чем более она соответствует принципам, изложенным здесь, тем удобнее в использовании она окажется для разработчиков-пользователей.
А для этого, нельзя полагаться на верность данных, получаемых "извне", от вызывающего кода и бессмысленно ставить асерты на условия, зависящие от вызывающего кода. Перенося обязанность проверки на вызывающий код, автор библиотеки усложняет жизнь вызывающему (который может использовать десяток-другой различных библиотек и будет обязан разобраться в тонкостях работы с каждой). хорошая библиотека (как и любой кусок хорошего кода) должен быть "готов к использованию", должен быть "кирпичём", из которого можно сложить необходимое, а не полуфабрикатом, который надо бережно и внимательно доготовить.
Прикладной програмист должен думать о своих задачах, и не удилять _излишне_ много времени изучению кода, который он вызывает, и это достижимо, когда вызываемый код понятно говорит о том, в чём проблема, а не ставит, например, перед фактом — "некая переменная по такому-то адресу оказась равной null".
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>>>Извини, но ты програмируешь на .NET? Часто нарывался на асерты в сторонних библиотеках? А на ArgumentNullException? Не задумывался, почему для проверки предусловий в стандартных библиотеках используются исключения вместо асертов?
L>>Может быть потому что стандартные библиотеки скомпилированы не в дебаге, а в релизе?
_FR>Именно об этом я и говорю. В .NET ещё (или ужЕ) на уровне основной среды разработки (MSVS) не предусмотрено использование разных (конфигураций) сборок в зависимоти от конфигурации проекта, поэтому подавляющее большинство програмистов пишет и отлаживает свой код с релизом чужих сборок. Поэтому, чем более "умная" окажется чужая сборка, чем более удобные и понятные сообщения об ошибках из неё можно получить, чем более она соответствует принципам, изложенным здесь, тем удобнее в использовании она окажется для разработчиков-пользователей.
Но вы кажется обсуждаете использование ассертов как таковое, а не конкретно в .net. Поэтому не совсем понятно при чем тут отсутствие/наличие дебажных версий сборок в фреймворке.
Здравствуйте, Lloyd, Вы писали:
L>Но вы кажется обсуждаете использование ассертов как таковое, а не конкретно в .net. Поэтому не совсем понятно при чем тут отсутствие/наличие дебажных версий сборок в фреймворке.
Нет, выше я уже говорил, что тут надо ориентироваться на стандартные библиотеки и на технологию.
Если же говорить вообще, то Саттер или Маерс где-то хорошо об этом сказали, но у меня нет сейчас доступа к своим книгам
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Кто должен нести ответственность за соблюдение "предусловий" (если под предусловиями понимать значение передаваемых аргументов, как в рассматриваемом примере
)? Вызывающий. Если мы проверяем предусловия асертом,
Да не проверяем мы предусловия ассертом.
_FR>а у вызывающего только релиз — как он об этом узнает?
Из контракта. Может выражаться разными способами:
//pre a > 0 Явно в документации void foo(int a);
//или так(что лучше)void foo(positive_int a);
или еще как-нибудь...
_FR> _FR>Получит исключения, как в правильном по моему мнению примере _FR>Программа глухо свёрнётся из-за ошибки доступа по невалидному адресу _FR>Программа будет как-то неправильно работать _FR>_FR>Я предпочитаю исключения.
Вот. Получается что вызывающий, в твоем случае, не выполнил контракт, но программа диагностировала это как "нормальную" ситуацию. Вот это я называю "замазыванием" ошибок. Для меня это значит что программа попросту некорректна и ее надо исправлять, т.к. произошло нарушение контракта. Повторюсь — "проверки аргументов никуда не исчезают, они переносятся на уровень выше". Утверждения, проверяемые assert'ами _всегда_ выполняются. Поэтому их можно выкидывать из релиза. В случае с positive_int(выше) assert теоретически вообще не нужен. т.к. контракт выражен статически(если для positive_int инвариантом является хранение положительного числа) и проверка что 'a>0' выполняется выше.
Тот способ которым ты пытаешься использовать assert не соответствует его пердназначению . Например проверять ассертом входные данные для отдельной БИБЛИОТЕКИ это моветон.
Хорошим стилем для интерфейса модуля является проверка входных данных и генерация исключения если данные невалидны.
Здравствуйте, minorlogic, Вы писали:
M>Тот способ которым ты пытаешься использовать assert не соответствует его пердназначению . Например проверять ассертом входные данные для отдельной БИБЛИОТЕКИ это моветон.
M>Хорошим стилем для интерфейса модуля является проверка входных данных и генерация исключения если данные невалидны.
Я, как раз то, считаю что асертом нужно проверять исключительно данные\состояния, на которые внешний, вызывающий код повлиять не может. Именно тогда асерт говорит о том, что _я_ нарушил один из _собственных_ инвариантов. И именно мой код (в котором выставлен асерт) нуждается в исправлении.
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Я, как раз то, считаю что асертом нужно проверять исключительно данные\состояния, на которые внешний, вызывающий код повлиять не может. Именно тогда асерт говорит о том, что _я_ нарушил один из _собственных_ инвариантов. И именно мой код (в котором выставлен асерт) нуждается в исправлении.
Тогда и спор у вас какойто странный , проверять ли библиотеке входные данные или нет. Конечно проверять! кто только об этом не писал .
Здравствуйте, _FRED_, Вы писали:
_FR>... чем более "умная" окажется чужая сборка, чем более удобные и понятные сообщения об ошибках из неё можно получить, чем более она соответствует принципам, изложенным здесь, тем удобнее в использовании она окажется для разработчиков-пользователей.
Как быть в случае необходимости локализации сообщений об ошибках?
_FR>А для этого, нельзя полагаться на верность данных, получаемых "извне", от вызывающего кода и бессмысленно ставить асерты на условия, зависящие от вызывающего кода. Перенося обязанность проверки на вызывающий код, автор библиотеки усложняет жизнь вызывающему (который может использовать десяток-другой различных библиотек и будет обязан разобраться в тонкостях работы с каждой).
Возникающие исключения — тоже тонкости работы.
Чем это:
try
{
int a = get();
foo(a); // даже если get гарантирует что возвращенное значение > 0, то в foo все равно будет повторная проверка
}
catch(InvalidArgument)
{
Message("error");
}
лучше чем это
int a = get()
if(a > 0) // А это можно убрать если get гарантирует что a>0
foo(a);
else
Message("error");
_FR> хорошая библиотека (как и любой кусок хорошего кода) должен быть "готов к использованию", должен быть "кирпичём", из которого можно сложить необходимое, а не полуфабрикатом, который надо бережно и внимательно доготовить.
То есть "значения аргументов могут быть любыми(предусловия отсутствуют), попытаемся вызвать, вдруг чего получится"?
Для некоторых ситуаций, да, такой подход имеет смысл, но только тогда, когда результат проверки предусловий теряет актуальность после этой проверки. Вроде выделения памяти: Если у нас будет функция проверки объема доступной памяти, то результат ее вызова не имеет смысла, поскольку за время между ее вызовом и запросом на выделение кто-то другой может забрать весь объем доступный объем.
Здравствуйте, _FRED_, Вы писали:
_FR>Я, как раз то, считаю что асертом нужно проверять исключительно данные\состояния, на которые внешний, вызывающий код повлиять не может. Именно тогда асерт говорит о том, что _я_ нарушил один из _собственных_ инвариантов. И именно мой код (в котором выставлен асерт) нуждается в исправлении.
Полностью согласен. Только это постусловия. Если мы не можем их выполнить, то нарушаем контракт и необходимо исправление. Только вот есть еще предусловия, за выполнение которых несет ответственность клиент.
Здравствуйте, minorlogic, Вы писали:
_FR>>Я, как раз то, считаю что асертом нужно проверять исключительно данные\состояния, на которые внешний, вызывающий код повлиять не может. Именно тогда асерт говорит о том, что _я_ нарушил один из _собственных_ инвариантов. И именно мой код (в котором выставлен асерт) нуждается в исправлении.
M>Тогда и спор у вас какойто странный , проверять ли библиотеке входные данные или нет. Конечно проверять! кто только об этом не писал .
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>То есть "значения аргументов могут быть любыми(предусловия отсутствуют), попытаемся вызвать, вдруг чего получится"?
Мне вот что не понятно: каким образом генерация исключений в случае не выполнения предусловий мешает описанию этих предусловий в документации?
Здравствуйте, anton_t, Вы писали:
ЮЖ>>То есть "значения аргументов могут быть любыми(предусловия отсутствуют), попытаемся вызвать, вдруг чего получится"?
_>Мне вот что не понятно: каким образом генерация исключений в случае не выполнения предусловий мешает описанию этих предусловий в документации?
"Генерация исключения X в случае выполнения condition(Y)" — Это постусловие. Предусловие выполняется всегда, поэтому оно и "предварительное условие". Можно сказать что любой код с 'if' проверяет некоторое предусловие.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>>То есть "значения аргументов могут быть любыми(предусловия отсутствуют), попытаемся вызвать, вдруг чего получится"? _>>Мне вот что не понятно: каким образом генерация исключений в случае не выполнения предусловий мешает описанию этих предусловий в документации? ЮЖ>"Генерация исключения X в случае выполнения condition(Y)" — Это постусловие.
Предусловие (выполнения метода) — это "condition", а не "Генерация исключения".
... << RSDN@Home 1 alpha 3 rev. 0>>
Help will always be given at Hogwarts to those who ask for it.