Стоит ли проверять правильность значений параметров в конструкторе? - PullRequest
5 голосов
/ 02 апреля 2009

Проверяете ли вы достоверность данных в каждом конструкторе, или вы просто предполагаете, что данные верны, и выбрасываете исключения в конкретной функции, которая имеет проблему с параметром?

Ответы [ 9 ]

14 голосов
/ 02 апреля 2009

Конструктор тоже функция - зачем дифференцировать?

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

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

2 голосов
/ 02 апреля 2009

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

Итак, если они передадут значение 107%, я установлю его на 100%. Я просто разъясняю в документации, что именно так и происходит.

Только если нет очевидного логического принуждения, я возвращаю им исключение. Мне нравится называть это «главным изумлением для тех, кто слишком ленив или глуп, чтобы читать документацию».

2 голосов
/ 02 апреля 2009

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

1 голос
/ 02 апреля 2009

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

0 голосов
/ 02 апреля 2009

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

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

0 голосов
/ 02 апреля 2009

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

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

Пример. Извините, мой синтаксис в фигурных скобках:

// precondition b<>0
function divide(a,b:double):double;
begin
  assert(b<>0); // in case of a programming error. 
  result := a / b;
end;

// calling code should be:
if foo<>0 then
  bar := divide(1,0)
else
  // do whatever you need to do when foo equals 0

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

// no preconditions.. still need to check the result
function divide(a,b:double; out hasResult:boolean):double;
begin
  hasResult := b<>0; 
  if not hasResult then
    Exit;
  result := a / b;
end;

// calling code:
bar := divide(1,0,result);
if not result then
  // do whatever you need to do when the division failed
0 голосов
/ 02 апреля 2009

Я всегда стараюсь потерпеть неудачу как можно раньше. Поэтому я окончательно проверяю параметры в конструкторе.

0 голосов
/ 02 апреля 2009

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

  • Проверка аргументов в конструкторе аналогична проверке аргументов для традиционного метода ... поэтому я бы не стал здесь дифференцироваться ...
  • Проверка аргументов метода, конечно, помогает убедиться, что переданные параметры верны, но также вводит много кода, который вам нужно написать, что, на мой взгляд, не всегда окупается ... Особенно, когда вы пишете коротко методы, которые довольно часто делегируют другим методам, я полагаю, что в конечном итоге 50% вашего кода будут просто проверять параметры ...
  • Кроме того, учтите, что очень часто, когда вы пишете модульный тест для своего класса, вам не нужно передавать допустимые параметры для всех методов ... Довольно часто имеет смысл передавать только те параметры, которые важны для текущий контрольный пример, поэтому наличие проверок замедлит процесс написания модульных тестов ...

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

0 голосов
/ 02 апреля 2009

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

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

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