Building Hexagonal Microservices with Go - Part One

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys my name is tensor today we're going to be building a URL shortener application using hexagonal microservice architecture now before we get into any of the code I just want to kind of explain what the hexagonal architecture is and why it's a nice way to structure in micro-service now the basic concept of this Court unquote hexagonal pattern is to make sure that we divide our software in such a way that each piece of the software maintains its separation of concerns and by doing this we make it so that our application is extremely modular and the basic way that this architecture works is that you have your app and domain logic in the middle and then you've got this layer on the outside which describes a set of ports and adapters which connect the app and domain logic to outside things like a user interface or a repository or a rest and graph QL API or maybe like a message queue or maybe some external API so each of these sides basically represents a port or our app and domain logic feeds into a user interface and into a set of databases and into a set of api's and so on there are a few loose guidelines that we do want to follow when building our application so firstly we want to make sure that the business logic itself is independent of any kind of large framework so this way if we rely on the framework then we connect to that framework to one of our ports and adapters if the framework were to become depreciated or if say we wanted to use a different framework you could just take our business logic and move it over to that other framework we also want to make it so that our app and domain logic are testable without any of the ports and adapters so even if we don't have a database or a user interface or a API we can still test the business logic and make sure that it actually works properly and then finally we want to make sure that the business logic is independent of any external IO or agency so the business logic doesn't know anything about the outside world and it only knows about its own domain now here's what the service that we're going to build is actually going to look like so we have our service which is our URL shortener domain logic and it will connect to a serializer which will either serialize the data into json or message pack before serving it through a REST API and then on the other side we'll have our repository which will either choose to use MongoDB or Redis based on how we start the application from the command line of course it's important to note that we'll be able to accept both JSON and message pack from our REST API and the repository will also be able to use both MongoDB and Redis and it won't really affect our service now for those of you don't know what message pack is it's basically just a binary serialization format and it's very similar to JSON but faster and smaller alright so now that we've got all the concepts out of the way let's get into our code so we're gonna be building a URL shortener and the main concept behind a URL shortener is that a user supplies a URL that they want to shorten and then they get back a code and that code is in our case it's going to be 9 characters long and if they use that code with our domain which in our case we'll just be localhost followed by the port so localhost 8080 direkt - the original URL really our application is just a glorified hash map where we have URLs which are attached to these key codes if the user passes in a key code then they'll get out that URL all right so let's go ahead and create the main model for our application so we're going to call this a redirect and it's going to have three things inside of it it'll have that code which is the key that we're going to use to fetch the URL then it will have the URL itself and then it will have a time stamp that will signify when the shortcode was created application is going to use MongoDB JSON and message pack as well as Redis so we want to go ahead and add some annotations to this model so for JSON we'll just say that we want to have the key code for the code string the key URL for the URL string and then the key created at for the created at timestamp then for MongoDB we use this beasts on annotation and again we'll use the same keys for each of these fields for message pack we just add message pack as the annotation and again we'll use the same keys for each of our fields we have an extra annotation attached to the URL field called validate and we're going to use a library that will allow us to use this annotation to validate this field we can say that we want this field to not be empty so we can say empty equals false and the format of this field is a URL so we can then validate that the input that we get from the user is not empty and it's in the format of a URL alright so now let's go ahead and create the main service interface we're gonna call it redirect service and it's going to have two functions attached to it the first one is called find which will take the code string and then give us back a redirect or an error and then we'll have the store method which will take in a redirect and then give us back an error if it fails our find method will take the code that we've produced and then give the appropriate URL that's associated with that code back to the user our store method will take in a redirect it will generate both the time stamp and the code which we can then send back to the user and then it will take that redirect and store it inside of our repository now speaking of repositories we need to define an interface to connect our business logic to our repository so we'll go ahead and define another interface called redirect repository and this interface will also have the find and store methods inside of them and they'll have the same exact function signatures so fine we'll take in a codes and then pass back a redirect and an error and then store will take in a redirect and then pass back an error now here's what the structure of our application will look like so we have our service which we're building inside of this shortener folder and the service will connect to a repository via a port and it will also have a serializer adaptor which connects to our HTTP transport so we want to define an interface for our serializer as well so that our service can pass messages through the JSON and the message pack formats our serializer interface will have two functions inside of it one of them will be called decode and then the other one will be called encode decode we'll take in a slice of bytes and then output a tuple of redirect and error and then encode will take in a redirect and then output a tuple of a slice of bytes in an error and we'll implement both of these methods to work with JSON and with message pack all right so now let's go ahead and build the logic for our application so first I want to define some errors here error redirect and not found and then error redirect invalid and these are the two main errors that our application will spit out so if we put in a code that doesn't exist in our database the more pass back that the redirect was not found and if we put in a code that is somehow mangled or if we put in a URL that is somehow mangled then we can pass back that it's invalid next we want to go ahead and create our redirect service structure and we're going to go ahead and implement our redirect service interface on this structure now notice this service structure has the repository inside of it we want to be able to feed data into the database and then get data back from the database we can now go ahead and create a function which will allow us to instantiate a new redirect service and this function will take in a redirect repository interface type and then pass back a redirect service interface type and of course it'll work because we're implementing that interface on this redirect service struct I've be find and the store methods down here let's start with fine so find is very simple we just want to call to our repository and then call its find method with the code inside of it and then we'll just return that and then that will return a tuple of a redirect and an error so we'll either get back our redirect or we'll get back an error if it fails and notice because we're using an interface it doesn't matter what type of database we're using we just kind of expect there to be some kind of repository with our data inside of it and so wrong is we have that repository or so long as we have some kind of mock repository this logic will still work our store method is going to be a little bit more complicated than the fine method we'll first go ahead and validate the redirect struct that we're passing in here and we're really just validating the URL of this redirect struct remember that we added that validate annotation to our URL in our redirect struct so that we can make sure that the string is in a URL format and it's not empty and to validate we're using this library here so it's just called deal answer validate version two and it uses a bunch of regular expressions and stuff like that to validate that the data is in fact what we want it to be then if this fails we'll use another library which will allow us to wrap our redirect invalid error and we want to basically just tell the console that our error occurred inside of the service redirect store function and so that's what this wrap method does we'll go ahead and we'll generate the code and I'm using a library here called short ID you can see it's just github.com terrorists I Oh short ID and what this does is it generates a string of nine characters and the characters are made up of numbers and letters and valid URL symbols like underscores and dashes and stuff so that goes into the code field and then we create our timestamp and we just use the time library we just go time now UTC and then we converted into unix time which gives us an n64 then finally we just pass this back by calling to our redirect repo and we call the store method with the new redirect inside of it that way it gets put inside of the repository and then if that fails we'll get back an error now we're finished building our service logic let's take a moment to reflect upon what we've done here if we go back to our little picture of our micro service what we've basically built is the internal hexagon so it's just the app and domain logic and we've also built a bunch of interfaces which we're going to use to describe what the ports and adapters need to look like so in our case we just have the repository and we're going to have the REST API we also need to connect to the REST API using a serializer and that's why we described the serializer interface as our adapter this pattern allows us to abstract away things that don't really matter to the service itself in the case of our repository for instance we don't really care how we get a redirect out of the repository all we care is that we get one and the same goes for the store method we don't really care how we're going to put the redirect into our database so long as it gets put somewhere and so this allows us to separate the concerns of this code versus the other modules that we'll build that will attach to this service that's it for part 1 of this tutorial series in the next video we'll go ahead and we'll build the repository and the serializers and then we'll go on and finish off this micro service if you like this video feel free to subscribe and like if you have any questions or comments feel free to leave them in the box below and if you dislike the video then by all means download it as much as you like if you want to catch the next videos in this series then feel free to click that notification bill have a good night
Info
Channel: Tensor Programming
Views: 35,673
Rating: undefined out of 5
Keywords: Hexagonal Microservice, golang, learn go, learn to program, learn golang, microservices architecture, microservices tutorial, software development, software development tutorial for beginners, go programming, golang tutorial, programming tutorial, go channels, microservice, go microservice, building microservices, hexagonal microservices
Id: rQnTtQZGpg8
Channel Id: undefined
Length: 12min 58sec (778 seconds)
Published: Thu Oct 24 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.