Давным-давно, когда я уже заканчивал университет и был программистом чуть выше младшего уровня, я пришел в новую компанию и получил их организованный, только что из печи, MVP-код.
Код был написан украинским разработчиком, которого я никогда не видел, но полюбил сердцем. Это был не первый раз, когда я видел многоуровневое приложение, но это был лучший из случаев.
Она поместила туда все: чистый слой контроллеров для API, слой сервисов для обработки логики процесса, слой обработчиков для обработки мелких действий, и, конечно, слой DAO для обработки всех вещей в БД. С тех пор все мои будущие проекты следовали ее красивой многослойности, и все было лучше.
Прошло несколько лет, и вот мы с моим партнером уже руководим командой R&D (не интересно и не важно). Как и большинство команд, мы завалены запросами на функции и прочей ерундой, которую руководство считает «КРИТИЧЕСКОЙ». Наша кодовая база все еще достаточно организована с наслоениями, которые мы знаем и любим, но мы начинаем замечать некоторые проблемы (Добавьте драматический звук…).
Каждый раз, когда нам нужно добавить новую CRUD-сущность в систему, даже самую простую сущность для какой-то конфигурации, нам нужно добавить много кода. Мы начинаем с копирования кода существующей сущности, затем:
- Обновляем контроллер с новой сущностью. Очистите неактуальный код.
- Обновляем сервис с новой сущностью, снова. Чистый не относящийся к делу код.
- Обновляем обработчик с новой сущностью, снова… Чистый не относящийся к делу код.
- Обновите DAO с новой сущностью, снова…….. Чистый не относящийся к делу код.
Следующее изображение не для слабонервных. Оно содержит шаблонный код, необходимый для одного из самых простых вариантов использования. Ужас!
Просто написав его и вспомнив старые времена, я устал. И что еще более важно, добавление новой сущности — это легкая часть, теперь у нас больше кода, который нужно поддерживать. Наша кодовая база растет, и внесение изменений в систему становится невозможным.
И вот однажды мы летим на какую-то конференцию, отключившись от всего мира и подключившись к своим внутренним мыслям (без wifi…). Мой партнер приходит ко мне и говорит: «Что если мы разработаем общий CRUD-фреймворк без котельных шаблонов, просто добавим сущность, и все остальное будет доступно через несколько секунд». Сначала я был настроен скептически, но он у нас самый умный, поэтому я еще раз подумал и решил попробовать.
И вот мой партнер и его надежный помощник сдержали свое обещание и после бесчисленных боев и итераций (по сей день) представили свой CRUD-фреймворк, не требующий шаблонов. Я не хочу утомлять вас большим количеством кода, но я просто обязан показать простой пример, чтобы почтить все, что мы потеряли на этом пути.
@Entity
@Table(name = "example")
@DefaultMappingTarget(ExampleDisplay::class)
class Example(
@MappedField
@Column
var exampleString: String?,
@MappedField
@Column
var exampleBoolean: Boolean?,
// ...
) : AbstractJpaEntity()
@DefaultMappingTarget(Example::class)
data class ExampleDisplay(
@MappedField
var exampleString: String? = null,
@MappedField
var exampleBoolean: Boolean? = null,
// ...
) : AbstractJpaDisplay()
@RestController
@RequestMapping("example")
class ExampleController : BaseCRUDController<Example, ExampleDisplay>() {
}
Вот и все! Теперь я знаю, что вы собираетесь мне сказать. Где же ваши слои, о которых вы не могли умолчать?! Самое прекрасное, что все они здесь. За кулисами фреймворка есть все слои, и он позволяет вам использовать хуки и другие механизмы для добавления дополнительной логики/фреймворка/…
С тех пор умные ребята добавили разрешения, безопасность и многое другое поверх CRUD-фреймворка, в соответствии с требованиями каждого проекта.
Итак, ваша следующая мысль, вероятно, «Где мне подписаться?». Придержите коней на минутку, я знаю, что ваша честная текущая мысль о том, что я глуп и ничего не знаю, справедлива. Также я был бы рад предоставить вам CRUD-фреймворк, но он не готов к работе с открытым исходным кодом. Если вы хотите взглянуть на него, он доступен здесь.
Поскольку это большой фреймворк, и потребуется время, чтобы довести его до уровня, который мы хотим получить для выпуска с открытым исходным кодом, мы решили начать с малого и выделить наши возможности отображения объектов в отдельную библиотеку. Конечно, самым сложным было найти название для этой библиотеки, но в итоге мы остановились на ShapeShift.
Если вы не знаете, что такое объектное отображение и зачем оно вам нужно, вы можете прочитать об этом здесь.
Если у вас есть какие-либо мысли/замечания/осуждения, которые вы хотели бы бросить в меня, я буду более чем счастлив пообщаться.