-
Notifications
You must be signed in to change notification settings - Fork 220
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
On modularity & reusable ASGI components #99
Comments
I like this as a goal, but I don't think we need to put too much focus on it, early on. |
Sure. To me it's super important, because it's potentially the difference between "let's design monolithic frameworks that have to completely own the space to succeed" vs. "let's build a better ecosystem, throughout". I think ASGI has a tremendous opportunity here to build a more collaborative ecosystem, and establish patterns whereby high-level frameworks are composed of nicely isolated units. For example, if responder designs it's request and response models like so... class Request:
def __init__(self, scope, receive):
... class Response
def __init__(self, scope):
...
async def __call__(self, receive, send):
... Then they become nicely reusable in any ASGI app. You can drop all the way down to writing a simple "hello, world" ASGI application, without any of the rest of responder, but using a from responder.models import Request, Response
# I'm a standard ASGI app, you can run me directly with `daphne`, `uvicorn`, or `hypercorn`.
# You can test me with any standard ASGI TestClient.
# You can wrap me in middleware, or dispatch to me from any ASGI framework's routing.
class HelloWorld:
def __init__(self, scope):
self.scope = scope
async def __call__(self, receive, send):
request = Request(self.scope, receive)
response = Response(self.scope)
... # Do stuff
await response(receive, send) Working at those lower levels of abstraction isn't necessarily what most of us would be doing day-to-day, most of the time, but being able to is super important, and breaks down the "I need to understand how the complete framework functions in order to understand one of it's components" I think it's important to start thinking about at least reasonably early on, otherwise you start introducing points of coupling that later become entrenched. (I'll park these thoughts for now) |
So I've been following a general approach with the design of Starlette, that I'd love to see Responder follow on with. The aims are to keep complexity nicely bounded into smallish components, that then end up being reusable across different ASGI frameworks. Some examples:
So, none of this means that you can't at the top level have an application interface that exposes a single point of configuration, but under the hood it all ends up just being composition of small nicely bounded components and middleware.
Places where this could be applied to responder:
on_request(req/resp)
interface stuff be implemented as a tiny ASGI app. It's independently usable/testable, you can apply middleware to individual views, you can reuse it in other frameworks, or you can use it as the basis for writing alternate class based view implementations (without the implementation all being tightly bound to the rest of the application class)The text was updated successfully, but these errors were encountered: