Fork me on GitHub
#clojure-russia
<
2019-01-21
>
kuzmin_m19:01:46

Привет. Я недавно спрашивал, как девать хитрые валидации на 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 Что думаете?

dottedmag20:01:46

Я заметил, что ключи типа :en в картах очень плохо куда угодно ложатся.

dottedmag20:01:00

Если только это не ключ->значение последнего уровня.