WEBVTT 00:00.450 --> 00:01.110 Hi. 00:01.200 --> 00:03.720 Welcome to a new section of this video course. 00:03.870 --> 00:10.770 Template momento and interpreter design pattern in this section we will see the next three behavioral 00:10.770 --> 00:12.220 design patterns. 00:12.240 --> 00:17.880 The difficulty is being raised does now we will use combinations of structural and creation or patterns 00:18.120 --> 00:22.360 to better solve the objective of some of the behavioral patterns. 00:22.380 --> 00:28.380 We will start with template design pattern a pattern that looks very similar to strategy pattern but 00:28.380 --> 00:34.980 that provides greater flexibility momento design pattern is used in 99 percent of applications we use 00:35.030 --> 00:40.200 every day to achieve undo functions and transactional operations. 00:40.200 --> 00:47.000 Finally we will write a reverse Polish notation interpreter to perform simple mathematical operations. 00:47.090 --> 00:49.940 Let us start with the template design pattern. 00:50.280 --> 00:55.650 In this video we are going to write an algorithm that is composed of three steps and each of them returns 00:55.650 --> 00:56.620 a message. 00:56.640 --> 01:01.770 The first and third steps are controlled by the template and just the second step is deferred to the 01:01.770 --> 01:02.990 user. 01:03.030 --> 01:08.340 The template pattern is one of those widely used patterns that are incredibly useful especially when 01:08.340 --> 01:10.590 writing libraries and frameworks. 01:10.590 --> 01:15.820 The idea is to provide a user some way to execute code within an algorithm. 01:15.840 --> 01:21.930 In this section we will see how to write idiomatic go template patterns and see some go source code 01:22.110 --> 01:24.000 words wisely used. 01:24.000 --> 01:30.030 We will write an algorithm of three steps where the second step is delegated to the user while the first 01:30.030 --> 01:35.220 and third aren't the first and third steps of the algorithm represent the template. 01:36.120 --> 01:41.850 While with the strategy pattern we were encapsulating algorithm implementation in different strategies 01:42.140 --> 01:43.590 with the template pattern. 01:43.590 --> 01:49.470 We will try to achieve something similar but with just part of the algorithm the template design pattern 01:49.620 --> 01:55.230 lets the user write a part of an algorithm while the rest is executed by the abstraction. 01:55.230 --> 02:01.920 This is common when creating libraries to ease in some complex task or when reuse ability of some algorithm 02:02.070 --> 02:04.950 is compromised by only a part of it. 02:04.950 --> 02:11.850 Imagine for example that we have a long transaction of H TTP requests we have to perform these steps. 02:11.850 --> 02:15.930 First we authenticate user and then authorize them. 02:15.930 --> 02:20.280 Next we retrieve some details from a database and make some modification. 02:20.790 --> 02:24.750 Lastly we send the details back in a new request. 02:24.750 --> 02:30.240 It wouldn't make sense to repeat steps one to five in the user's code every time he needs to modify 02:30.240 --> 02:31.670 something on the database. 02:31.860 --> 02:38.850 Instead steps 1 2 3 and 5 will be abstracted in the same algorithm that receives an interface with whatever 02:38.850 --> 02:41.830 the fifth step needs to finish the transaction. 02:41.880 --> 02:43.840 It doesn't need to be an interface either. 02:43.860 --> 02:45.830 It could be a callback. 02:46.050 --> 02:51.300 The template design pattern is all about reuse ability and giving responsibilities to the user. 02:51.360 --> 02:57.450 So the objective for this pattern are listed here differ a part of the algorithm of the library to the 02:57.450 --> 03:04.890 user and improve reuse ability by abstracting the parts of the code that are not common between executions. 03:04.890 --> 03:09.870 A brief description of what the template pattern has to do is to define a template for an algorithm 03:09.960 --> 03:15.420 of three steps that defers the implementation of the second step to the user. 03:15.420 --> 03:19.380 Here are the requirements and acceptance criteria for our example. 03:19.440 --> 03:26.340 So each step in the algorithm must return a String and the first step is a method called first and returns 03:26.370 --> 03:28.070 the string hello. 03:28.170 --> 03:33.330 While the third step is a method called Third and returns the string template. 03:33.330 --> 03:36.360 Then the second step is whatever string the user wants to return. 03:36.420 --> 03:41.630 But it's defined by the message retriever interface that has a message string method. 03:41.640 --> 03:48.240 Finally the algorithm is executed sequentially by a method called execute algorithm and returns the 03:48.240 --> 03:53.280 strings returned by each step joined in a single string by a space. 03:53.280 --> 03:57.660 Now let's move on to the unit tests for the simple algorithm. 03:57.690 --> 04:00.860 Now we will focus on testing the public methods only. 04:00.960 --> 04:02.640 This is a very common approach. 04:02.640 --> 04:03.360 All in all. 04:03.360 --> 04:08.830 If your private methods aren't called from some level of the public ones they aren't called at all. 04:08.850 --> 04:15.190 We need to interfaces here one for the template implementers and one for the abstract step of the algorithm. 04:15.240 --> 04:21.390 As you can see I have created a folder called template and I have two files created here with the names 04:21.390 --> 04:25.350 template dot go and template underscore test dot go. 04:25.590 --> 04:28.890 So let's open template dot go here. 04:28.900 --> 04:34.890 Let's add the package name and type interface a template implement or will accept a message retriever 04:34.890 --> 04:38.990 interface to execute as part of its execution algorithm. 04:39.030 --> 04:42.770 We need a type that implements this interface called template. 04:42.840 --> 04:44.310 We will call it template. 04:44.370 --> 04:49.320 I am p l let's add the code for the template implement a struct. 04:49.410 --> 04:54.200 So our first test checks the fourth and fifth acceptance criteria. 04:54.330 --> 04:59.550 We will create the test struct type that implements the message retriever interface returning the string 04:59.790 --> 05:05.850 world and has embedded the template so that it can call the execute algorithm method. 05:05.940 --> 05:09.660 It will act as the template and the abstraction. 05:09.840 --> 05:12.920 Let's save this file for now and move on to template test. 05:12.930 --> 05:18.990 Dot go here we have named the package as template and imported strings and testing. 05:18.990 --> 05:22.930 Since this is a test first defined the test struct type. 05:23.040 --> 05:27.930 In this case the part of the algorithm deferred to us is going to return the world text. 05:27.930 --> 05:30.690 This is the string we will look for later in the test. 05:30.690 --> 05:35.890 Doing a check of type is the word world present in the string. 05:35.910 --> 05:41.970 Take a close look the test struct embeds a type called template which represents the template pattern 05:41.970 --> 05:43.570 of our algorithm. 05:43.770 --> 05:49.350 When we implement the message method we are implicitly implementing the message retrieval interface. 05:49.410 --> 05:55.230 So now we can use test struct type as a pointer to a message retrieval interface. 05:55.230 --> 06:01.470 Next let's add the code for the function test template algorithm in the test we will use the type we 06:01.470 --> 06:05.580 have just created when we call the execute algorithm method. 06:05.610 --> 06:11.550 We need to pass the message retrieval interface as the test struct type also implements the message 06:11.550 --> 06:12.630 retriever interface. 06:12.750 --> 06:19.490 We can pass it as an argument but this is not mandatory of course the result of the execute algorithm 06:19.490 --> 06:25.400 method as defined in the 5th acceptance criterion must return a string that contains the return value 06:25.400 --> 06:28.940 of the first method the returned value of test struct. 06:29.000 --> 06:34.970 That is the world string and the return value of the third method separated by space. 06:34.970 --> 06:37.630 Our implementation is on the second place. 06:37.670 --> 06:42.970 That's why we check that the space is prefix and suffix on the string world. 06:43.220 --> 06:49.580 So if the return string when calling the execute algorithm method doesn't contain the string world the 06:49.580 --> 06:51.090 test fails. 06:51.110 --> 06:55.910 This is enough to make the project compile and run the tests that should fail. 06:55.910 --> 07:02.370 Let's save this file and open the terminal type the command go test iPhone V. 07:02.560 --> 07:04.710 As expected the test fails. 07:04.820 --> 07:11.750 Go time to pass the implementation of this pattern as defined in the acceptance criteria we have to 07:11.750 --> 07:16.070 return the string hello in the first method and the string template. 07:16.070 --> 07:22.760 In the third method that's pretty easy to implement open the templates not go file and let us modify 07:22.760 --> 07:26.140 the code here. 07:26.350 --> 07:28.650 Let me add proper indentation. 07:28.720 --> 07:34.810 Also make sure to change the type template interface to temper later as we can not have to type with 07:34.810 --> 07:35.800 the same name. 07:35.950 --> 07:39.210 Save the file with this implementation. 07:39.260 --> 07:44.780 We should be covering the second and third acceptance criteria and partially covering the first criterion 07:44.990 --> 07:50.730 that is each step in the algorithm must return a String to cover the fifth acceptance criterion. 07:50.780 --> 07:56.570 We define an execute algorithm method that accepts the message retriever interface as an argument and 07:56.570 --> 07:58.160 returns the full algorithm. 07:58.310 --> 08:03.170 A single string done by joining the strings returned by the first message string. 08:03.170 --> 08:10.550 And third methods the strings dot joint function has this signature. 08:10.550 --> 08:16.580 It takes an array of strings and joins them placing the second argument between each item in the array. 08:16.580 --> 08:21.780 In our case we create a string array on the fly to pass it as the first argument. 08:21.860 --> 08:26.160 Then we pass a whitespace as the second argument with this implementation. 08:26.180 --> 08:28.820 The tests must be passing already. 08:29.020 --> 08:33.070 Let us save the file navigate to the terminal and run the test. 08:33.320 --> 08:40.930 Go test hyphen v enter the tests passed the test has checked that the string world is present in the 08:40.930 --> 08:47.410 returned result which is the hello world template message Hello text was the string returned by the 08:47.410 --> 08:53.770 first method the world string was returned by our message retrieval implementation and template was 08:53.770 --> 08:56.150 the string returned by the third method. 08:56.380 --> 09:03.040 The white spaces are inserted by ghost strings dot join function but any use of the template implementation 09:03.040 --> 09:07.680 dot execute algorithm type will always return Hello something. 09:07.690 --> 09:10.150 Template in its result. 09:10.150 --> 09:13.240 This is not the only way to achieve the template design pattern. 09:13.300 --> 09:19.500 We can also use an anonymous function to give our implementation the execute algorithm method. 09:19.500 --> 09:25.930 Let us write a test in the same method that was used previously so open the template test dot go file 09:26.110 --> 09:29.440 and add the code at the bottom of the file. 09:29.500 --> 09:32.830 Our new test is called using anonymous functions. 09:32.860 --> 09:39.100 We have also extracted the checking on the test to an external function to reuse it in this test. 09:39.160 --> 09:43.910 We have called this function expected or error because it will fail with an error. 09:43.960 --> 09:50.680 If the expected value isn't received in our test we will create a type called Anonymous template that 09:50.680 --> 09:56.950 replaces the previous template type the execute algorithm method of this new type accepts the func method 09:56.950 --> 10:02.930 string type that we can implement directly in the test to return the string world. 10:02.950 --> 10:07.290 Now let's save the file and move to the templates not go file. 10:07.300 --> 10:10.960 Here we are the anonymous template type structure. 10:10.960 --> 10:16.390 The only difference with the template type is that the execute algorithm method accepts a function that 10:16.390 --> 10:20.260 returns a string instead of a message retrieval interface. 10:20.260 --> 10:24.890 Let us run the new test save the file and go back to the terminal. 10:25.180 --> 10:26.740 Let us run the test command. 10:26.830 --> 10:29.030 Go test hyphen V. 10:29.350 --> 10:34.780 As you can read in the output of the test execution the error is thrown on the using anonymous function 10:34.780 --> 10:37.540 test which is what we were expecting. 10:37.570 --> 10:44.620 Now open the templates dot go let's write the implementation by modifying the return statement in the 10:44.620 --> 10:46.380 anonymous template type. 10:46.480 --> 10:49.750 The implementation is quite similar to the one in the template type. 10:49.780 --> 10:55.210 However now we have passed a function called f that we will use as the second item in the string array 10:55.210 --> 11:00.190 we used on joint function as f is simply a function that returns a string. 11:00.220 --> 11:05.590 The only thing we need to do with it is to execute the proper place which is the second position in 11:05.590 --> 11:06.730 the array. 11:06.730 --> 11:10.330 Don't forget to save the file for the changes we made. 11:10.500 --> 11:13.870 Let's open the terminal and run the tests again. 11:13.870 --> 11:14.740 Awesome. 11:14.770 --> 11:18.970 Now we know two ways to implement the template design pattern. 11:19.180 --> 11:25.830 Now a question which may arise here is that how do you avoid the modifications on the interface. 11:25.870 --> 11:31.060 The problem of the previous approach is that now we have two templates to maintain and we could end 11:31.060 --> 11:32.960 up duplicating code. 11:33.040 --> 11:39.220 What can we do in the situation that we cannot change the interface we are using our interface was the 11:39.220 --> 11:43.320 message receiver but we want to use an anonymous function now. 11:43.720 --> 11:46.960 Well do you remember the adapter design pattern. 11:46.960 --> 11:52.720 We just have to create an adapter type that accepting a function string type returns an implementation 11:52.720 --> 11:54.910 of the message receiver interface. 11:54.970 --> 11:57.660 We will call this type template adapter. 11:58.200 --> 12:02.410 Let's open templates dot go and add the template adapter. 12:02.410 --> 12:07.450 As you can see the template adapter type has a field called My bunk which is of the type. 12:07.540 --> 12:08.950 Func string. 12:08.950 --> 12:14.410 We have also defined adapter as private because it shouldn't be used without a function defined in the 12:14.410 --> 12:16.180 my func field. 12:16.180 --> 12:21.090 We have created a public function called The Message retrieval adapter to achieve this. 12:21.220 --> 12:25.710 Let's save the file and go back to the Template test dot go. 12:25.990 --> 12:28.150 And here let's add the test. 12:28.210 --> 12:32.040 So this is how our test should more or less look like. 12:32.240 --> 12:36.260 Look at the statement where we called The Message retriever adapter method. 12:36.260 --> 12:40.790 We passed an anonymous function as an argument defined as func string. 12:40.790 --> 12:46.250 Then we reuse the previously defined template type from our first test to pass the message retrieve 12:46.250 --> 12:47.570 or variable. 12:47.570 --> 12:52.340 Finally we checked again with the expected or error method. 12:52.340 --> 12:58.370 Take a look at the message retrieve or adapter method it will return a function that has nil value. 12:58.370 --> 13:04.460 If strictly following the test driven development rules we must do tests first and they must not pass 13:04.460 --> 13:06.430 before implementation is done. 13:06.440 --> 13:10.760 That's why we returned nil on the message retrieve or adapter function. 13:10.760 --> 13:13.160 So let's run the tests first. 13:13.160 --> 13:19.790 Save the file and move to the terminal run the command go test hyphen V. 13:19.790 --> 13:24.500 The test fails on line 42 of the code and it doesn't continue. 13:24.620 --> 13:30.130 Again depending on how you wrote your code the line representing your error could be somewhere else. 13:30.170 --> 13:34.760 We stop test execution because we will need a valid message receiver interface. 13:34.820 --> 13:41.330 When we call the execute algorithm method but the implementation of the adapter for our template pattern 13:41.540 --> 13:44.840 we will start with message retriever adapter method. 13:44.990 --> 13:47.560 So let go back to the Template dot go. 13:47.570 --> 13:50.680 Let us modify the message retrieval adapter. 13:50.720 --> 13:52.330 It's very easy right. 13:52.370 --> 13:57.020 You could be wondering what happens if we pass nil value for the F argument. 13:57.020 --> 14:01.520 Well we will cover this issue by calling the my func function. 14:01.520 --> 14:08.420 Now let's modify the type template adapter struct so the adapter type is finished with this implementation. 14:08.660 --> 14:14.120 When calling the message function we check that we actually have something stored in the my func function 14:14.390 --> 14:15.770 before calling. 14:15.770 --> 14:19.110 If nothing was stored we return an empty string. 14:19.130 --> 14:25.310 Now our third implementation of the template type using the adapter pattern is done save the file and 14:25.310 --> 14:32.230 move to the terminal let us run the test command as you can see we have passed the test. 14:32.250 --> 14:33.470 Wonderful. 14:33.480 --> 14:39.720 Now let's see how to look for the template pattern and go source code the source packaging goes source 14:39.720 --> 14:46.050 code can be considered a template implementation of a sort algorithm as defined in the package itself 14:46.290 --> 14:51.930 the source package provides primitives for sorting slices and the user defined collections. 14:51.930 --> 14:58.190 Here we can also find a good example of why go authors aren't worried about implementing generics sorting 14:58.200 --> 15:02.760 the lists is maybe the best example of generic uses in other languages. 15:02.760 --> 15:06.020 The way that go deals with this is very elegant too. 15:06.120 --> 15:08.680 It deals with this issue with an interface. 15:08.700 --> 15:10.490 Let me show you this interface. 15:10.680 --> 15:13.460 I have already created the file sort underscore. 15:13.470 --> 15:14.860 Example dot go. 15:15.300 --> 15:17.150 Let me open this. 15:17.160 --> 15:21.350 This is the interface for lists that need to be sorted by using the source package. 15:21.360 --> 15:29.040 In the words of go's authors a type typically is a collection that satisfies sort interface can be sorted 15:29.040 --> 15:31.290 by the routines in this package. 15:31.320 --> 15:36.470 The methods require that the elements of the collection be enumerated by an integer index. 15:36.480 --> 15:42.630 In other words write a type that implements this interface so that the sort package can be used to sort 15:42.750 --> 15:49.310 any slice the sorting algorithm is the template and we must define how to retrieve values in our slice. 15:49.440 --> 15:55.080 If we peak in the sort package we can also find an example of how to use the sorting template but we 15:55.080 --> 16:00.700 will create our own example here add the lines of code as I do. 16:00.880 --> 16:05.370 First we have done a very simple type that stores an entire list. 16:05.380 --> 16:10.090 This could be any kind of list usually a list of some kind of struct. 16:10.150 --> 16:11.830 Then we have implemented the sort. 16:11.830 --> 16:17.590 Don't interface interface by defining the land swap and less methods. 16:17.590 --> 16:20.370 Finally let's write the main function. 16:20.530 --> 16:24.840 The main function creates an unordered list of numbers of my list type. 16:25.000 --> 16:30.490 We print the list that we created unordered and then we sorted the sorted out sort. 16:30.490 --> 16:34.930 Method actually modifies our variable instead of returning a new list. 16:34.930 --> 16:36.480 So beware. 16:36.490 --> 16:37.960 Finally we print again. 16:37.960 --> 16:39.570 The resulting list. 16:39.700 --> 16:43.650 Now we are ready to see the console output of this main method. 16:43.810 --> 16:46.480 Save the file and open the terminal. 16:46.900 --> 16:48.800 Run the command go run. 16:48.840 --> 16:49.400 Sort. 16:49.420 --> 16:56.240 Example dot go the sword dot sword function has sorted our list in a transparent way. 16:56.380 --> 17:02.710 It has a lot of code written and delegates land swap and less methods to an interface like we did in 17:02.800 --> 17:03.800 our template. 17:03.910 --> 17:06.970 Delegating to the message retriever interface. 17:07.120 --> 17:08.460 Superb. 17:08.470 --> 17:11.590 Now let me summarize the template design pattern. 17:11.830 --> 17:16.960 So we wanted to put a lot of focus on this pattern because it is very important when developing libraries 17:17.020 --> 17:22.510 and frameworks and allows a lot of flexibility and control to users of our library. 17:22.510 --> 17:28.720 We have also seen again that it's very common to mix patterns to provide flexibility to the users not 17:28.720 --> 17:31.990 only in a behavioral way but also structural. 17:31.990 --> 17:37.510 This will come in very handy when working with concurrent apps where we need to restrict access to parts 17:37.510 --> 17:40.240 of our code to avoid races. 17:40.480 --> 17:45.650 In this video we have learned about the template design pattern in the next video. 17:45.700 --> 17:48.820 We will be exploring about momento design pattern.