More precise types in BaseService#821
Conversation
|
@kazqvaizer @nvo87 @e-stepanov @nkiryanov |
Мне кажется может даже помещать — бывает, что хочу, чтоб сервис возвращал не связанный с вызовом тип или ничего не возвращал ( @dataclass
class OrderCreator(BaseService):
def act(self) -> Order:
...
order = OrderCreator()()
reveal_type(order)Вот чего мне в сервисе не хватает, но получается сложным и не уверен, что нужно в базовый шаблон:
|
|
@nkiryanov спасибо, что подчеркнул важные нюансы!
Это да, но внутри редактора с этим не всегда порядок. Зря я на mypy гнал, проблема судя по всему только для LSP чтобы на лету типы показывать.
В случае если у нас такой сервис с сайдэффектом, который ничего не возвращает можно сделать вот так: А в старой реализации IDE опять думает, что там Any: С нас вроде как не убудет от таких изменений, но бонусом получим лучшую поддержку LSP в редакторах. А по теме списка ошибок и вообще более глубокой работы с ними, я бы вынес на обсуждение вообще Result паттерн популярный в Rust/Gleam/прочие около фп языки. С типами дружит, всякие Есть либа для питона , базовый пример оттуда: from returns.result import Result, Success, Failure
def find_user(user_id: int) -> Result['User', str]:
user = User.objects.filter(id=user_id)
if user.exists():
return Success(user[0])
return Failure('User was not found') # ВОТ ТУТ можно enum | list[enum] для ошибок пихать как вариант
user_search_result = find_user(1)
# => Success(User{id: 1, ...})
user_search_result = find_user(0) # id 0 does not exist!
# => Failure('User was not found')Я фанат такой темы, но это сильно нас к фп толкает (а я и не против). Зато решает проблему с не очень четкими ошибками, размазанными по коду. Ну и сам паттерн уже опробованный и доказавший свою состоятельность. Я б это отдельно обсудил, может даже уже внутри bc (но если идея нравится, то у меня в голове уже есть примерная реализация базового сервиса и валидаторов по этому принципу) |
Я бы забил: думать потом ещё почему это тут появилось + может докрутят типы или LSP.
Я бы посмотрел: мне нравится идея Result + слышал хорошие отзывы. |
Понимаю тебя. Но у меня прям внутренний перфекционист плакать начинает от того, что в шаблонном сервисе, который везде переиспользуем, типы выводятся через Any неявно 😅 Интересно, что у нас ребята еще скажут по этой теме, ну и по Result тоже особенно интересно 👀 |
|
Видел уже несколько итераций приправить python функциональщиной вроде Result и пока ни одна из них не прижилась, по моим наблюдениям, потому что плохо бьется с семантикой python и не поддерживается нативно. Т.е. точно не стоит добавлять это в базовый шаблон. Если что, я не против попробовать, только нужно выбрать более живую либу, эта не коммитилась уже год. Ну и надо поставить четкую задачу, которую решаем, мол "так вот было до - это плохо,а теперь делаем так, это хорошо потому-то" |
Сходу мне сложно сказать, станет хуже или лучше. Я бы пожил на каком-то проекте и посмотрел. В целом в Pycharm мне вроде это не беспокоило никогда (но я не сильно упарываюсь по типизации).
2 года назад Никита Соболев в курсе по типизации (у Феди в школе) давал returns - вот [тут] запись (https://youtu.be/InHDRsjWmhs?t=3114) подробный его пример. Сама идея выглядит очень круто, но когда попробовал делать домашки - мозгу реально больно и очень не привычно. Я тогда подумал, что многим это тоже будет не привычно и непонятно сначала - и это лишний порог вхождения для будущих сотрудников, поэтому так и оставил эту идею с ФП. Прикольно, что ты тоже предложил такой вариант! |
У меня проблем с Any в базовом сервисе не возникало, но я вообще не пользуюсь поддержкой типов на уровне LSP. Но я не против добавить сюда Generic на возвращаемый тип. Единственно, попробывать бы для начала на каком-то реальном проекте, уже с нормальной кодовой базой. Порой с типами, особенно дженериками, у меня возникают проблемы в довольно неожиданных местах.
Я тоже слушал Никиту на эту тему, хотя домашки на курсе по типизации не делал :) Честно, я не увидел сильного профита от такого подхода. Несколько лет назад использовал его на котлине, но там меня напрягали постоянные switch конструкции: код получался слишком развесистым. Согласен с @kazqvaizer, что если ты видишь конкретное место для применения, то было бы интересно опробовать в качестве эксперимента. |
Я на текущем проекте у себя добавил дженерик в базовый класс. Кодовая база ни сильно большая, но сервисов много, в т.ч. всякие вложенные друг в друга. И проблем не встретил. Единственное отличие от варианта в этом PR'е - у меня питон 3.11 со старым синтаксисом дженериков, чуть более массивном, чем тут. А так всё здорово. |
Тогда я не против дженерика в базовом сервисе. |
208c604 to
494a557
Compare




Добавил точный вывод возвращаемого типа для вызовов сервисов вместо Any. (до этого всегда брался Any из базового класса)
Как-то лёг глаз на то, что не совсем корректная сигнатура у
__call__иactу нас была, и решил поправить.До этого проблем не было из-за всеядного
Any, но и вывода типа из вызова SomeService()() не было нормального, а теперь вывод типов будет точным.Мелочь, а приятно.