Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Где лучше выполнять проверку корректности исходных 
:(
    Опции темы
Нитонисе
Дата 23.5.2013, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Есть класс, данными которого являются в том числе численные значения. Например есть некий параметр Х, который может принимать значения от 0 до 1. Есть некоторая функция, которая задает этот параметр, например SetX(double x). Всякий раз в подобных случаях я ломаю голову - где лучше проверять корректность данных - внутри функции SetX или же на стадии подготовки данных для этой функции, в данном случае это аргумент x. Казалось бы удобнее это делать вне класса, но иногда кажется что и внутри класса это уместно. Ведь если функцию SetX этим механизмом проверки корректности аргумента не снабдить, то можно ненароком этому параметру присвоить какое-то некорректное значение.

Это сообщение отредактировал(а) Нитонисе - 23.5.2013, 16:51
PM MAIL   Вверх
baldina
Дата 23.5.2013, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



внутри. так будет проверено каждое обращение функции.
и вне - так будет проверено значение, введенное пользователем, что даст возможность не отвалиться по исключению, возбужденному в SetX(), а повторно выполнить ввод.

Добавлено через 1 минуту и 57 секунд
во втором случае проверка должна быть не перед вызовом SetX(), а после получения значения.
если это значение не ввод пользователя, а вычисленный результат, проверять его нужно, видимо, в точке принятия решения - передавать его дальше или нет, т.е. зависит от конкретного приложения.
PM MAIL   Вверх
Нитонисе
Дата 23.5.2013, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Если проверять аргумент х и на стадии его формирования и внутри функции - то это будет дублирование проверки. Разумно ли это?
PM MAIL   Вверх
bsa
Дата 23.5.2013, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



внутри функции параметры проверяются на корректность для данной функции. А вне функции они проверяются на допустимость для данного алгоритма.
PM   Вверх
Нитонисе
Дата 23.5.2013, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



То есть если для некоторых вычислений, где используется этот параметр Х должен принимать значения от 0 до 1, то при выполнении функции SetX(double x) проверку аргумента надо производить перед вызовом функции? А в самой функции тогда остается просто SetX(double x){this->X = x};
PM MAIL   Вверх
NoviceF
Дата 23.5.2013, 19:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 13.3.2012
Где: Ростов-на-Дону

Репутация: нет
Всего: 2



Считаю внутри функции нужно проводить в любом случае.. Сегодня ты проверяешь результаты снаружи, а завтра кто-то воспользуется твоим классом и начнёт туда записывать непонятно что. Класс должен сопротивляться при помощи ассертов, возвратов фолсов и выбрасывания исключений smile
PM MAIL   Вверх
Нитонисе
Дата 23.5.2013, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(NoviceF @  23.5.2013,  19:13 Найти цитируемый пост)
Считаю внутри функции нужно проводить в любом случае.. Сегодня ты проверяешь результаты снаружи, а завтра кто-то воспользуется твоим классом и начнёт туда записывать непонятно что. Класс должен сопротивляться при помощи ассертов, возвратов фолсов и выбрасывания исключений 

А как насчет дублирования проверки в таком случае?
PM MAIL   Вверх
NoviceF
Дата 23.5.2013, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 13.3.2012
Где: Ростов-на-Дону

Репутация: нет
Всего: 2



Цитата(Нитонисе @ 23.5.2013,  19:16)
То есть если для некоторых вычислений, где используется этот параметр Х должен принимать значения от 0 до 1, то при выполнении функции SetX(double x) проверку аргумента надо производить перед вызовом функции? А в самой функции тогда остается просто SetX(double x){this->X = x};

Если для класса this->X имеет смысл только при положительных значениях или в определённом диапазоне - это и нужно бы проверить, перед выполнением присваивания this->X = x.  Вообще, если значимы только 0 или не ноль, логичнее было бы bool использовать.

Добавлено через 1 минуту и 3 секунды
Цитата(Нитонисе @  23.5.2013,  20:14 Найти цитируемый пост)

А как насчет дублирования проверки в таком случае? 

Корректность работы намного предпочтительнее производительности в большинстве случаев.

Добавлено через 12 минут и 22 секунды
Когда функция одна, может и не совсем виден масштаб проблемы.. А если 4-5 функций последовательно вызывают друг друга и на пятой приложение падает.. а в процессе отладки выясняется, что проблема в аргументах переданных первой функции второй. По плану первая функция должна была всё правильно расчитать, но где-то закралась ошибка и результат её работы не может быть корректно обработан второй функцией.. И если во второй функции (и всех последующих) не делать проверку агрументов - ошибка лавиной пройдёт через весь маршрут. Ну, и если нет предположений о причине ошибки (а обычно у меня их нет smile ), то отладка начинается с пятой функции в направлении первой, что тратит кучу лишнего времени.
PM MAIL   Вверх
borisbn
Дата 24.5.2013, 05:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Есть такое правило - если ф-ция public, то она должна проверять параметры, если private - нет.
Ессно, это - не догма, но я пользуюсь и мне так удобно


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
NoviceF
Дата 24.5.2013, 09:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 13.3.2012
Где: Ростов-на-Дону

Репутация: нет
Всего: 2



На мой взгляд, даже в приватных функциях, как минимум ассерты не повредят smile

Это сообщение отредактировал(а) NoviceF - 24.5.2013, 09:06
PM MAIL   Вверх
bsa
Дата 24.5.2013, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(Нитонисе @  23.5.2013,  20:14 Найти цитируемый пост)
А как насчет дублирования проверки в таком случае? 

Смотри, квадратный корень можно брать от любого неотрицательного числа. Поэтому функция извлечения корня проверяет параметр на отрицательность. Если он отрицательный, то тогда выдает ошибку. Твой алгоритм считает сложную функцию. И на каком-то этапе перед извлечением корня ты проверяешь промежуточный результат (по идее, правильно проверять только входные параметры, но иногда для проверки необходимо проделать половину всех вычислений) на корректность. И не обязательно на неотрицательность. Вот именно это я и имел в виду.
Смысл проверять перед функцией имеется только тогда, когда функция не может сигнализировать об ошибке.
PM   Вверх
Нитонисе
Дата 24.5.2013, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(bsa @  24.5.2013,  15:49 Найти цитируемый пост)
Смысл проверять перед функцией имеется только тогда, когда функция не может сигнализировать об ошибке.

Да, именно. И мне кажется рациональнее проверять именно перед функцией, а не внутри нее. Одна из причин - если проверять внутри функции, то нужно разрабатывать систему сигнализирования о том что именно функции не понравилось. Например аргумент должен быть положительным и не больше единицы. Значит функция своим возвращаемым значением должна уметь сказать - "работа не сделана, аргумент отрицательный" или "работа не сделана, аргумент больше единицы". По идее этим возвращаемым из ункции значением может быть простой int. Например если вернули 1 - функция сработала как надо, вернули 2 - получили отрицательный аргумент и поэтому не обработали, вернули 3 - получили аргумент больше единицы и поэтому не обработали. 

Мне кажется такой подход чересчур громоздкий. Он может быть оправдан только если разрабатываемый класс будут использовать сторонние разработчики, которые могут и не знать какие проверки надо выполнять перед выполнением функции. Поэтому для них все проверки можно сразу в функцию зашить. А если только я использую этот класс и четко понимаю как надо его использовать, то такая внутренняя проверка может и не нужна.
PM MAIL   Вверх
NoviceF
Дата 24.5.2013, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 13.3.2012
Где: Ростов-на-Дону

Репутация: нет
Всего: 2



Цитата(Нитонисе @  24.5.2013,  17:09 Найти цитируемый пост)
А если только я использую этот класс и четко понимаю как надо его использовать, то такая внутренняя проверка может и не нужна. 

Если только ты используешь, чем плох 
Код

assert(x == 1 || x == 0);

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

Добавлено через 6 минут и 37 секунд
Цитата(Нитонисе @  24.5.2013,  17:09 Найти цитируемый пост)
Значит функция своим возвращаемым значением должна уметь сказать

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

У меня вообще нет никакой принципиальной позиции в этом вопросе, но небольшой практический опыт говорит, что лучше проверять..
PM MAIL   Вверх
Нитонисе
Дата 24.5.2013, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: нет
Всего: 2



Цитата(NoviceF @  24.5.2013,  16:29 Найти цитируемый пост)
На дебаге тебе же самому будет полезно сразу видеть где ошибка, вместо того, чтобы лишний раз расставлять printf() или лезть в отладчик

Я пишу программы в Builder XE. Там при запуске программы в отладочном режиме, если происходит сбой, место в программе где произошел сбой выявляется автоматически. Так что если бы вдруг затупила эта функция, то отладчик бы на нее и указал. То есть это как сигнал для меня, что при передаче аргумента в эту функцию я не все внештатные ситуации обработал.
PM MAIL   Вверх
baldina
Дата 24.5.2013, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



независимо от того, в чем ты пишешь, ошибка произойдет не в месте assert, а когда все протухнет. это может оказаться совсем другая функция. в каких-то случаях приложение не обрушится, просто будет работать криво. и ты будешь бегать с бубном в отладчике
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0580 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.