Welcome back.
In this video I want to do something called code review and specifically for the front end of our application
a code review is something that you want to do every once in a while when you're working with your codebase
because it can always be improved.
It's never perfect and the project we've been working on is pretty good but there's minor adjustments
that we could make.
So in this video I want to go through a simple code review process to show you how we can improve the
app so that you can take this code base and expanded it, make it even better, on your own.
Let me show you a bug that we have.
If I create a new user Mike and Mike has an email and password. Now if I log in with Mike and I have a
sample face here that we can use. If I enter this face, I get up to my face dissection which is great but
when I sign out now and I register with a new user, let's call him Wes
Well, we never clear the state of the front end application.
So Wes now somehow sees what Mike submitted. So let's fix this.
If we go to our front end application and let's open up app.js, we have the onRouteChange that
gets called right over here
when we sign up. And when we sign out, all we do is setState to isSignedIn: false.
But if we look at our state, we never clear out the user object, do we?
The user object which at the beginning was Mike stays the same.
And when we come logging back in as Wes, this has Mike's information.
So we can do something interesting here we can just create an initial state
so outside of the app we'll call it initial state and this initial state will have this entire object
so that this dot state will be initial state.
All right.
And we can now simply use this variable to change onRouteChange when we sign out.
We want to remove all the information.
So instead of doing setState is signed in to false we can just say that we want to set state to initialState.
Let's see if that works.
I'm going to save go back to our application and let's log in as Mike again.
And we'll grab this face again.
Face is detected.
If we sign out now and sign in as Wes
we get an error - bad request.
Oh and that's because I misspelt his name.
We'll try that again. Sign in. All right!
There you go.
We have Wes now with a clear profile.
He doesn't know what Mike has been up to.
All right.
We managed to fix a bug which is great.
What else can we do with this code base.
There's a lot of things that I think we can clean up for example it's always important to have a catch
statement every time you do some sort of a fetch.
We see that we're using fetch but we never catch if for some reason this fetch response to localhost
image ever fails.
The only thing we catch is we catch if the clarifai API fails.
But a good practice is to always have a dot catch after you do any dot then.
Then we can do something simple like a catch console dot log to log out any errors we have.
And that's something that will improve our what we call error handling to make sure that you don't have
errors that happen without us knowing.
So that's one thing we can improve we also have the register and sign-in components. If you remember
those are very very similar, we did a lot of copy and pasting.
And the only thing that was really different with them was these input values. The register form has an extra
field which is name, and the sign-in, well just had email and password.
And we won't get into it
into this video because it is pretty simple and there's many ways of doing it. But we can imagine maybe
having a shared component maybe we'll call it form and this form accepts different props like input
types so that we can set and share that component between sign-in and register so we don't have this duplicate
codebase.
All right.
Awesome.
So that's something that we can do with our front end just to improve some of our errors and some of
the duplication of code.
We can probably even put this into a container component so that App.js App.css and App.test.js
are all in a container component.
But overall the front end looks pretty nice and clean.
Pretty simple.
As we expand the app we can always move components and make them smaller and smaller if we want so we
want to reuse them.
We see we already talked about how we can break down the sign-in and register component. Maybe inside the
image link form if we go to that component.
We can divide up the input and the button so that we can reuse it somewhere.
But for an app of this size I think this is a good enough place to leave this application.
So let's move on to the back-end and see how we can improve the back-end.
You remember here our API, which is connected to a database, and we have our four simple routes, and we've
kept this a little bit messy.
We've had everything in just one file server.js.
But ideally in any large project you don't have just one single file that contains everything.
Although this is just four routes, you can imagine this getting bigger and bigger.
So one thing I like to do in the back-end is create something called a controllers folder.
And what controllers do controllers are things that control whatever happens when an endpoint gets hit.
Let me show you what I mean.
I'm going create a new file and this file will say register.js and within register.js
we can copy this entire function, this entire transaction that we use
so that now we have apt dot post register and we can call the function here instead of having that entire
block.
So let's say that we're going to call it register dot handleRegister.
So how is this going to work.
Well let's go into the register file and I'm going to copy the function that I just copied
out of there.
Looking at server dot js we see that Register dot handleRegister will get the request response so
that when register endpoint gets hit I'll receive the request and response and get called with it.
So all we will be doing here is
module dot exports.
If you remember this syntax
and within here we'll just have a handle register function that we'll create.
And we're just exporting it and this handle register function will just be this block of function
that we are creating.
So we'll call it const handleRegister.
equals this block but you may notice a problem here.
We have the request and response but we don't have DB or bcrypt.
If I run this function in this file I'll get an error saying I have no idea what bcrypt is and I have
no idea what DB is and we have two options.
We can either within this file place the
bcrypt and KNEX imports and connect to the database or we can pass these to the function.
Let me show you.
Within the register, well I can simply just do a request response.
And this request response will receive the request response as well as the database connects and bcrypt.
So it has that available. This what we called dependency injection we're injecting whatever dependencies
this handle register function needs.
So if we go back and now change our parameters to include the ones that we've stated and save well.
Let's go down and see that.
Yeah.
We have modular exports everything looks fine on this end.
If I go back to the server and now within here I do a const the register require and we give it a
path.
In our case it will be controllers and register.
So let's see if this works. Go to Tim Tim at gmail dot com password 1 2 3 register and looks like I'm registered.
If I go to my database and make sure that we have Tim in there I can select star from users.
All right I have Tim in there and if I go to the login table
I have Tim's email as well.
So we haven't changed any of our functionality.
Everything is still working but the only difference is that we've now made register just have one
line and separate it out the register function to just be in this file. So that if we wanted to have more
things added specifically to register we separate these concerns of the register logic to be in this file.
And this is a better way of doing things.
So let's follow suit and do that to the rest of the functions as well.
We'll start with the signin now.
Again I'll just copy this and we see that signin requires the bcrypt and the DB as well.
I will say request response will be run with a function that is signin dot handle signin that
will have a request response
DB and the bcrypt
and I make this smaller just so you can see better.
All right.
And we can create that up here by saying signin require and we'll create that file right after this.
We'll call it signin.
Going to the controllers.
It looks like we've got an error here let's just check this -
cannot find module that's because we're creating it right now.
I'll say new file signin dot js copy and paste our function and we'll call it handleSignin it will receive
the database and bcrypt through dependency injection and we'll export it
handleSignin as handleSignin
Let's save. Make sure that we can still sign into our app. We'll sign out, sign into Tim at gmail dot com
and his password was 1 2 3 right we get a bit of an error.
Let's see. That request
Oh we want to make sure that we spell that right - bcrypt. Be sure we have that on the server as well
bcrypt.
All right let's give it a try.
We'll go to sign and we have Wes at gmail password 1 2 3 we're able to sign it.
All right.
OK things are starting to look a little bit cleaner.
Let's continue with this one again.
And you can see that there is a bit of repetition here.
But hopefully this now makes sense.
We know that here we're not using bcrypt but we are using the DB.
So we'll do request response
we'll say profile
handleProfile and we'll say Get here.
And be request response and the DB. Again we'll create a new file calling it profile dot js.
const handleProfileGet which receives the DB. And of course we'll do module dot exports
and we'll do handleProfileGet and I'll show you again with ES6
we actually don't need de-value.
So if I do this go to the server let's
do profile here and profile.
And then finally let's do our image endpoint which does not need bcrypt but does need the DB dependency.
So we'll do a request response
image.handleImage requests response DB.
Create a new file image dot js
Copy that properly so I'll have to
handleImage
module dot exports
handleImage
and make sure we get that database in there as well.
Go back to our servers and let's just make sure that this image endpoint works.
If I go back sign is in as Wes
and I'll submit a face here.
And I'm not getting the entry point so we made a mistake let's go back here
image is not defined and that is because up at the top over here
we haven't imported yet
controllers and image. All right.
Let's give that a go.
Make sure we don't have any errors.
Let's try that again detect we're doing one.
And if we detect again we're a two.
Everything is working.
Awesome.
So that was a little bit of repetition but look how much cleaner our server dot js looks now.
We just have very simple files very simple one liners and somebody can come and look at the server
and know exactly what our endpoints are.
And anytime we want to add more functions to handle images maybe we don't want to do a post request
with an image maybe with profile we also want to do a delete request.
We can just expand on this and know exactly where our concerns lie with the profile and just import
them into our server as a way of handling things.
The one last thing I wanted to show you is how we can clean this up.
So this is really nice because you get to see exactly what each function depends on.
But you can also do something like this where instead of declaring the function
and we now because of the way we're doing this we're first running this function with DB and bcrypt.
And then it automatically receives request and response.
So this function gets run.
Then request response gets called as well.
And I know that's a little bit confusing and it's a little bit advanced but if you remember our functions
section advanced function section in javascript. It's similar to that we can go back to our handle signin
and within here we can now have
request response.
I know this looks a little bit scary but let's just see what happens if I save this
sign in as Wes and it works fine add another image here.
Everything is still working.
And this is a little bit advanced and it might take a while to wrap your head around it.
We have a function that returns another function and then runs this.
But if you look at it step by step it's pretty clear right.
We're running handleSignin with DB and bcrypt.
If we go back to him -to signin again we're passing this and then we are also when signing gets hit.
We're passing the request response so we're running the function again request response.
So that this order is the exact same as this order right here.
And this is a matter of preference if this you find a little bit too confusing you can resort to this
other way of doing it.
I don't think one is better than the other is just a matter of preference I do like the fact that this
looks a lot cleaner than the repetition here but it might be more confusing for some team members so
I wanted to show you both ways.
All right.
I think that's enough for a code review.
We've made this server a little bit cleaner.
Our server dot js looks pretty nice pretty clean.
We only have 35 lines of code here and we know exactly where to go to find our controllers how each
route gets called.
All right that's it for now.
I'll see you in the next video.
Bye-bye.