Trying Another Way... (Dependency Injection)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so you've been watching my channel for any amount of time you've likely seen my struggle with how the heck do you set up and structure a golang backend server whatever I have gone through several very different iterations of this I've tried structuring it like an Express app I've tried doing things the sort of go away which I do like actually it's grown on me a lot I've tried a bunch of different things done a million different projects and I've never really found a way that I thought was decent and this way that I'm going to show you today is a new way and I think it's very good and it has a lot of promise I'm not going to sit here and pretend that I think it's the perfect uh Silver Bullet solution because I think one of the biggest things I've learned about go and go back ends and all these different things is that there is no Silver Bullet there's no perfect way to do everything that's why would you create like a template or something for go it doesn't make as much sense there's no exact framework and structure to do things it's very unopinionated and that's a beautiful thing and that's also a terrifying thing it makes it very difficult for newbies to get into it and it makes it very it makes starting out projects a little more more tricky so today I want to talk about dependency Management in the golang package FX this is a way to help you structure your apps in a way for you to help a way to help you set things up in a way that makes a little bit more sense and even though there's a weird little learning curve here once you get the hang of it it's very easy so what we're going to do today is I'm going to go through I'm going to show you how I structure the ghost felt to Do's back end API thing that I talked about in these previous two videos I'm going to be expanding on it even more in the next video we're going to be adding crud roots to this but for now we're just going to be talking about the layout and the structure how I'm providing everything all the source code is linked in the description below and I highly recommend that either before or after you watch this video go through the FX documentation this will give you a very good understanding of how it works and it will give you a deeper look into it than I'm going to give you here I'm going to try and keep this as brief as possible to dot drone on so you can get the key information and get out so without further Ado let's get into it so let's start with as we usually do high level overview of how this is actually going to work so FX is a dependency management system so if you're not familiar with the concept of dependency injection you're likely a TS Dev I am not a c-sharp guy or anything like that but I think that this is a much more common pattern in I did spring boot Dev for like a week I played with it and dependency injection was a big thing there it's very common in a lot of these other Frameworks and it's something that FX will help us do here so the core concept that we're going to be talking about and I'm not going to get too much further into it than this again the docs are there I highly recommend you read those to get more into it but the whole thing that we're going to be talking about here is going to be providing dependencies to FX so that FX can then provide those to other different things that we provide to it so I know that doesn't make a whole lot of sense let me try and explain this with an example so this is a high level overview of the core components of this back end so I have my user Handler user storage all this stuff and the big thing we need is this Fiverr server now this fiber server has dependencies there are things that it requires to run like a database connection like the user handlers like all these different things that require for me to spin up my Fiverr server to spin up my roots and to and to send it down to the end user so the first thing we're going to need to provide to our fiber server is we need to get access to our user to our user handlers these are going to be the things that handle the endpoint calls that we make from our fiber back end so we're gonna go ahead here and we're going to provide this user Handler to FX so I'm going to call FX I'm going to provide this to FX I'll show you the syntax soon but we're going to be giving this user Handler over to FX okay great so now FX Has registered into it this pointer to a user Handler within my backend so now FX can then go ahead and provide this to the Fiverr server so far so good however this user Handler has some dependencies of its own if we're going to handle our users we need to also be able to handle our user storage we need to be able to manage those users in our database and we also need to be able to manage our sessions because remember in the last video we implemented authentication authentication requires jwts well in this case we didn't use jwts it requires sessions and that kind of thing and it requires redis so those two need to be provided to the user Handler so FX can handle that for us and once you see the code it's like magic it's crazy how this actually works no clue how they implemented this but this session Handler gets provided to FX username Handler gets provided to FX everything's great then FX is smart and it can provide that back to the user Handler so it goes right here we provide those backup to our user handlers so these go into FX go up to our user Handler but once again we've run into this problem our user storage needs a postgres connection and our session manager needs a redis connection because we need to store our session in redis so what are we going to do provided to FX and then it's going to be provided back out to our session manager and then all of this flows back to the Fiverr server so looking at this diagram alone it probably makes very little sense and it just seems like magic but really it is so let's look at the code and see how clean and easy this really is so this is the code this is my main function and all I'm doing right here is I'm doing exactly what we said before I'm providing and then I'm consuming so up here we have this new Fiverr server method this is the Beating Heart of the app this is that bottom box that creates and runs our fiber server so what I'm passing into this method is I'm passing in this LC this which is an fx lifecycle we'll talk about that in a moment but the big thing is remember that my Fiverr server back here in our diagram it depended on the user Handler we needed to pass that dependency into our Fiverr server we needed to inject the dependency so up here I have my user handlers and that's being passed in here and then down in here within the app itself I can go ahead and initialize it and then I use these user handlers to set up my roots all makes sense very good we set up our handlers elsewhere and then within our fiber server method we can hook up our do our actual routing and stuff so I think this is a pretty nice way to do it let me handle all that in here the life cycle section of FX is super super useful because it allows us to run things when our app starts and when our app stops so right down here I am doing lc.appen and I'm passing in this FX hook and this FX Hook is going to have an onstart function and an onstop function the onstop start function is simply going to start up our app now I'm calling it as a go routine because I don't want to block the main thread uh FX is smart and it'll just like run forever and just let things go so I can just start this up here so if I had something else I wanted to set up like say maybe a q service or a logging service or whatever I wanted to do I could set that up on the same app in the same way by just providing it an onstart function that includes a go routine so this allows me to handle things concurrently it's a really clean way to do it and then this on stop is going to return the cleanup for this and all that cleanup is going to be is to shut down the app itself and then all this on stop function is going to do is it's going to take in another method and it's going to go ahead and return the app.shutdown which returns an error which is all that this takes in so we can shut down the app gracefully and this will make sure that we never have any weird crashes and everything is handled properly so this is all that's in our new fiber server method and then down here remember it's all about providing so this create postgres connection is being provided and all it does is it takes in an LC of an fx life cycle and it's really nice to remember when I talk about the lifecycle thing earlier we can provide that to any method that we're putting in to provide or into invoke we can use that to handle things like closing our database so what I'm doing in here is I'm going ahead and I'm initializing my postgres connection and then I'm calling it on start function to I'll check if there's an error and if there is an error I'll throw it I put this note in here because I'm not entirely certain if this is perfect again I've been using FX for a bit here but I'm not an expert by any means so someone smarter than me is probably watching this and if this is dumb they'll tell you in the comments so go look for that then the big thing that is really important here is the onstop function is connection.close so what we're going to do is anytime we stop our FX server we will close our postgres connection so going back to our main.go we're providing our pgx.pool and then we're going to provide our user storage and this user storage is going to take in this pgx.pool it doesn't matter what order we put these things in all that matters is that these are being provided into FX and then any of these other different functions can consume those dependencies and use them as they see fit which is super super useful I know this is kind of hard to explain and I highly recommend that you play around with this yourself try making a little example app with this try some weird edge cases that you come up with and you'll learn a lot so we're just passing all these in and then finally we can call this invoke method the provide method is we'll just send all these things to FX and then let them go so finally down here we're going to invoke the new Fiverr server which means that we're actually going to run this function and not just provide its dependencies which is the dependencies come from the return values up here but we're going to actually invoke this method and when we invoke that method we are going to call our app.listen if we go down here you can clearly see I have provided up here so remember we are providing things we've provided the postgres connection pool we provided the user storage provided the handlers provided the client provided the session manager all of these are now available to be used by any of our different functions and they do they rely on each other but we can inject them accordingly if I wanted to swap out my user storage I could just put a different user storage in as long as it implements the same interface it would work so we Implement all that stuff in then it provides you know the life cycle stuff here and then the key is it will call the onstart hooks and when it calls these onstart hooks you can see the output printed out right here you can see this hook on start starting fiber server on port 8080 and our fiber server is running right here so this is a clean way to structure things because what it does is it lets you handle things um it lets you group them really nicely and it lets you handle things via dependencies what I can do here is within my user storage method so we go into my private directory we go into my storage and we go into users my user storage can now have a connection that's associated with it which is a dependency and that dependency can be injected from the main method so I can swap out the implementation for that as much as I see fit it makes it really modular and it makes it really clean this gives us a very easy way to set up and structure things and the way you want to organize this is ultimately up to you there's debate on how to do it some people like grouping things by concern So within your private directory you would have a user's directory and within your user's directory you would have handlers and then storage and then whatever else you had and then you would also have a to-do's directory and so on and so forth I personally kind of like having things just globally under a Handler's and a storage I know a lot of you aren't going to like that but that's just my personal preference again neither one is inherently right or wrong it's kind of up to personal preference it was not particularly opinionated on this stuff and I think that's one of the things that's beautiful about it so give this a shot I highly recommend you download the source code for this and play with it on your own I'm not going to go line by line through the entire thing like I often do because I think that's just going to get repetitive and boring and there's no real reason for that so I hope you guys enjoyed this if you did make sure to give it a like subscribe do all that stuff I'm gonna have more coming up for this series later this week we're going to be implementing the crud methods for the to do's and then we're going to be looking at hosting and a bunch of other stuff so make sure you stay tuned for that thanks for watching and have a great day
Info
Channel: Ben Davis (Davis Media)
Views: 12,684
Rating: undefined out of 5
Keywords: Go, GoLang, FX, Tutorial, Programming, Concept, Svelte, SvelteKit, JavaScript, TypeScript, WebDev, Development
Id: 8Oosc55SKrM
Channel Id: undefined
Length: 11min 23sec (683 seconds)
Published: Wed May 17 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.