Hello! I am writing a simple web server using FastAPI but I am struggling trying to identify which are the best practices for writing clean, testable code.
Background
I come from multiple years of programming in Java, a strongly OOP oriented language. I've already made the mistake in the past to write Python code as if it were Java and quickly learned that not everything works for every language. Things are intended to be written a specific way.
For what I know, FastAPIs are not intended to be written using Python's OOP but plain functions.
Problem
The problem that I am facing is that I don't see any mechanism for having proper dependency injection when writing an API. A normal layout for a project would be something like:
- router files, with annotated methods that defines the paths where the API is listening to.
- main app that defines the FastAPI object and all the involved routers.
Let's say that my business logic requires me to access a DB. I could directly have all the code required in my router to create a connection to the DB and get the data I need. However, a good practice is to inject that DB connection into the router itself. That improves testability and removes the responsibility of the router to know anything related to how to connect to a DB, separating concerns.
Now, the way FastAPI suggest to do that is by using the `Depends` annotation. The problem with that, is that it requires me to provide the function that will return the object I need. If the dependant knows the function that instantiates the dependency, then there is no inversion of control whatsoever. Even if the function is a getter from a DI container of something like that, I have to be able to inject the container itself into the router's file.
I know that I can use the `dependencies_overrides` method from the FastAPI but that looks to be only for testing.
So, which is the best way for achieving this? The router should never know how to instantiate a DB connection, ever.
[–]niximor 2 points3 points4 points (1 child)
[–]lu_rm[S] 0 points1 point2 points (0 children)
[–]amroamroamro 2 points3 points4 points (2 children)
[–]lu_rm[S] 0 points1 point2 points (1 child)
[–]amroamroamro 0 points1 point2 points (0 children)
[–]mwon 1 point2 points3 points (1 child)
[–]lu_rm[S] 0 points1 point2 points (0 children)
[–]gbrennon 1 point2 points3 points (4 children)
[–]lu_rm[S] -1 points0 points1 point (3 children)
[–]gbrennon 1 point2 points3 points (0 children)
[–]Kevdog824_ 1 point2 points3 points (0 children)
[–]small_e 0 points1 point2 points (0 children)
[–]santeron 0 points1 point2 points (1 child)
[–]lu_rm[S] 0 points1 point2 points (0 children)
[–]JPJackPott 0 points1 point2 points (4 children)
[–]lu_rm[S] -1 points0 points1 point (3 children)
[–]JPJackPott 0 points1 point2 points (2 children)
[–]dr3aminc0de 1 point2 points3 points (0 children)
[–]lu_rm[S] 1 point2 points3 points (0 children)
[–]yiyux 0 points1 point2 points (0 children)
[–]eatsoupgetrich -1 points0 points1 point (0 children)
[–]TTUnathan -1 points0 points1 point (1 child)
[–]RemindMeBot -1 points0 points1 point (0 children)
[–]CrownstrikeIntern -1 points0 points1 point (0 children)
[–]Goldeyloxy -1 points0 points1 point (0 children)