Актуально ли использовать Assert как хорошую практику?
Вопрос: Использование Assert для проверки параметров функции — хорошая практика?
Я изучал исходный код Spring Framework и обратил внимание, что они часто используют Assert.notNull
. Вот пример:
public static ParsedSql parseSqlStatement(String sql) {
Assert.notNull(sql, "SQL не должен быть null");
}
И вот другой пример:
public NamedParameterJdbcTemplate(DataSource dataSource) {
Assert.notNull(dataSource, "Аргумент [dataSource] не может быть null.");
this.classicJdbcTemplate = new JdbcTemplate(dataSource);
}
public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) {
Assert.notNull(classicJdbcTemplate, "JdbcTemplate не должен быть null");
this.classicJdbcTemplate = classicJdbcTemplate;
}
Для справки, Assert.notNull
(это не оператор assert
) определён в утилитарном классе следующим образом:
public abstract class Assert {
public static void notNull(Object object, String message) {
if (object == null) {
throw new IllegalArgumentException(message);
}
}
}
Собственно, мой вопрос: является ли использование Assert
для проверки параметров функции хорошей практикой? Каковы преимущества и недостатки такого подхода?
2 ответ(ов)
В больших и плохо спроектированных системах, если вы стремитесь повысить предсказуемость в методах длиной, скажем, 6000 строк, которые никто в компании уже не понимает, использование ключевого слова assert
может быть полезным — это позволяет разработческим средам "выдавать" ошибки и выявлять баги. Однако если вы реализуете эти проверки в продакшене, это может привести к прерыванию работы патча, который, хотя и плохо спроектирован, решает определённую проблему. Ваша цель — выявить этот плохой патч в среде разработки, а не в продакшене. Поэтому стоит включить assert
в процессе разработки и выключить их в продакшене.
Еще одно уместное использование ключевого слова assert
на этапе разработки — это внедрение проверок на корректность в алгоритмы, которые должны выполняться за подпороговые миллисекунды и достаточно изолированы от непредсказуемых или непроверенных вызовов. В таком случае, возможно, вы не сможете позволить себе сохранить проверку корректности в продакшене, хотя она будет очень полезна на этапе разработки. С другой стороны, если источник параметров, которые вы проверяете, непредсказуем или может стать таковым (например, если частично зависит от ввода пользователя), вы, вероятно, никогда не сможете позволить себе пропустить проверку, даже в продакшене, и должны будете принять снижение производительности как цену за ведение бизнеса. (В последнем случае, вероятно, не стоит использовать assert
.) Однако применять assert
, чтобы исключить проверку корректности времени выполнения в продакшене, следует только после профилирования, которое покажет, что вы просто не можете позволить себе накладные расходы.
Да, это хорошая идея. Вы тем самым обеспечиваете соблюдение контракта интерфейса или класса. Если происходит нарушение контракта, вы хотите выявить это как можно скорее. Чем дольше вы ждете, тем более непредсказуемыми могут быть результаты, и тем труднее будет диагностировать проблему.
Когда вы явно проверяете условия, стоит также предоставить информационное сообщение, которое, попадая в лог-файл, может дать полезный контекст для поиска коренной причины проблемы или помочь понять, что вы сделали неверное предположение о том, каков этот контракт.
Как проверить, что в JUnit-тестах выбрасывается определенное исключение?
Неоднозначный вызов метода: обе методы assertEquals(Object, Object) и assertEquals(double, double) в Assert совпадают
Что значит 'synchronized'?
Как объявить массив в одну строку?
Какие проблемы следует учитывать при переопределении equals и hashCode в Java?