Должен ли код предотвращать логически неверный вызов, даже если это не повредит? - PullRequest
3 голосов
/ 14 декабря 2009

Этот уже давно озадачивает мою.

Давайте представим класс, который представляет ресурс, и для того, чтобы иметь возможность использовать этот ресурс, необходимо сначала вызвать для него метод Open, иначе будет выдано исключение InvalidOperationException.

Должен ли мой код также проверять, пытается ли кто-нибудь открыть уже открытый ресурс или закрыть уже закрытый?

Должен ли код предотвращать логически недопустимый вызов, даже если не будет причинено никакого вреда?

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

Что вы, ребята, думаете?

Edit:

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

Ответы [ 7 ]

6 голосов
/ 14 декабря 2009

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

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

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

3 голосов
/ 14 декабря 2009

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

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

2 голосов
/ 14 декабря 2009

Если ваш пример действительно так, то функциональность Open, вероятно, должна вызываться конструктором класса.

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

То, что вы не должны делать, это разрешать вашим программам молча принимать любые старые входные данные в качестве параметров. Например, это будет неправильная реализация strlen ()

int strlen( const char * s )
{
   if ( s == 0 )
   {
      return 0;     // bad
   }
   else
   {
      // calculate length not shown
   }
} 

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

1 голос
/ 15 декабря 2009

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

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

1 голос
/ 15 декабря 2009

В случае открытия файла, который уже открыт, зависит от знания эффекта запроса, сбросит ли он, например, текущее местоположение чтения.

В случае закрытия файла, который уже закрыт, воспринимайте его как запрос на перевод файла в известное состояние. Код не должен ничего делать, но достигается желаемое состояние, чтобы код мог вернуть условие успеха. Это не так, если существует какая-то файловая буферизация, о которой нужно позаботиться или, возможно, связанный ресурс для координации, например модем / последовательный порт или принтер / спулер.

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

Однажды мы добавили ссылку «Выход» в меню приложения, которое отображалось независимо от вашего статуса входа. Зачем? Потому что потребовался только простой (и очень короткий) метод для возврата вас на экран входа в систему с экрана входа в систему и сохранено большое количество проверок для отслеживания состояния входа в систему, чтобы элемент меню «Выход» отображался только тогда, когда Вы вошли в систему.

1 голос
/ 15 декабря 2009

Если это часть общедоступного SDK, который вы выпускаете на волю, то открытые вызовы API должны пройти строгую проверку. Это поможет вашим «пользователям» (разработчикам) и гарантирует, что вы не застряли с поддержкой использования, которую вы никогда не намеревались поддерживать.

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

1 голос
/ 14 декабря 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...