Pull to refresh
1
0
Send message

Наконец удалось выкроить время и посидеть над собственной имплементацией)
Вот репозиторий, сильно не увлекался оформлением 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)

Также позволил себе переписать вашу реализацию на свой лад чтобы лучше вникнуть в имплементацию, если интересно - могу поделиться репозиторием после шлифовки :)

Information

Rating
Does not participate
Registered
Activity