Модератор форума
-
Автор темы
- #1
Всем привет, на связи член модераторского состава форума yougame.biz, по совместительству бэкенд разработчик в аутсорсиноговой компании. На пути своего становления в этом ремесле, столкнулся с проблемой, что информация в интернете по бэкэнд разработке, в особенности на spring boot, в некоторых моментах страдает плохим качеством, а то и вовсе отсутствует. Поэтому сформировать полноценный пласт знаний в этой области начинающему разработчику бывает достаточно сложно. В связи с этим, появилась мотивация сделать цикл статей, в которых с самого нуля будет рассмотрено создание демо - сервиса, в котором будут отражены все основные аспекты, которыми должен владеть начинающий разработчик.
В этой статье пойдет речь о фундаменте любого приложения, не важно, web это или десктоп. Без понимания этой концепции строить надежные и легко расширяемые приложения будет практически невозможно. И говорить мы будем об Архитектуре.
Как скомпоновать приложение? Какие в нём должны быть слои? Как назвать пакеты? Где расположить DTO, маперы, реализации интерфейсов? И нужны ли вообще интерфейсы?
Когда человек начинает делать свой первый проект, то у него нету однозначных ответов на эти вопросы. Он смотрит код, "до которого может дотянуться" - открытые GitHub репозитории, обучающие статьи, и если повезет, то у новичка есть все шансы научиться писать хороший, чистый, код. Если же не повезёт, то человек будет цепляться за то, что есть, нахватается плохих практик, и по прошествии года-двух он уже сам будет себе авторитетом, которого не так-то просто будет переубедить.
В посте ниже я описываю личный и командный опыт, под который я постарался подвести теоретическую базу, опираясь на "Чистую архитектуру" Роберта Мартина. Да, этот пост - для новичков, хотя, эта тема жива и среди устоявшихся программистов, поскольку споры о компоновке приложения не утихают и среди сениоров.
Зайду я немного издалека и напомню, что такое луковичная архитектура.
Что такое луковичная архитектура?
В "Чистой архитектуре" Роберта Мартина описывается центрическая архитектура, ядром которой является бизнес-сущность.
![Луковичная архитектура Луковичная архитектура](https://yougame.biz/data/attachments/279/279765-3acdb34c37b729cab66d1763d05a2f8a.jpg)
Давайте же попробуем разобрать, что происходит на изображении, пройдясь по каждому из слоев.
Бизнес-сущность (Entity)
Бизнес-сущность (по англ. Entity) ничего не знает ни о логике приложения, ни о слое доступа к данным, ни уж тем более о подключаемых внешних интерфейсах - она содержит только собственные поля и базовые методы для работы с ними - геттеры, сеттеры, контроллеры, билдеры и всё, что необходимо сущности для работы с самой собой. Как правило, Entity необходим для отображения данных, с которыми работает java приложение в базу данных, именно поэтому entity чаще всего аннотируется, в соответствии с используемой в проекте спецификацией для работы с бд (JDBC, JPA) Вот тут, конечно, стоило бы оговориться, что при использовании Entity как объекта для отображения данных из бд в код и наоборот, нарушается принцип независимости, но в производственной сфере мало кто обращает на это внимание, так что опустим этот момент ;)
Пример:
![1719081008288.png 1719081008288.png](https://yougame.biz/data/attachments/279/279769-309abc58bbb07842dc0e9cf175224239.jpg)
Репозиторий (Repository)
Данный слой стоит на один уровень выше Entity. Основная его цель - обеспечить основные операции над данными (так называемый CRUD) между бд и приложением. На вход Repository получает сформированный Entity, на выходе он должен предоставить тоже Entity, то с до заполненным полями из бд, если таковые имеются (database-generative fields - поля, которые генерирует база данных), ничего более репозиторий уметь не должен.
Пример:
![1719081449865.png 1719081449865.png](https://yougame.biz/data/attachments/279/279770-77e532d0415077e403076697c8e43f91.jpg)
На самом деле, репозиторий не обязательно должен выглядеть именно так, его внешний вид напрямую зависит от, опять же, используемой спецификации общения бд и приложения.
Сервисы (Services)
Вот это уже поинтереснее. По факту, сервисы являются сердцем любого web приложения, именно они реализуют бизнес логику. Сервис общается только с одним репозиторием, это важно! Если в приложении вы видите такую цепочку зависимостей: Entity->Repository->Service, то это означает, что приложение проектировали осознанные люди :) Старайтесь всегда соблюдать это правило - на один энтити один репозиторий, на один репозиторий один сервис. Если вам нужно обращаться к другим энтити, сделайте межсервисное взаимодействие.
Как раз о нем. Формат общения сервисов друг с другом и с вышестоящими слоями заключается в использовании так называемых DTO - data transfer objects. Это обычные классы, которые так же содержат только собственные поля и базовые методы для работы с ними - геттеры, сеттеры, контроллеры, билдеры и всё, что необходимо сущности для работы с самой собой. DTO бывает двух видов - RequestDTO и ResponceDTO.
RequestDTO содержит только те поля, которые необходимы для выполнения вызова сервисом, ничего более.
ResponceDTO, как правило, содержит в себе отображение Entity, хотя вполне допускается и дополнительная информация.
Контроллер (Controller)
Является слоем, отвечающим за отображение данных service в формат, который понимает клиент. Контроллеры бывают разных типов, как пример RestController - взаимодействует с пользователем при помощи RestAPI.
Я умышленно не буду рассматривать в этой статье положение остальных компонентов системы, так как они не являются обязательными, в отличие от вышеприведенных.
В итоге мы получил следующую иерархию проекта:
Буду рад услышать комментарии и дополнения к этой статье. До встречи!
В этой статье пойдет речь о фундаменте любого приложения, не важно, web это или десктоп. Без понимания этой концепции строить надежные и легко расширяемые приложения будет практически невозможно. И говорить мы будем об Архитектуре.
Как скомпоновать приложение? Какие в нём должны быть слои? Как назвать пакеты? Где расположить DTO, маперы, реализации интерфейсов? И нужны ли вообще интерфейсы?
Когда человек начинает делать свой первый проект, то у него нету однозначных ответов на эти вопросы. Он смотрит код, "до которого может дотянуться" - открытые GitHub репозитории, обучающие статьи, и если повезет, то у новичка есть все шансы научиться писать хороший, чистый, код. Если же не повезёт, то человек будет цепляться за то, что есть, нахватается плохих практик, и по прошествии года-двух он уже сам будет себе авторитетом, которого не так-то просто будет переубедить.
В посте ниже я описываю личный и командный опыт, под который я постарался подвести теоретическую базу, опираясь на "Чистую архитектуру" Роберта Мартина. Да, этот пост - для новичков, хотя, эта тема жива и среди устоявшихся программистов, поскольку споры о компоновке приложения не утихают и среди сениоров.
Зайду я немного издалека и напомню, что такое луковичная архитектура.
Что такое луковичная архитектура?
В "Чистой архитектуре" Роберта Мартина описывается центрическая архитектура, ядром которой является бизнес-сущность.
![Луковичная архитектура Луковичная архитектура](https://yougame.biz/data/attachments/279/279765-3acdb34c37b729cab66d1763d05a2f8a.jpg)
Давайте же попробуем разобрать, что происходит на изображении, пройдясь по каждому из слоев.
Бизнес-сущность (Entity)
Бизнес-сущность (по англ. Entity) ничего не знает ни о логике приложения, ни о слое доступа к данным, ни уж тем более о подключаемых внешних интерфейсах - она содержит только собственные поля и базовые методы для работы с ними - геттеры, сеттеры, контроллеры, билдеры и всё, что необходимо сущности для работы с самой собой. Как правило, Entity необходим для отображения данных, с которыми работает java приложение в базу данных, именно поэтому entity чаще всего аннотируется, в соответствии с используемой в проекте спецификацией для работы с бд (JDBC, JPA) Вот тут, конечно, стоило бы оговориться, что при использовании Entity как объекта для отображения данных из бд в код и наоборот, нарушается принцип независимости, но в производственной сфере мало кто обращает на это внимание, так что опустим этот момент ;)
Пример:
![1719081008288.png 1719081008288.png](https://yougame.biz/data/attachments/279/279769-309abc58bbb07842dc0e9cf175224239.jpg)
Репозиторий (Repository)
Данный слой стоит на один уровень выше Entity. Основная его цель - обеспечить основные операции над данными (так называемый CRUD) между бд и приложением. На вход Repository получает сформированный Entity, на выходе он должен предоставить тоже Entity, то с до заполненным полями из бд, если таковые имеются (database-generative fields - поля, которые генерирует база данных), ничего более репозиторий уметь не должен.
Пример:
![1719081449865.png 1719081449865.png](https://yougame.biz/data/attachments/279/279770-77e532d0415077e403076697c8e43f91.jpg)
На самом деле, репозиторий не обязательно должен выглядеть именно так, его внешний вид напрямую зависит от, опять же, используемой спецификации общения бд и приложения.
Сервисы (Services)
Вот это уже поинтереснее. По факту, сервисы являются сердцем любого web приложения, именно они реализуют бизнес логику. Сервис общается только с одним репозиторием, это важно! Если в приложении вы видите такую цепочку зависимостей: Entity->Repository->Service, то это означает, что приложение проектировали осознанные люди :) Старайтесь всегда соблюдать это правило - на один энтити один репозиторий, на один репозиторий один сервис. Если вам нужно обращаться к другим энтити, сделайте межсервисное взаимодействие.
Как раз о нем. Формат общения сервисов друг с другом и с вышестоящими слоями заключается в использовании так называемых DTO - data transfer objects. Это обычные классы, которые так же содержат только собственные поля и базовые методы для работы с ними - геттеры, сеттеры, контроллеры, билдеры и всё, что необходимо сущности для работы с самой собой. DTO бывает двух видов - RequestDTO и ResponceDTO.
RequestDTO содержит только те поля, которые необходимы для выполнения вызова сервисом, ничего более.
ResponceDTO, как правило, содержит в себе отображение Entity, хотя вполне допускается и дополнительная информация.
Контроллер (Controller)
Является слоем, отвечающим за отображение данных service в формат, который понимает клиент. Контроллеры бывают разных типов, как пример RestController - взаимодействует с пользователем при помощи RestAPI.
Я умышленно не буду рассматривать в этой статье положение остальных компонентов системы, так как они не являются обязательными, в отличие от вышеприведенных.
В итоге мы получил следующую иерархию проекта:
Код:
/src
/controller
/service
/repository
/model
/entity
/DTO
/request
/responce
Буду рад услышать комментарии и дополнения к этой статье. До встречи!
Последнее редактирование: