Наконец удалось выкроить время и посидеть над собственной имплементацией) Вот репозиторий, сильно не увлекался оформлением https://github.com/Neznakomec16/job_scope
Из явных отличий, я не стал разбираться с crud билдером. Убрал функциональные тесты, т.к они повторяют то что вы делаете в интеграционных тестах. В целом это больше похоже на апи тесты, а не функциональные. Так же со своей интерпритацией сделал работу с бд. Плюс не сильно вникал в то как работает остальная инфраструктура, добился просто того чтобы инфра поднималась.
Если будет интересно пообщаться насчёт решений - буду рад ответить в личке или тут в комментах)
Спасибо за статью. Почерпнул для себя несколько идеи из Вашей работы. Работаю с использованием чистой архитектурой, в частности с DDD+TDD последние 2 года, наблюдаю сильное ускорение по доставки кода на среды с использованием этого подхода. Не согласен с ораторами, которые говорят что ЧА - избыточно. Везде можно найти (или постоянно находиться в поиске) золотую середину, что, кажется, и было показано в этой статье
В Вашем видении сразу бросается в глаза зависимость от внешних библиотек (pydantic) в domain слое. Это добавляет одну неприятную ответственность из презентационного слоя - валидацию (и десериализацию в случае AnyUrl). Я убежден что эту ответственность лучше делегировать точкам входа, таким как fastapi или обработчики faststream. К тому же в моей практике на тренировочных проектах с похожей реализацией пробовал переезжать с pydantic v1 на v2 и случилась боль обратной совместимости.
По поводу мапперов обычно я позволяю модели бд иметь classmethod from_domain, куда приходит доменная сущность как аргумент и to_domain чтобы модель бд могла конвертироваться в доменную сущность. Это даёт удобство абстрагирования маппинга в миксин, построение связи между моделью и сущностью. Пока не нашёл противоречий в таком подходе. К тому же это позволяет быстро использовать методы orm
async def update(self, user_data: User) -> User:
"""Update user fields based on input data.
:param user_data: Domain model containing updated user fields.
:return: Updated user as a domain model.
"""
obj = UserDB.from_domain(user_data)
await self._session.merge(obj)
await self._session.flush()
return obj.to_domain()
(Возможно стоит делать запрос по pk перед merge чтобы выбрасывать ошибку UserNotFound)
Также позволил себе переписать вашу реализацию на свой лад чтобы лучше вникнуть в имплементацию, если интересно - могу поделиться репозиторием после шлифовки :)
Наконец удалось выкроить время и посидеть над собственной имплементацией)
Вот репозиторий, сильно не увлекался оформлением https://github.com/Neznakomec16/job_scope
Из явных отличий, я не стал разбираться с crud билдером. Убрал функциональные тесты, т.к они повторяют то что вы делаете в интеграционных тестах. В целом это больше похоже на апи тесты, а не функциональные. Так же со своей интерпритацией сделал работу с бд. Плюс не сильно вникал в то как работает остальная инфраструктура, добился просто того чтобы инфра поднималась.
Если будет интересно пообщаться насчёт решений - буду рад ответить в личке или тут в комментах)
Спасибо за статью. Почерпнул для себя несколько идеи из Вашей работы. Работаю с использованием чистой архитектурой, в частности с DDD+TDD последние 2 года, наблюдаю сильное ускорение по доставки кода на среды с использованием этого подхода. Не согласен с ораторами, которые говорят что ЧА - избыточно. Везде можно найти (или постоянно находиться в поиске) золотую середину, что, кажется, и было показано в этой статье
В Вашем видении сразу бросается в глаза зависимость от внешних библиотек (pydantic) в domain слое. Это добавляет одну неприятную ответственность из презентационного слоя - валидацию (и десериализацию в случае AnyUrl). Я убежден что эту ответственность лучше делегировать точкам входа, таким как fastapi или обработчики faststream. К тому же в моей практике на тренировочных проектах с похожей реализацией пробовал переезжать с pydantic v1 на v2 и случилась боль обратной совместимости.
По поводу мапперов обычно я позволяю модели бд иметь classmethod from_domain, куда приходит доменная сущность как аргумент и to_domain чтобы модель бд могла конвертироваться в доменную сущность. Это даёт удобство абстрагирования маппинга в миксин, построение связи между моделью и сущностью. Пока не нашёл противоречий в таком подходе. К тому же это позволяет быстро использовать методы orm
(Возможно стоит делать запрос по pk перед merge чтобы выбрасывать ошибку UserNotFound)
Также позволил себе переписать вашу реализацию на свой лад чтобы лучше вникнуть в имплементацию, если интересно - могу поделиться репозиторием после шлифовки :)