Pull to refresh

Comments 10

Здравствуйте, спасибо за статью

А как в рамках концепций из статьи относитесь к декортатору dataclass и их методу "__post_init__"?

Часто встречал в коде, что "математику" располагают там.

Заранее, спасибо

Здравствуйте. Рад, что статья оказалась интересной для вас)

По поводу post_init: Нужно смотреть конкретные примеры, что там происходит.

Если там происходит создание новых полей на основе тех, которые пришли в init, то в рамках эволюции при создании объекта, мне такой подход нравится меньше.

Если условная фабрика полностью конструирует объект, то post_init как будто доделывает чью-то работу. Выходит, что он не забирает на себя всю сложность создания. Эта сложность размазывается между init и post_init.

Учитывая, что они неразрывно связаны, то получается, что это то же самое, что, если бы мы в конце init вызывали post_init(За нас в данном случае это делает механизм dataclass)

Подытожу: При написании бизнес-логики я бы старался не использовать post_init для целей создания одних полей на основе других или валидации данных.

Но не забывайте о том, что как dataclass, так и архитектура кода, это инструменты, которые мы используем для решения бизнес задач.

Поэтому всем нам нужно учиться балансировать между "качеством кода" и "скоростью разработки". Далеко не всегда есть время писать так, как правильно, но лучше осознано оставлять тех долг, чем неосознанно писать некачественный код.

Большое спасибо за такой подробный и обстоятельный ответ. Подчерпнул для себя, как из статьи много дельных мыслей

Поэтому всем нам нужно учиться балансировать между "качеством кода" и "скоростью разработки".

Тоже для себя по опыту работы сделал для себя такой вывод. Кратко для себя и коллег всегда говорю: "Что в каждом случае нужно о ужас думать?. Ну или хотя бы задумываться, а не слепо следовать, каким-то парадигмам".

Про dataclass уже сказали. Сам pydantic не пользовался, но вот примерный псевдокод:

from typing_extensions import Self
from pydantic import BaseModel, ValidationError, model_validator

class PriceRequestData(BaseModel):
    method: str
    path: str
    content_type: ContentTypeEnum
    data: dict[str, Any] | None = None
    headers: dict[str, Any] | None = None

    @field_validator('method')
    @classmethod
    def clean_method(cls, value: str) -> str:
        if value not in ('POST'), 'GET'):
            raise ValueError('Method name not valid.')
        return value

    @model_validator(mode='after')
    def clean(self) -> Self:
        if self.method == 'POST' and not self.headers.get('X-authorization-id'):
            raise ValueError('Authorization headers not found.')
        return self

Я стараюсь не тащить сторонние библиотеки в бизнес-логику.

Для меня DTO не должен быть валидатором и сериализатором.

В контроллере или адапторах да, без проблем. В бизнес логике только DTO, value object, entity, которые являются простыми классами или dataclass

Может быть и зря. Оборачивать каждый класс в фабрику и размазывать логику по фабрике выглядит странным. Например, в расте принят интересный подход: объект можно сконструировать только через статический метод try_new, если у вас объект создан, то можно всегда гарантировать, что его состояние корректно (все поля проверены итд). Для этого и существует система типов.

У вас же класс кто-нибудь может импортировать напрямую и сконструировать объект не через фабрику. И потом: ой, разве здесь не должно быть валидаторов? Что-то в другой системе теперь null.

Конструируйте без фабрики, нет проблем. Клас лишь ожидает пачку примитивов, если вы смогли их получить без фабрики, то пожалуйста. Но тогда вы будете нарушать dry.

Я лишь показал свой путь эволюции при усложнении создания объектов.

А так да, большинство механизмов(репозитории, клиенты, источники и т п) имеют фабрики для создания, что бы не перегружать контроллер этой работой

Возможно у вас большие и сложные проекты где мой подход кажется вам плохим. В компании где я работаю используется микросервисная архитектура, и мы отлично справляемся с ценностями чистой архитектуры(Мартин), и не тянем сторонние библиотеки в бизнес-логику.

Если так рассуждать, можно и Джанго модели считать DTO? Повторюсь, для меня pydantic это валидация и сериализация.

Мне кажется, если мои объекты изначально на pydantic, то нехотя бизнес-логика может начать готовить ответ сразу клиенту прямо в бизнес-логике, примешивая уровень презентации.

И я не предлагаю серебряную пулю. Я рассказываю свою историю. Я так делаю и для меня это работает :)

Может быть у вас был другой опыт, и вы нашли лучшее или просто другое решение, которое вас устраивает. Это хорошо!)

А по поводу того, что кто-то может не так использовать код - да, может. Я не боюсь этого. Мы специалисты не просто так, ну и никто не отменяет анализаторов и подсветки idea, которые решают 99% подобных проблем, если вы качественно аннотируете код :)

В копилку к тому, что кто-то, что-то сделает не так - мы применяем TDD при разработке, и вполне уверены в коде который пишем )

Интересная статья, кое-что обязательно возьму на вооружение.

Единственная просьба - орфография (как в "Нелюбой объект в коде") и пунктуация, которая порой сбивает с мысли.

Спасибо, поправил. Прогоняю статью после написания через сервис. Не везде могу точно сказать, как будет правильнее(мой минус).

Sign up to leave a comment.

Articles