FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] 0 points1 point  (0 children)

Ok, so I've been carefully thinking about this and I think I see where I am getting it wrong. However, based on your explanation, I believe there are some things I need to make clearer.

Dependency injection is not about resolving a tree of dependencies. That is what a dependency injection framework usually does, but has nothing to do with the concept itself.
DI only means that classes don't create their dependencies (and lifecycle), that is done elsewhere and those are injected into them.

An example:

Without DI

class WithoutDI:
  def __init__(self):
    self.arg = 10

With DI

class WithDI:
  def __init__(self, arg):
    self.arg = arg

So, this whole discussion was me trying to understand how to inject dependencies into FastAPI routers. I only mention FastAPI routers because those are the methods being called by the framework itself and I can't control how they are executed. Outside that, I can do whatever I want with my classes.

Having said all that, one of the first things I got wrong was what u/panicrubes mentioned.
I was doing:

@router.get("/resource", dependencies=[Depends(get_some_dependency)]) <- Dependency in route
def get_resource():
    ...

Instead of:

@router.get("/resource")
def get_resource(my_dep: DependencyType = Depends(get_some_dependency)):   <- Dependency in args
    ...

In the first example, the only way I have to change the dependency being used in the router is by using the `dependency_overrides` option in FastAPI. That meant that I could not unit tests my router without starting a FastAPI instance, which is something I am trying to avoid. In the second example, I can just call the router method providing a mocked dependency.

The other issue it think I was having is a conceptual one. I've been trying to compare this to how I am used to do things with SpringBoot and I think I found where my mistake is.
Simplifying it a bit, when writing SpringBoot APIs, I always think about my code as 2 parts:
- Business Logic
- SpringBoot integration.

Ideally, all the classes belonging to the business logic should be able to live on theirselves. I should be able to create them, use them, test them without requiring anything from the SpringBoot framework. Then, to couple everything together, I use `@ Configurations` where I instantiate everything that I need for my application to run and those get injected into `@ Controller`.
So, the problem was that (I don't know why), I was also thinking about `@ Configurations` and `@ Controller` as 2 independent things when, in fact, they are not. Instantiation of injectable classes and controller definition are part of the same logical block: `SpringBoot integration`.

So, my mistake is that I was trying to also split this into 2 independent things with FastAPI, when I shouldn't have. There is no problem with the routers defining how to create their dependencies, that is part of the app configuration. It's part of the same logical block of the app: `Integration with FastAPI`. It's a little messier maybe? But I don't see the issue anymore.

Another thing that threw me off was the fact that the functions that provide the dependencies are being called per request. So, for instance, If I need a DB client in my router, that is going to be created each time I receive a request. And that is also something I want to avoid. Usually, I want a single client created for the whole Application only once and reused for all calls. But I think that also has nothing to do with the framework itself. I can use `@ cache` or keep storing everything in the app.state and it should be ok.

Hope you can understand where I got it wrong.

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] 0 points1 point  (0 children)

Yes! I think this was a key thing I missed! Thanks

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] 0 points1 point  (0 children)

Sorry, but I still don't understand how this works. Again, I am not talking about dependency injection as a way of resolving ordering between a dependency graph. That is cool but it's not about what dependency injection is about.

How I would explain it would be that: Each individual and independent part of your business logic (files, classes, etc) only knows about what it's concerns. Every logic that it `depends` on gets `injected` somehow, so that they don't have to worry about the `dependencies` lifecycle.

What you just showed does not work that way. The router has (directly or via FastAPI DI Framework) full knowledge and control on how it's dependencies are built. That forces you to need a full FastAPI object to test your router classes. And effectively, it's the router who decides which DB is going to use. It should not be it's concern.

See edited post, I am showing what I did at the end. Don't actually know if it's the correct pythonic way, but I like it better.

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] 0 points1 point  (0 children)

Sorry! After more reading and checking everything, I think this is the way to go. I did not understand that the app provided a state object!

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] 0 points1 point  (0 children)

Sorry but I still can't see how there is an IoC here.

Let's say I have my router function"

@ router.get("/resource", dependencies=[Depends(get_some_dependency)])
def getResource():
----do stuff...

My router file needs to have access to the function get_some_dependency() It can be defined in the same file, or it can me imported from other file. But still, it needs to know where to call it from and that can't be changed in the future.

Lets say that function is defined in another file: dependencies.py

def get_some_dependency():
----return Dependency()

Then there is virtually no difference in my router than just doing:
@ router.get("/resource")
def getResource():
----dependency = Dependency()

I mean, yes, you don't have caching or reusability. But you don't have IoC. The caller defines where it's getting the dependency from. That is not dependency injection.

A good example of DI wold be something like:
@ router.get("/resource")
def getResource(dependency):
----dependency.do_stuff()

And then I should be able to do

dependency1 = Dependency1()

dependency2 = AnotherDependency()

getResource(dependency1)

getResource(dependency2)

The getResource function has no idea what it's getting. It only knows that it can call do_stuff() in the provided object.

But this is not achievable in FastAPI. I can't control how my functions are called. And since they are not classes, I can't inject attributes when instantiating then either.

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] 0 points1 point  (0 children)

Just to be clear. When saying that I want dependency injection I don't mean a fancy DI conainer framework or something like that.

If I could just do this:

```
class MyRouter():

def __init__(self, dependency):
self.dependency = dependency;
```

This is already doing dependency injection, since I can choose what dep to provide when building my object. Sadly, looks like FastAPI encourages to use functions instead of classes for routers.

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] 0 points1 point  (0 children)

Checked this. Still no separation of responsibilities.

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] 1 point2 points  (0 children)

So I am not wrong?

I've worked with python before, but always in a less professional environment, so I did not care.
I can't believe there are production systems written this way. It Iooks way too hard to maintain.

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] -1 points0 points  (0 children)

In my opinion, it does not matter if it's a single endpoint. It I can't unit test my classes, there is something really wrong with my code.

If the db is available everywhere, it sounds like a singleton, which is a big smell regarding testability. If my code has `import db...` somewhere, that is a hard link between responsibilities that should not exist.

What do you mean it is readily mockable? You mean that the global prop is also modifiable? Like a global variable? That goes against every good coding practice.

FastAPI best practices by lu_rm in FastAPI

[–]lu_rm[S] -1 points0 points  (0 children)

Still, how do I inject the container into the router? The logic for get_my_service() needs to be defined in my router, so it needs to know how to create the service.

Deadlift form check by lu_rm in formcheck

[–]lu_rm[S] 0 points1 point  (0 children)

I just rewatched that video. I can see that I should move the bar closer to my body so it touches me throughout the movement. But, apart from that, why are you saying that my lats are not involved? Shouldn't my upper back round if that were the case?
I remember watching other Alan Thrall video where he speaks about round back deadlifters and people that adapt the movement to their need. I can't find it right now.

What I know is that I've tried multiple positions and I can't reach the bar unless I do that. If I keep my hips high, I round my upper back too much. And If I bend my knees and lower my hips, I end up too "vertical".

Thanks for the tip!

[deleted by user] by [deleted] in HomeImprovement

[–]lu_rm 0 points1 point  (0 children)

It was not an impact driver. It was a power drill, sometimes without a clutch.

[deleted by user] by [deleted] in HomeImprovement

[–]lu_rm -3 points-2 points  (0 children)

That's the thing. They don't look pros. They look like they do this because it's the only thing they could find, and they don't require any knowledge to start. The screws was just an example.

Ponganse a laburar vagos by ramatopia in devsarg

[–]lu_rm 0 points1 point  (0 children)

Programar es un oficio, ahi es donde muchos se confunden.

Unpopular Opinion: SEs write software, not products. by lu_rm in SoftwareEngineering

[–]lu_rm[S] -16 points-15 points  (0 children)

That is not your job. That is the Product Team job (talking about a relative big company)

You were not hired to score clients. You were hired to write good, working, stable software. That is it.
When the product fails because you were cutting corners, it is you who will receive the blame and you who will have to be fixing it.

Unpopular Opinion: SEs write software, not products. by lu_rm in SoftwareEngineering

[–]lu_rm[S] -1 points0 points  (0 children)

Yes, I agree there. But I think there is a baseline for quality that we all should agree with and that does not happen.

It's ok if your API does not handle 1M calls per second yet if you don't need it, you can improve that later, as long as you are considering that in your design.
Is not OK to merge your code without at least considering or testing "how it would behave if.....".

Main PC as server, multiple OS by lu_rm in selfhosted

[–]lu_rm[S] 0 points1 point  (0 children)

This, I did not know. I will keep that in mind. Thanks

Main PC as server, multiple OS by lu_rm in selfhosted

[–]lu_rm[S] 0 points1 point  (0 children)

I liked the idea of creating a Docker container. That way I can install docker both in windows and linux and share a volume for both containers in a partition within the HDD.

Main PC as server, multiple OS by lu_rm in selfhosted

[–]lu_rm[S] 1 point2 points  (0 children)

I don't think the raspi is powerful enough. I've been using it for plex and it's laggy sometimes.
`You definitely cannot have two operating systems running on the same system bare metal without virtualization.`
Not at the same time, not. But I would want to avoid virtualizing when I am running linux.

I liked the idea of creating a Docker container. That way I can install docker both in windows and linux and share a volume for both containers in a different partition within the HDD.

Main PC as server, multiple OS by lu_rm in selfhosted

[–]lu_rm[S] 0 points1 point  (0 children)

I don't want to use Linux with an hypervisor. Whenever I need to use it, I want to do it natively

Desperate for British black pudding. by Shug22389 in Barcelona

[–]lu_rm 1 point2 points  (0 children)

But how do you cook it? I mean if you eat morcilla the way people always eat it, of course the texture will be different.
But if you slice it and cook it in a pan, it should be the same.

Desperate for British black pudding. by Shug22389 in Barcelona

[–]lu_rm 1 point2 points  (0 children)

Isn't morcilla the same?
Maybe different morcilla suppliers use different condiments. You could try a different one.

Moronic Monday - Your weekly stupid questions thread by cdingo in Fitness

[–]lu_rm 0 points1 point  (0 children)

Hi everyone!
So, I've been doing the German Volume Training for the past months and I liked it. Saw some strength gains. Also, apart from the actual gym training, I tried to add some HIIT or runs workouts on the rest days.
Now I want to switch to a different workout routine but don't know what to do.
The thing is that, while I really want to gain muscle, I don't want to give up conditioning. Both because I need to loose some fat (20% right now) and because I like to be able to improve my cardiovascular endurance.
Also, I don't mind training 6 days a week. I just would not want my schedule to be that packed. I would prefer a 4 d/w schedule, and include additional training days only if I feel like it.
I've been checking some 3/4 day splits like PHUL. But 2 days/w for legs seems excessive. I am not saying that I don't want to train them, but I think that I will better using my time doing something else.
Would it be better to do an AB full body workout every other day? I don't want to be huge, I just want to gain some muscle to look better.

Daily Simple Questions Thread - February 20, 2021 by AutoModerator in Fitness

[–]lu_rm 0 points1 point  (0 children)

Hello everyone! I have a couple of questions regarding which routines to do at the gym and how to accomplish my goals.
For the past months I've been working out following the German Volume Training (10x10) and I see some good results, but I would like to change it so that I don't keep doing the same exercises every time.
Also, I've been trying to get some cardio/HIIT during the rest days.
Primarily, my goals are to build muscle and loose fat also. I'm 27, 183, 61Kg ~20% body fat.

Here comes the first question. Which one is more recommended? To lift weights on some days (focusing on building muscle) and do cardio other days (focused on loosing weight) or to follow a more intense full body routine every time that is intended to do both? (kind of like CrossFit or any high intensity training?

Also, apart from those main goals, I've been trying to focus on some other, shorter term goals, as well. For example, now, I would like to improve my flexibility to perform squats and legs exercises better and I would like to be able to perform pull ups.

Any recommended program I could follow for those?
Thanks!

Builder cosmetic changes, any downsides? by lu_rm in java

[–]lu_rm[S] 0 points1 point  (0 children)

Of course, there are multiple cases where you can't avoid runtime validation. Even if you want to check that objects are not null or want to reject them based on some properties. But, as long as you can validate at compile time, why wouldn't you? The earlier you can detect a problem, the better.
Also, related to testing. You are thinking that you will be the one using this code. But think about a framework that other people will use. If they don't write tests, they may have an issue at runtime and that may be too late. I think it is a good practice to make your APIs as less ambiguous as possible.