Lecture thumbnail 0:00 / 0:00 Okay.
So we’re now going to take a look at yet another principle from the solid principles.
And this one is called the open closed principle.
So what is this all about?
Well, once again, I’m going to set up a scenario where we’re going to violate the open closed principle
and then we’re going to rectify this and get the implementation, which actually doesn’t break open
closed.
So let me first of all, show you a very simple demo.
Now, let’s suppose you’re building a ordering system, maybe some website where you can buy products
and the products have certain categories and certain traits.
So for example, you might have different colors of products, so you might have red, green, blue
and so on products, and you might similarly have an enumeration for the size of the product, how big
it is.
So you might have small, medium, large, maybe huge if you’re Donald Trump fan.
So now that you have this setup, you might have a class which actually implements these particular
traits or not so much implements them as uses them to describe a particular product.
So we’re going to have a class called product.
So the product might have a name, you might have a name like.
So you might also have a color and you might have a size as well.
And I want to keep all of these public, by the way, so I’m not making properties.
Instead, I’m just making public fields, which is completely legal in dot net, as you may know.
So let’s make a constructor where we initialize all of these fields.
So this is the name, the color and the size, and that’s it for the product.
Now let us suppose that somewhere on our wonderful website we want to be able to filter the kind of
products that we actually get to see.
And instead of using Linq to filter out a collection of products, we are having to restrict ourselves
to only filtering by certain criteria, kind of like Amazon, which doesn’t let you filter by the actual
rating anymore.
So we’re going to restrict the kind of filtering that you can do by using a product filter.
So let’s suppose that your boss comes to you and you says, Well, how about filtering by size, for
example.
So can you please ensure that customers can filter the products by size so you implement a method for
doing exactly that.
You say public static ienumerable of product.
Please filter by size or by color.
Doesn’t really matter.
Let’s have filter by size so you specify a bunch of products, enumerable of products, which is the
products, and you specify the size that you want.
So the obvious output of this is that you go through each of the products.
So for each var P in products, you say if P matches in terms of the size.
So if P dot size is equal to size, then you would return P That’s really pretty much it.
Now with this kind of setup, you can already start using it for certain things in the sense that we
might want to do a scenario now.
So I’m going to make a couple of products, I’ll make an Apple, which is going to be a new product,
which is called an apple.
Obviously its color is green and its size is rather small.
Okay.
In addition, we’ll have let’s have a tree.
You might go to a gardening store and buy a tree.
So that’s going to be a new product, not a string.
So it’s going to be a product called a tree.
And it’s also green, but its size is rather large.
And in addition, we’ll have a house which is yet another product like so.
So that’s a house.
It might be blue instead of green.
So it’s going to be a blue and also a large item.
Okay, So these are the three items.
We can make an array out of them or some other kind of enumerable.
But I’m going to go with an array here.
So we have a product array called products, and that’s what we’re going to have the apple tree and
house and then of course we want to start using that filtering functionality.
So I make a product filter, var P equals new product filter, and let’s suppose that I’m looking for
all the green products.
So what I can say is I can write line, for example, green products and that’s going to be, I’m going
to say old because that’s going to be the old way of doing things.
But you’ll notice that so far we don’t have any filtering by color.
We only have filtering by size, which isn’t what we want.
So in order to implement this new functionality, we unfortunately have to go back into the filter and
we have to modify the filter.
So we have to take this code, we can duplicate this and we need to filter by color this time around.
So filter by color and here we specify color, color.
And then of course this check becomes p dot color is equal to color.
There we go.
So now that we have this, we can actually start using it on the.
Product.
So we say for each var p in p f dot filter.
So in this case we have to make it public or actually it is already public because it just has to be
filtered by color here.
So we specify the products and we specify the color as green, for example.
So we want to find all the green items.
And when we do find a green item and by the way, let’s see what’s going on here.
So we make it, oh, it’s non-static.
Let’s keep these things.
No static for for now.
And I’ll get rid of this thing here as well.
It’s really up to you.
It can be static if you want it to.
So for now, we filter the items by color.
We can write line the information about the item.
So I’ll just put a dash here.
So I’m going to say p dot name is green and we can actually execute this and see what we get.
So we’re getting the right output.
Apple is green, tree is green, everything is fine now, unfortunately, what happens now is your boss
comes back and the boss says, Well, now you’re going to filter by both size and color.
You’re going to let people specify both the size and the color you want to search items by.
So this is a bit of a problem because now once again, you have to open up product filter, you have
to jump into that class and you have to add yet another piece of functionality.
So this time around, it’s not just a simple duplication and renaming, it’s a bit more.
So we’re going to filter by size and color.
And if you want to filter by size and color, you have to specify size, size, color, color.
And then you say p dot size is equal to size and color is equal to color.
So this is how you implement this.
And then of course you can start using it.
And this whole thing, everything that I’ve shown right now happens to break the open closed principle
because the open closed principle states that classes should be open for extension, which means it
should be possible to extend the product filter.
It should be possible to make new filters, but they should be closed for modification, which means
nobody should be going back into the filter and actually editing the code, which is already there because
we can assume that the filter might have already been shipped to a customer.
Now how can we extend things without actually going back and changing their bodies?
The answer is of course, inheritance.
The answer is that you can implement interfaces, thereby extending the capabilities of the system.
So instead of having this brute force approach, what we can do is we can implement a pattern and that’s
going to be a new thing for us.
We haven’t actually done any kind of patterns before and now we’re going to implement a pattern, but
not a gang of four pattern.
Instead, we’re going to implement what you might call an enterprise pattern called the specification
pattern.
And this is precisely the thing that will allow us to avoid violating the open closed principle.
So how are we going to do it exactly?
Well, instead of having this rigid functionality, we’re going to make a bunch of interfaces.
So let’s have a bunch of interfaces.
And the first interface that we’re going to make is going to be called I Specification.
Now I specification implements the specification pattern, which basically dictates whether or not a
product satisfies some particular criteria.
So you can think of a specification as a kind of predicate which operates on any type T So notice I’m
keeping my options here.
I’m basically saying that an I specification can work on virtually anything.
So here I can specify the only method which will be required by anyone implementing I specification
and that is a method called is satisfied.
So what’s happening here is we’re saying that we allow people to make specifications and we check whether
a particular item of type T is actually satisfying some criteria.
Now, we’re not specifying the criteria here.
We’re going to do it in just a moment.
Now, the other part of the puzzle is another interface, and this one is going to be called an eye
filter.
Now, an eye filter is precisely a filtering mechanism, but it’s a filtering mechanism which once again
operates on any type T.
So we take a bunch of items of type T and we filter them according to the specification which is defined
here.
So the interface is that you return an eye enumerable of T and you basically filter a bunch of enumerable
of the items by enumerable of T items.
Given the appropriate specification, given an eye specification of T, which I’m going to call spec.
So this is the interface.
You feed it a bunch of items, you tell it what the specification of those items should be and how to
filter them, and you get a bunch of filtered items back.
So now we can implement everything that we’ve done up until now using eye specification and eye filter
as well.
So let me show you how to make a specification for color.
Let’s suppose you want to filter items by color so you make a color specification.
So it’s a very simple thing.
This would implement an eye specification and once again, the type here can be virtually anything.
But we’re filtering products, right?
So we are working with products.
We’re not working with something else, although we might be.
So we say that we implement eye specification of product.
There we go.
So let’s go ahead and implement the missing members.
And here we need to have a definition for the color.
We’re going to filter by.
So here I say color color like so I can initialize it in the constructor and then to check whether the
color specification is satisfied, I simply return the t dot color is equal to color just like that.
All right, so this is our color specification and we can now do the same kind of green product filtering,
but we can do it in a much nicer way.
So for that we need another piece of the puzzle, which is of course a new functionality for filtering
products.
Because remember we made this interface eye filter, but we haven’t implemented it yet.
So that’s what we’re going to do right now.
We’re going to make a better filter.
So here’s a class called Better Filter, which is an eye filter of products because that’s what we are
filtering.
So let’s implement the missing members here.
Now the implementation of this particular class is very trivial because all we do is we go through each
of the items in turn and if indeed the item satisfies a particular specification.
So if the specification that we provide is satisfied by the item, I then we would return that item.
That’s pretty much it.
That’s all you have to do to make the better filter work.
But now let’s take a look at how to actually use it.
So var bf equals new better filter like.
So we’ll write line here that we’re getting green products once again, but this time using the new
filter.
And then of course I’ll do another for each var p in and here we use the better filter.
So bf dot we say filter and then we have to provide both the items as well as the specification.
So the items is products as before.
But for the specification we make a new color specification where we specify that the color should be
green and then we can output it just as we did previously.
So I’ll just copy this over.
All right.
So this is an identical way and of course it gives us identical results, which is exactly what we wanted.
All right.
So now you might be wondering, well, okay, this was color.
Now how about color and size?
How about filtering by both of these, for example?
So first of all, we have to make a size specification.
So once again, I’ll make a size specification, which is an eye specification of product.
And here just implement the missing members.
Here we specify the size.
We might provide it in the constructor, for example.
And then when you want to check whether it’s satisfied you return T dot size is equal to size, so that’s
fairly easy.
And now what we can do is we can filter items by size in the same way that we’ve done here.
So now coming back to this.
Question.
What if you want to filter by both size and color as well?
Well, this is actually possible using a combinator which is also going to be an AI.
Specification of something or other.
So let’s take a look at how to build one.
So I’m going to make a class called and specification.
So this and specification and it’s going to be a generic one is going to be an AI specification of T,
So we’re keeping things generic for now.
We’re not really doing anything in terms of categorizing and saying, Oh, this is going to be only
for products and nothing else.
It’s going to be a very general thing.
So the idea is that the and specification will actually take two specifications like a color specification
and a size specification and it will add them together in the is satisfied.
So one of the ways of doing it is you simply specify a specification T first and second, you might
want to make a constructor which actually initializes both of them.
You may as well use some C-sharp seven features here if you want, so you can sort of do like this.
And for the second one as well.
So the double quotation marks.
And then of course, when it comes to checking whether it’s satisfied, you simply return, whether
the first specification is satisfied by T and the second specification is satisfied by T.
All right.
So having made this, let’s take a look at how we can find, for example, all the large blue items.
So let’s write line here, large, a large blue items like so.
And then for each var P in better filter dot filter.
Okay, so now we need to make an and specification so new and specification which has to provide a name
in particular have to provide a type.
And here we’re going to have the two arguments.
So the first argument and by the way, we forgot products as the first argument here.
So the first argument is products and the second is an specification and we need to specify the color
specification here.
So the color has to be blue.
And in addition, the size specification where the size has to be large.
So we’re looking for a large blue item or a set of items, in fact.
So this is how you would make a composite specification using a combinator.
And here we can go through the items and once again we can write line the actual item.
So we can say P dot name is big and blue like so.
And of course when I run it, I get the house.
So the house is big and blue.
So this has been a demonstration of the open closed principle.
Just as a recap, the open closed principle states that parts of a system or indeed subsystems have
to be open for extension.
So you should be able to extend the functionality of a filter, for example.
But they should be closed for modification.
So you shouldn’t have to go back into beta filter, for example, and start adding things right here.
You shouldn’t be able to do that.
Instead, if you want more functionality, you make new classes, you implement, I specification and
you feed those into something that has already been made and something that may have already been shipped.
You don’t want to re ship the functionality of beta filter to your customers, but you can ship additional
modules which implement AI specification and which make use of better filter.
So that is what the open closed principle is all about.
Play Play Stop Play Play Play Play