hey guys I'm starting a new series
called code like a pro and what we're
gonna basically teach you is how to code
professionally it's pretty apparent when
you open up somebody's project and it's
a hobby or they're just starting out and
they don't know how to improve their
code make it so that it looks
professional it looks readable
maintainable these are all going to be
things that I've picked up as my years
as a developer but also that I've you
know I can't take credit for most of
them because like you know I read books
and I do courses and I've learned these
from people with many more years of
experience than I have so what does it
mean to have professional code like what
I mean by that well I want to give a
sort of analogy to explain it a lot of
times when you're getting started all
you really care about is does your code
run and does it deliver the features
that you're you know the client wants
does it work and it can and I'm assuming
it does in both situations where you're
writing professional level code and then
you're just writing some code where
you're gonna you know getting started
and learning it's sort of like comparing
a tree house to a home it's how I feel
like it like there is something that's
going to last the test of time because
we have written it in such a way that
it's going to be maintainable and easily
update it and then you have a tree house
which is going to slowly get worn down
because we didn't build it in the proper
way
both shelters one's going to outlast the
other so what makes clean maintainable
code well we're gonna be talking about a
whole slew of things in this series and
we're actually going to be giving in
specific examples not just like hey you
should do it this way we are going to
tell you how to do this way and why but
we're also gonna give coding examples
we're gonna say okay when I say variable
names need to be descriptive and how
what does that mean exactly and how can
we showcase that our code will be now
more readable by using something like
you know object or ad structuring for
instance to get us going here and see
actually see in our in real time how we
can take this set of code and now we
make it this set of code and it makes a
whole lot more sense so we're gonna talk
about code readability
you don't write code for yourself or the
client even well I mean you do because
they're cutting the checks right so but
the reason the not the reason but one of
the reasons that you write code is you
write it for the next person has to
maintain it right the average dev is a
job two years or something like that and
chances are that projects gonna outlive
you for a very long time and so you need
to make sure that you're writing the
cleanest code possible the most
maintainable code and to do that you
have to write readable code so what is
the link team to those of us who are new
the concept well linting really is two
things and these are always I whenever
you're incorporating a tool you have to
answer what I call the big two the what
and the why so what is a linter it is a
tool that you set up essentially one
time usually per project that will flag
airs programming errors bugs stylistic
errors and suspicious constructs was I
mean it's basically gonna catch syntax
errors that's it it's going to find out
if you're making simple mistakes in your
code we're hey you're declaring this
here outside of its scope and that's
gonna break Java Script is one of those
languages where sometimes we don't find
if that happens until we work our way
through the application so linters give
us the opportunity to find those airs
earlier and more often it also adds a
readability what that means is we're
gonna make sure that we our code is
formatted in such a way that is the
industry standard or is a standard for
that language that programming items and
that's the why so it's gonna catch
errors syntax there sometimes for more
than syntax errors it's gonna have
trouble catching logic errors but yeah
but that's that's usually more so a
developer issue and we'll talk about how
to catch those later on this something
that can also be automated so you don't
have to run it every time it's just
there and we'll start picking up good
habits by just sort of being trained by
the linter to a degree and this will
lead to more readable code less prone
less bug buggy code and we'll be writing
in better standards because of it so
let's go ahead and jump into an exam
all right so what we have here is a
typed script file which is just
JavaScript it's a superset of JavaScript
and what we're gonna be looking at is
you know immediately because he didn't
intend this file to retire if we have
some error so I'm not too worried about
that right now
we should have some worries but you'll
see here this is before we turn the
linter on by the way and so what's gonna
happen here is we're gonna go ahead and
turn the linter on and see hey let's
take this file from someone just getting
started and see how we could just clean
up our code to follow the standards and
don't worry about the setup of linters I
will include as I mentioned two videos
but I'm gonna go ahead and turn the
linter back on and reload the app and
what we're gonna see here is quite a bit
of difference supposed to be oh there
goes just a little bit of a hiccup so
you can see that now there's something
wrong with pretty much everything in
this file and this is so where linters
excel at is catching those small errors
that are cement semantics in nature or
that are you know we want to anything
that we can compare that they're not
logic based errors there our structure
heirs they are formatting heirs items
like that and so what you'll see here is
that the standard for comments for
instance this have a space between them
and so that's something we can fix
you'll see here that and in modern
JavaScript you know the VAR keyword is
essentially forbidden and that's what
the word they use and it'll say okay
this is something that we have decided
that you know use letter constant so for
the time being we'll go ahead and change
all the VARs here and there's quite a
bit right there's quite a bit to let so
we'll change that to let go ahead and
replace all of those far so we may have
to change some of them the cons you'll
also see that when we hover over this
the CS lint is saying hey on average you
can use you should be using double
quotes that's in quotes that's kind of a
silly one but you can change that
depending on your preference but I think
the the more important point here is
that you see double quotes here singing
quotes here is we want to have a set
and 'red of what it is we're doing you
shouldn't have multiple ways of how you
do things like this in your code so
let's go ahead and replace all the
single quotes with double quotes but you
can see how we're slowly going to make
this file just look a little bit cleaner
this isn't something necessarily the
winter would do but from a personal
standpoint I would say that that you
know you want your codes spaced out
evenly as well when we're getting
started here your code needs to look
like you cared that's really what code
readability means as we're going through
here so we'll go ahead and put a space
here put a space here and there's gonna
be other things that we're gonna want to
do this file as we progress but we just
want to make it a little bit more
readable and we can do this in just a
few more steps anytime you'd have
commented code in here as well you can
go ahead and remove that there's no
reason to have that anyhow so right now
you're going through the file we're
doing these minor changes a lot of this
will be syntax stuff so if it's
important right we're using a let
instead of a Const and there's there's
hundreds of rules when it comes to this
and so what you'll end up picking up are
these good conventions these conventions
that say hey what makes a good what
makes a eight well what makes good clean
code because that's really what a linter
is therefore for what it can do in that
aspect and you'll pick these up just
your habit if you're having yam so what
we've done is now we have made our code
just using the linter and there's still
some errors in here and that's we'll
talk about those in a later section but
we have been able to make our code much
more readable much more understandable
and to the latest standards and in terms
of just basic TS lint things and linters
to get going so laters are here to stop
those syntax mistakes lint trees are
here to get you the code in a certain
manner in a cleaner manner in a more
readable manner and they are the first
step to writing cleaner more
maintainable code this will be the more
of the hard code like this is the only
tool the rest of the stuff we're gonna
be talking about this is stuff that you
have to learn that you have to implement
and one thing about linters and in our
case we're just using TS lint but one
thing is that you have the ability
override rules because they're not
absolutes right we don't live in a world
of absolutes but these always help to
get you going these always help to get
you started especially when you're just
getting started to writing cleaner code
and in especially in a JavaScript
environment where this is kind of a
newer idea when you're getting it going
and knowing maybe I've told you about it
which is kind of occurred to me like
this is where we should start today
we're going to be talking about how we
can define our variables and use them
better to accomplish a couple objectives
right we all want to be able to write
software like a professional and these
are some of the items that you need to
keep in mind when you're using variables
as well as defining names for variables
so what is that going to accomplish
we're gonna have three objectives by the
end of this course you're gonna write
code that is more searchable readable
and understandable there's a lot of uh
bolts there but this is what our
objective is here and we're gonna talk a
little bit about what those what how
we're gonna accomplish those objectives
now these are just some of them but
we're gonna be diving into other things
as well we're talking about following
language standards limiting scope of
variables we're talking about creating
new variables versus reusing them
eliminating magic numbers and magic
strings and items like that in general
we're gonna talk about naming varial in
a good portion of time talking about
that about choosing a name that
describes what a variable does or what
its purpose is not how it does it and
then we're going to talk about what I
called the this relates to name and the
variable is what I call the parent or
significant other test well dive into
that in the code examples and we're also
gonna talk about when we can use long
names for variables and when verse short
names and you know some of the you know
how we can incorporate that into our
code and more some of the and more
sections we're going to talk about is
the practices that a lot of people do
that we need to break right you're
actually causing more harm than good and
those are some of the examples we're
gonna give so I'm not one that really
like looking at at slides I learn from
the code let's go ahead and dive in
alright so let's start with a couple
different things here here we have a
simple algorithm to return a factorial
of a number it's not important about the
code it's not important that's in
JavaScript but the important point here
is there's a couple things that we can
fix immediately with our variables one
we can start following the language
standards right this is something that's
very simple and immediately going to be
apparent in JavaScript for instance you
would never ever have something and I'll
captain unless you're dealing with a
constant and an actual constant meaning
it's not an object or an array that
you're going to be modifying but this is
something that we need to keep in mind
at the very least because before we can
get get into the higher-level things of
hey we need to be able to to understand
how to write good variable names this
week we have to just understand how to
write variable so we have to write this
to our standards so we're gonna use our
camel case lower case camel case which
is the standard here and go ahead and
fix this alright the next thing that we
need to start thinking about is can we
eliminate variables the less variables
the better and this is actually some
code I wrote from like three years ago
so you know don't think that you know
everyone writes bad code and we all
improve as well as long as we put effort
into but can we eliminate things this is
something that we need to start thinking
about because it's rather important and
the less variables we have to maintain
the better so in our example here we can
actually eliminate this count variable
altogether there's really no reason to
have it and you know you'll see here
okay what are we doing with it we're
saying it zero okay can we eliminate it
well yeah because number here which is
just a number and this is typescript
right and we're expected to return the
number here just provide some context
but count isn't counts doing nothing
count is doing absolutely nothing for
what we need to do it here is it
performing anything different than
number no then what we can do is we can
just eliminate it there's no shame in
eliminating variables when needed you
know this is just clutter at the end of
the day you should if you can't have as
few variables as possible because then
there's less moving parts there's less
things that we have to keep track of now
you start we start looking here where we
have another no no at the end of the day
this this is debatable but in my opinion
we need to numb is not a descriptive
enough word and we probably shouldn't be
reassigning the values either as we are
going through here as you can see right
so we're modifying them which is now
going to break this for loop but let's
go ahead and create a variable that
actually has a good name now when we
create a variable we want to describe
what it does or what it is and not how
it does it a lot of times when people
start getting descriptive you know I let
me give you a very bad example of a
variable name in this instance let
factorial let total multiplications and
we'll you know initialize it to numb all
right total multiplications is
technically true for a variable name but
it isn't what we need to do here and
it's not what we we should want to do
either yeah
so total multiplications is not a good
name and a better name is factorial
factorial total now what is this well it
is the number that we are storing our
factorials in our total factorial all
right now let's go ahead and set up here
and we can do it just like so and now
here we'll return our factorial total
and not some random numbnuts coming in
let's give another example of some bad
variable names all right let's take a
look at this function all this functions
supposed to do is return today's date
now you'll see here we have this D and
this is a very simple function but we
have this D here and we're creating it
now if we didn't know what this was and
we didn't know what this was would we
know what D is if we had a conversation
so earlier I rec I talked about the
parent our significant other test so if
I said to you baby what do you think
variable D is what would you say
okay okay oh well what would you say if
we renamed it to I said hey what do you
think today's date as a variable would
would be excellent that is the
significant other or apparent test you
should be able to Hansel won a piece of
paper and this is the title really at
the end of the day and it should be that
readable when you get going
let's go ahead and give some other
examples let's give a few more examples
of how we might refactor our code in a
relatively clean project where we want
to make it more readable and more
understandable when it comes to our
variable names here we have an algorithm
that is going to take in some values a
double nested array for when we last
backed up some items that's all we need
to know about it now the first thing
that we can do is what we're going to be
returning back is a are the file IDs
that we want to update but you might be
thinking hey we're just returning file
elegies another way that we could up
that make it a little bit better is it's
actually technically we only want the
ones to update so go ahead and make that
more descriptive is now making this this
function more descriptive in the process
and you have an idea of what it is
you're trying to accomplish it's going
to update this like so all right next
one thing I want I've talked about in
the intro was that there are times to
use short variable names and there are
times you use long variable names now in
here when your scope is very short
meaning it's like a callback function
it's returning something it is alright
to be using short names such as here so
we're having file IDs all we're doing is
sorting it is I personally will still do
file ID but this is an understandable
situation especially in typescript where
we might do we might drop that F put ID
and then maybe we add a type of file
onto here right and then it's it's just
as descriptive as before but now we can
eliminate a little bit of clutter but in
terms of short scope of our variables
like so this is completely fine if we
wanted to shorten those
a little bit but one thing I would
highly suggest is that you start using
tools that are built into the language
where if you are going to iterate
through an entire array for instance
there's no reason to do a for loop like
this we're iterating through the entire
array and we have tools to make this
more descriptive while still iterating
through it so let's use a four of loop
for instance and I'll talk about how
we're gonna make it more descriptive so
in our for of loop we're gonna remove
some variables we're gonna remove all
these ugly eyes and instead we're gonna
replace changes eye with a more
descriptive word that allows us to write
cleaner more readable searchable and
maintainable code so how can we do this
well what which what we're gonna have is
a change of changes and we could maybe
let's let's just refactor it's one piece
at a time so here we're not eliminating
pieces of pieces of text here
piece by piece by piece and it's a
little bit cleaner now what are we
iterating through well we're clearly
iterating through our array of changes
which is an excellent name and when you
were talking about renaming variables
make sure that you take into
consideration renaming functions and
renaming parameters because they are
equally as important when you're moving
forward and we'll have a whole section
on functions and parameters as well but
that's nice neither here nor another
there but you'll notice that we have
this change 0 and change 1 and change
one and you know if you're super into
familiar with the changes array it may
make sense but we want to look at our
code and not have to dive deeper we want
to have the simplest ways that we can do
that and we can use things in JavaScript
and other languages as well where we can
give a more descriptive descriptive
descriptive descriptive variable name
and assignments here while making our
code so what is change 0 change 0 is
greater than last backup time doesn't
make anything but if we go ahead and
create a Const air and we say hey let's
do some will say Kant's is equal to what
we want to change we'll create a
variable here so each one these changes
are
ray will do a little bit of array
deconstruction and we'll say last
updated time and we'll go ahead and also
create a variable here called file ID or
updated file ID and we'll just set this
equal to change and we have those
variables now that we have this we can
make our code here so much more readable
we're saying hey is our code was our
last updated time greater than the last
backup time that makes more sense than
change to zero right and was our updated
file ID do we already have does our file
IDs to update already include the
updated file ID if it doesn't go ahead
and add two file IDs to update our
current file ID now with just a couple
changes in our logic here not not
changes in our logic changes in our
structure we have eliminated some of the
floating sort enough floating but index
values that aren't needed and we have
instead done a little bit of array
deconstructing to pass in values and now
this reads very very clear at least in
when it talks about our variable define
menemen so it's a weird where do you say
one thing i wanted to say is don't be
afraid to change variable names as well
so the thing you have to remember when
you're writing code is that it's always
changed your I new features are coming
out updates are coming out and even just
sitting here I was thinking about this
variable name a little bit and I was
gonna move on to the next section by
sinking this isn't even completely
correct it's not that file IDs we want
to update we want to backup files that's
what we're trying to get here now we are
storing file IDs in there but what is
what is it we're trying to accomplish we
are trying to backup files and so file
IDs to backup we're not trying to update
anything and so these are the IDS to
back it up
so don't be
to jump in and change this and if you
dive into the code and the variable
names are bad or the variable names have
slightly changed don't be afraid to go
and change it a lot of times people are
especially if it's code they didn't
originally write one thing that people
do all the time especially when they're
getting started with object-oriented
oriented programming is they start
prefixing property names with the name
of the class and it's a really bad item
what I mean by that is say we have this
cat class and it is our friend's cat
that's whose cat it is and we want to
update our friends cats age so we've
just had a birthday you would have the
properties right now which essentially
are variables at the end of day of an
object say hey cat age is now 10 and
then our friend's cat dot name we're
updating his name to be Tito we do not
need to prefix property names in our
classes so we could go ahead and just
remove that like so this is something
that people do all the time all the time
all the time and I've been guilty of
this as well so don't think most of
things that I'm telling you are things
that I've done and learned from there's
no reason to preface preface prefix
these items you know we have
intellisense we can hover over we can
see the type we can look through the
code all it does is create clutter and
confusion so when you're dealing with
objects you don't want to be doing that
another thing to keep in mind is when
you have constants when you have
variables older developers although it's
not too common nowadays well use what's
called Hungarian notation or essentially
you're going to include the type in your
item so let's say we have a type here
and I remember our file IDs so we do 5
IDs and then you would include number at
the end or at the beginning depending on
the convention but this is essentially
Hungarian notation now this is a very
bad practice and something I encourage
you not to do for one if you're using
typescript you don't need to and most
programming languages that aren't that
is not JavaScript will have a type that
you can assign to it
- what else could file IDs be it could
be a string I guess I could be a number
but this adds clutter and unnecessary is
actually a dynamic type and so we get a
number of string sometimes a string
number what do we do all we're doing is
adding confusion to our code so avoid
Hungarian notation as much as possible
all right one thing that you need to
avoid as well are what we call magic
numbers and strings for that matter when
when it when you are but that's a little
bit different magic strings refers to
passing in a key into an object that you
haven't defined you typically want to
avoid that but here magic numbers refers
to passing in numbers that apparently
came out of nowhere with no context
right so here you'll see 63,000 667 and
point four four four seven do you know
what this is I I do just because I had
recently looked at it but it took me a
second to figure it out
this is actually the earth radius to
figure out the orbital period so let's
go ahead and provide contacts and
context and we'll make this a a big old
constant in this case and all caps and
we're gonna set it equal to this value
now we have a much better idea what this
is
and when go ahead and pass in earth
radius actually I don't really like that
now we're gonna do it like this if I was
doing a global constant I might have
liked that but either way so we have
earth radius here and then what is this
big ol number well it's going to be the
gravitational metric we'll do grab
metric and set it equal to this and
insert crap metric here now our code is
much more readable we do have more
variable so that's alright but it's more
readable which is the objective here so
avoid magic numbers win at all possible
another thing to keep in mind when
working with variables is you want to
limit the scope to be as
small as possible and what I mean by
that is you know here we have this
beginner project that we've will be
refactoring or we did a refactor and
upcoming linter video but we we have a
ton of of global variables typically you
want to avoid global variables if at all
possible and when you can such as like
this answer buttons used in two spot
it's used in this function here
same thing with only used in this
function the same thing I would imagine
with this one and what's with this one
so what we can do is we can go ahead and
take this jump down to here and put it
into our where it belongs which is in a
more local scope to where it's at the
idea here with your variables is you
want to keep them as close to where they
need to exist because it's going to
provide the most context for how much
they are useful right so you typically
want to avoid the global scope if you
can and put variables in the most
limited scope possible so that you can
get that additional context another
variable naming to consider is when
working working with boolean
specifically there is a is for present
tense or has for past tense in terms of
the naming convention this sort of lets
you flag it out here and we can you know
typically we don't ever want to put the
variable types in here if we can avoid
it so we can do something like this
where instead of is box boolean with is
box meaning it is a box or it is not a
box or if you prefer that past tense has
box or does not have box in that sense
the only thing I will say that when you
are naming this keep it singular because
part of our objective here is to make
items readable and pronounceable so his
box would be how I would go about it
typically for me in the present tense so
we can go ahead and replace box boolean
with a box everywhere and clean that up
a little bit so that's something to keep
in mind when you're working with naming
for boolean variables
now this is a little bit of a personal
preference I would say but one thing for
variables is default parameters a lot of
times you'll see people use this or you
know if we have a invalid value here a
falsie value but I would I would argue
that if you need a default value for
your parameters they should be which
essentially are variables at the end of
the day right we're passing data
anything it passes data we're
considering very well at this point but
we instead want to have this value here
the reason for it is now the reason for
it is it's its default value thus you
can assign the only the only caveat to
that is that it does it work slightly
different than our or operator so this
will only assign a default value if it
is actually undefined while here it will
do it for any false a value so keep that
in mind but in general you want to
unless you have a good reason want to
put it in your default parameters
because it's in one location
one one place to look at and it's it's
in my in my opinion a little bit cleaner
than using the or operator
we're talking about functions our
objectives for functions are gonna be
pretty similar to what our objectives
for or for variables we want to have
readable searchable and understandable
code which will lead to more
maintainable code we could go ahead and
put that in there as well if we want to
but three bubbles seems like enough so
are some of the ways that we're gonna
consciousness us where it's gonna differ
slightly we're gonna write smaller
functions and we're gonna say showcase
how we might do that and why and when
might we might do that and we are gonna
also go ahead and hide me for a second
[Music]
movemove there we go we're gonna move
Dylan over here and what we're gonna do
is we're going to eliminate boolean
flags we're going to talk a little bit
of all these things we're talking about
why I just want to tell you why to do
things this is the right way do it my
way it's not not always my way but do it
but can't tell you why that's important
so uh we're going to talk about writing
our functions so they read top to bottom
making sure that's the correct way we're
going to talk about correct function
naming how do we know we're naming
functions I work over about three four
things that we can do to name our
functions properly and give some
examples we're gonna talk about limiting
parameters and how we might go about
doing that and why we need to do that
we're gonna of course talk about the DRI
principle which hopefully everyone's
familiar with don't repeat yourself and
why that's so important we're gonna talk
about avoiding side-effects in our code
to the best our ability and we're going
to be talking about why there should
never be global functions these are some
of the topics we're gonna hit on let's
go ahead and dive into some of the
examples this file might look somewhat
familiar we're going to continue to
refactor it so we've talked about one
concept per or at least I think we have
one concept per action item right so if
you were going to get some data you
might preface that with the verb get you
know you're not gonna start using
interchangeable words like retrieve and
and uplifter i don't know why you wanna
say upload typically you'd say get and
that's the idea here and that goes the
same for like if you're going to use the
word update for updating something that
would be what you would do you wouldn't
say set you want to say update you you
choose a verb to stick with because you
want your code to be readable and part
of that process is renaming the very by
renaming the function names as well as
in the process
eliminating comments now I in future
section we're going to talk about
comments but right now we're not going
to worry too much about it because it's
more about functions but they kind of
are interchangeable at times so we have
random number here for the most part
this is a this is a decent decent
variable name some things that we could
change about it is variable names are
supposed to be verbs there are actions
that are happening so how do we change
this to verb well we add get we have
getting on here is more descriptive of
what it actually is
you'll see here we have a min and a max
I don't we could maybe change random
number here to be get random number from
range if we really wanted to be specific
I think that's fine because I that
that's that's as descriptive as we can
probably get and you know this is
typescript in JavaScript typically you
don't have return types this is a
personal preference I will say what I
think makes more maintainable code is
when we actually put explicit return
types typescript is optional and in
JavaScript it doesn't exist but in most
languages you have the ability to add an
explicit return type as well as
explicitly saying what these values will
be which I think are is equally
important you know I think let's just go
through this this project from the top
to bottom and see if there's a way that
we can update these functions just to
make the function names a little bit
more readable a little bit more
understandable let's see here so this is
our box-sizing prop add CSS to selected
buttons and changes answers in box
sizing so realistically I think this
should probably be broken out into
different app different different
functions whenever I see an if/else like
this I started thinking about how can I
eliminate it not because if an else
statements are inherently bad or
anything like that but usually it's
because they really are doing two
separate things and I want to treat it
that way so in in this instance I would
define a Bock a function update see
we're gonna update is Fox
so select changes answers in box there's
a update order box-sizing something like
that and in here let's start it looks
like we're not actually returning
anything which is why it's an update but
we know how to put a void return type
and instead let's start by here passing
this in here that should all still be
the same and then in here and I think
we'll do a little bit more updating in a
second as well this dot update order
box-sizing else this is going to be
content blocks function update content
box sizing it looks like we're not going
to be taking anything in else in here
try to put a void on that and we're
gonna go ahead and paste this in here
like so and go ahead and do this update
content books I think I'm sorry we don't
need to this on here because we're not
working within a class it's just a
generic type search application so we've
now put all the logic in two separate
files and if and we're saying at the end
of here reset so we have this double
order box and our else and we've sort of
put these in two smaller functions
that's really one of the things if your
functions more than ten lines long you
need to start reconsidering
reconsidering how we might be able to
how we might be able to go about and
refactor the
and you know that that includes renaming
these to provide additional context like
we could probably have guessed based off
the content that was in here that hey if
border box is true update border box
sizing but and then reading through here
to see oh well we're updating content
box right and that's how we did it to
name this but a better way of doing that
is to write cleaner more maintainable
code as we can and then that that way
also we can test these functions
individually as well we'll say hey
update content box sizing that makes
sense an update border box-sizing it's a
more descriptive variable name and it's
easier to read here as well and and what
happens on top of that I guess is that
once you you know if any of the codes
breaking you're obviously gonna look at
these functions but when you're looking
at this sort of container this public
function public function mean meaning
the users going to be dealing with it
while these would probably be private
functions meaning that the user doesn't
even know they exist they just see that
there's something that says update
border box sizing update content box
saucing they can't actually call these
directly then we have a month we really
only have to maintain one function and
be able to read one function to see what
it does in the in the meantime unless
something breaks or isn't working
properly okay so this would be a a great
example of how we might might modify a
name here this so we have this add
points where we're incrementing points
and you can make the argument that
perhaps what we're actually doing here
is updating the points add is a little
bit more descriptive but update update
points by one by by I so this is a
unique one because it looks like we're
always incrementing so you might
actually be able to say that hey when
we're always incrementing add is a good
name so I take it back I think this is a
good value here and then we are calling
great job after the fact now this is
more of a form anything and we'll do a
formatting video but typically you want
and we'll leave it but typically you're
gonna want to say your a lot you want
two separate blocks of code baseball
spaces
let's see here uh so this is probably a
a name that we would refactor very
quickly and the reason for it it's great
job is that descriptive right it doesn't
really provide any context it is it is
sort of a funny name in the fact that
like oh great job what is what is this
actually probably a completion and
animation this would be something like
trigger completion something like that
like you have animation probably on top
of there here we are saying like hey you
completed it it's an animation in this
trigger set right so this is much more
descriptive than great job let's see if
we have any more great jobs out there
nope just the one in here alright so
cool so we're triggering our completion
animation and I may have this slightly
wrong but triggering animation is right
there may be a trigger add points
animation that might even be something
that makes sense we're now adding points
I'm making the assumption that hey this
is this is something that is uh this is
something that is after they they're
completed the the example let's see here
set styles so I definitely would change
this to update styles because we are
trying to do one concept one verb per
concept right and you also notice that a
good job was not a verb as well
functions and methods these are verbs
and we need to treat them as such right
so I'm not really take so here we're
gonna do update CSS display again
because we are updating a ton of
different values here
yeah we'll leave it at that I think so
answer buttons a whole lot going on in
this thing let me take a quicker look
crow quick there's another great example
of how we're going to set different
values here there's a lot going on in
this function here and to be honest I'm
not fully sure everything that's going
on here we're gonna delete this line of
code because I don't do dick all right
so it sounds like this is updating the
answer buttons so we're gonna update
answer and I mean you could to preview
TN but there's really no reason to don't
be afraid to have a long variable names
long variable names are descriptive
variable names typically we have three
things here you know we all use
intellisense
it doesn't matter that we're using extra
extra buttons these are all all the
great things so uh how would we so I
think what we're gonna do here is we're
going to this incorrect won't ever use
it incredible and correct one and
correct so CSS is that here is a global
election so I'm going to and notice by
the way how when I'm writing these
additional functions that we're gonna
break out our code it's always right
next to it it's it's by convenience but
it's also by design where we want
functions that are used by other
functions if possible to be nested in
the code where you would expect them to
be right so I'm defining a function that
I'm going to use here and I want that I
want it to I want it to be nearby so I
can see it and provide context so in
this case we're going to write a get and
this is going to be get all answers and
this is going to take and what is this
taking in this is taking in anything it
is going to take in a nothing it's
actually going to just return things so
here
we're going to return an array of I
believe numbers cool and what we're
gonna do is we're gonna take pretty much
all of this and we're going to replace
it with a Const answers is equal to and
then we'll say that get all answers and
in here we're just gonna go ahead and
return turn this like so and what's the
problem here
oh yeah let's go ahead and put this in
here very nice okay so I'm not worried
about formatting and spacing that's why
I'm not cleaning this up for some of
your losing their mind
it's what I'm what I'm worried about is
cleaning up our function code so now
we've put this all in one one function
where we're gonna handle that and then
the thing that heats us thought it was
sorting the answer buttons wasn't so we
might as well just delete this code
while we're at it know that comments not
relevant I'll leave that in there for
the comment video okay so for each one
dot HTML and even something like this
this is this is actually so here we're
updating answer buttons I guess this is
part of this one we could break this out
if we wanted to but I think that's fine
but now we've been able to take a lot of
this logic slightly change it and do
something with it that that now makes
sense right we don't really need it all
in here this is getting all the answers
incorrect and correct and if we wanted
to make it more descriptive we could
even put in correct and crashed because
that's what I felt necessary to describe
right so start going off your your own
thing is like what's this dude gets all
the answers what is all it's incorrect
and and correct so maybe if you know I
usually go with the verbal test for a
lot of things and it helps a lot when
when
describe wouldn't describing functions
yeah one other thing we talked about was
eliminating boolean flags and that's
sort of what I meant with this this
if-else cuz that's really what it is
it's a bullet I mean typically a boolean
flag would be passed in here but in our
application one thing that we could do
is we could probably eliminate this
dysfunction altogether and just do our
best to have these trigger the correct
code and we could go ahead and throw
reset into each one of these when
they're called and we can just say hey
we need to make sure that this is only
on the one with the ID of border box and
now we don't have to have this sort of
boolean flags if else that goes in there
or or a flag that goes in into the event
or the the the parameter or anything
like that so typically if you can and
it's not always possible but it's
possible more often than people think
it's great to do try and eliminate those
those boolean flags so that you don't
have to worry about them now somehow
this is not I mean after I think I
talked about it when it comes to
variables about not having Global's but
so in this in this project we have this
CSS here which is you know we don't we
don't even really do anything with it we
just initialize it so we want to do our
best to not have Global's and there's
quite a bit of Global's in here and the
reason for that is even an
object-oriented programming one has have
a SKU side effects as possible it's not
always possible you know this so you'll
see this like CSS global variable here
honestly when it when it's like this or
even you let me see if we're even using
this anywhere yeah yeah we are
I use but you'd probably be better off
doing something like this where let's
just eliminate this variable altogether
and in here we are going to get the
width the pack padding the margin and so
we can eliminate this global variable by
writing a function where we say
something get CSS box model properties
and in here we will go ahead and take
all this and put this in here and what
we're going to return and it's just an
array of those values right now with the
pad the vrdr the god I would probably
rename a lot of this stuff so I'm going
to guess this is order I'm also going to
guess that this is margin and I'm going
to guess that this is a border style so
I start by renaming those even though
this isn't about variable rename is just
as important margin and then order style
all right so that's what I'm going to
return here which is with pad margin
border we don't care about that right
now
other places where we're going to use
this we're going to update it down below
so in this instance we are going to say
counts and I think what we'll do is
we'll just do some array D constructor
in here
and we'll say this is equal to
it co sucks well small properties that's
a cost all right cool
what's the issue here shadows there you
go I think I think whiff might be so
sort of global variable or might be a
reserved keyword same with border no
shadow oh maybe they want us to use it
no we're using with so pad it should be
padding I don't like pad either all
right so here for padding we're going to
throw it in like so for border gonna
throw it in like so shadow a shadow damn
no shadows variable like that I know I
think there's probably some naming thing
in here but instead of focusing on that
on the video you just focus on the idea
here so I'm just gonna throw out one on
this so we're just gonna do some so
string interpolation here into a
mortgage in one and then we'll go ahead
and do a border style one for oh it's
not border so this is box-sizing see Wow
box is one and go ahead and do that and
then down here let's update our stuff
boxing excellent now this is the same
thing here I don't have to look into
there's a shadow variable thing is but
okay now now we've gone and created this
this item here and where we're going to
be using those CSS properties let's go
ahead and find the CSS here here we go
and say Kant's CSS is equal to gets CSX
box model properties like so we still
have access to them we will eliminate a
global variable and in our functions
we've eliminated side effects throughout
the entire application where we have to
we have to track like okay I set the CSS
box CSS property here and now I call
five functions it's this after this step
this after this step you got updated
here got reverted here we don't want
side-effects like that we want to even
an object-oriented programming to take a
somewhat functional approach eliminate
side-effects we're gonna be talking
about comments comments are a little bit
of an interesting topic compared to the
other items because in this section
there's more why we don't use comments
and how to write good comments so that
but those are gonna be our two main
objectives so we're gonna be talking
about what are good comments what are
bad comments and how we can know if it's
worth point worth having one what are
some of the downsides of having them and
how we can for the most part remove
comments in why right so the very first
aspect that we're gonna be talking about
are what makes comments bad this is just
two points there's a lot of other things
but these this is a first example we're
gonna get so these are the two most
common reasons I would say that comments
are used that the the major issue with
comments these main two and then there's
about five others were uncovering the
second but comments are used when they
really aren't needed
and typically comments are used to
explain bad code usually when you are
writing your code at this point you've
seen you know good variable names and
we're gonna showcase an example of that
good function names we're gonna showcase
an example of that as well then if you
write your code well in a descriptive
fashion you shouldn't really ever need
comments so let's go ahead and jump into
an example so we won't focus on two
things in here one where there's
unneeded comments and two where comments
are unnecessary right and I even talked
about this in the slide but misleading
comments as well one of the reasons you
don't want to leave comments is that's
another additional thing that we have to
update another thing that we have to
maintain its documentation essentially
that we have to maintain and it could be
counter productive to our code so let's
look at an example of that first where
we have a function name here called
longest string it's singular at one
point perhaps this returned a single the
single longest string however examining
the code and reading the comment here
says gets all the longest string so our
comment here is different than the
function variable name and one thing
that we can do to eliminate this comment
is we can actually update this name too
to make more sense right so typically
your function names just want to be
verbs and in this case we're getting an
array of things so we're going to get
the long string so we can eliminate this
comment and now we have a much more
descriptive name and this is these are
things we've already talked about but
here our next comment is a example of
just a length length of what right so it
here we have we're initializing the
longest let two index at zero right so
this comment doesn't make a lot of sense
it's really unnecessary right so instead
of length we can we can call this
because let's look at how its utilized
here we're checking to see what the
longest word length is in the string and
so we can do something like this longest
word length
easy enough now we've eliminated that
comment we have one less line of code
and we have a much more descriptive word
and in this case we don't really need to
put I've said in this case like 8 times
but there's no reason to define that hey
we're getting these ear that that
comment basically said we're
initializing it to a length of zero does
that help anybody can no one tell that
that's what's happening here it's it's
very you just have to have read the one
line of code in its they're adding that
provides no additional value so we now
can go ahead and put this into here
we've eliminated our comments and here's
another great example of a comment that
really isn't necessary checks if the
current string is longer well I think we
can all tell that the current string is
in fact like this is what's going on
here this isn't an overly convoluted if
statement this isn't a you know anything
that's outside of the norm we're doing a
simple single comparison in this comment
here as well filters out any values not
equal to the longest string we can we
can tell that this is a essentially a
one-line and even we could remove some
characters here as well just to clean it
up if we wanted this is a one line
callback function here that's filtering
out now one thing that we can do as well
is to just hone this in is rename our
variable here and we can call this
longest words and what we've done now is
we've eliminated some misleading
comments or miss act technically the
comment wasn't misleading but the
function name was misleading but
typically it's in the reverse order and
we've also eliminated unneeded comments
just by renaming our variables and just
comments that really weren't doing
anything right hey hey here we're
telling it to to you know check the
length like we can we can see that very
easily two more things that people love
to leave in that are really bad comments
are leftover code that's code that we've
commented out and then that we don't
plan on using at that time and then
version control
so let's go ahead and give some examples
now this doesn't happen too often
anymore but occasionally some some
developers will have this bad habit left
over when version control was a little
bit more of an issue and this this both
these section I'm kind of combining the
two because I think they stem from a
place where version control is kind of a
pain to work with so you have these
blocks of code here where the whole
prayer it's a log you know they're
basically locks hey on the fourth of
July you put a comment in and then you
know on the tenth we put in you know a
comment here all this stuff is handled
in the version control with our comments
and there's really no point or place for
it in it now the other thing that is
really bad practice is having you know
you can comment code out when you're
working when you're testing when you're
going things but you should never have
code commented out in your application
when it's in production or it's moving
forward the reason for it is you're
gonna confuse future developers why is
this commented out is this supposed to
be commented in should I go and delete
it if you're no longer using a piece of
code delete it if you need to go back
and get it that's what version control
is for we have references to it there's
tons of logs that have all this sort of
stuff we can jump back in and get it
there's absolutely no reason in today's
world to have combinated code in in your
in your production application so either
come I'm coming back in because this is
part of one of my actual projects but
delete it from the application and move
on
with your your with your programming so
visual markers are another really bad
tendency when it comes to common so it's
a visual marker essentially a just a
block of code of a commented out code to
say this is what is here this is what is
there let's go ahead and give an example
so I know we've all seen at least one
file in our lifetime that has done this
where you have these sort of blocks of
codes that really describes what's going
on with the structure of your page
what's going on with the formatting of
the page here you know dependencies are
here many information here properties
are here public functions are here
really when it comes to structuring up
and this is
angular but this is the same for any
sort of class or any sort of component
or just code in general you want to you
know that this is much like other
comments just filler text that takes up
space and room and if you actually think
that you need to break out this part of
your code you need to consider having a
new file because it's the concern is so
different that you need to put eight
like a big block like this then maybe it
is something that's entirely different
instant we need to pull that out and
give it its own sort of domain but
there's no there's no reason to have
these tags let the structure of your
classes be what they should be right so
tip properties are excellent example
typically your properties would be the
first thing in your class and you know
followed by maybe a constructor and then
a function no no real need to put
self-explanatory sort of tags like yeah
this is clearly you know the decorator
meta information this is clearly the
dependencies which come up at top by you
know by standard so these sort of visual
cues visual markers there is absolutely
no reason to have it in your application
the last sort of item I want to sort of
caution you when it comes to comments
are to do's so if you're not familiar
with to do is to do something def
selected e where they like to I'm trying
to think of a different word than do but
they like to do to dues to say hey go
back and add this feature expand upon
this remove this delete this and I don't
really have any examples to show you for
this but I just want you understand why
it's bad convention for one a to do much
like other comments or something you
have to maintain it's something that you
have to keep track of now if you want to
keep track outside of the application
that's perfectly fine but requirements
change which means that to do may no
longer be it to do and you may not be
the one doing it but if someone sees in
the code they may do it and it may no
longer be relevant and in fact it may
actually break the code it's just
another piece of it's just another thing
we have to maintain and that can cause
confusion and issues down the road so
please avoid to do's now we've talked
about
some pretty much all a ton of bad
comments and if you've kind of got a
little feeling from this side you
shouldn't leave comments in general
that's a good practice right we've
talked about how we can make it we could
eliminate the need for comments because
comments are really there when we have
failed to name our functions and our
variables properly and in our code to be
descriptive right we want the code we
want the better structure our code so
that we can tell what's going on in the
code without having to leave the comment
that's our objective here we write
better code where comments are not
needed now there are some times where
comments are especially needed and and
we're going to give some examples of
what those might be so let's talk about
the characteristic of some good comments
and some comments that we have to have
to have so the first thing is that needs
to be short and concise it's whenever
you see a paragraph of commented out
something chances are a lot of that's
fluff a lot of its unneeded or it's
redundant and is it's going to cause
more issues and not and with such a big
comment it's it makes it even harder to
maintain so we want to make it we want
to make it short and concise right if it
goes longer than one line you've messed
up on your comment so you need to
refactor it it provides value you know
just saying hey constructor here we can
see a constructors there but what's the
value and so when do we use a comment
all right so these next two things kind
of our kind of grouped together but we
use a comment when it clarifies code
that has a business purpose but looks
out of sort right so what I mean by that
is there may be some domain knowledge in
the system that you know newer
developers may not be familiar with and
here we we say a warning or an
amplification of it's important to say
hey I know this looks strange and it's
you know there's not a cleaner way of
doing this but we have to do this to get
we have to do this to protect ourselves
or we have to do this to provide the
functionality that's needed and here is
why so when there's something that's
strange like that like oh I don't think
we have to do this but we actually do
that's where we want to have a comment
comment for that business purpose as
well as to provide a warning or the
amplification of its importance and then
of course legal comments legal comments
there's no real way around it sometimes
when you're using open source libraries
you need to have a legal comment at the
top of your file to use it that's just
something that's part of it and there's
other ones as well those are the types
of good comments so let's go ahead and
give a couple examples of a warning or
or a amplification of importance type
comment all right so let's take a look
at some examples of what perhaps could
be considered good comments so the very
first one is a legal comment so as I
mentioned sometimes to use open source
libraries you they'll have you paste
this in to one of your pages where
you're using it and so these typically
will go at the top there's really
nothing you can do it get around it if
that's what the the license says and
this I'm just using a random open source
library I just made something up and
sort of what it would expect so gotta
have that so I consider that a good
comment not the best comment the next is
an informative comment that isn't
readily apparent right so something that
show cases but needs clarification and
there's not really a good way when we
have these three different date
matchings to in the variable do it
without it getting clustered and
cluttered and it's just not going to
look all that good so here we say hey
this regular expression it's expected
format is these three items now or are
these three items rather these three
formats and so that's a great way to do
it now that there could be an argument
made that perhaps we could see this in a
in a test for wherever use this function
that's a fair argument but this is an
example of something that I might leave
a comment to provide value because I
mean at first glance I don't think
anybody's gonna look at this and be like
oh yeah this is what it does no it's
it's not like nothing like I so another
thing is remember I told you about
warnings or amplifications this is an
example right so let's say we're taking
in an ID and you know this might look a
little strange to you when we're
comparing these numbers that we're
trimming the value that comes in and
we're parsing as an int all this sort of
stuff so
perhaps what we you know and probably
want to do that for this for JavaScript
but say say there there was an
outstanding issue and even this is kind
this is best I could come up with
thoughts top of my head but we're trying
to explain why we're removing the trim
from the from the string and the reason
for it is there's an outstanding issue
with the UI ulay arias injecting
characters and perhaps we can't solve it
or we you know it's something in there
but it's a warning to say hey why are we
doing this and why are we treating it as
a string and all this sort of stuff and
why are you removing the characters it
shouldn't be passing any empty
characters with it if we did our our job
right right so those sort of warnings as
to hey this doesn't really make sense
this is kind of odd those are the
comments that you have to leave for when
when you when there's no way around it
when there's something that you need to
tell them like if you remove this trim I
know it looks like it doesn't need to be
here but if you remove it it's gonna
break everything and that we haven't
found a way to fix it yet or we're going
to fix it but short and concise provides
value of some sort telling you what it
is and then legal comments now by then
this you've probably said hey man
so we don't leave comments anymore
that's a good thing that's another thing
we don't have to maintain our unit tests
are going to be our form of
documentation to explain how our
application of all's our code structure
should be clean and concise and follow
standards and there's no reason for
those blocks of codes you know comments
for what a function does our variable is
should be nut should be should be far
and few between because we're going to
name our variables properly and we're
going to name our functions properly so
that they're descriptive and and and
show us what our code is doing instead
of us talking us through comments
typically are used as they're redundant
and they're you know they're used to
tell you what you can already see but
worst of all they are a crutch for bad
code and so we're gonna make our code
better so we don't need comments if
you've never heard the solid acronym
you're not familiar with it don't worry
bring it you caught up to speed so what
are these solid principles well as I
mentioned it is an acronym and the S
stands for the single responsibility
principle the oh is for the open-closed
principle the L is the Liskov
substitution principle the I which is
one of my more favorite principles of
the solid principles is the interface
segregation principle and finally we
have the dependency inversion principle
so there's a lot bit lot of principles
going on here five right so somewhat
intertwined some of them all of them are
important and we're gonna dive into a
little bit about the history of the
solid principles so where or who rather
did these principles come from where did
solid come from right because these
things don't just come from nowhere and
they came from Robert C Martin who you
might more affectionately know him as
Uncle Bob who is the author of clean
code the clean coder and clean
architecture which if you haven't read
the clean code the clean code regardless
of what skill level you're at
whether you're a super senior or you
just got started today I highly
recommend those books and clean
architecture I recommend as well but I
think you should wait till you probably
have at least a junior level role and
there's links for all that in the
description below if you're interested
but with that being said he introduced
it in a paper in 2000 about almost 20
years ago on the design principles and
design patterns and that is really what
the solid principles are there are ways
for us to write our code and deliver
some things and we're going to talk
about why we should write our code in
such ways so that they support certain
development practices now he's also the
co-author of the agile manifesto and you
might be saying well why is that
relevant well because that's part of the
solid principles goals you know if
you've been working in software
development for the last 10 years or so
well you've probably seen is that the
waterfall software development life
cycles are dry and
agile is a flowing river if you will and
so that is what we're trying to
accomplish with the solid principles is
in general I would say that they are
designed for object-oriented programming
but that you can use them with other
like functional stuff but it's most
performance not the right word but I'd
say it aligns best with object-oriented
programming I would also say that it's
language agnostic this isn't something
that you just do for Java this isn't
just something that you do for
JavaScript or C sharp or you know your
language of choice go whatever Russ
whatever it is and that's one of the
great things about it and it also sports
agile so as I mentioned agile is sort of
the way of the of software development
nowadays and because of that it because
of that rapid development lifecycle that
you know if you're you're doing scrum
you have two week iterations where
you're delivering features every two
weeks right you know we have you know
some places are doing continuous
integration and continuous deployment
mean when it goes out it's out like it
goes straight to master and so we need
to make sure that our architecture is
great and we need to make sure that the
testing and the test-driven development
processes are followed and the solid
principles help us to do that so why
does it help us do that
well it help us accomplish a couple
things it helps our code to be more
understandable or readable it helps it
to be easier to maintain and it allows
it to be flexible so the strengths of
the solid principles is it abstracts
some things so it's so when changes
happen it's it's much more flexible to
get them to work and it allows us to
extend things instead of instead of
breaking things and having to rewrite
things and so that it's much easier to
add something than to have to rewrite an
entire thing
and that's one of the strengths of solid
principles and it accomplishes these
three things through the the five
principles alright so let's go ahead and
dive in a little bit to each one of
these principles so just to get a
high-level overview of what they're
trying to accomplish so the single
responsibility principle favorites the
famous quote a class should have one and
only one reason to change so this is
about good Google good organization of
your code and understanding you know how
good inheritance works and understanding
how to write our code in such a way that
things are bite-sized to a degree and
are not going to have more than it
should write a a will give some code
examples but there's a lot of and we've
talked about this in other clean code
series where you don't really want to
pass boolean sin to tell it to do one
thing or another for instance that could
depending on this situation change the
the logic that's happening not if
something should happen but it's like
hey do it if is this person don't or do
it if this this other customer type that
would might might be something where now
we have multiple responsibilities in a
single class we don't want to do stuff
like that because it makes it much
harder down the road to follow the logic
to follow the code but it's all about
keeping things in to the bare-bones
minimum that a certain object should do
and enforcing that with the single
responsibility principle so we after the
s comes the Oh open/close principles you
should be able to extend a class
behavior without modifying it so this
goes to my earlier statements about we
want to extend functionality we don't
want to modify functionality and you
know in a principles are in a perfect
world I sometimes requirements don't
come through and
sometimes this is impossible but this is
the general idea these are what we are
trying to follow in a perfect world and
so another item about this is you want
to be able to if you're if you're
following proper inheritance you should
be able to swap in different versions of
different services and items like that
so you can extend maybe an interface
that we'll go into in for your service
or items like that and the open closed
principle is refers to that it'll make a
little bit more senseless code I did a
very important job of explaining that
but essentially we want to extend items
without changing the code base right so
if we're adding a new feature in theory
we shouldn't really need to modify the
previous code and if we have our if we
have written our code in such a way
we're going to we're going to add upon
it instead of modifying what we already
have the Liskov substitution principle
and I don't know too much about the
gentleman named Liskov but he had some
good insight here so uh most of these
principles are not necessarily Uncle
Bob's ideas but ideas that he has used
and and catered and somewhat tweaked and
over the last 20 years or so put out
there too and that's sort of his goal to
get people software developers to write
them and let's guy was just one of the
many people along the way that have you
know he has learned from I suppose this
what I'm trying to say so with that
being said derived classes must be
substitutable for their base class so in
any good object-oriented programming
language you usually have a base class
that you can extend to your child class
a an example of this an excellent
example on Stack Overflow for you to
look this up is a square class extending
from from rectangle so the the reason
that this wouldn't you wouldn't be able
to subset swap to essentially swap the
base with their derived classes it's
because
function differently right at first
thought it may it may seem that yeah you
know what why wouldn't they why wouldn't
want to inherit from the other right
every square is a rectangle but not
every rectangle is a square and that
should be your hint right there because
if you can't swap them out then there's
something going on wrong here and you
might want to rethink your approach
right because let's say a you change
usually in rectangle or in in a perfect
square you always want the length and
height to be the same so there might be
logic in there that would handle that
but that's not necessarily the case for
a rectangle so you wouldn't necessarily
swap them or inherit from from one and
so those are the types of things you
want to think about because there's
probably a better approach than
inheriting from a classes so that's what
the Liskov substitution principle
derived classes must be you must be able
to substitute them for their base level
classes so the interface segregation
principle one of my favorite principles
I like a lot of them but the clients
should not be forced depend on methods
that they do not use at first glance
this this quote I could probably could
show some better quote but the idea here
is that you don't want to couple the
code so tightly that you can't make a
change without making changes in
multiple places and so to help
facilitate that we add a level of
abstraction which we do through
interfaces and this allows us to do a
lot of things once it allows us to
easily overwrite code if we need to
right so like a common use that I use
the interface segregation principle for
is testing right so sometimes when
you're testing on the front end you
might inject an interface and it's going
to that your service extends and then
you can maybe mock it out or expect
different things or override it there's
a whole bunch of different things that
you can do with that but the interface
segregation principle is key to that
because if we were passing in hard the
hard
code it's not hard-coded but the actual
service call itself it'd be very
difficult and probably actually it
actually hit the API so we don't want
that either but we'll dive more into
that but the idea here is that couple
twofold one that you should have a layer
of abstraction and two that you
shouldn't force people to use things
that then makes it so tightly coupled
that they they that you can't override
it and that's the idea here with the
interface segregation principle now if
you haven't noticed by now I've said the
word abstraction about 15 times and in
the dependency inversion principle that
will continue on so high-level modules
should not depend on low level modules
both should depend upon abstractions
this goes back to depending on not
necessarily interfaces although you will
but it depends on instead of having your
actual code depend on other aspects of
your code what you want or to have those
abstraction layers is that you code in
there and that allows a lot of
flexibility especially when it comes to
testing and mocking things out and so
the dependency inversion principle helps
support that as well today we're gonna
be talking about the first letter of the
solid acronym the S the single
responsibility principle I'll be your
host as always still in Israel so what
exactly is the idea behind the single
responsibility principle well it states
that every software module should have
one and only one reason to change now
what does that actually mean it means
that we're gonna have smaller classes
we're gonna have single responsibility
classes and this is gonna allow us to
limit the impact of change so you know
what does this actually mean so this is
a quote from Uncle Bob who is a very big
proponent of solid principles
essentially the Creator gather together
the things that change for the same
reason separate those things that change
for different reason so what I take that
to mean is we're gonna have Kohi
where it matters and we're in a decouple
our code where it doesn't matter now
most people focus only on making things
as small as a as possible to automatize
things to such a degree because that's
more so the issue more so people have
things that are just too big but you can
also go in the opposite direction you
make things to minut and too small and
but that oftentimes doesn't get any
attention but I wanted to bring that up
because that is an issue in itself so
let's go ahead and I want to share this
link actually real quick before we jump
into the code but this is a this is a
link to Uncle Bob's blog where you can
read more about the single
responsibility principle here and I
think it's really helpful so go ahead
and check that out I'll put it in the
description below as well but let's go
ahead and see an implementation example
of how we might use the single
responsibility principle all right so
let's take a very simple example here of
how we are not using the single
responsibility principle and how we can
go ahead and use it to make it better
so I'm doing this in typescript you can
just think of it as JavaScript for the
most part now everyone should be
somewhat familiar with the cash register
right we have ways you know they charge
tax that keeps track of our totals you
know there's a subtotal typically
Annegret the grand total which is your
subtotal plus tax and fees so a very
simple example here and we have a
function called calculate total all
calculate total does is we have it
updates our grand total so it gets the
total wit tax and then we email a
receipt to to the client say hey thank
you for your business your total was you
know one hundred one hundred dollars if
you're balling hard and you buy like
groceries or something so you might be
saying why is this breaking the single
responsibility principle well should
this email private email receipt
actually be sending anything in reality
and mind you it's an empty
that or should the cash archer be
worried about having logic to email or
receipt and the answer is no it
shouldn't what what should happen here
is that there should probably be an
email class or message class that
handles this that we then instantiate
that class and have it go there and the
reason for that is it takes it's still
going to send an email right because our
mail class is going to handle that logic
but that's really where it should live
right and that way if we change our code
down the road we're you know what we
need to update how we email clients
customers it's all in one central
location and we now we now have a single
reason to change right before we had two
reasons we had well if the total changes
you know if the cash register code
changes and great we have it's right
here but also if you want to change how
we email customers and clients we have
to go into every class that we had this
email logic and we then have to modify
it well instead if we have a central
class that handled that we can go ahead
and and do exactly that
in one central location so it makes our
code a little bit smaller and puts it in
different files so how might we fix this
well pretty straightforward right we go
ahead and create a new what's a let's
just call it email email class TS you
can go ahead and export a class here and
then here what we're gonna call this
email and email is going to have a
message and note shall we before we had
to send receipt this is a more of a
generic class where maybe it's going to
be something like send message right so
we'd have a public send message and in
our example it just took in a message
this would be a strength
and this would go and email you know
let's just say we pretend that we have
something to say email console.log the
message whatever our lard logic here
does it doesn't it doesn't really matter
and then we could simply go ahead and
take what's here and we're going to
create a in the constructor we can
create a property here you know we'll
call this public email equals new or
public cotton maybe mail would be a good
name public you know some new equals a
new email you know just go ahead and
import it from there oh you don't be
better actually let's just make that a
static method right because are we
really ever gonna create multiple
versions of it this is a little bit more
of object-oriented well this is going to
be a static send message and now this is
gonna do the same thing every time right
similar if you're not familiar of static
it essentially means that this is a
property or a function on a class that
you can use you can import it once and
use it and it's not going to be
something that you're ever going to
necessarily redo so here we have email
dot send message our static method and
we'll go ahead and just pass that
message like so and we can delete this
logic here and now we've set it up so
that it has one reason to change we're
still sending an email with the receipt
but our cash register the only reason
our cash register changes is this
something regarding the cash register
domain changes well now that we have
this email class if anything in our
email class changes then it will auto
update if in our
- right anywhere else were used in that
class because it has a single purpose
now and so that's really what what the
single responsibility principle is
trying to instill a good rule of thumb
when you're trying to decide what's what
is if you find yourself having to put an
ore ore into your variable names and
function names you oftentimes will see
that you probably don't have things
broken down enough and because of that
you're gonna you're probably breaking
the single responsibility principle a
good way to to also help and sometimes
developers will find themselves in this
developers aren't used to like maybe
object-oriented programming will find
themselves into a situation where they
start doing like boolean flags that's
another example a lot of times of not
always but where you might so perhaps
extending a class or using some
inheritance you might be having using a
boolean flag to change between two
pieces of logic that do two completely
different things that's another sort of
gotcha to watch out for when using the
single responsibility principle we're
now on the open-closed principle let's
go ahead and jump right in so what is
the general idea for the open-closed
principle well you've probably heard
this if you've ever heard of the
open-closed principle many many times
but software should be open for
extension but closed for modification
I'm usually software very generally
we're talking about classes we're
talking about modules pretty much any
anything any aspect of software that's
reusable we want to make it open to
expand upon but close to modify that
original level of code so what does that
really mean well what it means is and
this is my interpretation but
essentially means we want to extend the
code so that we don't have to refactor
legacy code legacy code bean code that
was there before we started writing our
code before we started expanding upon
this and this is especially
helpful not necessarily in greenfield
development but when you are adding new
features to code or refactoring code so
what does this actually mean right what
it actually means is the successful use
of inheritance properly you know how we
can extend things using inheritance
makes it a lot gives us some flexibility
to make our code more wait for it solid
and it allows us to change our code
easier and allowed these changes to
occur easier easily rather so that we
don't have to worry about it breaking
and it being an issue to jump into the
code we have to we don't have to update
it in multiple spots that's this last
note here is a well-written class should
not have to be updated in multiple spots
now again these are principles these are
not the end-all be-all there's always
exceptions to the rules or exceptions to
the principles but these are the general
things that it will actually allow us to
do so let's go ahead and just make a
quick note
saude principles are a lot of people
have preached about them but one person
in particular is Uncle Bob or Robert
Martin as you might know him and his
blog post here goes into greater detail
on the open-closed principle and I'd
highly encourage you to check it out
just to have a you know multiple
interpretations of it I'm gonna give you
my interpretation of it and you can get
someone who's much more familiar with it
than myself because it's been preaching
about it for about 15-20 years but
that's a lot of words let's go ahead and
give a live example now let's jump back
into our previous example with the cash
register you'll notice here that I've
added a constructor that's going to take
a balance and we're going to it's going
to be a number of the balance of the
drawer essentially and so a bad example
of how we would be modifying our code is
exactly like this right and so we might
have a balance property here and we're
gonna sign that to a number and it's
somewhat relevant right so we're gonna
say like this dot balance
equal to the balance that comes in but
now what's happening sir we're actually
modifying the original code and this
will happen again and again as we
continue to expand upon our cash
register example but you may be saying
like Dylann well shouldn't the balance
be part of the cash register and isn't
gonna need you know subtotal tax rate
maybe the grand total because we may
have to you know find out if we have
enough cash in the drawer but by
modifying this we're now adding
complexity to the cash register that may
be what we really need to do is to find
a drawer class that extends the cash
register that inherits from that and
that's where the balance list because
it's sort of new functionality that we
can actually make it a little bit more a
little bit of a smaller class while
still having access to that so let's go
ahead and do that because that's gonna
show an example here we showed an
example of what we don't want to do we
wanted to be close to modification well
how would we make this open for
extension all right and to do that let's
go ahead and just create a little file
here and we'll call this drawer cash
drawer if we want and what we're gonna
do here is we're going to export this
class here I guess we don't technically
have to export it but I'll call it our
cash drawer cash dryer drawer I don't
know someone will correct me in the
comments I have no doubt and in our
constructor here we'll go ahead and
essentially do the same thing that we
did it's gonna be a number and we'll go
ahead and have a property here public
balance like the number and then we'll
set it just start number is equal to
balance oh this top balance excuse me
they stopped balance sequel to balance
cool and now I'll just go ahead and take
this out of here because we don't want
that in there because that would be
extending it but here we just need to
extend
our original cash register and when
we're doing at least in type shape when
we're extending a class we need to call
super which is just essentially saying
that this is a child or being extended
from our cash register which is the
parent here and now although we have all
the access to subtotal tax rate
calculate total but it has its own draw
we have our own drawer here where maybe
we need to use some of those properties
later on we will we could have access to
that we can reference them here and not
have any issues and we've successfully
been able to extend the cash register
class without actually modifying it so
open for extension closed for
modification now this is just one
example and a very simple one at that
but these are the sorts of things that
you need to think about as you're
developing code right what separates a
junior developer from a senior developer
is the ability to not only make the code
run but both of you will have your code
running but having something that is
going to last the tests of time the best
our ability be easy and maintainable and
testable - and allows change in a much
more simplistic fashion so that's the
open closed principle today we're going
to be diving into the Liskov
substitution principle our third or
fourth video on the solid principles as
we're working our way through and this
one's a little bit of a doozy you know
if for a lack of a better word so I'm
gonna give you the very computer-science
heavy and if you're if you've ever gone
and pursued a bachelor's in computer
science or really looked into the
fundamentals of it this wording will
seem very similar because a lot of these
principles are worded in such a way the
idea from that stance is if s is a
subtype of T then objects of T maybe
replaced with objects of s without
altering altering any of the desirable
properties of the program so this
reminds me of college quite a bit and
it's it's a little bit confusing right
it's even for people who write software
professionally there's probably a better
way of explaining the concept that we
can do that so what does this actually
mean well what it essentially means is
that subtypes should retain the behavior
of the main type now we're talking about
inheritance you know an easy way of
playing that is children should be like
their parents for what they inherit you
know if you are overriding the
properties of the parent then probably
what should happen is you might want to
rethink how you are abstracting your
code and how you are inheriting your
code and the structure that because you
might have something wrong because it
may not be a child right and a basic
example is if I'm a human April is a
human and that is our type and we have
children and it's a duck something went
wrong because we should not be able to
have a duck you know it could still have
a name property it could still have an
age right but it definitely should not
be a duck should probably be a human
child no it definitely should be a human
child we have to rethink it so the
common thing that happens is you know
that that's what that actually means and
you know the way that most people
explain this to you is that if you
cannot substitute a child class for its
parent class in your code still be
functional then that means that you
broke something that that class is
inheriting because all your child class
is doing it is should be extending the
behavior it should not be altering the
behavior of a parent class right and so
with that being said let's go ahead and
jump into an implementation of this
because it's a little computer science
heavy but you know we'll give a good
example as with all things software
stack overflow
this is excellent example I think that
really hammers the Liskov substitution
principle down so let's take a look at
the code here we all have a rectangle
class a rectangle has a height and a
width they are independent of one
another right the height can be any
value and the width can be any value any
positive value I should say and when we
set the height with a method and we set
the width all it's doing is saying the
height in the width now one thing that
people suffer with and one thing that
people get wrong about object-oriented
programming is they oftentimes say that
it models real-life that is a fallacy
that is somebody who wants it to make
sense but you are building you were
taking the abstract and making it
concrete you're not taking the concrete
and making it abstract is how I kind of
think of it and although there are
similarities is not always the case when
it comes to code and this is a great
example as Y so we have our rectangle
class and our square class as well which
extends rectangle it inherits from it is
a child of our square claw of our
rectangle class and the issue here is is
when dealing with a square and a perfect
square your height and width are going
to be the same thing and you'll see here
we set the height it's gonna set the
height and the width we set the width
it's gonna set the width and the height
and now what ends up happening is
anywhere we actually want to use this
rectangle class we are going to if we
were to swap the child with the parent
it no longer would be an accurate
representation of what it is we're
trying to accomplish and because the
parent class here cannot be substituted
although a rectangle it can still be a
perfect square it defeats all other
rectangles right it's not that it's
impractical it's not that it doesn't
really from a logical standpoint makes
sense that hey let's extend rectangle
for our square because you know it is
that is makes sense mathematically but
the
Akala t of it is is that's going to
break the substitution principle and
cause issues down the road because we
should be able based off the principle
pass in the child for the parent without
any additional setbacks so how might we
how might we solve this issue if we
wanted to extend rectangle well the
honest answer is one you could remove it
entirely which we could do here the
other answer is we could maybe
reorganize our code so that we have a
shape class and so perhaps we would this
is just me sort of free balling it but
perhaps we create a new file called
shape I'm gonna export class shape and
in here we might have a public type you
can go ahead and make that a string and
that would maybe be enough if we wanted
some similarities probably not what I
would prefer to do but perhaps all
shapes will have a height and a width
and in here this also be a number and
from this will have rectangle we got
that out that extends shape and we will
have square that extends shape and now
we have a class that if we were to swap
it in now it'd be fine now granted it's
a very basic class and we don't even
need type in this current iteration but
here if we were to swap either one for
the parent class we shouldn't have any
issue right we're not gonna override
height and width are still gonna be
numbers take out the time and that's all
we're really checking for here there
aren't gonna be any side-effects but in
our previous example we would have just
fine by extending upon a rectangle
because we can't substitute for them
hence the substitution principle the
Liskov substitution crystals will harder
ones in my opinion because you you
almost have to be you have to have very
real-world working examples before you
sort of run into this issue we're going
to be talking about the interface
segregation principle in this episode of
code like a pro the fourth principle of
the solid principles so what is the idea
well the idea is to not force the client
the client could be people consuming
your your class or your object or other
developers right so that could be third
party in house but to make it so that
they are not forced to depend on methods
they do not use that's the idea so what
does that actually mean well it supports
the what we've sort of been talking
about with smaller classes or interfaces
this idea of role interfaces which is
essentially breaking out into the
smaller classes and interfaces that
should be defined and we'll give an
example of that and this supports
abstraction because as a application
continues to grow we're gonna start
having these issues where I have to make
one change in here and one change in
there and one change over here to do
this one change and so if we start
following the solid principles and the
interface segregation principle that
abstraction will allow us to make those
change in a much easier manner without
having a lot of side-effects which is
something we want to avoid so how do we
do it well
let's go ahead and give an example so
let's take this very large interface
here and typically a large interfaces or
large classes indicative of a very
complex object they have to say is this
object does this object need to be that
complex does it really handle this is
that is this everything you want to be
so so just sort of a red flag but you'll
see here we have our vehicle interface
just defining what our vehicle class
would be right we have a get speed that
returns a number a good vehicle type
which is gonna be a string you know some
some financing things you know as tax
paid are the lights on have we started
the engine have we accelerated and we
stopped the engine a start radio how we
[Music]
function do we want to play a CD do we
want to stop the radio so we have all
these sorts of various properties of
what a car or a vehicle might have and
looking at this this is gonna cost us a
lot of problems where every time we
modify the vehicle class for any aspect
whether it's the engine or the music or
the lights whatever it may be we're
gonna run in these issues where we are
treating this vehicle object as one and
the same and and the rowdy of the
situation is that's not necessarily true
so how might we go ahead and fix this
well let's do a little bit of
refactoring here where instead of just
the IV achill
we can have maybe in highlights right so
let's at defining interface here called
eye light and I in type scripts you
typically denote an interface with an
eye oftentimes I I'll build a abstract
class because interfaces are just sort
of ain't and you can do a little bit
some more complex interfaces stuff but
um I don't want to get too much into
typescript but if we have lights
why wouldn't we have it is lights on and
have that over here and it'll be the
same thing right you're just returning a
boolean so you go ahead and take that
out and it is lights off excellent and
we could do another thing where let's go
ahead and create a radio interface right
because we're playing with the music
radio and we would have our start stop
and play CD that's all of our radio
object and then of our I engine right so
let's see here we have start engine
accelerate that all looks like to be an
engine go ahead and do something this
interface alright excellent and so now
you'll see that we've sort of broken
this out a little bit more and we can
reuse these as needed and if we needed
to
let's go ahead and actually say we had a
vehicle class
and we wanted to consume these things
right the vehicle class is going to
extend a vehicle like so no expense
there you know a few months didn't you
save this is that why it's not finding
it there we go so and you'll see here
that we need to implement some functions
right we want to implement the get speed
that get vehicle type is tax play so we
can go ahead and define public get speed
and I'll do something you know we're
gonna say public is tax payable all
right here for the time being I'm just
filling this out real quick
so we return that just return to one
something like that and we have two more
implementations and then we're gonna
actually use the other interfaces in a
second here so that we can consume those
in a more responsible manner if we felt
that we needed to do that right so turn
this just an empty string here for time
being
well this is just a property excuse me
just for the sake of time we'll go ahead
and make that a function and then go
ahead and throw that on there as well
and we'll just return truth all right so
now we've been able to actually
implement that in our vehicle class but
we might have other things that we want
as well where maybe we have a radio of
type I radio we have to export these as
well but and then we'll go and we'll
assign whatever properties to sorry I'd
probably have a class in reality but
what this gives us the ability to now is
that all our radio logic is now
separated out over here we have our
various interfaces and we can use them
and it's all broken out to what it needs
to be right and we've now separated out
piece by piece so we don't have to and
abstracted it so that we don't have to
rely on this a massive vehicle interface
or class for that matter so you know
it's it's a lot of these principles will
sort of fall into that hole that each
sort of touch each other like some of
this may feel very similar single or
responsibility principle and some of you
may be saying like well why am i
importing you know why am i importing
radio into the vehicle class well you
have to understand let's say we want to
let's say one of our developers wanted
to use just a radio right they had a
need for a radio class and we wanted to
follow that if it wasn't broken out like
this they would then be forced to
install the vehicle class just to use
the radio so what we're doing is we're
gonna have strapped it break it down a
little bit so that you only care about
the pieces that affect your development
that affects your code and it's for a
good object-oriented principles so as
always guys I hope you found
helpful don't forget to comment like
subscribe and share and look forward to
our next video the dependency inversion
principle which is by far one thing that
I would say I found I didn't fully
understand but is by far my favorite
solid principle and I think has made my
software my code writing taken to the
next level so I really hope you take
particular interest in the dependency
inversion principle we are finishing up
our section on these solid principles
going to be talking about the dependency
inversion principle my favorite
principle of all five principles mainly
because I I really do use it almost
daily and I find that it to be one of
the most helpful I didn't fully
understand why but the more and more
I've practiced the solid principles the
dependency inversion principle has been
a crucial one for me to maintain my code
and make sure that it's clean and does
what it needs to do so what is the idea
you're gonna see if you if you're going
to do a Google search on the dependency
inversion principle you're gonna see
something like this high level objects
should not depend on the low level
implementations or high level modules
should not depend on low level modules
something very similar then I say okay
okay so what does that mean well three
main things that kind of duplicated this
but uh duplicated the first a second one
we wanted to pin on a dependent on
abstractions festival string along and
abstraction should not depend on low
level details and we just want to
generally support abstracting our code
now the dependency inversion principle
is quite unique in the fact that there
are several great ways that you can use
this and we've talked and remember it
relates to object-oriented programming
the solid principles and in our code I'm
gonna give you example how I use it
almost every day by creating mocks for
testing and making sure that it is the
test mocks match our actual
implementation that
as our actual abstraction class so that
everything is synced up and working well
together so let's go ahead and dive into
it so let's take a little bit of some
angular code this is gonna be a mixture
typescript and angular and what we're
looking at is a service here so this
service is gonna go and do some API call
our service is called hacker news
service and christen you know it's
pretty pretty normal it's nothing out of
the ordinary but it's not utilizing the
dependency inversion principle which
would have us abstract a interface to
allow us to not only extend the extend
this but make it so that other
dependencies are dependent promise class
R and so let's say we wanted to mock
this file out for testing purposes
because you know we already have our
test make sure Hacker News Service is
doing what it needs to do but we don't
necessarily want to actually use the
actual implementation and make those API
calls obviously so we're gonna have a
mock class but there's nothing tying
these two together at the very least we
can tie them together and make sure that
we don't have an issue with our mock not
matching what it's supposed to be so how
might we solve it well if you had a
interface in this click in this case
we're using an abstract class was the
same idea but if we had a interface to
invert the dependencies so that we don't
really care about the low-level
dependencies in low level low level in
this aspect it's actual implementation
of the mock the implementation of the
actual service and instead we're just
going to define the actual class itself
like so what we're gonna do is we're
going to take this and we're going to
extend the I hacker new service which is
fine was the issue here no this is just
some tighter stuff actually ringy's
implement so I have to say same same
thing more or less and so now we're
saying ok cool we actually understand
that it has all everything it needs for
AI hacker
service and we might find out that our
mock is doing it wrong it might be that
there's an issue there so let's kind of
implement I hack their new service and
in this case still the future decorator
but I thought this is gonna blow up but
didn't but now both of these are
extending the correct dependency it is
extending the abstract class or the
interface now in typescript we have a
way of injecting the interface and that
would be how we would actually consume
this is we will inject the interface
into the class and then depending upon
our dependency injection method and
angular you have modules to handle that
it would inject your actual surface
itself it's service itself while
providing the the interface let's go
ahead and let me show you some code of
where you might do something like that
so here we're looking at the module
which is how angular handles its
dependency injection or hat handles it's
managing of dependencies might be a
better way of saying that and you'll see
that we are providing the abstract class
that doesn't do anything but it is there
to say this is what is expected of our
service this is what our service should
be doing we don't really care how it
does it just as long as you meet the
requirements and then when we actually
go and want to have the actual
instantiation of that extra class which
is the actual surface itself use this
class use that class and then if we had
like a component if we were to do a
component
comp component - yes
and we want to X at now it's getting a
little angular 3 but if we had a
component like so that's supposed to be
component and we want to export whatever
X for class something in the constructor
the dependency we inject is the actual
interface and then it's just gonna go
and pull that class because we've
inverted error dependencies we may share
dependency injections on that that's
just a little more of how you might
actually use it but you get the general
idea is that if you're gonna have
something mocking a service or you're
gonna what you will and you want to have
a high-level object maintained what
everything does if you won't think of
that way and then extend that out or
implement it out and that's that that's
a very realistic I am that I use quite
often for the dependency inversion
principle putting out guys
we found that helpful as always don't
forget to comment like subscribe share
all that good stuff if you're
interesting in my courses I highly
recommend the 100 I'll give them a
challenge help you ace your next
technical interview there's a link in
the description below gate just for 10
bucks I'll see you guys next time
bye