WEBVTT 00:00.530 --> 00:01.180 Hi. 00:01.310 --> 00:03.880 Welcome to the last section of this course. 00:03.920 --> 00:07.760 More on structural patterns with this section. 00:07.760 --> 00:13.460 We will finish with the structural patterns we have left some of the most complex ones till the end 00:13.640 --> 00:19.460 so that you get more used to the mechanics of design patterns and the features of the go language. 00:19.670 --> 00:26.270 In this section we will work at writing a cache to access a database a library to gather weather data 00:26.630 --> 00:32.900 a server with runtime middleware and discuss a way to save memory by saving shareable states between 00:32.900 --> 00:34.740 the type of values. 00:34.740 --> 00:41.320 Let's move on to the first video of this section that deals with proxy design pattern in this video. 00:41.340 --> 00:47.840 We're going to create a remote proxy which is going to be a cache of objects before accessing a database. 00:47.840 --> 00:52.820 Let's start the final section on structural patterns with the proxy pattern. 00:52.820 --> 00:58.760 It's a simple pattern that provides interesting features and possibilities with very little effort. 00:58.820 --> 01:03.650 The proxy pattern usually wraps an object to hide some of its characteristics. 01:03.650 --> 01:09.620 These characteristics could be the fact that it is a remote object that is remote proxy a very heavy 01:09.620 --> 01:14.510 object such as a very big image or the dump of a terabyte database. 01:14.510 --> 01:22.310 Or we could say virtual proxy or a restricted access object that is protection proxy the possibilities 01:22.310 --> 01:24.230 of the proxy pattern are many. 01:24.230 --> 01:29.830 But in general they all try to provide the same functionalities which are listed here. 01:29.900 --> 01:31.910 I don't object behind the proxy. 01:31.910 --> 01:38.120 So the features can be hidden restricted and so on and provide a new abstraction layer that is easy 01:38.120 --> 01:41.080 to work with and can be changed easily. 01:41.120 --> 01:46.820 For our example we are going to create a remote proxy which is going to be a cache of objects before 01:46.910 --> 01:48.830 accessing a database. 01:48.830 --> 01:54.410 Let's imagine that we have a database with many users but instead of accessing the database each time 01:54.410 --> 02:01.520 we want information about a user we will have a first in first out that is FIFO stack of users in a 02:01.520 --> 02:08.300 proxy pattern as we are aware that FIFO is a way of saying that when the cache needs to be emptied it 02:08.300 --> 02:11.650 will delete the first object that entered first. 02:11.990 --> 02:18.170 We will wrap an imaginary database represented by a slice with our proxy pattern then the pattern will 02:18.170 --> 02:21.350 have to stick to these acceptance criteria. 02:21.350 --> 02:26.830 First all access to the database of users will be done through the proxy type. 02:26.870 --> 02:32.900 Next a stack of any number of recent users will be kept in the proxy. 02:32.900 --> 02:39.330 And if a user already exists in the stack it won't query the database and will return the stored one. 02:39.680 --> 02:44.390 And if the query the user doesn't exist in the stack it will query the database. 02:44.390 --> 02:47.440 Remove the oldest user in the stack if it's full. 02:47.540 --> 02:50.550 Store the new one and return it. 02:50.570 --> 02:53.790 So now let's start with the unit test. 02:54.020 --> 03:01.730 Since Version 1.0 7 of go we can embed tests within tests by using closures so that we can group them 03:01.730 --> 03:08.160 in a more human readable way and reduce the number of test functions referred to the first section. 03:08.210 --> 03:12.570 Ready steady go to learn how to install the new version of go. 03:12.680 --> 03:19.430 If your current version is older than Version 1.0 7 the types for this pattern will be the proxy user 03:19.670 --> 03:26.160 and user lists drugs as well as the user finder interface that the database and the proxy will implement. 03:26.180 --> 03:31.990 This is key because the proxy must implement the same interfaces as the features of the type. 03:32.000 --> 03:40.490 It tries to wrap let me open the file proxy thoughts go and add the package and add the interface the 03:40.490 --> 03:44.740 user finder is the interface that the database and the proxy implement. 03:44.750 --> 03:50.690 The user is a type with a member called I.D. which is int 32 type. 03:50.690 --> 03:54.350 Let me replace string with int 32. 03:54.410 --> 03:57.780 Finally the user list is a type of slice of users. 03:57.860 --> 04:05.310 Let's add the lines of code for it if you are asking why we aren't using a slice of users directly. 04:05.310 --> 04:07.910 The answer is that by declaring a sequence of users. 04:07.920 --> 04:13.410 This way we can implement the user finder interface but with a slice we can't. 04:13.440 --> 04:20.730 Finally the proxy type called User List proxy will be composed of a user list slice which will be our 04:20.730 --> 04:22.480 database representation. 04:22.680 --> 04:29.460 The stack cache members which will also be of User List type or simplicity stack capacity to give our 04:29.460 --> 04:31.470 stack the size we want. 04:31.530 --> 04:32.670 We will cheat a bit. 04:32.670 --> 04:39.390 For the purpose of this tutorial and declare a boolean state on a field called last search used cache 04:39.720 --> 04:45.900 that will hold if the last performed search has used the cache or has access the database. 04:45.900 --> 04:48.900 So let's add the code for this the user list. 04:48.900 --> 04:55.710 Proxy tribal cache a minimum of stack size users and rotate the cache if it reaches this limit the stack 04:55.740 --> 05:00.510 cache members will be populated from objects from mocked database type. 05:00.660 --> 05:07.680 The first test is called test user list proxy and we list it in the other file which we have named as 05:07.680 --> 05:09.480 proxy underscore test. 05:09.550 --> 05:10.580 Don't go. 05:10.800 --> 05:19.280 Let's open it and add the code this test creates a user list of 1 million users with random names to 05:19.280 --> 05:19.860 do so. 05:19.910 --> 05:25.160 We feed the random number generator by calling the seed function with some constant seed. 05:25.160 --> 05:31.530 So our randomized results are also constant and the user I.D. are generated from it. 05:31.580 --> 05:35.780 It might have some duplicates but it serves our purpose. 05:35.810 --> 05:42.570 Next we need a proxy with a reference to MOX database which I've just created at this point. 05:42.620 --> 05:49.880 We have a proxy object composed of a mock database with 1 million users a cache implemented as a FIFO 05:49.880 --> 05:52.190 stack with the size of 2. 05:52.240 --> 05:56.930 Let's get three random ideas from most database to use in our stack. 05:56.960 --> 06:02.400 Okay we took fourth fifth and sixth I.D. from the slice. 06:02.420 --> 06:05.230 Remember that arrays and slices start with zero. 06:05.390 --> 06:12.120 So the index 3 is actually the fourth position in the slice this is going to be our starting point before 06:12.120 --> 06:16.230 launching the embedded tests to create an embedded test. 06:16.230 --> 06:21.960 We have to call the run method of the testing dot t pointer with a description and a closure with the 06:21.960 --> 06:26.470 function t asterisk testing dot t signature. 06:26.520 --> 06:33.720 So let's add the line of code to call the run method for example in this code we give the description 06:33.780 --> 06:36.050 blind user empty cache. 06:36.120 --> 06:38.180 Then we define our closure. 06:38.220 --> 06:43.920 First it tries to find a user with a known I.D. and checks for errors as the description implies the 06:43.920 --> 06:44.970 cache is empty. 06:45.030 --> 06:50.070 At this point and the user will have to be retrieved from the mocked database array. 06:50.100 --> 06:56.970 Finally we check whether the returned user has the same I.D. as that of the expected user at index 0 06:57.150 --> 07:05.520 of the known I.D. slice and that the proxy cache now has a size of 1 the state of the member last search 07:05.670 --> 07:11.240 used cache proxy must not be true or we will not pass the test. 07:11.250 --> 07:16.800 Remember this member tells us whether the last search has been retrieved from the slice that represents 07:16.800 --> 07:19.340 a database or from the cache. 07:19.520 --> 07:25.790 The second embedded test for the proxy pattern is to ask for the same user as before which must now 07:25.790 --> 07:27.710 be returned from the cache. 07:27.740 --> 07:33.890 It's very similar to the previous test but now we have to check if the user is returned from the cache. 07:33.890 --> 07:36.240 Let me add the code for this. 07:36.370 --> 07:42.310 So again we ask for the first known I.D. the proxy cache must maintain a size of 1. 07:42.340 --> 07:49.210 After this search and the last search used cache member must be true this time or the test will fail 07:50.200 --> 07:54.750 the last test will overflow the stack cache array on the proxy type. 07:54.850 --> 08:00.490 We will search for two new users that our proxy type will have to retrieve from the database. 08:00.490 --> 08:06.670 Our stack has a size of 2 so it will have to remove the first user to allocate space for the second 08:06.910 --> 08:08.740 and third users. 08:08.740 --> 08:12.870 Now let's add the code for overflowing stack here. 08:12.910 --> 08:15.220 We have retrieved the first three users. 08:15.220 --> 08:19.210 We aren't checking for errors because that was the purpose of the previous tests. 08:19.210 --> 08:25.390 This is important to recall that there is no need to over test your code if there is any error here 08:25.540 --> 08:27.650 it will arise in the previous tests. 08:27.670 --> 08:33.760 Also we have checked that the user 2 and user 3 queries do not use the cache they shouldn't be stored 08:33.790 --> 08:35.140 there yet. 08:35.140 --> 08:39.040 Now we are going to look for the user one query in the proxy. 08:39.040 --> 08:46.110 It shouldn't exist as the stack has a size of 2 and the user 1 was the first to enter hence the first 08:46.120 --> 08:47.310 to go out. 08:47.350 --> 08:49.090 Let's add the code. 08:49.090 --> 08:52.000 It doesn't matter if we ask for a thousand users. 08:52.000 --> 08:56.030 Our cash can't be bigger than our configured size. 08:56.050 --> 09:01.780 Finally we are going to again range over the users stored in the cache and compare them with the last 09:01.780 --> 09:04.060 two we queried this way. 09:04.060 --> 09:09.390 We will take that just those users are stored in the cache both must be found on it. 09:09.430 --> 09:11.990 So here's the code for this logic. 09:11.990 --> 09:13.810 Let's save the file. 09:13.810 --> 09:17.610 Running the tests now should give some arrows as usual. 09:17.650 --> 09:25.720 Let's run them now and here's the output so let's implement the find user method to act as our proxy 09:26.850 --> 09:33.390 let's move on to the implementation in our proxy the find user method will search for a specified I.D. 09:33.420 --> 09:37.390 in the cache list if it finds it it will return the I.D.. 09:37.530 --> 09:40.230 If not it will search in the database. 09:40.230 --> 09:45.210 Finally if it's not in the database list it will return an error. 09:45.210 --> 09:50.040 If you remember our proxy pattern is composed of two user lists types. 09:50.160 --> 09:54.630 One of them a pointer which are actually slices of user type. 09:54.630 --> 10:01.890 We will implement a find user method in user type 2 which by the way has the same signature as the user 10:01.890 --> 10:03.750 finder interface. 10:03.750 --> 10:11.160 Now let's add the code so right under the user list we add these lines of code to find the user method 10:11.340 --> 10:13.050 in the user list slice. 10:13.110 --> 10:19.500 We will iterate over the list to try and find a user with the same I.D. as the I.D. argument or return 10:19.500 --> 10:20.060 an error. 10:20.190 --> 10:26.440 If it can't find it you may be wondering why the pointer t is between parentheses. 10:26.580 --> 10:32.310 This is to D reference the underlying array before accessing its indexes. 10:32.310 --> 10:37.920 Without it you'll have a compilation error because the compiler tries to search the index for D referencing 10:37.980 --> 10:44.820 the pointer so the first part of the proxy point user method can be written as I'm going to show you 10:44.820 --> 10:49.130 now is the code for the first part of the proxy method. 10:49.200 --> 10:53.730 Here we use this method to search for a user in the stack cache member. 10:53.850 --> 10:56.520 The error will be nil if it can find it. 10:56.520 --> 11:02.190 So we checked this to print a message to the console changed the state of the last search used cache 11:02.190 --> 11:08.570 to true so that the test can check whether the user was retrieved from the cache and finally returned 11:08.580 --> 11:09.840 the user. 11:09.840 --> 11:14.940 So if the error was not nil it means that it couldn't find the user in the stack. 11:14.940 --> 11:18.290 So the next step is to search in the database. 11:18.300 --> 11:20.340 Here's code for the search. 11:20.610 --> 11:25.070 We can reuse the blind user method we wrote for user lists database. 11:25.080 --> 11:31.920 In this case because both have the same type for the purposes of this example again it searches the 11:31.920 --> 11:35.820 user in the database represented by the user list slice. 11:35.820 --> 11:43.080 But in this case if the user isn't found it returns the error generated in user list when the user is 11:43.080 --> 11:43.710 found. 11:43.710 --> 11:45.180 Error is nil. 11:45.180 --> 11:48.490 We have to add the user to the stack for this purpose. 11:48.510 --> 11:53.340 Let's write a dedicated private method that receives a pointer of type. 11:53.340 --> 11:55.390 User List proxy. 11:55.410 --> 11:59.520 Now let's add the append method below the return statement. 11:59.670 --> 12:06.630 The add the user to stack method takes the user argument and adds it to the stack in place. 12:06.630 --> 12:10.490 If the stack is full it removes the first element in it before adding. 12:10.680 --> 12:15.770 We have also written an add user method to user list to help us in this. 12:15.930 --> 12:23.270 So now in find user method we just have to add one line and here's the line which I just told you. 12:23.310 --> 12:25.460 This adds the new user to the stack. 12:25.530 --> 12:28.690 Removing the last if necessary. 12:28.770 --> 12:34.950 Finally we just have to return the new user of the stack and set the appropriate value on last search 12:34.980 --> 12:36.660 used cached variable. 12:36.750 --> 12:41.330 Also let's write a message to the console to help in the testing process. 12:41.400 --> 12:44.490 With this we have enough to pass our tests. 12:44.490 --> 12:48.050 Let's save this file move to the terminal and run the command. 12:48.060 --> 12:56.490 Go text hyphen v you can see in these messages that our proxy has worked flawlessly it has returned. 12:56.490 --> 12:58.430 The first search from the database. 12:58.500 --> 13:02.450 Then when we search for the same user again it uses the cache. 13:02.460 --> 13:08.130 Finally we made a new test that calls three different users and we can observe by looking at the console 13:08.130 --> 13:13.410 output that just the first was returned from the cache and that the other two were fetched from the 13:13.410 --> 13:15.100 database at the end. 13:15.390 --> 13:18.910 Let's have a look at proxy seeing around actions. 13:19.080 --> 13:24.780 You can wrap proxies around types that need some intermediate action like giving authorization to the 13:24.780 --> 13:27.110 user or providing access to a database. 13:27.210 --> 13:33.690 Like in our example our example is a good way to separate application needs from database needs. 13:33.690 --> 13:39.400 If our application access at the database too much a solution for this is not in your database. 13:39.420 --> 13:45.090 Remember that the proxy uses the same interface as the type it wraps and for the user. 13:45.090 --> 13:48.390 There shouldn't be any difference between the two. 13:48.390 --> 13:52.950 In this video we have learned about proxy design pattern in the next video. 13:52.980 --> 13:55.890 We will be learning about decorator design pattern.