-
Notifications
You must be signed in to change notification settings - Fork 39
More precise types in BaseService #821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
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()() не было нормального, а теперь вывод типов будет точным.Мелочь, а приятно.