Преамбула
В этой серии постов я собираюсь обсудить различные преимущества микросервисов как архитектурного паттерна. Я постараюсь охватить аспекты, которые либо не обсуждаются в сети совсем или обсуждаются, но недостаточно глубоко.
Все паттерны разработки, как правило, имеют свои плюсы и минусы. Таким образом, преимущества зачастую носят субъективный характер и разработчику следует выбирать подходящие модели в зависимости от условий и контекста.
Я постараюсь выделить объективные или почти-объективные плюсы — преимущества, которые дадут положительный эффект любому разработчику независимо от языка программирования, размера команды или диеты. Первая статья посвящена стоимости плохо написанного кода – мы сравним эффекты влияния такого кода на монолитные приложения и на микросервисы.
Кроме того, позже, когда наберется несколько статей, я планирую смонтировать видео для YouTube – анимации и скринкасты донесут мою точку зрения яснее.
Введение: Как конвенции и фреймворки улучшают запутанный код
Когда вы пишете программу из 100 строк, то, в принципе, не имеет значения насколько крутой вы выбрали дизайн или насколько четко вы будете следуете модным идеям. Небольшое приложение относительно легко понять, просто потому что оно небольшое. А начать его оптимизировать было бы анти-паттерном само по себе – такую оптимизацию часто называют преждевременной.
Как правило, вы начинаете рефакторить код, когда заметили, как выросли исходные файлы или как вы повторяете одну и ту же логику более двух раз. Но если у приложения всего 100 строк, сколько реально таких повторений может поместиться?
И тут ваш начальник просит все больше и больше фич, и ваше приложение начинает расти. Теперь уже не имеет смысла держать всю логику в одном файле, необходимо разбить приложение на несколько файлов. А когда файлов стало много, вы начинаете организовывать их в папки. Когда стало много и файлов и папок, вы ищете способ логически сортировать элементы. Вероятно, вы начинаете делить исходные файлы на модели, контроллеры и так далее.
Начинает появляться опасность запутанного кода – файл X обращается файлу Y, Y зависит частично от файла Z, файл Z импортирует несколько функций из файлов А и Б. Приходит младший разработчик, изменяет один файл и ломается всё приложение, а вы должны исправить ошибку, прежде чем боссу позвонит первый разгневанный клиент.
Решать проблему к нам пришли фреймворки. Фреймворки зачастую насаждают свои конвенции (правила), систематические разбиение приложения на файлы и каталоги. Например, контроллеры должны иметь дело только с веб-запросами, классы моделей должны содержать бизнес-логику, шаблоны должны содержать только HTML, конфигурация должна храниться в отдельном месте и желательно зависеть от текущей среды.
Хотите добавить ресурс? Измените файл маршрутов!
Хотите добавить дополнительную логику, которая запускается после сохранения записи? Подпишитесь на событие!
Хотите добавить дополнительные условия для запросов в базу данных? Создайте класс поведения таблицы!
И так далее.
Это не просто помогает разрабатывать более крупные монолитные приложения, это единственный способ разработать крупное приложение и не сойти с ума! Если каждый член команды будет иметь право добавлять код куда угодно, то ваш процесс разработки выскочит из-под контроля довольно быстро.
Посмотрим на структуру пустого приложения на Ruby on Rails:
./app/assets ./app/assets/config ./app/assets/images ./app/assets/javascripts ./app/assets/javascripts/channels ./app/assets/stylesheets ./app/channels/application_cable ./app/controllers ./app/controllers/concerns ./app/helpers ./app/jobs ./app/mailers ./app/models ./app/models/concerns ./app/views/layouts ./bin ./config ./config/environments ./config/initializers ./config/locales ./db ./lib ./lib/assets ./lib/tasks ./log ./public ./test ./test/controllers ./test/fixtures ./test/fixtures/files ./test/helpers ./test/integration ./test/mailers ./test/models ./tmp ./vendor ./vendor/assets ./vendor/assets/javascripts ./vendor/assets/stylesheets
Реальность такова, что в вашей команде могут быть неопытные (или с похмельем) коллеги, которые будут нарушать вроде бы простые конвенции время от времени, и код будет становится всё сложнее и уродливее, несмотря на выбор «правильных» фреймворка и структуры.
Написание хорошего кода особенно важно в контексте большого приложения. Принципы SOLID, паттерны разработки, фреймворки и конвенции появились в первую очередь, чтобы помочь разработчику с крупными приложениями.
Монолиты и микросервисы: Влияние на спагетти-код
Вот что делают микросервисы со спагетти:
Ой, не та картинка. Вот так примерно выглядит спагетти-код в случае монолитного приложения:
Один класс (или функция) вызывает другой класс, а тот класс зависит от другого класса, а тот класс зависит от нескольких других классов и так далее. Вы хотите пробежаться по коду и исправить ошибку — будьте готовы открыть много файлов и изучать их параллельно. Почему я считаю, что это является характеристикой именно монолитного приложения?
В монолитном приложении, модули (элементы) кода вызывают друг друга непосредственно –используя тот факт, что все они загружены в оперативную память в рамках одной машины. Это приводит к тому, что ленивые разработчики излишне тесно связывают части приложения между собой.
Микросервисы, с другой стороны, как правило, общаются через веб-запросы (обычно RESTful) или через сообщения. Таким образом, разработчик не может просто взять и вызвать функционал одного микросервиса из другого микросерфиса – как минимум, придется создать дополнительный маршрут, открыть этот метод в контроллере и так далее. Это дополнительная работа, барьер, который разработчики не будут преодолевать без абсолютной необходимости. Существует также вероятность того, что тот другой микросервис в настоящее время поддерживается другой командой вашей компании, а разработчики там вредные и они не хотят добавлять ненужный (с их точки зрения) маршрут лишь ради того, чтобы сделать вашу жизнь проще.
В результате, вы, скорее всего, будете иметь меньшее количество по-лучше организованных соединений. А факт меньшего количества зависимостей между микросервисами (различными функциональными модулями вашего приложения) означает, что если микросервис А плохо реализован, он не будет иметь такого дурного влияния на другие микросервисы.
В среде микросервисов, плохой код изолирован.
Микросервисы: Успокой своего внутреннего перфекциониста
Так как отдельно взятый микросервис – это не более, чем класс или два, вырезанных из вашего монолитного приложения, то теперь у вас меньше, значительно меньше файлов в рамках одного открытого приложения в IDE. Таким образом, вероятно, уже не нужно так сильно заботиться о строгих правилах наименования файлов и папок и, возможно, вы даже можете ослабить правила SOLID.
Теперь вы можете позволить себе «халяву» – можно сделать несколько ошибок, несколько неоптимальных реализаций, а ваше приложение всё еще достаточно легко читать и править, потому что ваш LoC (Lines of code) упал с нескольких тысяч до жалких десятков или сотен!
Процесс разработки ускорится, потому что вы меньше обеспокоены строгими правилами и мириадой зависимостей!
Вывод
Микросервисы, как архитектурный паттерн, позволяют снизить стоимость (издержки от) неоптимального исходного кода, ускорить разработку и повысить качество сна.
ссылка на оригинал статьи https://habrahabr.ru/post/318520/
Добавить комментарий