Junior Vs Senior Code - How To Write Better Code - Part 2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
do you wish your code was cleaner and better written it seems like a lot of people do because my last new versus Pro coding video was incredibly popular so I'm gonna take that same concept and look at two more examples of different types of code I'm gonna show you how a beginner would write it how a more advanced developer would write it and how a senior-level developer would write this code let's get started now with all of this new clean code that you're going to be writing you're gonna need a place to host your websites which is perfect because today's sponsor atlanticnet is going to be giving you an entire year long free trial of their web hosting which is an incredible deal on top of that you're gonna get an additional 50 dollars of credit if you use the code Kyle when you checkout and these servers they're giving you for free are incredibly powerful they're more powerful than you're gonna get at the free trials of any other hosting providers like digitalocean or the node so make sure you check out Atlantic net hosting link down in the description below welcome back to web dev simplified my name's Kyle and my job is to simplify the web for you so you can start building your dream project sooner so if that sounds interesting make sure you subscribe to the channel for more videos just like this now to get started I have here a really simple example of some asynchronous code this first example I want to go over for these new through advanced and pro is all gonna be based on how to handle asynchronous code whether it's what promises async await or callbacks there's a bunch of different ways so I want to show you the best way to handle this versus some not so good ways so first we're gonna look at the more noobish junior-level of code thinking and this is how a lot of people including myself will write asynchronous code when you get started so here all this function does is it uses this read line command in node which allows us to type things into the console so it's essentially asking a question what is your name and then it waits for us to type an answer in and then it responds with that name we typed in same thing down here for job and same thing down here for age but something you'll notice about this is they're all nested inside of each other which in this small example is not too big of a problem but as your code starts to get more complex and you have more nesting it becomes really hard to read and manage what's going on you can imagine if you needed to ask seven questions you would have seven levels of nesting or what if you had a bunch of code in between each of these different levels of nesting which makes it just really hard to follow where you are in this nested hierarchy so that's one major problem with this noobish version of the code and that's probably the biggest thing that I would look to change in a more advanced version of this another slight problem that I see here is just the console dot log this could really use template literals to drastically clean up this code goes it's a little bit difficult to parse exactly what's going on and making sure you have spaces in the correct spots between all of your different elements before the pluses and after the pluses it's just a little bit difficult to handle so I just want to run this program real quick to show you that it works so let's just select that new version it's gonna ask what is your name I'll say Kyle what is your job I am the developer and how old are you let's just say 25 and it prints out hello Kyle you're a 25 year old developer and then ends the program so everything works as expected and really this codes not too bad you may see this code all over the place but it can definitely be improved so let's move on to the advanced version where we have a lot of improvements the first major thing you're going to notice is that all of that nesting is essentially gone we just have three equally leveled functions here with no nesting at all and you may look at this code and think it's more complex and more difficult because it's longer than this new version code here as you can see we have quite a bit more code but actually what we're doing is we're creating abstractions we're taking all of this abstraction from ask question and moving it down here into this function called ask question so that way when we're actually going through our main function here of our code we don't have to think about what asked question does we just know we call it we pass it the read line interface which essentially is how we actually ask the question that's how we tell the computer to wait for the response and we give it our question and then it actually just does all the code it needs to do for us and it will return to us the actual name here and the way that we're able to make this work in line so we'll look like normal synchronous code without all that nesting is by using async/await and we're also using promises if you're not familiar with promises or async late I have an entire video covering both I'll link down in the description or the cards you can check out but essentially what we're doing with this is we're taking this old non promise based code which is based around callbacks here because it sends a function which is gets called when it finishes and instead we're converting this to a promise and that way we can use async await with our promises so something you'll notice from a lot of higher-level developers is that they'll take these old you know callback based functions and they'll convert them with a very simple wrapper that returns a promise instead of a callback which allows you to use a single weight or just normal promise then and catch syntax in order to handle these types of situations and overall it just makes working with the code so much easier because we just have this really simple main function here and the only reason I have this wrapped in a function called name is because with JavaScript if you use a weight it must be in an async function so I had to wrap this in a main function or just calling it right here so it's essentially the same as not having the main function just in this instance we need it to be wrapped in a function so to make sure this works let's just do the exact same thing we'll call the advanced version prints out what is your name Kyle job is developer age 25 and you can see it works exactly the same as the previous example you'll also know our console dot log here is using template strings which I think just makes it a little easier to work with but something else you'll notice is that we have to always pass this red line interface into this asked question I'll be always have to close this red line interface which is a little bit clunky because this ask question should be kind of self-contained but we need to know what to pass into it and we also need to know to make sure to close our read line interface when we're actually done asking our questions so that is something that we need to manage on our own and I don't really like having those extra dependencies and implementation details leaking out of our function also you'll notice this asked question function is the same file as our main function but they're completely separate they should probably be in different files so that's where the pro version comes in it's going to clean up a lot of this code if we open this up you'll see that our code here looks similar but a lot of our code is just not here anymore it's been moved to its own file which we're importing here you'll notice this red line stuff we don't have that anymore there is no red line anywhere in this code we don't actually care how we implement this implementation of asking a question we just care that there's a function called ask question we pass it a question it'll get a user response and return it to us a synchronously so that's what we do we call that function three times in a row and then we're logging out that output and just to make sure that this works just like everything else we'll call the pro version my name is Kyle job is developer and age here 25 and as you can see it prints out just like before so let's look really quickly at what this ask question file is doing I just have it in this pro folder here if we open this up you can see we have our red line here and then a single function which were exporting down here which contains all of our implementation details we're creating that read line interface inside of here or also taking that question and returning a new promise which asks that question it's going to return at the answer to that question and also importantly close out of our interface for us that way like in our Advanced section here we don't have to manage closing our interface on our own that's implementation details leaking out of our ask question function but with our pro version all of that implementation on it that's read line interface or maybe instead of read line interface we're using some other library that does that for us instead so we don't have to worry about handling that we can change this to be some other library and it's not gonna affect any of our code out here put our advanced version if we change this from read line to be some other library we now have to change all of our code that calls asked question and that's annoying that's difficult it makes it hard to change things in the future if we go to this pro version here we don't have to manage that difficulty of changing things in the future because we just change it in one place here this asked question file and it's going to just work everywhere else that we used it also you'll notice our asynchronous nature of doing this is exactly the same as the advanced version the main thing I want to take away from this section for async code is that callbacks like this is bad this is what's called callback hell when you just start nesting callback and callback and call back and the best idea is to break this out into promises and use async await if applicable to actually manage those different dependencies and different asynchronous nature's of your code it just makes it easier to read when it's all like this instead of deeply nested inside of each other potentially many many levels deep now with the asynchronous code done let's just close all those files I want to open up here the next section which I call the fat functions and essentially what this is is actually a comment that I got a lot on my last video of a suggestion which is a lot of people create functions which are really really big when they should really break them out into smaller discrete pieces also their functions may do more things than they really lead on and this new version is a really good example of that we have some really simple API code which is going to update our user and create our user and this code really doesn't do anything it's just placeholder is just updating our user creating our user we're not actually saving it anywhere so it's just kind of a placeholder API imagine there's an update and create user function and then we have this save user function which does a bunch of stuff as you can see it's a quite large function and then all we're doing down here is we're taking a user with a username and a password and we're calling that save user function but something really interesting happens you would think by calling save user all we do is save the user but really what this function is doing is that doing validation for our user right here it's also printing out all of our validation errors and it's saving the user so this save use function which is named save user is actually doing validation error printing and it's doing saving is doing three different things even though its name implies that it only does one thing that is a big problem I see and I like to call this essentially unintended side effects this function called save user it saves the user that's good that's correct but it also has unintended side effects of both validating the user and printing out the errors that we get from our user validation a great way to show this is if we call this so we can just come down here we're going to call our new version you can see we get printed out created user because we successfully created our user what happens if we don't pass in a user name this is going to fail our validation so now when we call this you can see it prints out user name as required so calling save user we somehow printed out an error that's probably not the intended behavior that you wanted when you call this function so it's really important that you understand exactly what goes on in a function so having all of these extra side-effects is really bad for your function overall and as you can see we have really complex messed logic in here with a bunch of nested if else's I kind of covered this in the last video it's really not a good idea as you can see down here again more nested logic we have our printing out for our errors and then down here this is some really important code if the idea is null we create the user otherwise we update them because if they have an ID then that means they exist so we want to update them so really the big takeaway from this nubes version here is that this function right here does way too much and it does more than it actually says it does and it's really misleading when you are trying to use this code in the future you may not always have the luxury of looking at the source code of save user because it's too big or just not something that you've worried about for multiple years so when you call save user you expect it to do one thing and only one thing and when it does other things that's when you can run into unintended bugs so now let's jump over this advanced version we break out many of the different features of saving validating and so on so as you can see here our save use function save user function is much smaller all it does is check if the user ID is null and it creates the user otherwise it updates the user so that's really good the save user function does one thing only and it does exactly what we expect with no side effects at all now the next thing we're going to have is our validate user function and this just calls to helper functions for validating our username and validating our password which both return an array of errors so if we don't have a username it's going to set user names required and if the username length is too short it's going to tell us that same exact thing for our password this code is almost identical but it's just checking the password and it has slightly different worded error messages as you can see password is required versus username is required then down here what we're doing is we're getting our user we're validating them so we can get our errors and then if we have any errors so if our errors length is greater than zero we're printing out our different errors so let's test this version we can just say here we want to select the advanced version and you can see when we don't pass a username or password says user names required password required and the password must be eight or more characters but if we pass in for example WDS and password which is going to pass our validation and call that you can see that we created the user so the code works exactly the same as the new version but the important thing is that we have all of our different logic broken out into functions that logically make sense they only ever do one thing save user only saves the user validate user only validates the user and obviously these validation functions only validate the particular parameter that we actually want to check but there's still some problems with this code that could be cleaned up in my opinion probably the biggest one is this validation is really repetitive this required validation check is exactly the same between these two different properties and same thing with this length validation it's exactly the same so we have a lot of duplicated code and you can imagine if user had 20 properties that all had different user required and character limit validations it can be a ton and a ton of repeated code especially if you have 10 different models all with 10 different fields that's a hundred times you have to repeat this code and that's a problem because if you need to change it in the future you not have to change it in 100 different places so in the pro version of this what I want to do is take that validation logic and make it something that we can actually use all over the place without repeating our self which is really important another important thing is that our validate function is a bit misleading it's called validate user but really what it does is get a list of all of our errors because we're returning an array of error messages instead of actually returning true or false for validation so this validate user function I think is a slightly misleading because it returns an array of errors and you must know that the array of errors is being returned and that if there are errors then it's invalid and if there's nothing in the error array then it is valid and that's an implementation detail that you need to understand in order to actually use this validate user function and like I mentioned in the async function I don't like it when implementation details leak out so that you need to understand those details in order to use the code so let's jump over into the final section which is our pro version and take a look at what we have here the first thing you'll notice is we broke our validation out into a new file it's something that we want to have separate from our user and that can be reusable across our entire application so we broke it out into its own individual file to manage all the validation in one place again it's a perfect idea to break out your different logical components into their own files because it doesn't make sense to have your validation grouped in with your model for example when in reality there are two different things now we also have our save user function exactly the same as before we didn't change any event but our validate user function is much much different takes in the user just like before and now we have particular validation rules setup we're saying our user name is required with a length of 3 or more and our password is required with a length of 8 or more and then we're calling this validation messages function which is coming from our validations here we're returning an object so remember I said the implementation details where you need to know in empty array means valid and a non empty array means invalid well that logic I broke out here so if we have an empty array it returns true for valid and if we have an actual array with errors it returns false for valid so that way implementation details do not leak out also our errors themselves are being returned so we can print them out later now let's go down here we have our user with an ID of one username and a password and you can see here we're validating our user which gives us a list of errors as well as true or false for valid and if it is valid we save the user otherwise what we do is we print out those errors which again is a function I put away inside of our validations because printing out the errors is something that the validation should handle because it's the one that created the errors and not the user the user should not handle that logic so we broke that out into its own the file and now if I run this section you can see if we just do this you can see username as your pirate username must be three or more characters it's being printed out if we add in a username WDS you should see that our user is updated because they have an ID so we updated our user so that as you can see has allowed us to drastically modify our code and break it out and as you can see all we're doing for our user is defining a single object which essentially maps to how our parameters are required what length they need to be all of our different validations and we pass that off to this validation class essentially so let's open up this pro folder with this validation here and as you can see we have a bunch of different functions in here we have our printing of our errors as well as validating for required and validating for length and as you can see it just has really simple checks it's going to return a error message if the length is not satisfied and if we're required it's going to return an error message if it required is not valid and then up here this code itself is kind of complex and a little bit messy but just kind of look past that and essentially what we're doing is we're passing in our user object here and we're passing in our hash of validations this hash right here of how we want to validate things and all we're doing is looping through this we're saying for our username if it's required checkout required parameter if there's a length check the length requirement same thing for password and then we're constructing our error messages based off of that so as you can see our errors are like is required must be three or more characters and then when we print that out we're just taking that property which in our cases username password and all we're doing is adding our message on to the end of it so it'll say username is required or password is required and essentially all this is doing is just letting us take that complex logic that we have here in our advanced version all this repeated code that's you know built into this big file here with all of our user stuff it allows us to take all of that and completely remove it and put it in its own file so that way even if this code is complex even if it's difficult to understand it's completely abstracted away so that when you use this code all you ever do is call validation messages or print errors you don't have to worry about the implementation details of this complex function you just know what it does it's going to give you a list of errors and that is all you need to worry about where it's going to print out your errors to the screen for you so the big takeaway is from this section going from the noobish version to the pro version is that number one break up your big functions if your function is start to get really big and do multiple things especially if they do multiple things break it out into individual functions that have a single responsibility this actually follows the single responsibility principle I'll link in the cards and description down below I have a video on that secondly if your code starts to get a bit complex where you're doing things such as repeated validation like we did here we have a bunch of repeated code and you know for a fact that you're going to use this in other places then you should break that out into its own file like we've done here that way you can use it all over the place and you don't have to worry about copying that code every single place that you want to use it you can just import the single file and it's going to be there ready for you to use it instead of having to recopy it and re-implement it every single time and that's all it takes to go from a junior developer to a more senior developer when it comes to writing code if you enjoyed this video make sure check out my other videos linked over here and subscribe to the channel for more videos like this thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 106,100
Rating: undefined out of 5
Keywords: webdevsimplified, junior vs senior dev, noob vs pro code, noob vs pro, junior vs secnior code, beginner code, how to write better code, how to programmer better, clean code, clean code js, clean code javascript, write clean code, how to write clean code, how to write code, the best way to write code, how to program better, how to be a better programmer, senior developer vs junior developer, senior dev vs junior dev, junior dev mistakes, junior developer javascript, javascript
Id: 5B587bQ-TNg
Channel Id: undefined
Length: 22min 0sec (1320 seconds)
Published: Sat May 30 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.