tgoop.com »
United States »
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc. » Telegram Web
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Pattern Specification можно реализовать парой строчек кода, в случае использования JSONB поля для хранения агрегата, путем применения jsonpath. Для реализации метода IsSatisfiedBy подойдет, например, - https://jsonpath2.readthedocs.io/en/latest/ А для компиляции…
С какими трудностями я обычно сталкивался в своей практике при реализации Specification Pattern?
1. Расслоение, если мы хотим применять его как для фильтрации объектов в оперативной памяти, так и в БД. Обычно эта проблема решается через Expression Tree, но в Golang такой опции нет, что, правда, легко обходится самодельным синтаксическим деревом.
При этом возникает вопрос о том, должна ли логика предиката реализовываться в виде интерпретатора на основе Expression Tree или дублироваться хардкодно?
2. Когда агрегаты храняться в JSONB колонке БД, обычно проблем не возникает, и мы можем применить коробочные реализации JSONPath.
Трудности возникают когда сущности агрегата хранятся в отдельных табличках без использования JSONB.
В частности, структура таблиц и структура агрегата нередко отличаются. Например, агрегат часто использует композитные первичные ключи и композитные ValueObjects. Это означает, что синтаксическое дерево для предиката агрегата будет отличаться от синтаксического дерева для запроса в БД. Т.е. просто так "коробку" прикрутить не получится. И мне известны только единичные специалисты, обладающие достаточной квалификацией, чтобы написать код трансформации одного дерева в другое.
3. Большинство коробочных интерпретаторов для Expression Tree, которые можно приспособить для реализации Specification Pattern, умеют оперировать только примитивными типами данных, и без существенной доработки не умеют совершать операции над ValueObjects, особенно, если язык программирования не поддерживает перегрузку операторов.
4. Инкапсуляция агрегата. Это отдельный большой вопрос, который часто обсуждается в отрасли и уже не раз обсуждался мной. Чаще всего для извлечения защищенного состояния агрегата используются:
1. Общие области видимости (как в Golang) или дружественные классы (C++).
2. Mediator Pattern (описан в красной книге Vaughn Vernon).
3. Рефлексия (нередко используется в коробочных решениях, особенно в ORM).
4. Memento Pattern, хотя и часто называют, но ошибочно, если внимательно разобраться.
5. Самая любимая моя проблема - это предикаты к атрибутам коллекции сущностей агрегата с использованием Expression Tree.
Как выразить в Expression Tree следующее условие:
хотя бы одна из сущностей коллекции агрегата имеет значение "x" атрибута "a" и значение "y" атрибута "b", или хотя бы одна из сущностей той же коллекции имеет значение "j" атрибута "с"?
Ничего не получится, если напишем нечто подобное:
Кажется, такое ни одна коробка не умеет, за исключением операторов wildcard "*" и локального елемента "@" в JSONPath. Собственно, оттуда я и перенял решение:
Если скомпилировать это выражение в SQL запрос к обычным реляционным табличкам (без JSONB), то получится два JOIN.
Не знаю, можно ли выразить нечто подобное с помощью LINQ в C# (если да, то сообщите, пожалуйста, в комментарии).
Когда должно вернуть true следующее выражение:
Когда совпадает хотя бы один элемент в обоих подмножествах, или когда оба подмножества эквиваленты?
Нет ничего сложного в реализации Specification Patrern on Expression Tree, если обладать достаточным опытом и квалификацией. Реализация занимает всего несколько сотен строк кода.
Сложно найти/подготовить такого специалиста в команду.
1. Расслоение, если мы хотим применять его как для фильтрации объектов в оперативной памяти, так и в БД. Обычно эта проблема решается через Expression Tree, но в Golang такой опции нет, что, правда, легко обходится самодельным синтаксическим деревом.
При этом возникает вопрос о том, должна ли логика предиката реализовываться в виде интерпретатора на основе Expression Tree или дублироваться хардкодно?
2. Когда агрегаты храняться в JSONB колонке БД, обычно проблем не возникает, и мы можем применить коробочные реализации JSONPath.
Трудности возникают когда сущности агрегата хранятся в отдельных табличках без использования JSONB.
В частности, структура таблиц и структура агрегата нередко отличаются. Например, агрегат часто использует композитные первичные ключи и композитные ValueObjects. Это означает, что синтаксическое дерево для предиката агрегата будет отличаться от синтаксического дерева для запроса в БД. Т.е. просто так "коробку" прикрутить не получится. И мне известны только единичные специалисты, обладающие достаточной квалификацией, чтобы написать код трансформации одного дерева в другое.
3. Большинство коробочных интерпретаторов для Expression Tree, которые можно приспособить для реализации Specification Pattern, умеют оперировать только примитивными типами данных, и без существенной доработки не умеют совершать операции над ValueObjects, особенно, если язык программирования не поддерживает перегрузку операторов.
4. Инкапсуляция агрегата. Это отдельный большой вопрос, который часто обсуждается в отрасли и уже не раз обсуждался мной. Чаще всего для извлечения защищенного состояния агрегата используются:
1. Общие области видимости (как в Golang) или дружественные классы (C++).
2. Mediator Pattern (описан в красной книге Vaughn Vernon).
3. Рефлексия (нередко используется в коробочных решениях, особенно в ORM).
4. Memento Pattern, хотя и часто называют, но ошибочно, если внимательно разобраться.
5. Самая любимая моя проблема - это предикаты к атрибутам коллекции сущностей агрегата с использованием Expression Tree.
Как выразить в Expression Tree следующее условие:
хотя бы одна из сущностей коллекции агрегата имеет значение "x" атрибута "a" и значение "y" атрибута "b", или хотя бы одна из сущностей той же коллекции имеет значение "j" атрибута "с"?
Ничего не получится, если напишем нечто подобное:
agg.ent[*].a == x && agg.ent[*].b == y && agg.ent[*].c == j
Кажется, такое ни одна коробка не умеет, за исключением операторов wildcard "*" и локального елемента "@" в JSONPath. Собственно, оттуда я и перенял решение:
agg.ent[*] ? (@.a == x && @.b == y) || agg.ent[*].c == j
Если скомпилировать это выражение в SQL запрос к обычным реляционным табличкам (без JSONB), то получится два JOIN.
Не знаю, можно ли выразить нечто подобное с помощью LINQ в C# (если да, то сообщите, пожалуйста, в комментарии).
Когда должно вернуть true следующее выражение:
agg.ent1[*].a == agg.ent2[*].a
?Когда совпадает хотя бы один элемент в обоих подмножествах, или когда оба подмножества эквиваленты?
Нет ничего сложного в реализации Specification Patrern on Expression Tree, если обладать достаточным опытом и квалификацией. Реализация занимает всего несколько сотен строк кода.
Сложно найти/подготовить такого специалиста в команду.
Telegram
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Pattern Specification можно реализовать парой строчек кода, в случае использования JSONB поля для хранения агрегата, путем применения jsonpath.
Для реализации метода IsSatisfiedBy подойдет, например,
- https://jsonpath2.readthedocs.io/en/latest/
А для компиляции…
Для реализации метода IsSatisfiedBy подойдет, например,
- https://jsonpath2.readthedocs.io/en/latest/
А для компиляции…
👍6👏2❤1🔥1