Compare with DIs in frameworks¶
Aiogram¶
Implicit VS explicit
Aiogram’s Dependency Injection makes injection in implicit way - they are created outside of handler context, so it is hard to tell where values came from. Also, to make it create only required values you need to do more work using flags, including validating & handling these flags all by yourself. The more your project grow, the more this abstraction leads to unclear, harder-to-debug code.
Let’s take a look:
from aiogram import Router, F
from aiogram.types import Message
from src.models import User
router = Router()
@router.message(F.text = "/whoami", flags={"requires": {User: "user"}})
async def on_whoami(message: Message, user: User):
pass
This code shows problem in detail:
I can’t tell where parameter user is created, neither is it created properly.
Also, I can set any values into flags and get no error at bot start.
How this looks with FunDI:
from fundi import from_
from src.models import User
from src.dependencies import require_user
async def on_whoami(user: User = from_(require_user)):
pass
FunDI makes it clearer. You can understand from where values came and where they are created. No flags, no implicit injection.
Yes, FunDI also supports implicit injection with scope. But also makes it much easier to debug
because, it tells you which function from which module requires value that was not passed to scope.
FastAPI¶
Request dependent VS fully independent
FunDI is similar to FastAPI’s Dependency Injection(because it was inspired by FastAPI). It has only one problem - you can’t use it outside of Request scope. FunDI was created to cover this issue and successfully does this job.
Summary¶
Is |
FunDI |
Aiogram |
FastAPI |
|---|---|---|---|
Implicit |
Optionally |
Yes |
Partially |
Independent |
Yes |
No |
No |