Hi.
Welcome to the last section of this course.
More on structural patterns with this section.
We will finish with the structural patterns we have left some of the most complex ones till the end
so that you get more used to the mechanics of design patterns and the features of the go language.
In this section we will work at writing a cache to access a database a library to gather weather data
a server with runtime middleware and discuss a way to save memory by saving shareable states between
the type of values.
Let's move on to the first video of this section that deals with proxy design pattern in this video.
We're going to create a remote proxy which is going to be a cache of objects before accessing a database.
Let's start the final section on structural patterns with the proxy pattern.
It's a simple pattern that provides interesting features and possibilities with very little effort.
The proxy pattern usually wraps an object to hide some of its characteristics.
These characteristics could be the fact that it is a remote object that is remote proxy a very heavy
object such as a very big image or the dump of a terabyte database.
Or we could say virtual proxy or a restricted access object that is protection proxy the possibilities
of the proxy pattern are many.
But in general they all try to provide the same functionalities which are listed here.
I don't object behind the proxy.
So the features can be hidden restricted and so on and provide a new abstraction layer that is easy
to work with and can be changed easily.
For our example we are going to create a remote proxy which is going to be a cache of objects before
accessing a database.
Let's imagine that we have a database with many users but instead of accessing the database each time
we want information about a user we will have a first in first out that is FIFO stack of users in a
proxy pattern as we are aware that FIFO is a way of saying that when the cache needs to be emptied it
will delete the first object that entered first.
We will wrap an imaginary database represented by a slice with our proxy pattern then the pattern will
have to stick to these acceptance criteria.
First all access to the database of users will be done through the proxy type.
Next a stack of any number of recent users will be kept in the proxy.
And if a user already exists in the stack it won't query the database and will return the stored one.
And if the query the user doesn't exist in the stack it will query the database.
Remove the oldest user in the stack if it's full.
Store the new one and return it.
So now let's start with the unit test.
Since Version 1.0 7 of go we can embed tests within tests by using closures so that we can group them
in a more human readable way and reduce the number of test functions referred to the first section.
Ready steady go to learn how to install the new version of go.
If your current version is older than Version 1.0 7 the types for this pattern will be the proxy user
and user lists drugs as well as the user finder interface that the database and the proxy will implement.
This is key because the proxy must implement the same interfaces as the features of the type.
It tries to wrap let me open the file proxy thoughts go and add the package and add the interface the
user finder is the interface that the database and the proxy implement.
The user is a type with a member called I.D. which is int 32 type.
Let me replace string with int 32.
Finally the user list is a type of slice of users.
Let's add the lines of code for it if you are asking why we aren't using a slice of users directly.
The answer is that by declaring a sequence of users.
This way we can implement the user finder interface but with a slice we can't.
Finally the proxy type called User List proxy will be composed of a user list slice which will be our
database representation.
The stack cache members which will also be of User List type or simplicity stack capacity to give our
stack the size we want.
We will cheat a bit.
For the purpose of this tutorial and declare a boolean state on a field called last search used cache
that will hold if the last performed search has used the cache or has access the database.
So let's add the code for this the user list.
Proxy tribal cache a minimum of stack size users and rotate the cache if it reaches this limit the stack
cache members will be populated from objects from mocked database type.
The first test is called test user list proxy and we list it in the other file which we have named as
proxy underscore test.
Don't go.
Let's open it and add the code this test creates a user list of 1 million users with random names to
do so.
We feed the random number generator by calling the seed function with some constant seed.
So our randomized results are also constant and the user I.D. are generated from it.
It might have some duplicates but it serves our purpose.
Next we need a proxy with a reference to MOX database which I've just created at this point.
We have a proxy object composed of a mock database with 1 million users a cache implemented as a FIFO
stack with the size of 2.
Let's get three random ideas from most database to use in our stack.
Okay we took fourth fifth and sixth I.D. from the slice.
Remember that arrays and slices start with zero.
So the index 3 is actually the fourth position in the slice this is going to be our starting point before
launching the embedded tests to create an embedded test.
We have to call the run method of the testing dot t pointer with a description and a closure with the
function t asterisk testing dot t signature.
So let's add the line of code to call the run method for example in this code we give the description
blind user empty cache.
Then we define our closure.
First it tries to find a user with a known I.D. and checks for errors as the description implies the
cache is empty.
At this point and the user will have to be retrieved from the mocked database array.
Finally we check whether the returned user has the same I.D. as that of the expected user at index 0
of the known I.D. slice and that the proxy cache now has a size of 1 the state of the member last search
used cache proxy must not be true or we will not pass the test.
Remember this member tells us whether the last search has been retrieved from the slice that represents
a database or from the cache.
The second embedded test for the proxy pattern is to ask for the same user as before which must now
be returned from the cache.
It's very similar to the previous test but now we have to check if the user is returned from the cache.
Let me add the code for this.
So again we ask for the first known I.D. the proxy cache must maintain a size of 1.
After this search and the last search used cache member must be true this time or the test will fail
the last test will overflow the stack cache array on the proxy type.
We will search for two new users that our proxy type will have to retrieve from the database.
Our stack has a size of 2 so it will have to remove the first user to allocate space for the second
and third users.
Now let's add the code for overflowing stack here.
We have retrieved the first three users.
We aren't checking for errors because that was the purpose of the previous tests.
This is important to recall that there is no need to over test your code if there is any error here
it will arise in the previous tests.
Also we have checked that the user 2 and user 3 queries do not use the cache they shouldn't be stored
there yet.
Now we are going to look for the user one query in the proxy.
It shouldn't exist as the stack has a size of 2 and the user 1 was the first to enter hence the first
to go out.
Let's add the code.
It doesn't matter if we ask for a thousand users.
Our cash can't be bigger than our configured size.
Finally we are going to again range over the users stored in the cache and compare them with the last
two we queried this way.
We will take that just those users are stored in the cache both must be found on it.
So here's the code for this logic.
Let's save the file.
Running the tests now should give some arrows as usual.
Let's run them now and here's the output so let's implement the find user method to act as our proxy
let's move on to the implementation in our proxy the find user method will search for a specified I.D.
in the cache list if it finds it it will return the I.D..
If not it will search in the database.
Finally if it's not in the database list it will return an error.
If you remember our proxy pattern is composed of two user lists types.
One of them a pointer which are actually slices of user type.
We will implement a find user method in user type 2 which by the way has the same signature as the user
finder interface.
Now let's add the code so right under the user list we add these lines of code to find the user method
in the user list slice.
We will iterate over the list to try and find a user with the same I.D. as the I.D. argument or return
an error.
If it can't find it you may be wondering why the pointer t is between parentheses.
This is to D reference the underlying array before accessing its indexes.
Without it you'll have a compilation error because the compiler tries to search the index for D referencing
the pointer so the first part of the proxy point user method can be written as I'm going to show you
now is the code for the first part of the proxy method.
Here we use this method to search for a user in the stack cache member.
The error will be nil if it can find it.
So we checked this to print a message to the console changed the state of the last search used cache
to true so that the test can check whether the user was retrieved from the cache and finally returned
the user.
So if the error was not nil it means that it couldn't find the user in the stack.
So the next step is to search in the database.
Here's code for the search.
We can reuse the blind user method we wrote for user lists database.
In this case because both have the same type for the purposes of this example again it searches the
user in the database represented by the user list slice.
But in this case if the user isn't found it returns the error generated in user list when the user is
found.
Error is nil.
We have to add the user to the stack for this purpose.
Let's write a dedicated private method that receives a pointer of type.
User List proxy.
Now let's add the append method below the return statement.
The add the user to stack method takes the user argument and adds it to the stack in place.
If the stack is full it removes the first element in it before adding.
We have also written an add user method to user list to help us in this.
So now in find user method we just have to add one line and here's the line which I just told you.
This adds the new user to the stack.
Removing the last if necessary.
Finally we just have to return the new user of the stack and set the appropriate value on last search
used cached variable.
Also let's write a message to the console to help in the testing process.
With this we have enough to pass our tests.
Let's save this file move to the terminal and run the command.
Go text hyphen v you can see in these messages that our proxy has worked flawlessly it has returned.
The first search from the database.
Then when we search for the same user again it uses the cache.
Finally we made a new test that calls three different users and we can observe by looking at the console
output that just the first was returned from the cache and that the other two were fetched from the
database at the end.
Let's have a look at proxy seeing around actions.
You can wrap proxies around types that need some intermediate action like giving authorization to the
user or providing access to a database.
Like in our example our example is a good way to separate application needs from database needs.
If our application access at the database too much a solution for this is not in your database.
Remember that the proxy uses the same interface as the type it wraps and for the user.
There shouldn't be any difference between the two.
In this video we have learned about proxy design pattern in the next video.
We will be learning about decorator design pattern.