Утверждать хорошую практику или нет? - PullRequest
48 голосов
/ 14 марта 2010

Полезно ли использовать Assert для параметров функции, чтобы обеспечить их достоверность. Я просматривал исходный код Spring Framework и заметил, что они часто используют Assert.notNull. Вот пример

   public static ParsedSql parseSqlStatement(String sql) {
    Assert.notNull(sql, "SQL must not be null");}

Вот еще один:

public NamedParameterJdbcTemplate(DataSource dataSource) {
            Assert.notNull(dataSource,
                    "The [dataSource] argument cannot be null.");
            this .classicJdbcTemplate = new JdbcTemplate(dataSource);
        }

        public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) {
            Assert.notNull(classicJdbcTemplate,
                    "JdbcTemplate must not be null");
            this .classicJdbcTemplate = classicJdbcTemplate;
      }

FYI, Assert.notNull (не оператор assert) определяется в классе util следующим образом:

public abstract class Assert { 
   public static void notNull(Object   object, String   message) {
      if (object == null) {
          throw new IllegalArgumentException  (message);
      }
   }
}

Ответы [ 7 ]

57 голосов
/ 14 марта 2010

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

Например, Java привязывает все обращения к массиву во время выполнения. Это делает вещи немного медленнее? Да. Это выгодно? Абсолютно! Как только происходит нарушение вне пределов, выдается исключение, и программист получает предупреждение о любой возможной ошибке! Поведение в других системах, где доступ к массиву не проверен на наличие ограничений, ОЧЕНЬ БОЛЬШЕ НЕПРЕДВИДЕННО (часто с катастрофическими последствиями!).

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

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

Еще один способ взглянуть на это - думать об утверждениях как об «активных комментариях». Нельзя утверждать, что комментарии полезны, но они ПАССИВНЫ; в вычислительном отношении они ничего не делают. Сформулировав некоторые понятия как утверждения вместо комментариев, они становятся АКТИВНЫМИ. Они действительно должны держаться во время выполнения; нарушения будут выявлены.


См. Также: преимущества программирования с утверждениями

28 голосов
/ 14 марта 2010

Эти утверждения предоставляются библиотекой и не совпадают со встроенным ключевым словом assert.

Здесь есть разница: assert s не запускаются по умолчанию (они должны быть включены с помощью параметра -ea), в то время как утверждения, предоставляемые классом Assert, не могут быть отключены.

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

public static ParsedSql parseSqlStatement(String sql) {
    if (sql == null)
        throw new IllegalArgumentException("SQL must not be null");
    ...
}

... что всегда является хорошей практикой в ​​публичных методах.

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

18 голосов
/ 14 марта 2010

Да, это хорошая практика.

В случае с Spring это особенно важно, потому что проверки проверяют настройки свойств и т. Д., Которые обычно поступают из файлов проводки XML. Другими словами, они проверяют конфигурацию веб-приложения. И если вы когда-нибудь сделаете серьезную разработку на основе Spring, эти проверки правильности сэкономят вам часы отладки, когда вы совершите глупую ошибку конфигурации.

Но обратите внимание, что существует БОЛЬШАЯ разница между классом библиотеки с именем Assert и ключевым словом Java assert, которое используется для определения утверждения Java. Последняя форма утверждений может быть отключена во время запуска приложения, и ее НЕ следует использовать для проверки правильности аргументов, которую вы всегда хотите выполнить. Очевидно, что дизайнеры Spring думают, что было бы очень плохой идеей отключить проверку работоспособности конфигурации веб-приложения ... и я согласен.

ОБНОВЛЕНИЕ

В Java 7 (и более поздних версиях) класс java.util.Objects предоставляет удобный метод requireNonNull, чтобы проверить, является ли аргумент null, и вызвать исключение. Вы используете это так:

 SomeType t = ...
 SomeType tChecked = Objects.requireNonNull(t);

или

 SomeType tChecked = Objects.requireNonNull(t, "t should be non-null");

Однако обратите внимание, что этот метод повышает NullPointerException, а не IllegalArgumentException.

6 голосов
/ 14 марта 2010

Исходя из руководства Sun по утверждениям, вы должны не использовать утверждения для проверки аргументов в открытых методах.

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

2 голосов
/ 06 ноября 2014

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

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

1 голос
/ 14 марта 2010

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

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

0 голосов
/ 19 сентября 2012

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

Подробнее здесь: http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/

...