(java || kotlin) && devOps
369 subscribers
6 photos
1 video
6 files
307 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
Всем привет!

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

Мы все используем библиотеки. Когда нужно написать тест (а книга в основном про то, как упростить написание тестов для legacy) - часто в наш класс передаются библиотечные объекты. И тут могут быть две проблемы:
1) объект-синглтон
2) final объект или объект с методами, которые не возможно переопределить.
Эти две проблемы приводят к одному и тому же - мы не можем создать mock, приходится инициализировать для тестов реальный объект из библиотеки. А он может быть "тяжелым", превращающий модульный тест в интеграционный.

Как вариант решения этой проблемы предлагается:
1) для singleton создавать фасад, который разрешает замену объекта через setter, т.е. по сути нарушать суть паттерна singleton
2) для final методов и объектов - убрать final, объявляя их логическими final в документации.

Оба предложения по сути об одном - нарушаем принципы проектирования на уровне языка, зато делаем возможным тестирование кода.

В целом - "соль" в этом есть. Код без тестов опаснее кода, нарушающего принципы проектирования. Но я бы уточнил, что оба метода - это крайние меры. А по хорошему, если вы разрабатываете код, который кто-то когда-то будет тестировать - надо заранее озаботится о тестируемости, и именно:
1) не создавать singleton самому, использовать для этого IoC контейнер. Spring если библиотека внутренняя, и у вас используется Spring, или CDI аннотации в других случаях. Причем это актуально не только для разработчиков библиотек, а для всех.
2) создавать интерфейсы для классов, вынесенных в клиентское API. Есть интерфейс - всегда можно создать mock в тесте без всяких ухищрений. Я против создания интерфейсов всегда и везде https://t.me/javaKotlinDevOps/235, но Java API - это как раз подходящий случай. Одних интерфейсов конечно же мало, нужно еще и четкое разделение на модель и сервисы. Первые можно использоваться AS IS в тестах, вторые часто приходится мокать. Да, спроектировать все правильно не так-то легко, но как говорится - дорогу осилит идущий.

#book_review #ood #dev_compromises #libraries