All right.
So let's now take a look at some bad code
that doesn't follow any of the principles or guidelines
that I showed you in the previous lecture,
and actually start fixing it in this video.
And the code that we're gonna fix
is also here in your starter files
and it is called clean.js.
All right.
Now let's open up our console back here
because it is still running Parcel from before.
And so, let's stop that now.
So with Control + C.
And then let's also come to our index.html file.
And then here let's copy this
because now we no longer want to include script.js.
So I will comment it out,
but instead we want clean.js that we will work on now.
So give it a save.
And now we will also run this code
again with live server and no longer with Parcel
because now there is nothing to bundle,
all we want to do is to take a look at our code
in a very simple way.
So live server.
And let me grab that tab
from another browser that I have opened,
and here we go.
So, you see indeed that the URL is different here
because the default URL of live server is 8080.
So as you see here,
and of Parcel it is on port 1234.
So it's different.
So we are not interested in this one anymore
but instead in 8080.
So we can close this, this one as well, and all sidebar too.
So let's reload this here so we can see our results.
Make it a bit bigger as well.
And, okay.
Let's start by analyzing here or clean code,
or actually the not so clean code
that we wanted to start fixing in this lecture.
So this code is basically
about a very, very simple budget application, let's say.
And so here we have an object which is called budget
which contains a couple of object.
So each of them is basically an entry in the budget.
So each one has a value, a description,
and a user of the person who created the entry.
So this one is jonas, this one as well.
And you see that here we have a negative value
which is basically an expense.
So for groceries, for example,
and here the positive one is for income
like selling an old TV or monthly salary or freelancing.
So we have jonas and the other user that we have here
is matilda.
Then down here we have a very simple object
which is basically spending limits.
So jonas can only spend 1500 euros, or dollars,
or whatever it is.
And matilda can only spend 100.
Then we have a function to add a new entry to the budget,
or actually this one is only for expenses.
And so, here we start seeing one of the bad practices
which is that this function name is not good at all.
So it's not really descriptive of what's happening here.
And so, let's actually start by fixing that right away.
So this one should be called, addExpense.
So you see I'm changing it here and here.
And I selected all of them by hitting Command + D.
So add next occurrence.
So that's the first fix,
but of course there are gonna be some more,
but let's keep going through our code here very quickly.
And so, next up we have a check function
which will basically check the budget
and see if any of the expenses are actually above the limit
that we defined here.
And if a certain expense is,
then it will flag that by adding a limit string
to a new flag property on the budget entry.
So this addExpense here actually checks
if the new expense is below the limit,
so that happens right here.
But there might already be an expense
that is below the limit,
or actually over the limit which is like this one here.
So 1800, if we don't consider the minors.
So I spent 1800 here and that of course is more than 1500.
And so, this one would be marked as a limit.
But again, we will see this in detail once we fixed the code
in each of them.
Then finally, we also have one function
which will log all the big expenses.
So we can pass in the limit
and then it will go through all the expenses
and to log the big ones in a certain way.
And let's actually call that function here.
And let's say a thousand.
And so, it then prints only the emoji of all the expense
that were more expensive than 1000.
All right.
And so, let's now fix all of this
and starting with the var keyword here.
So as we learned in the last lecture
we should always use const or let instead of var.
So I will select all of them
by clicking or hitting Command + D,
and change them to const
even though there is one that should not be a const
which is this one here.
So when we don't need a const then we should use let.
And we will see why that is here in a minute.
All right.
So that was the first fix.
Then this one here,
the name limits isn't the really meaningful,
so let's call it spendingLimits.
So again, selecting it everywhere and then spendingLimits.
And so this makes the code more readable
and more understandable,
especially if we look at it in the future.
Now we have some problem in line 39.
So it's the same problem as before.
It should also be a let.
And then line 59.
Here it should also be a let.
Now everything works as before.
Here we already changed the function name
to add expense as a before,
then here we have this parameter names
which actually makes sense.
So these are fine.
No need to change anything here.
Then next up we have this check.
So what happens here?
So if there is no user then set the user to jonas.
Now what does this actually mean?
Well, essentially this is like setting a default parameter.
So again, if the user is not set, as we're checking here,
then it should be set to jonas.
And let's confirm that that actually happens here.
And so indeed here when pizza is added
without the third argument which is user,
then it is automatically set to jonas.
But, again as we learned in the last lecture,
whenever possible
we should use the native language features.
So in this case, the default parameters.
So that's as simple as this.
And if we now check it again, then yeah, it is still jonas.
Nice.
Okay.
Next up, let's fix this ugly nested code here.
So this code looks like it was written
by a complete beginner,
and (chuckles) so we want to avoid that.
So instead of using this nested code
and this huge if else statement
with all of these blocks here,
let's instead use a nice and declarative turnery operator.
So let's actually call it limit
because lim again is not really a nice variable name.
It's not really descriptive.
So, to do this,
let's first analyze what actually happens here.
So the function of course receives a user,
and then here we check if there is actually a property
with the name of user in spendingLimits.
So for example, what the default argument here jonas,
then, of course, there is spendingLimits.jonas.
And so, then in this case
the limit will be set to that value.
So 1500.
And otherwise, if that name does not exist
then the limit will be zero.
And so therefore then here in this check
the expense will not be added.
So if the value is less than the limit
then the expense will not be added.
And so therefore we are setting the limit to zero.
If the name does not exist.
So, if someone else like Jay here
is trying to add a new expense
then the limit of Jay will be zero.
And so therefore he will not be able to add any expense.
So, basically here we can do just what we do here.
So we can basically just do what we do here.
So check if this exists,
and if it does then we return it,
and otherwise, we just return zero.
So we can not delete this.
And of course, you finally, we can change it to a limit.
And yeah.
So our code here still works the same.
We still get pizza added and going to movies for matilda
which has a value of -100,
and a bit more about that in a second.
Now, if we try to add value for matilda
which is greater than 100, let's say 110,
then you immediately see that it was not added.
So now with the last one that we have here is pizza.
And the same here for Jay.
So again, Jay is not in the spendingLimits,
therefore, his limit is zero.
And then, it means that his expense it's not gonna be added.
Now this one here works just fine
but we could make it even more clever if we want it.
So let me show you another way of doing the same thing.
And I said in the last lecture
that we shouldn't write too clever code
at least if we then cannot understand it.
But the one I'm gonna show you here is actually not too bad.
So, what we're gonna do here is to use optional chaining.
So optional chaining remember works like this
but we can even use it with record notations.
So here we can then ask for the user property again.
And so, as we learned before,
if there is a property with this name,
for example jonas here,
then all of this here will be that value,
but if not, then it will be undefined.
And so in that case, we then want to set it to zero.
And for that, we can use the knowledge coalescing operator
which was introduced in ES2020
as the same time as this one here.
So S optional chaining.
And these are actually huge additions to the language.
They're used all the time,
and so it's a good idea that you get used
to writing code like this.
So let's see.
And or result should be exactly the same,
and indeed it is.
Great.
So I think that this one year is even better.
So, in case that the value is indeed below the limit
then a new object is created like this,
and will then be pushed to this budget array.
That makes sense.
Now the value here will then be the value but negative.
So you see here that all our expenses are negative values
and the incomes are positive.
And since we're adding an expense
it should indeed be negative.
Now here we can actually improve our code a little bit
because we have description equal description,
and user equal user, but that's not necessary.
Because with the enhanced object literal syntax
we don't need to repeat that.
So if the property name is the same as the variable name,
we can simply do this,
and our result will still be the same.
Great.
So with this all code already looks a lot more professional
than it did in the beginning.
But anyway, let's move on here to the next one.
And so, as I said in the beginning,
what this function here does is to check all of the expenses
and see if none of them exceeds the spending limit.
So, the name here is, again, not ideal,
so let's actually call it checkExpenses.
And so, what this function does
is it loops over all of the entries of the budget like this,
and here it's simply called like el for element.
So let's change that to entry.
Entry.
So a budget entry.
That makes a bit more sense.
And then here, again, we get that spending limit
from the spendingLimits object.
Now here, of course, we don't have any user passed in
but the username is simply gotten
from each of the current budget entries.
And if any of this is a bit confusing to you
then please just pause the video
and analyze the code a bit better for yourself.
So that's not really the point of this video.
The point of this one is more to fix the code.
So to make it more clean and especially more modern.
So, you see that this code that we have here is very similar
to the one that we had before.
So here in this function.
So let's just copied this and put that here.
And then, here it is, entry.user.
And yeah.
Then we can get rid of all of this.
And here we need to go back to calling it to limit,
and let's see what happens then.
So here we have this bigger expense.
So it's over the 1500 limit.
And so, indeed, now we get a new property here,
flag set to limit just as we have it here.
There should be another one somewhere.
Yeah, I think for, yeah, for matilda,
because she has the limit of 100
but these toys were 125.
And so, this one also has the limit flag.
So flag set to the string of limit.
So that still works nice.
We can just improve this a little bit more
because this code is now essentially the same as this one.
So remember the dry principle.
So we should not repeat ourselves.
And so, what I'm gonna do is to refactor this code
into its own function,
which I'm gonna call, get limit,
And for these simple functions
I like to use a simple arrow function.
So it's gonna take a user,
and here of course it's not the arrow yet.
So it takes a user,
and then it basically just returns this.
And so here the limit is going to be
get limit for the user.
And then down here the same.
And let's actually put that right here.
So getLimit.
And remember it here it is entry.user.
Then we can get rid of this.
And because now we can actually
get rid of the block entirely
because now the only thing that we have in the loop
is just this one declaration.
So we don't need these ugly braces anymore
at the same actually here.
All right.
So that's a bit better.
And in fact, we will keep improving this
after the next lecture,
when we will basically make this whole code here
a little bit more functional and more declarative.
But for now,
this is already a lot better than what we had initially.
And here actually we can do the same,
take that put it here.
And then, just like this.
Let's just check again if everything is correct.
And indeed it is still flagged with the limit.
Okay, nice.
We can get rid of this one here.
Let's actually put all of the logs at the end.
And now finally we have the bigExpenses function
which will basically simply lock to the console
this string here.
And so, let's improve the name here a little bit
and set it to logBigExpenses.
So that's a little bit better.
And here this limit now seems a little bit
as if it is just spending limit of before,
but it's really not.
It's just like an arbitrary limit that we pass in
just to see expenses that are bigger than this value.
So let's just call this one here the bigLimit.
And again, because it's a different kind of limit.
So if I changed it here like to 100,
then this should here change the output.
So now these are all the expenses
that are bigger than 100.
If I put bigger than just one,
then probably all of them will appear here.
Let's put it to 500 maybe.
Then we have only these two.
So what can we improve here?
Well, first let's again,
let's change the name here to entry.
Then here we can transform this string here
which has this plus into a template literal
which is a lot more modern.
So here we want then this part,
and then simply this string.
So none of this, and just like this.
Now, just a small observation.
We are taking the emoji out here of the string
which is just entry.description
by getting the last two characters.
Now that's because emojis basically count as two characters.
If I had only one like this
then we would get this weird sign here.
So it counts as two characters only then it works.
Then we also have this small heck here which is necessary
because otherwise in the end we will have
this separator here,
but we will keep that here for now
and fix it in the lecture after the next one.
Then all we can fix here is to get rid of this ugly if,
and transform it once again into the turnery operator.
So, how can we do that?
So we want to add something
to the output conditionally, basically.
So in case the entry value is less than the limit,
then we want to add this.
And otherwise, we don't want to add anything.
And so, that is just the empty string.
Now we can get rid of this,
and once again get rid of these curly braces.
Give it a save.
And here we are back.
And now this looks a little bit better.
So we say it's more declarative.
So it's more readable,
and you will learn actually what declarative really means
in the next lecture.
And I think that is actually it for this lecture.
So we followed many of the guidelines of the last lecture.
Now of course not all of them
because it's quite difficult to create an example
which violates all of them.
That would have to be a huge example
but I think this example is nice enough
and we will again improve it in the next lecture,
or actually the one after the next lecture.
So take some time and review what we did here.
And again, if something is not 100% clear,
why it works the way it does,
then just take a minute and review this code.
And of course, take a minute to take another look
at all the guidelines for clean and modern code
that I showed you in the last lecture.
And then after that, let's move together to the next one.