Lecture thumbnail 0:00 / 0:00 Okay, so let’s attempt to summarize the things that we’ve learned in this section of the course.
So we looked at the solid principles, and the first principle we looked at is the single responsibility
principle, and that is the basic idea that a class should only have one reason to change.
Now, this is something that also relates to an idea called separation of concerns, which is roughly
the same idea that basically different classes handle different independent aspects of the overall system.
So they handle different tasks, they solve different problems.
And then of course, you can combine them together.
So once you have separation of concerns, what you can do is you can take all of those concerns and
you can make them interact with one another.
You can make them depend upon one another.
And this is the kind of the the object oriented part of composition.
So you compose systems out of these separate concern solving tasks.
So this is the single responsibility principle.
Next, we looked at the open closed principle.
Now the idea behind the open closed principle is that classes should be open for extension but closed
for modification.
What this means in practice is basically the following.
It’s stating that if you’ve already got a class and this class has been written, it’s been tested,
you know that it works.
It is really a bad idea to come back to this class and to add additional functionality to the source
code of this class.
If you can avoid it, if you can somehow extend this class by using inheritance and interfaces and,
I don’t know, dependency injection, for example, then it may be worth not touching the original.
So the whole open closed principle can actually lead you to design object oriented systems in a slightly
different way, in a way which is originally extensible by introducing interfaces, for example, and
then implementing those interfaces in whoever actually wants to extend the system.
And we certainly looked at an example of doing precisely this by implementing the specification pattern
in the example that I showed.
Next up, we had the Liskov substitution principle, a basic idea once again that you should only be
able to substitute.
A basic idea that you should be able to substitute a base type for a sub type because object oriented
design requires that you should be able to sort of cast a descendant to its base and store it in a variable
of type base, and it should still operate correctly for the most part, meaning that you might want
to make certain things virtual so that you are accessing the correct members.
So the no particular magic in the liskov substitution principle is just the basic idea that you are
going to meet situations where perhaps the consumers of your API would try to access things through
a base type and they might encounter problems if you don’t keep your own design of your classes consistent.
Next up, we looked at the interface segregation principle, a very simple idea, by the way, that
you shouldn’t just put too much in an interface, and if you put too much in an interface, you’re forcing
the implementers of that interface to implement things they don’t need.
That actually also relates to the so-called Yockney principle.
You ain’t going to need it.
Basically not putting in code, which you you don’t actually need to do anything.
And that is what an interface which is too fat forces people to do.
It forces them to make implementations of members they don’t need.
And then the question is, well, what do you put in those members?
I mean, do you throw an exception?
Do you make a no op?
Do you write to the log that this has been invoked even though it’s not implemented and and so on and
so forth.
So instead of having all of this, what you should do, if the interface is handling too many concerns
at the same time, is once again you split it into separate interfaces.
In this case, it’s also close to this idea of separation of concerns in that if your if whoever implements
the interfaces has to handle different concerns in different places, don’t try to bundle those concerns
into a single massive interface that everybody has to implement and has to pay the price for implementing
effectively.
So the last principle that we looked at is the dependency inversion principle.
And here the idea is simple.
It’s the idea that high level modules should not depend upon low level modules and that you should use
abstractions where possible.
So this is a very simple idea of object oriented design that if you have implementation details, then
you shouldn’t expose those implementation details directly.
If you are emulating a database store, you should not expose the store itself because, well, this
is what object oriented design is all about.
It’s the ability to change the internals of the system without changing the exposing interface.
So instead of exposing, for example, a collection, what you can do is you can make a new interface
and provide query mechanics for querying into the collection.
And certainly when we talk about typical interfaces like I Enumerable or I queryable, for example,
this is what it’s all about.
Instead of exposing the details of each different collection and their mechanic, you make a kind of
general interface and then the high level module can take this interface, perhaps as a constructor
parameter using dependency injection or something to that effect.
And it can start using this interface without knowing anything about the low level implementation details.
And these are the solid design principles.
Play Play Play Play Play Play Stop