Instructor: Now when working with classes and objects,
there are a couple of important rules
and principles out there which you might have heard
in the past already.
And all of these rules and principles and laws exist
to help you write more maintainable code.
That is the core idea.
Now, of course, as I already mentioned at the beginning
of this course section, there is a relation
between maintainable and extensible code and clean code,
which primarily focuses on readability
but therefore is also related to maintainability.
There is a connection for sure, but there are some patterns
and principles which are more important for a clean code
which have direct impact on the readability of code
whereas there are other patterns and principles which have
less of an impact there, but which instead really help you
with building large scale extensible,
maintainable applications where a lot of developers
can keep a project up and running over a long time
and where it's easy to add new functionalities ends on
and that is done only loosely related to clean code.
Now, of course, here I will focus on the principles and laws
which have a bigger impact on the cleanness of your code
and for that, we will start with the law of demeter.
Now, what is the law of demeter?
It is related to code like this.
Here in this code which could be in some method
of some class, we are accessing the customer property
of the class.
On that property, the last purchase property, as it seems
and on that last purchase property
which seems to be another object,
we access the date property.
You should avoid code like this.
Drilling deeply into other objects is something
which is discouraged by the law of demeter.
Now, why is it discouraged?
The law of demeter is in the end about the principle
of least knowledge, which means your class shouldn't rely
too much on the internals of strangers of other objects
you are interacting with in your code.
In this example, a customer would be a class property,
so interacting with it is fine and accessing last purchase
is fine but last purchase now is kind of a stranger.
We access it indirectly through customer,
and we shouldn't drill deeper into that.
Now, why shouldn't we do that?
Well, because whenever something changes
about the internal structure of last purchase,
all our code in this place where we have this line of code
needs to change as well.
And that then makes our code harder to extend and maintain
because simple changes can result in a lot of changes
in a lot of places of your application.
And this law is closely related to our concept
of writing clean code, because for one,
when writing clean code, we shouldn't repeat ourselves
and we often might do that if we have statements like this.
And in addition, statements like this are a bit harder
to read, analyzing such lines of code simply takes longer
than short, simple statements.
Of course, this isn't too difficult of a statement,
but it is also just a brief example.
So the law of demeter, which we should therefore
also follow to achieve clean code in the end states
that code in a method may only access the direct internals
which would be properties and methods of the object
it belongs to.
So you can access any property and method of the class
of which this method in which you run the code is part of.
You can access any objects, which are stored in properties
of that object.
So in this case, accessing customer is fine
because it is a property of the class this code belongs to,
as you can tell by the this keyword
and accessing last purchase is of course also fine
because that directly is part of that customer property.
You may also use any objects which you receive
as method parameters, so it's not just about properties
of the class, like customer,
but if customer would be received as a parameter,
we would also be allowed to access data in it
and of course, we also are allowed to interact with objects
which are created in the method.
So if we would instantiate another class,
we can of course, also work with the API
and properties of that class.
That's the idea behind the law of demeter.
And here's this example from the slide now in a
real dummy class.
I'm accessing date on last purchase on customer,
which is a property and only this part here would be okay,
because with this part, I'm directly working on the property
and the data in the property which is part of this class.
Date is not directly data of the customer property,
it's part of some other data,
which is stored in the customer property
and therefore we have only indirect access to it,
which is not allowed by the law of demeter.
Now here, in this example, we are, for example
getting this date to then call the deliver purchases
by date method.
And the obvious question now is
how could we clean this code up?
How could we change it such that we do follow
the law of demeter?
Well, one first simple solution could be
that we simply go to our customer class
so to our customer object and the class defining
that object structure and we add a new method in there.
Instead of this code, which for the moment
I'm commenting out so that we still have it for reference,
instead of this code, it would be better
if our customer class would have
a get last purchase date method.
This code would be allowed because we're directly accessing
a method in our customer property
and now this customer object simply needs such a method
which then internally accesses last purchase date.
And there, this would be okay because last purchase
of course will be a direct property or some data stored
in the customer object,
so then accessing date on that direct last purchase property
would also be fine inside of that customer class.
So this is how we could adjust our code
in the customer class
and then also in the delivery job class to not violate
the law of demeter anymore.
However, this is not a great solution
because now we basically force our code to follow
the law of demeter, but we still have some problems
and we didn't really end up with that much
of a cleaner code.
Yes, this code is a bit easier to read now,
so that is cleaner because it's a clear instruction
which requires no interpretation, but of course we now just
outsourced the problem into customer.
And whilst we technically are not violating
the law of demeter anymore, you'll of course quickly end up
with a lot of helper methods,
like get last purchase date here adjust to follow
the law of demeter on paper.
The better solution for solving problems like this
and the solution, which really makes this clean,
which is why I wanna cover this concept is that
you should tell, don't ask in your code.
Don't ask for information to then use it
but instead, simply tell other classes what to do,
if that is possible.
For example here, instead of getting that date
now with this helper method, just to then forward it
to deliver purchase by date, the better solution would be
to work on the warehouse instead of the customer class.
So that here on this warehouse, we, for example, can call
deliver purchase method instead of purchases by date
and here we pass this customer last purchase
and then it would be the job of the deliver purchase method
to extract the data from that last purchase
which it receives, which is required
to deliver this purchase.
Now we're not violating the law of demeter
because we're only accessing the customer property
and some data which is directly stored in that
and in deliver purchase, we just get a purchase object
which we also can use there to extract any data we want
because you can work with objects
and the data directly stored in them
if they are received as method parameters.
And this is now how you really would wanna solve this.
You wanna tell your code what to do and not ask
and that's all the why I wanted to cover this principle
or this law here because this certainly is clean code.
We don't have to interpret why we want that date
and what we could be doing with it.
Instead we, in the end, got rid of two lines of code,
which we required before, which we had to read
and we just got one line of code, which is 100% clear
about what it does.
That's the law of demeter and how you should follow it
and that's why it matters for writing clean code.
And as a side note and why I also wanted to include
this in the course, which is of course not just about
object-oriented programming and classes,
the law of demeter actually also can be applied to code
that uses just functions and no classes.
I mean, of course you can't apply it like this,
you can't apply the official law with all its definitions,
but you can apply its logic.
If you write code with just functions without any classes
because you are writing code in a procedural way
or because you use functional programming,
if you do either of these two things,
then you still wanna ensure that inside of your functions,
you don't dig too deeply into received data
unless there is kind of a data container only.
And you also wanna tell, not ask,
at least if it makes sense.
You should always ask yourself whether getting some data
to then do something with it in the next step
is the best possible way right now
or if you maybe just instead should tell some other part
of your application what to do next.
This is always something you can consider
because telling instead of asking is always super easy
to understand and automatically leads to shorter code
at least in the part where you are telling.
So the law of demeter is super important especially
when working with classes and objects
but also if you think about the general idea behind it
in other kinds of code.