I played around with it and molten is awesome. Still not sure, whether type hints are pythonic or not, but this gave me another tilt towards finding it perfectly suitable, especially for the web dev use case.
This specific usage of the type annotations is nice in terms of visual clutter, but I think that it will require extra cognitive work to understand and write the code.
I disagree, type hints are awesome especially for things like this.
Usually, when your route takes e.g. a user_id you either have to use the right regex (in Django’s urls.py) or remember to validate it yourself in every route. Screw up once -> boom.
Molten, similar to Rocket for Rust, makes sure that you’re handler is only called when the passed user_id is a valid integer (assuming user_id: int).
This becomes even more valuable with more complex types.
I agree that type hints can be useful to make sure that these kinds of bugs are taken care of easily. But the way it is used in the Todo example is that the TodoManager class is passed as an annotation in the methods “list_todos” and “get_todos” . Why not just use a keyword argument for this?
That “just” makes the problem seem less complicated than it really is! :D
Let’s say you’re using a framework like falcon that doesn’t provide DI support out of the box. Assuming you wanted to
be able to swap out the implementation of todo manager easily in your tests and
avoid global state and mocking,
then your API might look something like this:
from falcon import API
# Define Database and TodoManager here...
class TodosResource:
def __init__(self, todo_manager):
self.todo_manager = todo_manager
def on_get(self, req, resp):
resp.media = self.todo_manager.get_all()
def setup_app(db_impl=Database, todo_manager_impl=TodoManager):
db = db_impl()
todo_manager = todo_manager_impl(db)
app = API()
app.add_route("/todos", TodosResource(todo_manager))
return app
# In your entrypoint:
app = setup_app()
# In your tests:
app = setup_app(db_impl=StubDatabase)
This isn’t bad and it’s explicit, but manually configuring the dependency tree can get quite hairy over time and when a particular component’s dependencies change, rather than only changing that component’s code to depend on different deps, you’ll have to also change all of the places where the dependency tree is constructed (not a huge deal if you have this sort of setup_app function like I’ve got above, but not a particularly fun thing to do either way). Another downside here is that it’s not immediately clear what components the TodosResource.get method relies on from its header.
If, instead, you use type annotations to do the wiring for you then you get the best of all worlds in exchange for a little bit of magic (that, in my experience, people get used to fairly quickly).
Yeah, I was reminded a lot of Rocket when I was reading the examples. Which is a good thing. There are a lot of things in Rocket I wish I was able to do more transparently in Django.
I played around with it and molten is awesome. Still not sure, whether type hints are pythonic or not, but this gave me another tilt towards finding it perfectly suitable, especially for the web dev use case.
This specific usage of the type annotations is nice in terms of visual clutter, but I think that it will require extra cognitive work to understand and write the code.
I disagree, type hints are awesome especially for things like this.
Usually, when your route takes e.g. a user_id you either have to use the right regex (in Django’s urls.py) or remember to validate it yourself in every route. Screw up once -> boom.
Molten, similar to Rocket for Rust, makes sure that you’re handler is only called when the passed user_id is a valid integer (assuming
user_id: int).This becomes even more valuable with more complex types.
I agree that type hints can be useful to make sure that these kinds of bugs are taken care of easily. But the way it is used in the Todo example is that the TodoManager class is passed as an annotation in the methods “list_todos” and “get_todos” . Why not just use a keyword argument for this?
That “just” makes the problem seem less complicated than it really is! :D
Let’s say you’re using a framework like falcon that doesn’t provide DI support out of the box. Assuming you wanted to
then your API might look something like this:
This isn’t bad and it’s explicit, but manually configuring the dependency tree can get quite hairy over time and when a particular component’s dependencies change, rather than only changing that component’s code to depend on different deps, you’ll have to also change all of the places where the dependency tree is constructed (not a huge deal if you have this sort of
setup_appfunction like I’ve got above, but not a particularly fun thing to do either way). Another downside here is that it’s not immediately clear what components theTodosResource.getmethod relies on from its header.If, instead, you use type annotations to do the wiring for you then you get the best of all worlds in exchange for a little bit of magic (that, in my experience, people get used to fairly quickly).
I hope that makes sense!
Yeah, I was reminded a lot of Rocket when I was reading the examples. Which is a good thing. There are a lot of things in Rocket I wish I was able to do more transparently in Django.