#gotr #golang misc ep007 - Project Structure - Part 3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello good day and welcome back to go on the run and today oh apologies for being so late on the videos again um work has been sort of a little bit crazy for the past couple weeks but oh well such as life thanks to your patient glad you're here and thanks for sticking with me and um being patient um so let's continue from where we left off in program structures part two and um in that video um so let me do a minus r and so we're gonna do part two and we're gonna make it part three and so let's just go into part three and um we'll start up our visual code editor and we'll see where we left off um so in the last video what i was showing you is that in main we could handle error for each one of our function call and this could imagine at all we have a complicated initialization and other things that we're doing you know i'm just showing two here and you know this could kind of go on where we're testing everything and that is so we still have to do that if something is returning error if we care about it we should definitely check it and make sure we handle in that and so if you're not going to check an error for something returns an error you should make it clear with comments why you don't think it's important or why you're not checking it so to somebody else who has to maintain your code know why remember in software engineering we do not optimize for a number of lines of code i don't remember who said it but someone said um and someone who's really good in software engineering um that if you can write one line you probably should write three which means that um you know if you think about functional program people tend to try and optimize for lines for some crazy reason almost like if we don't have memory in our computer almost like if we get in charge for the number of the fewer lines of code that we have and to try to do like five things on one line that does that reduces clarity now we can have a different discussion um and i can talk to you about why i think that's sort of bad but i think in the long run what you want to do is your program to be clear and if you have to write it on four or five lines please do that and do not worry about trying to pack too many things online some people complain about go having you know every function call and then you have to test it we're not optimizing for fewer lines so if you have to test it test it it's clear that oh you call this thing it returns an error you're checking it so we're still gonna do that but what i'm saying is that i've noticed a pattern in the go community and there's this guy who gave a talk um i wanted to go for khan um meet up one time if i find the video i'll definitely put it in the description below where he talks about um how he uses this pattern i'm going to show you which is using a run function so um let's just start there so i left you here essentially and i showed that you know yes we can or features now um sort of randomly return a an error message dependent on some silly test and assuming this number is random then the error message when we get a message should be also random and we see that so that's fine and i updated all the features functions to do this and then um within the video i did application one but i didn't do application two so um if you didn't do application two yet definitely uh make sure to update application 2 to run this way it will still run because there we're ignoring the return value but we call feature a and then we call feature c in this case so there we go all right and so um oh i think i have one extra curly brace there okay so everything is fine and look like we don't have any error messages so the first thing we're going to do is we're going to create a rename our function main here to just call it run and then of course if we're going to call run to do all the work that maine usually used to do we also want one to be able to return an error of course if there's no error we're gonna return no so this doesn't seem like a big change really right um i will go ahead and i will say let's rename this pro the file from main to run okay now there's nothing wrong with us leaving this run function in this file but as you'll see there's something else that i want to show and so i'll put it in a separate file and so let's now recreate our main.co and this is in package main and of course we do function main and then now we have to call this run function okay and of course this still returns an error so if error you know then we do error not equals the nil then log rust that theta and so again this just looks like if we just shifted our problem just sort of bury it a little bit but like i said imagine that our main is a little bit more complicated and you'd call and run then you do some other things maybe you have to lock this error somewhere else maybe you have to send um you know um send it off to other places whatever maybe you have to do some cleanup or whatever you have to call some other thing to notify that since we failed to sort of get our stuff going maybe we're going to shut down whatever so you're doing a little bit more work in air and main but that's okay because the core thing that this program is about is in run and then all the other stuff around it that might need to do before it initialize or after it finish doing this core work um depending on what it's doing maybe that is also here so you know you have some pre-things some stuff that come after right um at least maine if you're not new to this code base you could kind of just say oh this program doesn't mean stuff then it tries to set up its core thing and if that fails then it doesn't clean up or notify some other applications and all this other stuff and then it shuts down and at least you feel like if you cut you have a basic idea what overall the structure of this application is without even knowing the details right and then when you want to dive in you can set us up okay let me dive in to see what run does no this is what ron does right is doing all this other extra stuff and then now at least you you're ready you're ready to sort of explore run because you sort of have an overall idea of maine itself and just imagine if run all the stuff that run did was actually in maine as soon as you approach the program you sort of overwhelm immediately i can say it's a mental trick but i really really like it and so this doesn't change anything or programs still run um the exact same way so i'm not going to waste time building it because i think you're convinced that though we haven't really changed code significantly but there's another advantage that you get from this you see before when we get an error we sort of did lock failure fatal and we could have actually put like you know um different things in there like you know um log fatal f or something and put some description but what i really like about this is allow us to do something like this allow us to do saying something like return fmt at error f and this is a relatively new feature in go i think i don't remember which version of code showed up in it's called a wrapping error right so you can wrap your errors and it allows you to unwrap errors so i can say oh um failed [Music] to initialize um you know feature a for example and this is the error message now normally you would see somebody probably do something like this right um v for a value but if you do this what you're doing is you're turning this into a string and the error into a string and then just print it out but you're not wrapping it but this new feature i talk about is this percent w which wraps the error now white wraps the arrow because when we return this error we have an arrow wrapping another arrow and the error package has it on wrap method so you can actually unwrap the errors and so that's really nice because no not only do we return the on the line error but we and we wrapped it with more description uh more information now if you come from something like java or something you've seen this with exceptions where it sort of prints out an exception star now you don't want to get too crazy with this i like the idea that you can wrap an error but i personally don't want to cross process boundaries and all that stuff with wrapped errors like um if module a cop module b comma just c and stuff um at some point i want to get a sensible error message from the thing i call and i don't need the very very low level error message that it call so you see this when you try to write a program that or if you have a program that tried to create a file and it can't create the file because the directory permission is wrong or whatever reason it can't do it or tries to open the file the file doesn't exist you don't actually see the operating system error you see an error message reflecting that's program inability to perform whatever action you want and the program of course got a low level error from the operating system but it doesn't show you that exactly now if you don't know c program and you never work with the lipsy library this might not make any sense but lipsy returns you know pretty much error coded number meaning something but no program really show you those error code they actually test their code and say oh this is what it actually mean and give you a meaningful error and i think that's the right thing to do so on the one hand like i say it's good to be able to wrap errors but don't take that too far where you have like wrapped arrow like a hundred level deep that that's just nuts you're passing up an error that most likely nobody is going to unwrap a hundred times and it doesn't really matter if they get to the very lowest error so use it with caution so anyway um a lot of these things are guidelines um so you don't always apply them but you you know you have to sort of know when to use them did the good things just start with um so we're doing ob feature b enough talking so i've quite kind of um changed it and i've shown that oh yes i've sort of explained exactly what i'm doing when it failed right so you can imagine that each one of these i made them very simple but you can imagine that oh i was doing something different and i kind of explain what i'm doing and that's more meaningful to the user right and here the advantage here now in run function we're not really dealing with the error in terms of what action we can take we've left that up to main to figure out like this error is severe enough for us to fatal on or just log on continue right um and main can do that because it has the error and plus it can unwrap it to whatever level it wants i don't show that here but it could unwrap it and get to the actual error and decide well oh this is not as serious as you know this this can be worked or wrong i would try something else you could imagine run was trying to open a file and the file doesn't exist then we can say well that's not that serious because we can try a default file so then we can recall run with some autofile name and you know things like that so um that is what this this gives you the ability to handle the error more elegantly plus that other benefit like i mentioned about just making me as simple as possible so two benefits there but the key pattern here is being able to push up most of the hard work of maine into a run function all right so that works and um you know you can totally go to the cmd and tap one for example and then we go build and you know we can run it of course and that's still run and we see our new error message here that filled in as well features that and it put the error message of course when it prints out a string it doesn't look like it's wrapped but you can trust me that it's unwrapped we haven't dealt with that yet but you can look it up um if you want to understand about unwrapping errors okay so this seems pretty silly that we just have this other function that we created and it's sitting right there in the command directory and we want the command directory to be simpler so main itself is simpler but the run function is right there and so there's one other thing we can do and i'm going to leave fixing up app2 the same way we fixed app one for as a to do for you but when i push the code up two will be fixed okay here's the next thing that i've seen and this is a feature of the go compiler remember when we have things in these directory they're packages okay so we have packed a feature in package a we have feature in package b we have a feature in package c and we can reuse those features or those packages in our application but the other thing that happened which we haven't done yet is that somewhere else when we push our code to a repository someone else could import our features and they too can reuse them okay and we'll i showed you in the presentation how you might want to hide certain features and all that stuff so what if we put run in its own package so you can own it can be used by app one but we also don't want it to be used externally and so for that reason there's this ability to do something called an internal package and so you can do internal and we'll see that you could put internal at sorry every level but we're going to put it here at root for now for this example and we're going to say what we want to put internally is the things that are in command and um we specifically want application let's say application one okay and so with this in place now what we can do is move run to this directory okay and if you go back here you'll see that it says that oh it can run is undeclared it doesn't know where to find and run which which sort of makes sense even though you know run says it's package main but this is not actually package main this package is actually package eight app one okay and so but isn't it's in a different package we know we couldn't access it because um it's was private so we have to make it a public function and then now we can go back here and call this function with capital r and then if we save it all right oh we say app one that row that's what we wanted to use and now you can see that we pulled in our run function from package app one and this is an internal package now there are some other things where internal well i'll leave that off because it'll get pretty confusing without being able to show you an example so we'll revisit using internal i think in the very next video so what did we do let's recap we have simplified main by putting all its work essentially most of his work in a run function we move that run function to a package but that package is internal and the reason why we did that is we don't want someone else who have access to our repository to be able to create the exact same program just by simply or most of the program by simply calling run so for whatever reason we don't mind exposing some of the features but supposing that run actually calls some other internal features which we haven't discovered discussed we discussed but we haven't shown how to do yet but it's going to be along the same line we don't want them to be able to call that so um so that is one way in which we can hide um things so this package this whole command package and the sub package app one they're all hidden and cannot be imported by someone who tried to use our repository because go tooling understand internal to means keep the seed and they can still use feature a b and c okay so that gives us a hint as to how we can create hidden packages but there's still more to internal and so i'll leave that here i think this is nice and short and hopefully you appreciate how you know go tooling just really allows you to structure your program and in a way i think it's sort of common sense um structuring and it's nice to have that sort of built into the tool um i really after you know using java and c and all these other things where you have to manage dependency and you have make files and stuff and you can still use make and go and you see that too but just imagine dependencies and stuff and how that's or all that stuff is dealt with i really appreciate the goal tooling for how it helps you as approach some of these things and the ghost credit it did this because they learn from all these other tools like if you have a you use in maven and you have a pom file or even gradle the dependency is crazy whereas in go you simply have these one entry and it sort of looked like all you might have in a gradle file but remember we didn't have to put this in directly like we just sort of said we're going to use it and then we say pull it and you know it sort of updates and self-manage of course you can manage it yourself but i don't want to lament too much on this and make this too long again thanks for your time thanks for your patience uh if you're enjoying the video and you're here you watch the entire video please consider and subscribe if you haven't subscribed if you are subscribed then hit that notification bell so you know when i do post videos and if you're able to you know contribute in whatever way you can either by you know thumbs up the video just just comment and help um keep it on um the top so the youtube algorithm will show to other people help grow the channel i would really appreciate that so the minimum please subscribe click the notification bell and comment and then if you want to go a little bit further then look at how you can support if you can in these different ways that i have here alright take care stay safe have a great rest of the day bye [Music] you
Info
Channel: Vilito Exquisitus
Views: 230
Rating: undefined out of 5
Keywords:
Id: PGHkvYl9p-U
Channel Id: undefined
Length: 18min 24sec (1104 seconds)
Published: Wed Oct 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.