Pull to refresh

Сервисы, микросервисы и пакетно-ориентированное программирование

Reading time7 min
Views12K
Многие программисты слышали о том, что иногда код следует выделять в отдельные библиотеки для дальнейшего повторного использования. Однако, вопрос, какой же все-таки код следует выделять в отдельную сущность, ставит многих разработчиков в тупик. При прочтении статей/разговоре на данную тему обычно вспоминается проблема преждевременного обобщения.

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

Хочу поднять тему повторного использования кода в контексте создания сервис-ориентированной и микросервисной архитектуры.

Что есть повторно используемый код


Повторно используемый код — это код, выделенный в отдельную сущность, называемую в разных языках по разному — библиотека, пакет, зависимость и т.д. Обычно такой код хранится в отдельном репозитории, и имеется документация по подключению и использованию этого кода(README.md). Дополнительно, код может быть покрыт тестами, может иметься инструкция по внесению изменений(CONTRIBUTING.md) и может быть настроен CI. Различные бейджи, прикрепленные к описанию, только улучшают визуальное представление зрелости данной сущности, а количество поставленных звезд скажет о популярности данного решения. За примерами далеко ходить не надо — достаточно открыть страницу github любого из популярных фреймворков на любимом вами языке, например vue.js. В общем, способов качественного оформления библиотек вагон и маленькая тележка.

Сервисы и микросервисы


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

Сервис-ориентированная архитектура предполагает, что каждый сервис минимально связан с другими. Тем не менее, межсервисное взаимодействие не исключено, а только предполагается, что оно должно быть сведено к минимуму. Для приема запросов в сервисе обычно реализуется какое-либо стандартизированное API. Это может быть что угодно — REST, SOAP, JSONRPC или новомодный GraphQL.

Условно, сервисы можно разделить на инфраструктурные и продуктовые. Продуктовые сервисы — это те, которые реализуют логику какого-либо клиентского продукта. Например, работают с заявками на его подключение, или организуют сопровождение этого продукта на всем жизненном цикле работы с ним клиента. Инфраструктурные сервисы — это больше про базовый функционал компании(или проекта), например сервис, содержащий клиентскую информацию, или сервис, хранящий информацию о тех или иных заказах. Также к инфраструктурным можно отнести сервисы, реализующие вспомогательный функционал, например сервис информирования клиентов (отправка push-сообщений или СМСок) или сервис взаимодействия с dadata.

Чуточку пофантазируем


Допустим, существует гипотетический интернет-магазин, построенный по сервис-ориентированной архитектуре. Разработчики этого чуда инженерной мысли смогли договориться между собой и пришли к выводу, что в качестве API все их сервисы будут работать, например, по jsonrpc-протоколу. Однако, поскольку интернет-магазин большой, он не стоит на месте и активно развивается, то групп разработки там несколько, пусть будет больше двух — две проектные, одна по сопровождению уже написанного. Также, для пущего эффекта, все команды пишут на одном стеке.

Архитектура гипотетического интернет-магазина:



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

Сервис клиентской информации хранит информацию о клиентах, умеет их заводить, авторизовывать, выдавать о них необходимую информацию.

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

Сервис заказов оперирует заказами. Тут находится логика формирования заказа, его подтверждения, выбора типа оплаты и адреса доставки и т.д.

Сервис информирования клиентов умеет отправлять PUSH/SMS/email-сообщения. Тип коммуникации, допустим, зависит от настроек конкретного клиента, также клиент может настроить желаемое время получения уведомлений.

Данные сервисы условно являются инфраструктурными, поскольку без них не может функционировать интернет-магазин как таковой.

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

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

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

В контексте предложенной архитектуры сразу становится ясно, что для быстрой продуктовой разработки крайне необходимы готовые библиотеки. Так, важно иметь готовую реализацию jsonrpc-сервера, а также клиента к нему, поскольку это основной протокол организации межсервисного взаимодействия. Также в данном примере во весь рост встает вопрос документирования API. Очевидно, для формирования документации у команд также должен быть готовый инструмент. Если предположить, что еще есть готовый инструмент и для генерирования smd-схем для jsonrpc-серверов, то скорость разработки новых сервисов может еще больше вырасти. В итоге, внутри компании, в идеале, должен быть набор готовых библиотек, которыми пользуются все команды для выполнения типовых задач. Эти библиотеки могут быть как собственные, так и open-source'ные, главное, чтобы хорошо выполняли свои задачи. Очевидно, что команда, которая находится в общем стеке и пишет сервисы используя готовые библиотеки, будет более эффективная, нежели команда, которая постоянно велосипедит. Наличие единого фреймворка и единой базы библиотек, которые используются во всех проектных командах, я называю единой экосистемой.

А как обстоят дела в крупных компаниях?


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

Так уж вышло, что у меня есть опыт работы в компании, в которой трудятся около 200 разработчиков, пишущих на различных языках — java, c#, php, python, go, js и др. Удивительно, но общую экосистему, в контексте единого стека, имеют и используют далеко не все команды разработчиков. Казалось бы, очевидная вещь — готовить повторно используемый код, оформлять его должным образом и использовать — далеко не очевидная. Конечно, команды разработчиков решают свои задачи. Кто-то использует шаблон сервиса — набор кода, составляющее ядро их каждого нового сервиса, из которого выкидывается все ненужное и дописывается нужное.

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

Преимущества единой экосистемы


Формирование единой экосистемы позволяет решить множество сложностей, и имеет огромный потенциал повышения производительности для большой компании. Фактически, эта практика взята из Open Source сообщества — выживают и наиболее популярны лучшие решения в своей области. Сейчас достаточно открыть любой менеджер зависимостей и только удивиться обилию предлагаемых решений. А ведь именно такой подход можно реализовать и внутри компании. Преимущества же такого подхода при реализации нового сервиса следующие:

  • Высокая стабильность — использование покрытых тестами, хорошо документированных библиотек повышает и стабильность сервиса в целом;
  • Легкая ротация коллег между командами — если все команды находятся внутри единой экосистемы, то при переходе из одной команды в другую разработчик не придется тратить много времени на знакомство с используемыми инструментами, ведь он уже с ними знаком;
  • Концентрация на бизнес–логике — действительно, разработка нового сервиса сводится к тому, что надо подтянуть необходимые зависимости, решающие все инфраструктурные задачи, и написать только бизнес-логику;
  • Ускорение разработки — нет необходимости велосипедить, готово все, кроме бизнес-логики;
  • Упрощение тестирования — тестировать нужно только бизнес-логику, ведь библиотеки уже протестированы;

Ложка дёгтя


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

PS


А пакетно-ориентированный подход — только лишь потому, что повторно используемый код на моем стеке называется пакетом. Ну и смешно это звучит. Недавно с одним из коллег у меня состоялся такой диалог, побудивший на написание данной статьи:
— Коллега: ты превращаешься в кассира в пятерочке
— я: всмысле?)
— Коллега: скоро будешь спрашивать «пакет надо?»
— я: раскрой пожалуйста мысль. я не понимаю
— Коллега: ну уже в который раз у тебя есть готовый пакет для решения моей задачи

Все дело в том, что в нашем сообществе разработчиков внутри компании готовых пакетов набралось около 20 штук, и создание нового сервиса выливается в подтягивание необходимых зависимостей, а также написании бизнес-логики. Затраты на обвязку в части написания кода практически сведены на нет.
Only registered users can participate in poll. Log in, please.
Есть ли в вашей компании культура выделения кода в отдельные библиотеки?
61.97% Да44
38.03% Нет27
71 users voted. 13 users abstained.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Total votes 15: ↑11 and ↓4+7
Comments5

Articles