WEBVTT 00:00.490 --> 00:06.700 We are now at the second video of the section momento design pattern in the previous video. 00:06.760 --> 00:10.410 We looked at the template design pattern in this video. 00:10.450 --> 00:13.840 We will develop a simple example using a string as the state. 00:13.840 --> 00:15.680 We want to save. 00:15.790 --> 00:18.530 Us now look at a pattern with a fancy name. 00:18.580 --> 00:24.790 If we check a dictionary to see the meaning of Memento we will find the description an object kept as 00:24.790 --> 00:31.840 a reminder of a person or event here the keyword is reminder as we will remember actions with this design 00:31.840 --> 00:32.770 pattern. 00:33.010 --> 00:38.290 The meaning of Memento is very similar to the functionality it provides in design patterns. 00:38.290 --> 00:39.820 Basically we have a type. 00:39.820 --> 00:45.770 With some state and we want to be able to save milestones of its state having a finite amount of state 00:45.770 --> 00:53.260 saved we can recover them if necessary for a variety of tasks undo operations historic and so on the 00:53.260 --> 00:58.610 momentum design pattern usually has three players which are usually called actors. 00:58.840 --> 01:03.750 The first one is Memento which is a type that stores the type we want to save. 01:03.760 --> 01:09.220 Usually we won't store the business type directly and we provide an extra layer of abstraction through 01:09.220 --> 01:10.360 this type. 01:10.540 --> 01:16.690 Next one is the originator a type that is in charge of creating mementos and storing the current active 01:16.690 --> 01:17.580 state. 01:17.590 --> 01:23.710 We said that the memento type wrap states of the business type and we use the originator as the creator 01:23.710 --> 01:24.960 of mementos. 01:25.180 --> 01:31.030 And the third one is caretaker which is the type that stores the list of mementos that can have the 01:31.030 --> 01:37.080 logic to store them in a database or not to store more than a specified number of them. 01:37.090 --> 01:44.470 Memento is all about a sequence of actions over time say to undo one or two operations or to provide 01:44.470 --> 01:47.870 some kind of transaction reality to some application. 01:47.890 --> 01:53.800 Memento provides the foundations for many tasks but its main objective can be defined with these two 01:53.800 --> 01:54.820 points. 01:54.820 --> 02:01.720 First to capture an object state without modifying the object itself and next to save a limited number 02:01.720 --> 02:04.750 of states so that we can retrieve them later. 02:04.990 --> 02:09.340 We will develop a simple example using a string as the state we want to save. 02:09.850 --> 02:15.820 This way we will focus on the common memento pattern implementations before making it a bit more complex 02:15.940 --> 02:17.860 with a new example. 02:17.860 --> 02:24.040 The String stored in a field of state instance will be modified and we will be able to undo the operations 02:24.040 --> 02:26.060 done in this state. 02:26.110 --> 02:32.140 We are constantly talking about state all in all the momento pattern is about storing and retrieving 02:32.140 --> 02:33.020 states. 02:33.130 --> 02:37.360 Our acceptance criteria must be all about states. 02:37.540 --> 02:43.390 So we need to store a finite amount of states of type String and we also need a way to restore the current 02:43.390 --> 02:46.480 stored state to one of the state list. 02:46.480 --> 02:51.820 With these two simple requirements we can already start writing some tests for this example. 02:51.940 --> 02:54.830 So let's start with the unit test. 02:54.880 --> 03:01.540 As mentioned previously the momentum design pattern is usually composed of three actors state momento 03:01.750 --> 03:07.300 and originator so we will need three types to represent these actors. 03:07.300 --> 03:14.380 I've created a folder with the name Memento and here I have two files memento dot go and memento underscore 03:14.410 --> 03:23.920 test dot go let's open momento dot go here we add the package name import F.M. T State type the state 03:23.920 --> 03:29.890 type is the core business object we will be using during this example it's any kind of object that we 03:29.890 --> 03:37.930 want to track now we add type momento the momento type has a field called state representing a single 03:37.930 --> 03:44.770 value of state type our states will be containerized within this type before storing them in the caretaker 03:44.770 --> 03:52.030 type you could be wondering why we don't just store directly state instances basically because it will 03:52.030 --> 03:57.400 couple the originator and the caretaker to the business object and we want to have as little coupling 03:57.460 --> 04:03.110 as possible it will also be less flexible as we will see in the second example. 04:03.400 --> 04:10.870 Now let's add the originator type the originator type also stores a state the originator struct objects 04:11.070 --> 04:17.440 will take states from mementos and create new mementos with their stored state the originator will have 04:17.440 --> 04:25.090 two public methods the new memento method and the extract and store state method the new momento method 04:25.300 --> 04:31.990 will return a new memento built with originator current state value the extract and store state method 04:32.170 --> 04:39.490 will take the state of a momento and store it in the originators state field a question which toggles 04:39.490 --> 04:46.300 here is what's the difference between the originator object and the momento pattern why don't we use 04:46.300 --> 04:49.060 originator patterns object directly. 04:49.150 --> 04:55.660 Well if the momento contains a specific state the originator type contains the state that is currently 04:55.660 --> 05:02.530 loaded also to save the state of something could be as simple as to take some value or as complex as 05:02.530 --> 05:10.330 to maintain the state of some distributed application next we add the caretaker type the caretaker type 05:10.510 --> 05:16.900 stores the momento list with all the states we need to save it also stores an add method to insert a 05:16.900 --> 05:23.050 new memento on the list and a memento retriever that takes an index on the memento list. 05:23.350 --> 05:30.310 So let's start with the add method of the caretaker type the add method must take a memento object and 05:30.430 --> 05:37.690 add it to the caretaker object list of mementos for now save this file and move to the memento test 05:37.810 --> 05:40.450 dot go as I said before. 05:40.450 --> 05:47.500 Let's add the add method of the caretaker type at the beginning of our test we created two basic actors 05:47.500 --> 05:54.790 for momento the originator and the caretaker we set a first state on the originator with the description 05:55.090 --> 06:02.530 idle then we create the first memento calling the new memento method this should wrap the current originator 06:02.530 --> 06:09.610 state in a memento type our first check is very simple the state description of the returned memento 06:09.730 --> 06:17.260 must be like the state description we pass to the originator that is the ideal description the last 06:17.260 --> 06:22.540 step to check whether our mementos add method works correctly is to see whether the memento list has 06:22.540 --> 06:30.310 grown after adding one item let's add the code for this logic we also have to test the memento into 06:30.310 --> 06:36.220 method this should take a memento value from the caretaker list it takes the index you want to retrieve 06:36.220 --> 06:36.960 from the list. 06:36.970 --> 06:44.080 So as usual with lists we must check that it behaves correctly against negative numbers and out of index 06:44.080 --> 06:44.940 values. 06:45.070 --> 06:48.630 So now we add the test for caretaker momento. 06:49.030 --> 06:55.540 We have to start like we did in our previous test creating an originator and caretaker objects and adding 06:55.540 --> 06:58.070 the first momento to the caretaker. 06:58.150 --> 07:01.490 Again we need to add a few lines of code for this. 07:01.750 --> 07:07.750 Once we have the first object on the caretaker object we can ask for it using caretaker dot momento 07:07.810 --> 07:13.810 0 index 0 on the momento into method retrieves the first item on the slice. 07:13.810 --> 07:16.370 Remember that slices start with zero. 07:16.390 --> 07:21.460 No error should be returned because we have already added a value to the caretaker object. 07:21.580 --> 07:26.980 Then after retrieving the first memento we checked that the description matches the one that we passed 07:26.980 --> 07:29.010 at the beginning of the test. 07:29.020 --> 07:32.010 Now let's add a few more lines of code. 07:32.050 --> 07:36.910 The last step on this test involves using a negative number to retrieve some value. 07:36.970 --> 07:42.240 In this case an error must be returned that shows that no negative numbers can be used. 07:42.250 --> 07:46.500 It is also possible to return the first index when you pass negative numbers. 07:46.630 --> 07:48.980 But here we will return an error. 07:49.000 --> 07:53.620 The last function to check is the extract and store state method. 07:53.620 --> 07:59.440 This function must take a memento and extract all its state information to set it in the originator 07:59.470 --> 08:00.150 object. 08:00.520 --> 08:04.260 So let's add this last function to our code file. 08:04.300 --> 08:05.600 This test is simple. 08:05.740 --> 08:09.430 We create a default originator variable with an idle state. 08:09.430 --> 08:12.780 Then we retrieve a new memento object to use it later. 08:12.850 --> 08:18.610 We changed the state of the originator variable to the working state to ensure that the new state will 08:18.610 --> 08:19.720 be written. 08:19.720 --> 08:25.990 Finally we have to call the extract and store state method with the idle memento variable. 08:25.990 --> 08:31.180 This should restore the state of the originator to the idle memento state's value something that we 08:31.180 --> 08:33.690 checked in the last if statement. 08:33.700 --> 08:40.900 Now it's time to run the tests save the file and open the terminal type of the command go test hyphen 08:40.900 --> 08:42.010 V. 08:42.010 --> 08:45.490 You can see that all the tests fail because the three tests fail. 08:45.520 --> 08:52.360 We can continue with the implementation now the momento patterns implementation is usually very simple. 08:52.450 --> 08:59.920 If you don't get too crazy the three actors memento originator and caretaker have a very defined role 08:59.950 --> 09:03.520 in the pattern and their implementation is very straightforward. 09:03.580 --> 09:06.450 Open the memento don't go file here. 09:06.490 --> 09:09.280 We need to modify the originator function. 09:09.670 --> 09:15.040 Done the originator object needs to return new values of momento types. 09:15.040 --> 09:20.830 When calling the new memento method it also needs to store the value of a momento object in the state 09:20.830 --> 09:27.570 field of the struct as needed for the extract and store state method let's make changes to the caretaker 09:27.600 --> 09:35.110 add method and momento method the caretaker type is also straightforward when we call the add method 09:35.290 --> 09:42.090 we overwrite the momento list field by calling the append method with the value past in the argument. 09:42.100 --> 09:47.380 This creates a new list with the new value included when calling the momento method. 09:47.470 --> 09:49.870 We have to do a couple of checks beforehand. 09:49.870 --> 09:55.120 In this case we check that the index is not outside of the range of the slice and that the index is 09:55.120 --> 10:00.690 not a negative number in the if statement in which case we return an error. 10:00.790 --> 10:06.840 If everything goes fine it just returns the specified memento object and no errors. 10:06.850 --> 10:08.520 Time to check the test results. 10:08.590 --> 10:17.430 Save the file and open the terminal run the command go test hyphen V that was enough to reach 100 percent 10:17.430 --> 10:18.430 of coverage. 10:18.540 --> 10:23.550 While this is far from being a perfect metric at least we know that we are reaching every corner of 10:23.610 --> 10:27.870 our source code and that we haven't cheated in our tests to achieve it. 10:27.870 --> 10:29.010 Superb. 10:29.010 --> 10:34.910 The previous example is good and simple enough to understand the functionality of the memento pattern. 10:34.950 --> 10:41.670 However it is more commonly used in conjunction with the command pattern and a simple facade pattern. 10:41.700 --> 10:46.520 The idea is to use a command pattern to encapsulate a set of different types of states. 10:46.680 --> 10:52.440 Those that implement a command interface and provide a small facade to automate the insertion of the 10:52.440 --> 10:54.370 caretaker object. 10:54.370 --> 10:58.750 We are going to develop a small example of a hypothetical audio mixer. 10:58.830 --> 11:05.700 We are going to use the same momento pattern to save two types of states volume and mute the volume 11:05.700 --> 11:10.370 state is going to be a byte type and the mute state a boolean type. 11:10.530 --> 11:15.930 We will use two completely different types to show the flexibility of this approach and its drawbacks 11:17.070 --> 11:18.070 as a side note. 11:18.120 --> 11:23.310 We can also shape each command interface with their own serialization methods on the interface. 11:23.310 --> 11:29.130 This way we can give the ability to the caretaker to store states in some kind of storage without really 11:29.130 --> 11:36.160 knowing what storing our command interface is going to have one method to return the value of its implementer. 11:36.210 --> 11:37.290 It's very simple. 11:37.350 --> 11:42.510 Every command in our audio mixer that we want to undo will have to implement this interface. 11:43.050 --> 11:49.110 So let's open the momento underscore command not go file and add the command interface. 11:49.110 --> 11:55.740 There is something interesting in this interface the Get value method returns an interface to a value. 11:55.740 --> 12:00.590 This also means that the return type of this method is well on typed. 12:00.600 --> 12:06.060 Not really but it returns an interface that can be a representation of any type. 12:06.060 --> 12:10.890 And we will need to typecast it later if we want to use it specific type. 12:10.910 --> 12:15.880 Now we have to define the volume and mute types and implement the command interface. 12:15.900 --> 12:17.220 Let's do this. 12:17.300 --> 12:18.550 Okay. 12:18.590 --> 12:20.810 They are both quite easy implementations. 12:20.870 --> 12:26.900 However the mute type will return a bull type on the Get value method and the volume will return a byte 12:26.900 --> 12:29.520 type as in the previous example. 12:29.580 --> 12:32.720 We'll need a momento type that will hold a command. 12:32.720 --> 12:37.250 In other words it will store a pointer to a mute or a volume type. 12:37.250 --> 12:44.600 So let's add type momento struct done the originator type works as in the previous example but uses 12:44.600 --> 12:48.680 the command keyword instead of the state keyword. 12:48.680 --> 12:55.370 Now let's add the originator struct the caretaker object is almost the same but this time we'll use 12:55.370 --> 13:00.700 a stack instead of a simple list and we will store command instead of a state. 13:00.740 --> 13:07.660 Let's add the lines of code for this however our momento list is replaced with a pop method. 13:07.690 --> 13:14.530 It also returns a momento object but it will return them acting as a stack last to enter first to go 13:14.530 --> 13:21.510 out so we take the last element on the stack and store it in the temporary memento variable. 13:21.590 --> 13:27.200 Then we replace the stack with a new version that doesn't contain the last element on the next line. 13:27.200 --> 13:30.830 Finally we return the memento variable. 13:30.830 --> 13:34.860 Until now everything looks almost like in the previous example. 13:34.970 --> 13:39.150 We also talked about automating some tasks by using the facade pattern. 13:39.620 --> 13:41.010 Let's do it. 13:41.150 --> 13:46.550 This is going to be called the momento facade type and we'll have the safe settings and restore settings 13:46.550 --> 13:53.180 methods the safe settings method takes a command stores it in an inner originator and saves it in an 13:53.270 --> 13:55.090 inner caretaker field. 13:55.250 --> 14:01.640 The Restore settings method makes the opposite flow restores an index of the caretaker and returns the 14:01.640 --> 14:04.590 command instead of the momento object. 14:04.610 --> 14:11.510 So now we add the momento facade type our facade pattern will hold the contents of the originator and 14:11.510 --> 14:17.630 the caretaker and will provide those too easy to use methods to save and restore settings. 14:17.720 --> 14:19.330 So how do we use this. 14:19.370 --> 14:22.250 Let's add the main function to use this. 14:22.340 --> 14:28.940 First we get a variable with a facade pattern zero value initialization will give us zero valued originator 14:29.180 --> 14:31.080 and caretaker object. 14:31.160 --> 14:35.880 They don't have any unexpected field so everything will initialize correctly. 14:36.080 --> 14:40.300 If any of them had a pointer for example it would be initialized to nil. 14:40.430 --> 14:47.030 As we discussed in the video on zero initialization from the first section of our previous part go classical 14:47.030 --> 14:48.070 patterns. 14:48.470 --> 14:51.470 We create a volume value with volume 4. 14:51.470 --> 14:58.640 And yes we have used parentheses the volume type does not have any in a field like struct so we cannot 14:58.730 --> 15:01.160 use curly braces to set its value. 15:01.370 --> 15:07.490 The way to set it is to use parentheses or create a pointer to the type volume and then set the value 15:07.490 --> 15:09.320 of the pointed space. 15:09.350 --> 15:13.940 We also save a value of the type mute using the facade pattern. 15:14.090 --> 15:19.090 We don't know what command type is returned here so we need to make a type assertion. 15:19.220 --> 15:25.100 We will make a small function to help us with this that checks the type and prints an appropriate value. 15:25.340 --> 15:29.780 Let's add a cert and print function fine. 15:29.930 --> 15:35.460 Now the assert and print method takes a command type and casts it to the two possible types. 15:35.540 --> 15:42.170 That is volume or mute in each case it prints a message to the console with a personalized message. 15:43.000 --> 15:46.310 Now let's continue and finish the main function. 15:46.450 --> 15:52.300 So here's how our main function looks the part highlighted in bold shows the new changes within the 15:52.300 --> 15:53.380 main function. 15:53.560 --> 15:59.560 We took the index 0 from the caretaker object and passed it to the new function and the same with the 15:59.560 --> 16:02.510 index one running this small program. 16:02.590 --> 16:06.450 We should get the volume and mute values on the console. 16:06.610 --> 16:09.990 Let's save the file and open the terminal and run the command. 16:10.060 --> 16:18.920 Go run momento underscore command dot go right in this small example we have combined three different 16:18.920 --> 16:22.860 design patterns to keep getting comfortable using various patterns. 16:23.000 --> 16:28.280 Keep in mind that we could have abstracted the creation of volume and mute states to a factory pattern 16:28.280 --> 16:28.870 too. 16:28.910 --> 16:33.060 So this is not where you would stop with the momento pattern. 16:33.110 --> 16:39.530 We have learned a powerful way to create undoable operations that are very useful when writing UI applications 16:39.800 --> 16:43.610 but also when you have to develop transactional operations. 16:43.610 --> 16:46.020 In any case the situation is the same. 16:46.100 --> 16:50.170 You need a memento an originator and a caretaker actor. 16:50.420 --> 16:55.880 A transaction operation is a set of atomic operations that must all be done or fail. 16:55.880 --> 17:01.940 In other words if you have a transaction composed of five operations and just one of them fails the 17:01.940 --> 17:09.480 transaction cannot be completed and every modification done by the other four must be undone in this 17:09.480 --> 17:10.080 video. 17:10.100 --> 17:14.400 We have explored about the memento design pattern in the next video. 17:14.460 --> 17:17.340 We will dive into interpret her design pattern.