Как разделить логику домена и доступ к данным в Grails

Как я могу разделить логику домена и доступ к данным в Grails (и это хорошая идея)?

Многие программные приложения, которые мы пишем, в большей степени ориентированы на данные (базу), а в Grails часто сохраняются от классов обслуживания или контроллеров непосредственно к базе данных, настроенной в DataSource.groovy. Изменить базу данных легко, но на самом деле мы не зависим от реализации персистентности в коде.

Я пытаюсь написать приложение, открывающееся для различных реализаций сохраняемости и источников данных (не только базы данных), и фокусирующееся на бизнес-области, а не на объектах базы данных. Это также плюс при тестировании (легко написать фальшивую / имитацию персистентности). Изначально у меня есть только одна реализация персистентности - классы домена Grails, использующие GORM. Но есть вероятность, что в будущем я хотел бы иметь другие источники данных, кроме базы данных, например службы отдыха или что-то еще.

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

Я не очень доволен этим решением. Я могу придумать как минимум два возможных улучшения / изменения:

  1. Мои классы предметной области Grails могли бы быть организованы более иначе, чем классы предметной области бизнеса, поэтому я не просто копирую свойства из одного класса в другой. Тем не менее, при чтении или записи из / в базу данных это по-прежнему будет включать в себя множество сопоставлений свойств от одного класса к другому.
  2. Может быть, есть способ использовать классы бизнес-домена из обычного пакета src / main / groovy и украсить их вещами GORM? Или как-то иначе разделить логику предметной области и настойчивость? Я видел, что это можно сделать, используя hibernate conf для классов домена. Это единственный способ?

Я видел несколько интересных обсуждений архитектуры Grails, включая чистую архитектуру, гексагональную архитектуру и ddd, но пока не нашел никаких примеров. Есть такие?

На данный момент, как я уже сказал, большая часть функциональности - это CRUD, но не все. Кроме того, в приложении может быть больше бизнес-логики, поэтому я бы предпочел не использовать «стандартную» архитектуру Grails с представлениями, контроллерами, службами и доменом. Мне нужно «базовое» приложение, которое не будет зависеть от представления / контроллеров grails и домена / GORM.


person peter_m    schedule 11.01.2015    source источник
comment
Возможно, я смогу использовать базовый класс и расширить его как в папке домена Grails, так и в папке бизнес-домена ...   -  person peter_m    schedule 11.01.2015
comment
Сам GORM легко подключается, и, как вы, вероятно, знаете, уже существует множество поддерживающих реализаций: Mongo, Hibernate, Neo4j, Redis и т. Д. (См. github.com/grails/grails-data-mapping). Пока вы избегаете HQL и собственного SQL (предпочитаете динамические поисковые системы и поисковые запросы), это возможно перемещаться между реализациями без значительных изменений кода.   -  person Andrew    schedule 12.01.2015
comment
Спасибо за ответ @Andrew. Да, GORM подключаемый, но, если возможно, я стараюсь быть независимым от базы данных как от постоянства. Таким образом, это должен быть репозиторий, который может быть чем угодно (например, имитацией, файловой системой и т. Д.). Возможно, моя модель базы данных вообще не должна выглядеть как бизнес-домен. По крайней мере, я должен это учитывать.   -  person peter_m    schedule 12.01.2015
comment
Хорошо, пара дополнительных мыслей: 1) Взгляните на grails.org/plugin/gorm- rest-client - один из примеров исключительной гибкости GORM; 2) Командные объекты - мощная концепция, которая может помочь в ваших усилиях, см., например: Skillsmatter.com/podcast/groovy-grails/   -  person Andrew    schedule 12.01.2015
comment
Я буду @Andrew. Ценить это! Спасибо.   -  person peter_m    schedule 12.01.2015


Ответы (1)


Прошло некоторое время с тех пор, как вы разместили свой вопрос, но для меня это очень интересная тема ...

В настоящее время я работаю над крупными проектами Java8, которые реализуют, среди прочего, принципы чистой архитектуры, ddd, cqrs и шестиугольной архитектуры. У меня также ограниченный опыт работы с проектами Grails 1.x, и я помню, что задавал те же вопросы, что и вы сейчас.

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

Все, что есть в Grails, предназначено для использования самоуверенным, основанным на соглашениях образом. Начиная с GORM, являющегося реализацией ActiveRecord, и следуя каждому небольшому решению, которое они принимали в отношении структуры каталогов, семантики артефактов, которые вам необходимо определить (контроллеры, службы, модели ...) и т. Д. Я не говорю об этом. плохо. Фактически, это здорово, когда вы разрабатываете что-то, что вписывается в эту схему вещей.

Эта связь и неявное поведение между вашими артефактами действительно затрудняет моделирование вашей бизнес-логики, помимо вашего доступа к данным (или вашего http-взаимодействия, или любого другого взаимодействия с третьими сторонами, если на то пошло).

С точки зрения DDD вам следует отдавать предпочтение репозиториям на основе данных или коллекций, а не реализациям ActiveRecord. Затем вы можете начать отделять логику сохранения от модели предметной области. Попытка сделать это при сохранении взаимодействия типа ActiveRecord с вашим уровнем персистентности приведет к получению очень «грязного» уровня адаптации с большим количеством повторений.

Вам будет очень сложно, особенно при попытке адаптировать сложный домен с агрегированными объектами, которые должны входить, например, в разные таблицы базы данных.

Теперь, обращаясь к двум предлагаемым вами улучшениям, я могу вам о них рассказать:

  1. Мои классы предметной области Grails могли бы быть организованы более иначе, чем классы предметной области бизнеса, поэтому я не просто копирую свойства из одного класса в другой. Тем не менее, при чтении или записи из / в базу данных это по-прежнему будет включать в себя множество сопоставлений свойств от одного класса к другому.

Вы действительно можете делать то, что говорите. Просто поместите код в папку src / groovy. Основная проблема, с которой вы здесь столкнетесь, - это внедрение зависимостей. Grails автоматически внедряет зависимости в ваши сервисы и контроллеры, когда они определены в стандартных каталогах. Для всего остального вам необходимо явно указать Grails, как принимать зависимости и передавать их в пользовательский артефакты.

  1. Может быть, есть способ использовать классы бизнес-домена из обычного пакета src / main / groovy и украсить их вещами GORM? Или как-то иначе разделить логику предметной области и настойчивость? Я видел, что это можно сделать, используя hibernate conf для классов домена. Это единственный способ?

Если вы украсите свои объекты домена, определенные в src / groovy, с помощью GORM (если это вообще возможно), у вас будет такая же проблема. Ваша миссия здесь - изолировать ваш домен от логики сохранения. Выполнение этого с помощью любого GORM в нем не выполняет своего предназначения.

Все, что я считал здесь моим советом, было бы следующим:

  1. переключитесь на другие менее связанные библиотеки, которые позволят вам спроектировать свою собственную архитектуру (например, Ratpack, Jooq) или
  2. Если это не вариант, просто полностью примите методику выполнения задач Grails.

Существует очень полный список библиотек, в которых вы можете найти вдохновение: Awesome Java

person ggalmazor    schedule 14.06.2015
comment
Спасибо за ваши комментарии. Я ценю ваши мысли и думаю, что вы, вероятно, правы, что следует принять путь Грааля. До сих пор я тоже этим занимался. Но я не отказался от этих мыслей :) На самом деле, размещение логики домена в src / main / groovy - это то, что я пробовал, но в этом случае я получил большую часть кода в сервисах - стандартный способ Grails. - person peter_m; 25.07.2015
comment
Некоторые идеи: 1) Можно было бы иметь ddd-подобное решение с логикой домена в src / main / groovy, вызываемое из служб и / или контроллеров Grails, и эта логика могла бы вызывать GORM-материал, который является реализацией интерфейса репозитория? Это потребует копирования данных, но это также относится и к Grails. 2) Если существует взаимно однозначное соответствие между таблицами домена и базы данных, можно поместить классы домена в стандартную папку домена Grails. Затем логику домена можно было бы разделить и поместить в src / main / groovy, а объекты (данные + логика домена) могли бы быть созданы во время выполнения. Есть мысли @ggalmazor? - person peter_m; 25.07.2015