VStamp

Архитектура Go проекта на практике

Практическое руководство по чистой архитектуре в Go с генератором кода Goro

LectureEvrone Development23,815 viewsJun 30, 2023

Тигран Ханагян из Delivery Hero делится опытом построения чистой архитектуры на Go и демонстрирует автоматизацию бойлерплейта с помощью библиотеки Goro.

Go
Чистая архитектура
Dependency Inversion Principle
Goro
Кодогенерация
Бизнес-логика
Инфраструктура
Use Case
Adapter
Handler
Delivery Hero
HungerStation
HTTP сервер
Репозитории
Микросервисы
Go project layout
Интерфейсы
Тигран Ханагян

Blurb

В этом видео инженер Тигран Ханагян из Delivery Hero рассказывает о построении чистой архитектуры в Go-проектах, выделяя ключевые слои: entity, usecase, service, adapter и handler. Он объясняет, как разделить бизнес-логику и инфраструктуру, избегать циклических импортов и утечек абстракций, а также демонстрирует принцип инверсии зависимостей. Вторая часть видео посвящена практической демонстрации использования библиотеки Goro — инструмента для генерации бойлерплейт-кода, который ускоряет разработку и поддерживает структуру чистой архитектуры. Тигран показывает, как быстро создавать проекты, описывать зависимости и реализовывать бизнес-логику на примере сервиса подписок.

Want the big picture?

Highlighted Clips

1.

Введение и знакомство с докладчиком

Тигран Ханагян рассказывает о своем опыте и текущей работе в Delivery Hero.

2.

Разделение кода на инфраструктуру и бизнес-логику

Обсуждение важности разделения инфраструктурного кода и бизнес-логики в Go-проектах.

3.

Проблемы с зависимостями и циклическими импортами

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

4.

Обзор чистой архитектуры и ее слоев

Объяснение слоев entity, usecase, service, adapter и handler с примерами и схемами.

Введение и знакомство с докладчиком

Тигран Ханагян начинает с краткого представления себя и своего опыта: он инженер в группе компаний Delivery Hero, работает с Go и имеет более десяти лет опыта в программировании на разных языках, включая PHP и Python. Он упоминает, что занимается высоконагруженными сервисами и делится знаниями на конференциях и в блогах.

"Меня зовут Тигран и на данный момент я работаю в качестве инженера в группе компаний Delivery Hero... За свой более десятилетний опыт я успел поработать с такими языками как PHP, Python... последнее время работаю в основном с Go."

Ключевые моменты:

  • Опыт работы с высоконагруженными сервисами.
  • Акцент на Go как основном языке.
  • Цель доклада — рассказать о чистой архитектуре на практике.

О чем будет доклад: проблемы и разделение кода

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

"Я предлагаю мысленно разделить наш код на два типа: это некий инфраструктурный код... и бизнес логика — это непосредственно наш продуктовый код."

Ключевые моменты:

  • Фокус на бизнес-логике, так как времени мало.
  • Следование стандартному Project layout для Go.
  • Частые ошибки: смешение ответственности, копипаст, циклические импорты.

Проблемы с традиционной организацией кода

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

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

Ключевые проблемы:

  • Сильная связность между слоями.
  • Утечка абстракций (например, роутер занимается бизнес-логикой).
  • Копипаст и сложности с тестированием.
  • Циклические импорты и трудности расширения.

Решение: чистая архитектура и ее слои

Тигран предлагает использовать чистую архитектуру (известную как архитектура дядюшки Боба), чтобы избавиться от перечисленных проблем. Он упрощает классическую схему, выделяя три ключевых слоя: entity (бизнес-логика и данные), usecase (бизнес-правила и оркестрация логики), и adapter (взаимодействие с внешним миром).

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

Ключевые моменты:

  • Слои общаются через интерфейсы.
  • Entity — данные и простая бизнес-логика, не зависящая от внешних сервисов.
  • Usecase — оркестратор бизнес-логики, реализует фичи приложения.
  • Adapter — реализация доступа к базе, API, очередям.
  • Важен принцип инверсии зависимостей: зависимости идут от нижних слоев к верхним через интерфейсы.

Детали слоя Entity и бизнес-логики

Entity — это структуры с данными и ограниченной бизнес-логикой, которая не требует внешних вызовов. Тигран предпочитает делать entity глобальными, чтобы они могли свободно передаваться между слоями, избегая утечек абстракций.

"Я обычно помещаю в entity бизнес-логику, которую могу осуществить с помощью данных, доступных в этом entity... Entity могут быть глобальными, чтобы переносить данные через все слои."

Ключевые моменты:

  • Entity — это структуры с данными и простой бизнес-логикой.
  • Использование тегов для базы данных и сериализации.
  • Глобальные entity упрощают передачу данных между слоями.

Слой Usecase: бизнес-правила и фичи

Usecase — это слой, который реализует бизнес-правила приложения, то есть фичи, которые клиент видит и использует. Он выступает как оркестратор, вызывая сервисы и управляя последовательностью действий.

"Usecase — это бизнес правило приложения, логика приложения, наши фичи... Usecase — это оркестратор нашей бизнес-логики."

Ключевые моменты:

  • Usecase реализует фичи приложения.
  • Usecase вызывает только слой сервисов, не обращается напрямую к репозиториям.
  • Интерфейсы сервисов объявляются приватными внутри usecase, что ограничивает область видимости.

Слой сервисов и принцип инверсии зависимостей

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

"Все наши сервисы объявляем так, что нам нужны интерфейсы, а не конкретные реализации... Это избавляет нас от циклических импортов и сильной связности."

Ключевые моменты:

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

Адаптеры и хендлеры: связь с внешним миром

Адаптеры — это слой, который реализует конкретные драйверы и протоколы для доступа к базе данных, очередям, API и т.д. Тигран рекомендует структурировать адаптеры по протоколам (например, HTTP, MySQL, Mongo).

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

"Адаптеры — это наша связь с внешним миром... Хендлеры отвечают за то, как фичи можно вызывать, определяют протокол, валидацию, ответы."

Ключевые моменты:

  • Адаптеры реализуют конкретные подключения и драйверы.
  • Хендлеры обрабатывают запросы и вызывают usecase.
  • Каждый слой изолирован и может быть вынесен в отдельный проект.

Проблема бойлерплейта и решение с библиотекой Goro

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

"Все это приведет к не малому количеству бойлерплейт кода... Я решил написать инструмент — библиотеку Goro, которая генерирует этот код."

Ключевые моменты:

  • Goro генерирует код для инфраструктуры и бизнес-логики.
  • Позволяет быстро создавать проекты и добавлять новые сервисы.
  • Активно развивается, уже покрывает базовый функционал.

Демонстрация работы с Goro: создание проекта и сервисов

Тигран показывает, как скачать и установить Goro, затем создать проект с помощью конфигурационного файла YAML. В конфиге описываются usecase, сервисы и адаптеры с их зависимостями. После генерации появляется структура с папкой internal и слоями entity, usecase, service, adapter.

"Мы скачиваем конфиг, запускаем генератор, и у нас появляется папка internal с пакетами entity, usecase, service, adapter."

Ключевые моменты:

  • Конфиг описывает методы usecase и зависимости.
  • Генератор создает интерфейсы и шаблоны для реализации.
  • Зависимости передаются по интерфейсам, что соответствует принципу инверсии.

Пример: сервис подписок и методы

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

"Давайте сделаем приложение подписок... Опишем методы Pay и GetSubscriptionPrice, укажем зависимости и сгенерируем проект."

Ключевые моменты:

  • Быстрое добавление новых сервисов и методов.
  • Репозитории указываются с конкретными драйверами (например, MySQL).
  • Генератор проверяет конфиг и сообщает об ошибках.

Запуск и проверка проекта

В конце Тигран запускает сгенерированный HTTP сервер и демонстрирует вызов метода ping, который сообщает, что нужно реализовать бизнес-логику в usecase. Это показывает, что структура готова к наполнению реальным кодом.

"Запускаем HTTP сервер, вызываем метод ping, он говорит, что нужно имплементировать метод в usecase."

Ключевые моменты:

  • Проект запускается сразу после генерации.
  • Можно постепенно добавлять бизнес-логику.
  • Goro облегчает старт и поддержание чистой архитектуры.

Заключение и благодарности

Тигран благодарит зрителей за внимание и приглашает задавать вопросы.

"Спасибо что выслушали до конца... Если есть вопросы, буду рад ответить."


Итог

В этом докладе Тигран Ханагян подробно разбирает проблемы традиционной организации Go проектов и показывает, как чистая архитектура помогает их решить. Он объясняет ключевые слои — entity, usecase, service, adapter, handler — и принцип инверсии зависимостей, который делает код независимым и тестируемым. Чтобы упростить работу с большим количеством шаблонного кода, он разработал библиотеку Goro, которая генерирует структуру и интерфейсы, позволяя быстро создавать и расширять проекты с чистой архитектурой. Доклад наполнен практическими примерами и демонстрацией работы с инструментом, что делает его полезным для разработчиков, стремящихся писать чистый и поддерживаемый код на Go.

Key Questions

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

Have more questions?

Analyzing video...

This may take a few moments.

Background illustration light mode

Ready to dive in?