Статьи

Проектирование по контракту и валидация бобов

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

public List<Person> getPersons() {
    return Collections.unmodifiableList(persons);
}

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

public void sendEmail(String email) {
    Assert.assertNotNull(email);
    // Real code after that
    ...
}

Не очень сложно. Но теперь я хочу поверхностно проверить электронную почту, чтобы не запрашивать дерево JNDI для SMTP-сервера ни за что.

public void sendEmail(String email) {
    Assert.assertNotNull(email);
    Validator validator = new EmailValidator(email);
    validator.validate(email);
    // Real code after that
    ...
}

Это намного труднее читать … пока. Если бы у меня было более одного параметра и несколько проверок для каждого параметра, сложность быстро вышла бы из-под контроля, и это только для предварительного условия !. Проверки после условия будут выполняться в конце метода и еще больше нарушат читабельность. Кроме того, внешний мир не знает о них: они должны быть написаны вручную в Javadoc и синхронизированы с кодом.

Что если эти ограничения могут быть отменены? Буду ли я более склонен использовать дизайн по контракту? Я верю, что это так. И когда я присутствовал на выступлении Эммануила Бернарда в Devoxx France, я не мог поверить, что его использование будет таким простым. Моя цель может быть достигнута только с помощью Bean Validation API 1.1 (он же JSR-349 ). Эта более новая версия повторно использует аннотации Bean Validation 1.0 (также известный как JSR-303 ), но там, где в предыдущей версии можно было аннотировать только атрибуты, теперь можно использовать и методы. Или, говоря более широко, до того, как состояние было подтверждено, теперь мы можем проектировать по контракту.

Предыдущий метод может быть обновлен следующим образом:

public void sendEmail(@Email String email) {
    // Real code after that
    ...
}

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

Kill-радости, вероятно, возразят, что это хорошо и хорошо, но это все еще в черновике. Это было бы правдой, за исключением того, что это не что иное, как область видимости HTML5. Кроме того, Hibernate Validator был эталонной реализацией Bean Validation API 1.0. Вполне естественно, что это относится и к версии 1.1 с Hibernate Validator 5. Однако она уже предоставляет все, что нам нужно, с версией 4.2. Если вы готовы использовать Spring, это просто:

  1. Получите правильные зависимости в вашем POM
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>2.3.2</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.3.1.Final</version>
    </dependency>
  2. Аннотируйте свои методы как выше
  3. Добавьте правильный постпроцессор Spring Bean
    @Configuration
    public class SpringConfiguration {
     
        ...
     
        @Bean
        public static MethodValidationPostProcessor methodValidationPostProcessor() {
     
            return new MethodValidationPostProcessor();
        }
    }
  4. Наслаждайтесь! На самом деле, все кончено, вы можете использовать дизайн по контракту, как душе угодно.

Источники для этой статьи можно найти в формате Eclipse / Maven здесь .

Чтобы идти дальше : смотрите соответствующие ссылки в статье

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