Проверка данных в Getter / Setter или где-либо еще?
Мне интересно, стоит ли делать проверки в геттерах и сеттерах или где-нибудь еще в коде.
Это может вас удивить, когда дело доходит до оптимизации и ускорения кода. Я думаю, вам следует делать проверки не в геттерах и сеттерах, а в коде, в котором вы обновляете свои файлы или базу данных. Я ошибся?
Ответов (8)8
Что ж, одна из причин, по которой классы обычно содержат частные члены с общедоступными геттерами / сеттерами, заключается именно в том, что они могут проверять данные.
Если у вас есть число, которое может быть от 1 до 100, я бы определенно поместил что-то в установщик, который проверяет это, а затем, возможно, выдаст исключение, которое перехватывается кодом. Причина проста: если вы не делаете этого в сеттере, вы должны помнить об ограничении от 1 до 100 каждый раз, когда вы его устанавливаете, что приводит к дублированию кода или, когда вы его забываете, приводит к недопустимому состоянию.
Что касается производительности, я здесь с Кнутом:
«Мы должны забыть о небольшой эффективности, скажем, примерно в 97% случаев: преждевременная оптимизация - корень всех зол».
Я стараюсь никогда не позволять моим объектам входить в недопустимое состояние, поэтому установщики определенно будут иметь проверку, а также любые методы, которые меняют состояние. Таким образом, мне никогда не придется беспокоиться о том, что объект, с которым я имею дело, недействителен. Если вы сохраните свои методы как границы валидации, то вам никогда не придется беспокоиться о фреймворках валидации и вызовах методов IsValid (), разбросанных повсюду.
С точки зрения того, чтобы код был максимально удобным в обслуживании, я думаю, вам следует проводить как можно больше проверок в установщике свойства. Таким образом, вы не будете кэшировать или иным образом работать с недопустимыми данными.
В конце концов, это то, для чего предназначены свойства. Если все, что у вас есть, это набор свойств вроде ...
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
... с таким же успехом они могут быть полями
Это зависит.
Как правило, код должен быстро выходить из строя. Если значение может быть установлено несколькими точками в коде, и вы проверяете только после получения значения, ошибка, по-видимому, находится в коде, который выполняет обновление. Если установщики проверяют ввод, вы знаете, какой код пытается установить недопустимые значения.
Вы можете попробовать Domain Driven Design Эрика Эванса. DDD имеет такое понятие спецификации:
... явные предикатоподобные ОБЪЕКТЫ ЗНАЧЕНИЯ для специализированных целей. СПЕЦИФИКАЦИЯ - это предикат, который определяет, удовлетворяет или не удовлетворяет объект некоторым критериям.
Я думаю, что быстро потерпеть неудачу - это одно, а другое - где сохранить логику для проверки. Домен - это подходящее место для хранения логики, и я думаю, что объект спецификации или метод проверки для ваших объектов домена были бы хорошим местом.
Валидация должна регистрироваться отдельно от геттеров или сеттеров в методе валидации. Таким образом, если проверку необходимо повторно использовать в нескольких компонентах, она будет доступна.
Когда вызывается установщик, такую службу проверки следует использовать для очистки ввода в объект. Таким образом, вы будете знать, что вся информация, хранящаяся в объекте, действительна в любое время.
Вам не нужна какая-либо проверка для получателя, потому что информация об объекте уже считается действительной.
Не сохраняйте валидацию до обновления базы данных !! Лучше быстро потерпеть неудачу .
Мне нравится реализовывать IDataErrorInfo и помещать свою логику проверки в его свойства Error и this [columnName]. Таким образом, если вы хотите программно проверить наличие ошибки, вы можете просто протестировать любое из этих свойств в коде или передать проверку привязке данных в веб-формах, Windows Forms или WPF.
Свойство привязки "ValidatesOnDataError" WPF делает это особенно простым.
@Terrapin, re:
Если все, что у вас есть, это набор свойств [simple public set / get] ... они также могут быть полями
У свойств есть и другие преимущества перед полями. Это более явный контракт, они сериализованы, их можно отлаживать позже, они удобны для расширения посредством наследования. Более громоздкий синтаксис - случайная сложность - например, .net 3.5 преодолевает это.
Распространенная (и ошибочная) практика - начинать с общедоступных полей и позже превращать их в свойства по мере необходимости. Это разрывает ваш контракт со всеми, кто потребляет ваш класс, поэтому лучше всего начать с собственности.