Проверка данных в Getter / Setter или где-либо еще?

Мне интересно, стоит ли делать проверки в геттерах и сеттерах или где-нибудь еще в коде.

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

Ответов (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 преодолевает это.

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