This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-21
Channels
- # announcements (1)
- # architecture (1)
- # beginners (125)
- # boot (6)
- # boot-dev (2)
- # calva (69)
- # cider (38)
- # cljs-dev (3)
- # clojure (212)
- # clojure-austin (7)
- # clojure-australia (1)
- # clojure-denver (2)
- # clojure-europe (3)
- # clojure-gamedev (1)
- # clojure-hamburg (8)
- # clojure-italy (10)
- # clojure-nl (31)
- # clojure-russia (3)
- # clojure-uk (57)
- # clojurescript (56)
- # core-async (3)
- # cursive (15)
- # datascript (1)
- # duct (28)
- # emacs (6)
- # events (1)
- # figwheel-main (11)
- # fulcro (22)
- # luminus (59)
- # lumo (2)
- # onyx (4)
- # overtone (1)
- # re-frame (1)
- # reagent (4)
- # remote-jobs (3)
- # rum (2)
- # shadow-cljs (84)
- # spacemacs (7)
- # speculative (5)
- # vim (1)
- # yada (127)
Привет. Я недавно спрашивал, как девать хитрые валидации на 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
Что думаете?