Всем привет!
На какие грабли можно наступить при распиле монолита на микросервисы?
Небольшой дисклеймер: я подразумеваю, что внедряются микросервисы + Agile, т.к по определению у микросервиса должен быть владелец - команда.
Примеры взяты из жизни)
1) Как я уже говорил https://t.me/javaKotlinDevOps/60 - начинать распил лучше с каких-то небольших частей существующего монолита или новых фичей для этого монолита. Тут важен вот какой момент - скорее всего монолит выполняет некую критическую функцию для компании и, следовательно, для него существуют некие требования. Например, 99,99-ая доступность. И первые "тренировочные" микросервисы не стоит делать для другого сервиса=приложения=монолита, например, потому, что у него более лояльные пользователи или там проще внедрение. Если так сделать, то при переходе от простого монолита к сложному появится куча неожиданных требований по надежности, масштабируемости, ИБ, удобству сопровождения, и архитектуру придется переделывать.
2) должна быть зафиксированная и согласованная со всеми заинтересованными лицами архитектура.
Почему это критично - потому что архитектура - это основа. Можно конечно создавать архитектуру параллельно разработке, по принципу ввяжемся в бой, а там разберемся. Но это приведет к переписыванию микросервисов, к микросервисам-фантомам, которые на бумаге есть, а в жизни оказались не нужны, и к их антиподам, про которых просто забыли и конечно же к проблемам на всех стендах из-за меняющегося API. В конце концов при таком подходе слова архитектура и архитектор по отношению к новой микросервисной платформе станут ругательными)
3) нужно время на обучение разработчиков, тестировщиков и сопровождения. Обучение может быть и должно быть на практике - на реальных сервисах, но оно должно быть учтено в roadmap перехода. Сроки перехода должны быть согласованы командами разработки и сопровождения, а не спущены сверху. Звучит очевидно, но по моему опыту не для всех)
4) нужно изменение релизных и контролирующих политик в компании, иначе Lead Time и сложность вывода в ПРОМ для микросервисов останется на уровне монолита. Это сложный момент, т.к. люди консервативны, они привыкают к правилам, и не всегда осознают, что цена ошибки в монолите и в микросервисе разная. Особенно консервативно сопровождение и DBA, работа у них такая, цена ошибки высока) С другой стороны, конечно же микросервисная система должна быть спроектирована так, чтобы падение одного сервиса не приводило к каскадным падениям других. Это снова про критичное влияние архитектуры.
Еще важный момент - в монолите процесс согласования был централизован, им занимались специально обученные люди. С микросервисами релизный процесс попадает в Agile команды. А правило 7 +-2 действует не только для людей, а и для команд. Ну и большое число внешних взаимодействий противоречит Agile-у.
5) к началу разработки нужен работающий и простой DevOps. Разрабочики монолита как правило занимаются только разработкой и если заставить их учиться DevOps - потеряем время. Даже если набирать новых людей - все равно не каждый разработчик готов разрабатывать пайплайны. Т.е. должна быть минимальная конфигурация pipeline в декларативном стиле и работающие CI и CD pipeline. Опять же релизы микросервисов происходят намного чаще, для них это важно.
Также не должно быть невнятных инструкций и десятков настроечных файлов, необходимых для работы pipeline. Конфигурация - это не код, писать его не интересно, разбираться в ней тем более. И это не DevOps на самом деле) Должны быть - генераторы конфигураций, принцип convention over configuration.
6) микросервисам нужно больше инфраструктуры по сравнению с монолитом: сервера, репозитории - и больше доступов. Если в монолите как правило получением инфраструктуры занималась выделенная команда(ы), то при микросервисной архитекторе этим занимается каждая команда. Следовательно, процесс выдачи должен быть максимально автоматизирован и упрощен. Снова работает правило 7+-2. Разработчики должны заниматься тем, что у них лучше всего получается, а не заявками.
#microservices #fuckup #conv_over_conf
На какие грабли можно наступить при распиле монолита на микросервисы?
Небольшой дисклеймер: я подразумеваю, что внедряются микросервисы + Agile, т.к по определению у микросервиса должен быть владелец - команда.
Примеры взяты из жизни)
1) Как я уже говорил https://t.me/javaKotlinDevOps/60 - начинать распил лучше с каких-то небольших частей существующего монолита или новых фичей для этого монолита. Тут важен вот какой момент - скорее всего монолит выполняет некую критическую функцию для компании и, следовательно, для него существуют некие требования. Например, 99,99-ая доступность. И первые "тренировочные" микросервисы не стоит делать для другого сервиса=приложения=монолита, например, потому, что у него более лояльные пользователи или там проще внедрение. Если так сделать, то при переходе от простого монолита к сложному появится куча неожиданных требований по надежности, масштабируемости, ИБ, удобству сопровождения, и архитектуру придется переделывать.
2) должна быть зафиксированная и согласованная со всеми заинтересованными лицами архитектура.
Почему это критично - потому что архитектура - это основа. Можно конечно создавать архитектуру параллельно разработке, по принципу ввяжемся в бой, а там разберемся. Но это приведет к переписыванию микросервисов, к микросервисам-фантомам, которые на бумаге есть, а в жизни оказались не нужны, и к их антиподам, про которых просто забыли и конечно же к проблемам на всех стендах из-за меняющегося API. В конце концов при таком подходе слова архитектура и архитектор по отношению к новой микросервисной платформе станут ругательными)
3) нужно время на обучение разработчиков, тестировщиков и сопровождения. Обучение может быть и должно быть на практике - на реальных сервисах, но оно должно быть учтено в roadmap перехода. Сроки перехода должны быть согласованы командами разработки и сопровождения, а не спущены сверху. Звучит очевидно, но по моему опыту не для всех)
4) нужно изменение релизных и контролирующих политик в компании, иначе Lead Time и сложность вывода в ПРОМ для микросервисов останется на уровне монолита. Это сложный момент, т.к. люди консервативны, они привыкают к правилам, и не всегда осознают, что цена ошибки в монолите и в микросервисе разная. Особенно консервативно сопровождение и DBA, работа у них такая, цена ошибки высока) С другой стороны, конечно же микросервисная система должна быть спроектирована так, чтобы падение одного сервиса не приводило к каскадным падениям других. Это снова про критичное влияние архитектуры.
Еще важный момент - в монолите процесс согласования был централизован, им занимались специально обученные люди. С микросервисами релизный процесс попадает в Agile команды. А правило 7 +-2 действует не только для людей, а и для команд. Ну и большое число внешних взаимодействий противоречит Agile-у.
5) к началу разработки нужен работающий и простой DevOps. Разрабочики монолита как правило занимаются только разработкой и если заставить их учиться DevOps - потеряем время. Даже если набирать новых людей - все равно не каждый разработчик готов разрабатывать пайплайны. Т.е. должна быть минимальная конфигурация pipeline в декларативном стиле и работающие CI и CD pipeline. Опять же релизы микросервисов происходят намного чаще, для них это важно.
Также не должно быть невнятных инструкций и десятков настроечных файлов, необходимых для работы pipeline. Конфигурация - это не код, писать его не интересно, разбираться в ней тем более. И это не DevOps на самом деле) Должны быть - генераторы конфигураций, принцип convention over configuration.
6) микросервисам нужно больше инфраструктуры по сравнению с монолитом: сервера, репозитории - и больше доступов. Если в монолите как правило получением инфраструктуры занималась выделенная команда(ы), то при микросервисной архитекторе этим занимается каждая команда. Следовательно, процесс выдачи должен быть максимально автоматизирован и упрощен. Снова работает правило 7+-2. Разработчики должны заниматься тем, что у них лучше всего получается, а не заявками.
#microservices #fuckup #conv_over_conf
Telegram
(java || kotlin) && devOps
Всем привет!
Поговорим про разделение функционала между микросервисами.
Для начала я бы разделил два случая - распил монолита или создание нового приложения.
При распиле есть несколько путей, которые можно комбинировать:
1) отделять в первую очередь менее…
Поговорим про разделение функционала между микросервисами.
Для начала я бы разделил два случая - распил монолита или создание нового приложения.
При распиле есть несколько путей, которые можно комбинировать:
1) отделять в первую очередь менее…
Всем привет!
Сегодня расскажу о нескольких неочевидных особенностях работы Maven.
1) за каждый этап жизненного цикла сборки Maven отвечает какой-то плагин. Один плагин может покрывать несколько этапов. Это не новость. Я надеюсь) Интересно то, что эти плагины не обязательно указывать в pom, вот минимальный рабочий pom, с которым ваш проект скомпилируется - https://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Minimal_POM
Работает принцип convention over configuration.
А вот описание алгоритма определения нужного плагина: https://maven.apache.org/guides/introduction/introduction-to-plugin-prefix-mapping.html
Перескажу его вкратце.
Если вы указали при сборке фазу жизненного цикла, например, maven install, то определяются все необходимые шаги сборки и требуемые плагины как описано вот тут https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
А далее Maven ищет специальные файлы maven-metadata во всех подключенных к проекту репо, сливает их в один и ищет плагин по атрибуту prefix, который равен указаному вот тут как plugin https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#default-lifecycle-bindings-packaging-ejb-ejb3-jar-par-rar-war
Вот пример базового maven-metadata из Maven Central https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml
Как можно заметить, у большинства плагинов, поисковый префикс является частью artefactId. Это соглашение о наименовании, хотя и не обязательное. Т.е. всегда можно сделать свой maven-metadata-local.xml и привязать нужный плагин к нужной фазе там. Но я бы не рекомендовал так делать, т.к. это завязка на конкретный сборщик, которая хранится отдельно от кода вашего проекта. Также при создании плагина можно назвать его как угодно и указать к какой фазе сборки он привязан, может быть полезно, когда одним словом сложно выразить задачу плагина.
Если вы явно указываете цель для сборки, например, compiler:compile, то выполняется только эта цель, Maven пропускает разбор жизненного цикла сборки, сразу переходит к поиску нужного плагина в maven-metadata, в данном случае по префиксу compiler.
Вопрос - а как Maven определяет версию плагина? Есть еще один maven-metadata файлик с версиями у каждого плагина https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml
И как раз здесь лежит подводный камень: когда Maven-у понадобится конкретный плагин - он возьмет последнюю версию из тех, что найдет в подключенных к проекту репозиториях. А брать последнюю версию не всегда хорошо - там могут быть баги, или она просто может криво закачаться, если речь про внутренний прокси репозиторий.
Поэтому рекомендую начинать с минимальным POM, а перед выходом на ПРОМ фиксировать все версии плагинов.
Еще может возникнуть вопрос - а нельзя ли этот фокус провернуть с неофициальными плагинами? Ответ - можно, нужно лишь указать в settings.xml где еще искать maven-metadata.xml:
<pluginGroups>
<pluginGroup>org.codehaus.modello</pluginGroup>
</pluginGroups>
Еще момент - всегда можно добавить в pom конфигурацию плагина и там переопределить фазу сборки, на которой он запустится.
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
В примере цель из плагина jacoco-maven-plugin привяза к фазе test.
Выше я описывал, как работает Maven в режиме convention over configuration.
Продолжение следует...
#maven #buildtool #conv_over_conf
Сегодня расскажу о нескольких неочевидных особенностях работы Maven.
1) за каждый этап жизненного цикла сборки Maven отвечает какой-то плагин. Один плагин может покрывать несколько этапов. Это не новость. Я надеюсь) Интересно то, что эти плагины не обязательно указывать в pom, вот минимальный рабочий pom, с которым ваш проект скомпилируется - https://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Minimal_POM
Работает принцип convention over configuration.
А вот описание алгоритма определения нужного плагина: https://maven.apache.org/guides/introduction/introduction-to-plugin-prefix-mapping.html
Перескажу его вкратце.
Если вы указали при сборке фазу жизненного цикла, например, maven install, то определяются все необходимые шаги сборки и требуемые плагины как описано вот тут https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
А далее Maven ищет специальные файлы maven-metadata во всех подключенных к проекту репо, сливает их в один и ищет плагин по атрибуту prefix, который равен указаному вот тут как plugin https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#default-lifecycle-bindings-packaging-ejb-ejb3-jar-par-rar-war
Вот пример базового maven-metadata из Maven Central https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml
Как можно заметить, у большинства плагинов, поисковый префикс является частью artefactId. Это соглашение о наименовании, хотя и не обязательное. Т.е. всегда можно сделать свой maven-metadata-local.xml и привязать нужный плагин к нужной фазе там. Но я бы не рекомендовал так делать, т.к. это завязка на конкретный сборщик, которая хранится отдельно от кода вашего проекта. Также при создании плагина можно назвать его как угодно и указать к какой фазе сборки он привязан, может быть полезно, когда одним словом сложно выразить задачу плагина.
Если вы явно указываете цель для сборки, например, compiler:compile, то выполняется только эта цель, Maven пропускает разбор жизненного цикла сборки, сразу переходит к поиску нужного плагина в maven-metadata, в данном случае по префиксу compiler.
Вопрос - а как Maven определяет версию плагина? Есть еще один maven-metadata файлик с версиями у каждого плагина https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml
И как раз здесь лежит подводный камень: когда Maven-у понадобится конкретный плагин - он возьмет последнюю версию из тех, что найдет в подключенных к проекту репозиториях. А брать последнюю версию не всегда хорошо - там могут быть баги, или она просто может криво закачаться, если речь про внутренний прокси репозиторий.
Поэтому рекомендую начинать с минимальным POM, а перед выходом на ПРОМ фиксировать все версии плагинов.
Еще может возникнуть вопрос - а нельзя ли этот фокус провернуть с неофициальными плагинами? Ответ - можно, нужно лишь указать в settings.xml где еще искать maven-metadata.xml:
<pluginGroups>
<pluginGroup>org.codehaus.modello</pluginGroup>
</pluginGroups>
Еще момент - всегда можно добавить в pom конфигурацию плагина и там переопределить фазу сборки, на которой он запустится.
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
В примере цель из плагина jacoco-maven-plugin привяза к фазе test.
Выше я описывал, как работает Maven в режиме convention over configuration.
Продолжение следует...
#maven #buildtool #conv_over_conf
maven.apache.org
Introduction to the POM – Maven
Всем привет!
Продолжим про Maven.
2) Несмотря на то, что к каждой фазе жизненного цикла по умолчанию привязана одна цель (goal) из конкретного плагина, на каждую фазу можно повесить сколько угодно целей. Порядок выполнения - как указано в pom.xml. Это еще одна одна причина, почему полезно явно обьявлять плагины в pom.
3) Если у вас в settings.xml указано несколько репозиториев с артифактами, и поиск по всем не дал результата - будет ошибка, но с некорректным текстом. В ней будет сказано, что артифакта нет в первом по списку репозитории
4) Если какие-то из репозиториев в settings.xml требуют аутентификации, данные для аутентификации были указаны и протухли, то вы узнаете об этом только тогда, когда понадобится обновить библиотеку, которая есть только в этом репозитории. Ошибка с аутентификацией будет в логах каждой сборки, но сборку не ломает
5) Может возникнуть вопрос - а зачем Maven каждый раз ходит по удаленным репозиториям, если зависимости не менялись. Это поведение контролируется параметром репозитория updatePolicy в settings.xml:
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2</url>
<releases>
<updatePolicy>always</updatePolicy>
</releases>
</repository>
Возможные значения: "always", "daily" (default), "interval:XXX" (in minutes) or "never".
Можно установить never, но есть два риска:
а) не будут подтягиваться новые snapshot,
б) не будут подтягиваться новые версии уже закачанных артифактов. А эту информацию индексирует IDEA и использует при AutoComplition
6) Если сохраненные локально зависимости были повреждены, то принудительно их перезагрузить можно через очистку локального репозитория, который находится в папке .m2. Командой mvn dependency:purge-local-repository, подробнее тут https://www.baeldung.com/maven-force-update или просто грохнув нужную папку в .m2
7) согласно уже упоминаемому ранее принципу convention over configuration по умолчанию в список репозиториев неявно включается Maven Central. Подробнее про settings.xml и его опции можно почитать тут https://habr.com/ru/post/339902/
8) список репозиториев можно задать как в pom.xml, так и в settings.xml. Предпочтительнее второй вариант, особенно при разработке библиотек, особенно внутренних. Причина: адрес репозитория может поменяться, а settings.xml проще обновить централизованно. Не говоря уже про библиотеки, которые придется перевыпускать. Конечно, если вы ходили по ссылке из предыдущего пункта - у нас есть возможность переопределить любой репозиторий из pom через зеркала\mirror в settings.xml. Причем при настройке зеркала можно не только указывать явно заменяемый репозиторий, но и использовать операторы * и ! Но это все же костыль)
#maven #buildtool #conv_over_conf
Продолжим про Maven.
2) Несмотря на то, что к каждой фазе жизненного цикла по умолчанию привязана одна цель (goal) из конкретного плагина, на каждую фазу можно повесить сколько угодно целей. Порядок выполнения - как указано в pom.xml. Это еще одна одна причина, почему полезно явно обьявлять плагины в pom.
3) Если у вас в settings.xml указано несколько репозиториев с артифактами, и поиск по всем не дал результата - будет ошибка, но с некорректным текстом. В ней будет сказано, что артифакта нет в первом по списку репозитории
4) Если какие-то из репозиториев в settings.xml требуют аутентификации, данные для аутентификации были указаны и протухли, то вы узнаете об этом только тогда, когда понадобится обновить библиотеку, которая есть только в этом репозитории. Ошибка с аутентификацией будет в логах каждой сборки, но сборку не ломает
5) Может возникнуть вопрос - а зачем Maven каждый раз ходит по удаленным репозиториям, если зависимости не менялись. Это поведение контролируется параметром репозитория updatePolicy в settings.xml:
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2</url>
<releases>
<updatePolicy>always</updatePolicy>
</releases>
</repository>
Возможные значения: "always", "daily" (default), "interval:XXX" (in minutes) or "never".
Можно установить never, но есть два риска:
а) не будут подтягиваться новые snapshot,
б) не будут подтягиваться новые версии уже закачанных артифактов. А эту информацию индексирует IDEA и использует при AutoComplition
6) Если сохраненные локально зависимости были повреждены, то принудительно их перезагрузить можно через очистку локального репозитория, который находится в папке .m2. Командой mvn dependency:purge-local-repository, подробнее тут https://www.baeldung.com/maven-force-update или просто грохнув нужную папку в .m2
7) согласно уже упоминаемому ранее принципу convention over configuration по умолчанию в список репозиториев неявно включается Maven Central. Подробнее про settings.xml и его опции можно почитать тут https://habr.com/ru/post/339902/
8) список репозиториев можно задать как в pom.xml, так и в settings.xml. Предпочтительнее второй вариант, особенно при разработке библиотек, особенно внутренних. Причина: адрес репозитория может поменяться, а settings.xml проще обновить централизованно. Не говоря уже про библиотеки, которые придется перевыпускать. Конечно, если вы ходили по ссылке из предыдущего пункта - у нас есть возможность переопределить любой репозиторий из pom через зеркала\mirror в settings.xml. Причем при настройке зеркала можно не только указывать явно заменяемый репозиторий, но и использовать операторы * и ! Но это все же костыль)
#maven #buildtool #conv_over_conf
Baeldung
Force Repository Update with Maven | Baeldung
Explore the options and goals of Maven that forcibly updates our local repository.
Всем привет!
Уже говорил про переиспользование кода в общих библиотеках https://t.me/javaKotlinDevOps/137
Поднимемся на уровень выше: возьмем набор библиотек с общим кодом, добавим туда реализацию обязательных архитектурных стандартов, требований сопровождения и безопасности - и получим платформу.
Какой должна быть хорошая платформа? Первый напрашивающийся ответ - смотри на Spring Framework. Но попытаюсь конкретизировать.
1) модульность и минимум зависимостей между модулей. Наверняка есть какое-то ядро, которое часто именно так и называется, обязательное в любом случае. Но подключение остальных модулей должно быть опциональным, пользователь должен понимать зачем ему нужен тот или иной модуль.
2) хорошая документация, cookbook, отвечающий на вопросы: зачем использовать? как подключить? особенности реализации, антипаттерны?
3) работающее синтетическое приложение, каркас, позволяющее в коде увидеть ответы на вопросы из предыдущего пункта. С одной стороны получается дублирование, но учитывая что мы пытаемся "продать" не библиотеку, а целую платформу - код первичен, но одного кода недостаточно, не все можно показать в коде.
4) код и документация должны быть актуальными. Скорее всего на это потребуются отдельные люди, возможно даже отдельная команда. Т.к. разработка платформы скорее всего разделена на команды, команды заточены под свои локальные цели и не смотрят на платформу в целом, в особенности не видят проблем как пользователи.
5) self-service - у бизнес-команды должна быть возможность самостоятельно выполнять любые задачи, не связанные с исправлением багов и доработками компонента платформы. Пример таких задач - регистрация нового потребителя, метаданные для компонентов платформы, валидация скриптов. Самостоятельно - т.е. без тикетов на платформу, без согласований в почте, без встреч с платформенной командой. В идеале - кладем нужные нам стройке в git, далее DevOps pipeline их обрабатывает и результат отражается как результат выполнения джоба. Если есть возможность доработать код платформы самостоятельно - через механизм Inner Source - вообще отлично!)
6) должны быть четко очерчены сроки поддержки старых версий платформы. Естественно, сроки должны соблюдаться
7) API платформенных компонент должен быть единообразным. Хороший пример из Spring - многочисленные xxxTemplate. Или использование application.yml как централизованное место для настроек. За этим должен следить архитектор(ы) и команда, отвечающая за cookbook и синтетическое приложение.
8) платформенные компоненты должны предоставлять заглушки для возможности локальной отладки, информация о них должна быть в cookbook
9) convention over configuration = минимум настроек, которые разработчики должны прописать руками. Как пример - Spring Boot, хотя надо сказать сам Spring пришел к этому не сразу) Конечно каждая бизнес-задача уникальна, но по моему опыту в большинстве случаев достаточно типовой конфигурации с небольшими доработками. Рассмотрим альтернативу: если для поднятия минимального каркаса нужны сотни настроек - никто не будет в них разбираться, все их просто будут копировать. И хорошо, если из последней проверенной версии синтетического приложения.
10) платформа должна своевременно выпускать фиксы уязвимостей. Вроде очевидно, но важно.
11) у платформенной команды есть свой team lead, свой бэклог и главное - свое видение продукта. И это правильно. Но фокус в развитии продукта должен быть на потребителях. Всех потребителях - сопровождение, ИБ и конечно же бизнес-команды. Лично знаю случаи, когда разработчики платформы уходили в бизнес-команды и говорили - да, что-то я не думал, что нашей платформой так сложно пользоваться) Еще кейс - в бизнес-командах изобретено несколько похожих друг на друга "велосипедов", которые по хорошему должны быть в платформе изначально.
#arch #conv_over_conf
Уже говорил про переиспользование кода в общих библиотеках https://t.me/javaKotlinDevOps/137
Поднимемся на уровень выше: возьмем набор библиотек с общим кодом, добавим туда реализацию обязательных архитектурных стандартов, требований сопровождения и безопасности - и получим платформу.
Какой должна быть хорошая платформа? Первый напрашивающийся ответ - смотри на Spring Framework. Но попытаюсь конкретизировать.
1) модульность и минимум зависимостей между модулей. Наверняка есть какое-то ядро, которое часто именно так и называется, обязательное в любом случае. Но подключение остальных модулей должно быть опциональным, пользователь должен понимать зачем ему нужен тот или иной модуль.
2) хорошая документация, cookbook, отвечающий на вопросы: зачем использовать? как подключить? особенности реализации, антипаттерны?
3) работающее синтетическое приложение, каркас, позволяющее в коде увидеть ответы на вопросы из предыдущего пункта. С одной стороны получается дублирование, но учитывая что мы пытаемся "продать" не библиотеку, а целую платформу - код первичен, но одного кода недостаточно, не все можно показать в коде.
4) код и документация должны быть актуальными. Скорее всего на это потребуются отдельные люди, возможно даже отдельная команда. Т.к. разработка платформы скорее всего разделена на команды, команды заточены под свои локальные цели и не смотрят на платформу в целом, в особенности не видят проблем как пользователи.
5) self-service - у бизнес-команды должна быть возможность самостоятельно выполнять любые задачи, не связанные с исправлением багов и доработками компонента платформы. Пример таких задач - регистрация нового потребителя, метаданные для компонентов платформы, валидация скриптов. Самостоятельно - т.е. без тикетов на платформу, без согласований в почте, без встреч с платформенной командой. В идеале - кладем нужные нам стройке в git, далее DevOps pipeline их обрабатывает и результат отражается как результат выполнения джоба. Если есть возможность доработать код платформы самостоятельно - через механизм Inner Source - вообще отлично!)
6) должны быть четко очерчены сроки поддержки старых версий платформы. Естественно, сроки должны соблюдаться
7) API платформенных компонент должен быть единообразным. Хороший пример из Spring - многочисленные xxxTemplate. Или использование application.yml как централизованное место для настроек. За этим должен следить архитектор(ы) и команда, отвечающая за cookbook и синтетическое приложение.
8) платформенные компоненты должны предоставлять заглушки для возможности локальной отладки, информация о них должна быть в cookbook
9) convention over configuration = минимум настроек, которые разработчики должны прописать руками. Как пример - Spring Boot, хотя надо сказать сам Spring пришел к этому не сразу) Конечно каждая бизнес-задача уникальна, но по моему опыту в большинстве случаев достаточно типовой конфигурации с небольшими доработками. Рассмотрим альтернативу: если для поднятия минимального каркаса нужны сотни настроек - никто не будет в них разбираться, все их просто будут копировать. И хорошо, если из последней проверенной версии синтетического приложения.
10) платформа должна своевременно выпускать фиксы уязвимостей. Вроде очевидно, но важно.
11) у платформенной команды есть свой team lead, свой бэклог и главное - свое видение продукта. И это правильно. Но фокус в развитии продукта должен быть на потребителях. Всех потребителях - сопровождение, ИБ и конечно же бизнес-команды. Лично знаю случаи, когда разработчики платформы уходили в бизнес-команды и говорили - да, что-то я не думал, что нашей платформой так сложно пользоваться) Еще кейс - в бизнес-командах изобретено несколько похожих друг на друга "велосипедов", которые по хорошему должны быть в платформе изначально.
#arch #conv_over_conf
Telegram
(java || kotlin) && devOps
Всем привет!
В развитие темы про готовые решения и переиспользование знаний хочу поговорить про переиспользование кода.
Ясно, что все разработчики переиспользуют готовые решения - Spring Framework, Apache Commons да и вообще любые подключаемые к проекту…
В развитие темы про готовые решения и переиспользование знаний хочу поговорить про переиспользование кода.
Ясно, что все разработчики переиспользуют готовые решения - Spring Framework, Apache Commons да и вообще любые подключаемые к проекту…
Всем привет!
Я часто вижу в проектах лишние настройки. Как правило, они попадают в проект следующими путями:
1) скопировали из каркаса\образца\соседнего сервиса не задумываясь - нужны эти настройки или нет. Да, принцип "работает - не трогай" встречается и у разработчиков)
2) решили явно прописать какие-то настройки, так сказать для надежности
Я считаю, что так делать не надо. Почему?
1) лишние настройки раскрывают нам лишние детали, которые или не нужны вообще, или нужны, но не сейчас. Повышается когнитивная сложность кода. Знать все детали своего сервиса - это хороший подход, был, лет 10-20 назад. Сейчас ПО очень сильно развилось в плане специализации, количество зависимостей среднего проекта - несколько сотен, поэтому знать все детали просто невозможно.
2) следствие из сказанного выше - ухудшается читаемость кода. Да, это моя любимая тема. Мы чаще читаем код, чем пишем. Настройки тоже часть кода.
3) среди скопированных настроек могут быть не нужные в данный момент. Код легко меняется, ТЗ меняется также легко, поэтому добавлять что-то "на вырост" не стоит
4) портянка настроек, в которую что-то постоянно добавляется, может превратится в некий аналог "большого кома грязи", который будут боятся трогать. Как разработчики, так и сопровождение. Чтобы этого не допускать - настройки нужно чистить. Чтобы меньше было чистить - не нужно добавлять лишнее. Как-то так)
А вообще есть такой хороший принцип, описывающий то, что я хочу сказать: convention over configuration. Тоже одна из моих любимых тем. Принцип говорит о том, что должны быть некие настройки по умолчанию, устраивающие большинство потребителей. Эти настройки потребитель не задает, они заданы где-то внутри сервера или библиотеки.
#clean_code #configuration #conv_over_conf
Я часто вижу в проектах лишние настройки. Как правило, они попадают в проект следующими путями:
1) скопировали из каркаса\образца\соседнего сервиса не задумываясь - нужны эти настройки или нет. Да, принцип "работает - не трогай" встречается и у разработчиков)
2) решили явно прописать какие-то настройки, так сказать для надежности
Я считаю, что так делать не надо. Почему?
1) лишние настройки раскрывают нам лишние детали, которые или не нужны вообще, или нужны, но не сейчас. Повышается когнитивная сложность кода. Знать все детали своего сервиса - это хороший подход, был, лет 10-20 назад. Сейчас ПО очень сильно развилось в плане специализации, количество зависимостей среднего проекта - несколько сотен, поэтому знать все детали просто невозможно.
2) следствие из сказанного выше - ухудшается читаемость кода. Да, это моя любимая тема. Мы чаще читаем код, чем пишем. Настройки тоже часть кода.
3) среди скопированных настроек могут быть не нужные в данный момент. Код легко меняется, ТЗ меняется также легко, поэтому добавлять что-то "на вырост" не стоит
4) портянка настроек, в которую что-то постоянно добавляется, может превратится в некий аналог "большого кома грязи", который будут боятся трогать. Как разработчики, так и сопровождение. Чтобы этого не допускать - настройки нужно чистить. Чтобы меньше было чистить - не нужно добавлять лишнее. Как-то так)
А вообще есть такой хороший принцип, описывающий то, что я хочу сказать: convention over configuration. Тоже одна из моих любимых тем. Принцип говорит о том, что должны быть некие настройки по умолчанию, устраивающие большинство потребителей. Эти настройки потребитель не задает, они заданы где-то внутри сервера или библиотеки.
#clean_code #configuration #conv_over_conf
Всем привет!
Снова попробую сам с собой поспорить ... санитары, ау ... так ли хорош принцип convention over configuration.
1) Первое возражение я уже упомянул в предыдущем посте. А как же полный контроль над настройками проекта? Мало ли что там в значениях по умолчанию.
Ответ: при текущей модульности и сложности ПО - это видимость контроля. Невозможно вынести все настройки в один файл. А даже если и возможно - как потом с этим работать?
С другой стороны достаточный набор модульных и регрессионных тестов плюс нагрузочное тестирование дает некую уверенность, что все настроено верно. А тесты нужны в любом случае.
2) Если система прячет от нас настройки - она менее гибка, и в нестандартном use case ее придется настраивать "через одно место". И это в самом деле важный момент. convention over configuration не означает, что разработчик компонента спрятал все настройки в "черный ящик". Это неправильный convention over configuration. Правильный - разработчик продумал некие настройки по умолчанию, удовлетворяющие основные use cases, но оставил возможность подтюнить при необходимости.
Это может быть application.yaml в Spring Boot, код на Kotlin или Groovy DSL в Gradle или даже написание плагина в Maven. Последний кейс может показаться антипримером - настроить что-то под себя достаточно сложно. Кто-нибудь делал свой Maven плагин?) Но как раз за это многие и любят Maven - сделать из скрипта сборки "большой ком грязи" на Maven гораздо сложнее, чем в том же Gradle. Так что кажется, что и такой вариант допустим.
#conv_over_conf #configuration
Снова попробую сам с собой поспорить ... санитары, ау ... так ли хорош принцип convention over configuration.
1) Первое возражение я уже упомянул в предыдущем посте. А как же полный контроль над настройками проекта? Мало ли что там в значениях по умолчанию.
Ответ: при текущей модульности и сложности ПО - это видимость контроля. Невозможно вынести все настройки в один файл. А даже если и возможно - как потом с этим работать?
С другой стороны достаточный набор модульных и регрессионных тестов плюс нагрузочное тестирование дает некую уверенность, что все настроено верно. А тесты нужны в любом случае.
2) Если система прячет от нас настройки - она менее гибка, и в нестандартном use case ее придется настраивать "через одно место". И это в самом деле важный момент. convention over configuration не означает, что разработчик компонента спрятал все настройки в "черный ящик". Это неправильный convention over configuration. Правильный - разработчик продумал некие настройки по умолчанию, удовлетворяющие основные use cases, но оставил возможность подтюнить при необходимости.
Это может быть application.yaml в Spring Boot, код на Kotlin или Groovy DSL в Gradle или даже написание плагина в Maven. Последний кейс может показаться антипримером - настроить что-то под себя достаточно сложно. Кто-нибудь делал свой Maven плагин?) Но как раз за это многие и любят Maven - сделать из скрипта сборки "большой ком грязи" на Maven гораздо сложнее, чем в том же Gradle. Так что кажется, что и такой вариант допустим.
#conv_over_conf #configuration
Всем привет!
И "последняя серия" про convention over configuration.
Я уже говорил, почему стоит придерживаться данного принципа разработчику и команде в целом. Но можно посмотреть чуть шире.
1) с настройками приложения могут работать люди, не относящиеся к команде - тестировщики, DevOps-инженеры (да, они не должны этим заниматься, но занимаются), сопровождение ПРОМ. И у них будут похожие проблемы:
а) слишком много настроек
б) не понятно, что важно, что нет
в) не понятно, у всех одинаковые настройки (скопированные из каркаса) или у кого-то есть особенности, требующие, чтобы на них обратили внимание. По-хорошему, все это должно быть описано в документации к релизу, но случается всякое)
2) если ты разработчик какой-то библиотеки или сервиса, то вывалить на пользователей сотню настроек, давая им возможность все кастомизировать "под себя" - самый простой, но не самый правильный вариант. Даже если ко всем настройкам есть подробная документация, но как я уже написал выше - случается всякое) Правильный подход - подумать, как этим сервисом будут пользоваться. Это на самом деле критическая проблема. Не для всех, для того же open sourse проблема видится не критичной - библиотека, которую неудобно использовать, скорее всего не пройдет "естественный отбор". А вот в "кровавом enterprise" проблема вполне себе существует. Не всегда пользователи могут отказаться от использования какой-то части платформы. Так вот, чтобы понять оптимальные настройки по умолчанию - надо поставить себя на место пользователя. Или собрать обратную связь, или пользоваться своим продуктом. Т.об. принцип convention over configuration способствует движению в правильном направлении. Хотя конечно не является гарантией.
Вот теперь пожалуй всё)
#configuration #conv_over_conf
И "последняя серия" про convention over configuration.
Я уже говорил, почему стоит придерживаться данного принципа разработчику и команде в целом. Но можно посмотреть чуть шире.
1) с настройками приложения могут работать люди, не относящиеся к команде - тестировщики, DevOps-инженеры (да, они не должны этим заниматься, но занимаются), сопровождение ПРОМ. И у них будут похожие проблемы:
а) слишком много настроек
б) не понятно, что важно, что нет
в) не понятно, у всех одинаковые настройки (скопированные из каркаса) или у кого-то есть особенности, требующие, чтобы на них обратили внимание. По-хорошему, все это должно быть описано в документации к релизу, но случается всякое)
2) если ты разработчик какой-то библиотеки или сервиса, то вывалить на пользователей сотню настроек, давая им возможность все кастомизировать "под себя" - самый простой, но не самый правильный вариант. Даже если ко всем настройкам есть подробная документация, но как я уже написал выше - случается всякое) Правильный подход - подумать, как этим сервисом будут пользоваться. Это на самом деле критическая проблема. Не для всех, для того же open sourse проблема видится не критичной - библиотека, которую неудобно использовать, скорее всего не пройдет "естественный отбор". А вот в "кровавом enterprise" проблема вполне себе существует. Не всегда пользователи могут отказаться от использования какой-то части платформы. Так вот, чтобы понять оптимальные настройки по умолчанию - надо поставить себя на место пользователя. Или собрать обратную связь, или пользоваться своим продуктом. Т.об. принцип convention over configuration способствует движению в правильном направлении. Хотя конечно не является гарантией.
Вот теперь пожалуй всё)
#configuration #conv_over_conf
С чем проще работать - Maven vs Gradle?
Как ни странно - ответ на этот вопрос не очевиден.
Если говорить о чтении глазами разработчиком - Gradle выглядит попроще т.к. там почти нет boilerplate кода. И тот, и другой инструмент придерживаются принципа convention over configuration, но Maven проигрывает из-за xml.
Но если проект начинает развиваться - что-то может пойти не так) Gradle позволяет легко выстрелить себе в ногу создав очень сложный скрипт деплоя. Причем много кода появляется там, где его не ожидаешь - в build скрипте. И этот код не на Java, т.е. может отличаться от кода проекта. А если добавить сюда multiproject - разбираться в этом становится сложно. Maven выносит весь императивный код в плагины, скрипты сборки чисто декларативные.
И можно глянуть с другой стороны - со стороны tooling, например, той же IDEA. Тут победа на стороне Maven - распарсить xml легко, а вот чтобы понять структуру Gradle проекта - нужно начать его исполнять. Это и дольше, и процесс подвержен ошибками, а в теории и уязвимостям.
Вывод - оба инструмента хороши, имеют свои плюсы и минусы. Рекомендую изучить оба. Я для себя не определился)
#buildtool #maven #gradle #conv_over_conf
Как ни странно - ответ на этот вопрос не очевиден.
Если говорить о чтении глазами разработчиком - Gradle выглядит попроще т.к. там почти нет boilerplate кода. И тот, и другой инструмент придерживаются принципа convention over configuration, но Maven проигрывает из-за xml.
Но если проект начинает развиваться - что-то может пойти не так) Gradle позволяет легко выстрелить себе в ногу создав очень сложный скрипт деплоя. Причем много кода появляется там, где его не ожидаешь - в build скрипте. И этот код не на Java, т.е. может отличаться от кода проекта. А если добавить сюда multiproject - разбираться в этом становится сложно. Maven выносит весь императивный код в плагины, скрипты сборки чисто декларативные.
И можно глянуть с другой стороны - со стороны tooling, например, той же IDEA. Тут победа на стороне Maven - распарсить xml легко, а вот чтобы понять структуру Gradle проекта - нужно начать его исполнять. Это и дольше, и процесс подвержен ошибками, а в теории и уязвимостям.
Вывод - оба инструмента хороши, имеют свои плюсы и минусы. Рекомендую изучить оба. Я для себя не определился)
#buildtool #maven #gradle #conv_over_conf