Привет. Я недавно спрашивал, как девать хитрые валидации на clojure.spec. Вот, что у меня получилось. Сущности можно по-разному моделировать, можно использовать мапы, можно рекорды. У меня сущности сгруппированы по агрегатам. Агрегат имеет корневую сущность. Агрегат целиком извлекается и сохраняется. Агрегат проверяет свою целостность. И я изначально хотел использовать для этого простые мапы. И тут возникают вопросы. 1) как сделать отображение мапы на строчку в бд? Эта мапа может быть вот такой:
{:id 1
:state :draft
:translations {:en {:title "text"
:summary "text"}
:ru {:title "text"}}}
И появляется хитрый маппер, который переводит это в плоскую структуру и обратно
{:id 1
:state :draft}
{:lang :en
:title "text"
:summary "text"}
{:lang :ru
:title "text"}
2) Для удобства работы с БД, формами и т.п. хочется для вложенных сущностей иметь идентификаторы,
уникальные в контексте агрегата. Их нужно самому генерировать. В пример выше идентификатор (ru/en)
вообще находится снаружи сущности.
3) хочется использовать clojure.spec, т.к. он будет стандартом. Но он плохо справляется с вложенностью
и плохо подходит для валидации, особенно когда валидация зависит от состояния сущности.
4) сложно валидировать, т.к. нужно выдать путь до ошибочного значения.
Т.е. у значения должен быть идентификатор, например путь до этого значения.
А что, если так случилось, что в агрегате сущности связаны циклически?
5) хочется контролировать изменения агрегата и проверять его целостность.
Мапы/рекорды имеют несколько “изменяющих” функций, вроде assoc, dissoc, update, update-in, merge.
По этому проверки делаются с помощью валидаторов атомов, рефов, хранящих сущность.
В итоге я взял datascript.
Он “реляционный“. Каждая сущность плоская, без вложенности и легко мапится на строчку в БД.
Каждая сущность имеет автоматически генерируемый идентификатор.
Каждое значение можно однозначно идентифицировать по идентификатору и аттрибуту,
для :db.cardinality/many
нужно добавить само значение.
Есть отличный язык запросов.
Все обновления идут через один метод.
+ https://github.com/darkleaf/publicator-ext/blob/master/core/src/publicator_ext/domain/abstractions/aggregate.clj
+ https://github.com/darkleaf/publicator-ext/blob/master/core/src/publicator_ext/domain/aggregates/publication.clj
+ https://github.com/darkleaf/publicator-ext/blob/master/core/src/publicator_ext/domain/aggregates/article.clj
+ https://github.com/darkleaf/publicator-ext/blob/master/core/src/publicator_ext/domain/errors.clj
Что думаете?Я заметил, что ключи типа :en
в картах очень плохо куда угодно ложатся.
Если только это не ключ->значение последнего уровня.