(java || kotlin) && devOps
339 subscribers
14 photos
2 videos
7 files
429 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
assert в боевом коде?

На всякий случай напомню https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html

Пример:

Connection conn = getConnection();
assert conn != null;


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

Теперь на отойдем на шаг назад.
Все ошибки во входящих данных можно разделить на две категории - ожидаемые и нет.
Это деление не дискретное, а непрерывное, но в любом случае приводит к вопросу - как проверять данные на неожиданные ошибки? Нужно ли это делать вообще?
С ожидаемыми все понятно - пишем проверку, if и далее возврат кода ошибки\exception\запись в лог.
А неожиданные - что с ними делать?
Самый яркий пример - проблема nullability в Java. Объекты у нас везде, тогда в теории почти в любом методе нужна проверка на null.
Или не нужна, т.к. это сильно увеличивает объем кода и ухудшает читаемость.

Тут как раз предлагается использовать assert - для ошибок, которых при нормальной работе программы быть не должно.
Почему мне это не нравится.
Как раз по двум причинам выше - мы решили проверить данные и вроде закрылись assert-ом.
А потом кто-то убрал -ea в ПРОМе. И вообще говоря такой путь часто рекомендуют - разработка с assert, ПРОМ - без.
Или кто-то удалил assert посчитав его отладочным. Проект то живет долго, люди меняются.

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

Еще предлагаемый кейс для assert - pre-condition, post-condition, инварианты - т.е. реализация контрактов для методов и классов в коде.
Причем часто основная идея здесь не проверка условий, а именно документирование контракта с помощью assert.
И тут снова вступает в силу ненулевая вероятность удаления assert-ов, т.к. в боевом коде они выглядят чужеродно.
Я тут за JavaDoc, т.к. по JavaDoc можно построить отдельный jar с документацией, который может использовать IDE.
С контрактами есть отдельный важный момент: контракт - это часть класса, выносить его в слой валидации плохо.
Но в таком случае лучше его реализовать или обычным кодом или JavaDoc.

Итого остается редкий кейс разработки кусочка монолита, когда нет уверенности, что контракты соблюдаются. Условно разработка чего-то уровня JDK.

Используете ли assert в боевом коде? Для чего?

#book_review #contracts #validations