WEBVTT 00:00.450 --> 00:01.060 Hello. 00:01.140 --> 00:07.310 We are now at the second video of this section decorator design pattern in the previous video. 00:07.350 --> 00:10.950 We looked at proxy design pattern in this video. 00:10.950 --> 00:17.620 We will prepare a pizza type where the core is the pizza and the ingredients on the decorating types. 00:17.640 --> 00:21.850 We will have a couple of ingredients for our pizza onion and meat. 00:21.870 --> 00:27.690 We'll continue this section with the big brother of the proxy pattern and maybe one of the most powerful 00:27.690 --> 00:31.890 design patterns of all the Decorator pattern is pretty simple. 00:31.890 --> 00:37.340 But for instance it provides a lot of benefits when working with legacy code. 00:37.340 --> 00:43.590 The decorator design pattern allows you to decorate an already existing type with more functional features 00:43.710 --> 00:45.710 without actually touching it. 00:45.720 --> 00:46.710 How is it possible. 00:47.010 --> 00:52.560 Well it uses an approach similar to match your shadows where you have a small doll that you can put 00:52.560 --> 00:57.600 inside a doll of the same shape but bigger and so on and so forth. 00:57.660 --> 01:03.420 The decorator type implements the same interface of the type it decorates and stores an instance of 01:03.420 --> 01:05.600 that type in its member. 01:05.610 --> 01:12.270 This way you can stack as many decorators that is Doles as you want by simply storing the old decorator 01:12.450 --> 01:14.490 in a field of the new one. 01:14.550 --> 01:19.500 When you think about extending legacy code without the risk of breaking something you should think of 01:19.500 --> 01:21.580 the Decorator pattern first. 01:21.600 --> 01:27.390 It's a really powerful approach to deal with this particular problem a different field where the decorator 01:27.390 --> 01:33.600 is very powerful may not be so obvious though it reveals itself when creating types with lots of features 01:33.840 --> 01:39.220 based on user inputs preferences or similar inputs like in a Swiss knife. 01:39.330 --> 01:47.610 You have a base type or the frame of the knife and from there you unfold its functionalities so precisely 01:47.610 --> 01:50.280 when are we going to use the Decorator pattern. 01:50.280 --> 01:55.530 Here's the answer to this question when you need to add functionality to some code that you don't have 01:55.620 --> 02:02.280 access to or you don't want to modify to avoid a negative effect on the code and follow the open or 02:02.280 --> 02:04.610 closed principle like legacy code. 02:05.370 --> 02:10.620 When you want the functionality of an object to be created or altered dynamically then the number of 02:10.620 --> 02:13.810 features is unknown and could grow fast. 02:14.070 --> 02:20.100 The acceptance criteria for a decorator pattern is to have common interface and core type. 02:20.100 --> 02:22.940 The one that all layers will be built over. 02:23.160 --> 02:27.030 We must have the main interface that all decorators will implement. 02:27.180 --> 02:33.630 This interface will be called ingredient add and it will have ADD ingredient string method. 02:33.750 --> 02:40.410 We must have a core pizza decorator type the decorator that we will add ingredients to. 02:40.410 --> 02:47.280 We must have an ingredient onion implementing the same ingredient add interface that will add the string 02:47.430 --> 02:49.870 onion to the returned pizza. 02:49.920 --> 02:56.490 We must have an ingredient meat implementing the ingredient add interface that will add the string meat 02:56.640 --> 03:04.120 to the returned pizza when calling add ingredient method on the top object it must return a fully decorated 03:04.120 --> 03:09.430 pizza with the text pizza with the ingredients meat and onion. 03:09.490 --> 03:13.450 Let's start with the unit test to launch our unit tests. 03:13.450 --> 03:19.480 We must first create the basic structures described in accordance with the acceptance criteria to begin 03:19.480 --> 03:25.800 with the interface that all decorating types must implement is as I'm going to show you now. 03:25.870 --> 03:30.440 I have already created a file and named it as pizza underscored decorator. 03:30.440 --> 03:31.650 Don't go. 03:31.780 --> 03:34.810 Let's add the decorator package and import errors 03:38.310 --> 03:38.950 next. 03:38.970 --> 03:45.600 Let's add the code to defined the pizza decorator type which must have ingredient add inside and which 03:45.660 --> 03:47.060 implements ingredient. 03:47.070 --> 03:49.170 Add to after this. 03:49.170 --> 03:54.540 Let's add the definition of the meat type which will be very similar to that of the pizza decorator 03:54.540 --> 03:55.860 structure. 03:55.860 --> 03:59.480 Now we define the onion struct in a similar fashion. 03:59.520 --> 04:01.190 Let's add the code for this. 04:01.290 --> 04:03.140 Let's save the file. 04:03.150 --> 04:09.240 This is enough to implement the first unit tests and to allow the compiler to run them without any compiling 04:09.330 --> 04:10.230 errors. 04:10.230 --> 04:13.910 Now let's open the pizza decorator test dot go. 04:13.980 --> 04:18.380 Here we start with the name of the package and import strings and testing. 04:18.390 --> 04:22.890 And now add the adds ingredient method saved the file. 04:22.890 --> 04:27.730 Now it must compile without problems so we can check that the test fails. 04:27.990 --> 04:30.110 So move to the terminal first. 04:30.140 --> 04:36.510 Navigate to the working directory and run the test and here's the output and you can see that the test 04:36.510 --> 04:43.200 fails our first test is done and we can see that the pizza decorator struct isn't returning anything 04:43.200 --> 04:43.860 yet. 04:43.860 --> 04:45.390 That's why it fails. 04:45.450 --> 04:48.610 We can now move on to the onion type. 04:48.610 --> 04:54.360 The test of the onion type is quite similar to that of the pizza decorator but we must also make sure 04:54.360 --> 05:00.790 that we actually add the ingredient to the ingredient add method and not to a null pointer. 05:00.810 --> 05:03.070 Let's go back to pizza decorator test. 05:03.120 --> 05:04.190 Don't go. 05:04.290 --> 05:08.080 Let's add the code for test onion. 05:08.280 --> 05:14.100 The first half of this test examines the returning error when no ingredient add method is passed to 05:14.100 --> 05:18.940 the onion struct initialized as no pizza is available to add the ingredient. 05:18.990 --> 05:21.750 An error must be returned. 05:21.750 --> 05:25.210 The second part of the onion type test actually passes. 05:25.210 --> 05:27.740 Pizza decorator structure to the initialize. 05:28.050 --> 05:33.360 Then we check whether no error is being returned and also whether the returning string contains the 05:33.360 --> 05:35.250 word onion in it. 05:35.250 --> 05:39.500 This way we can ensure that onion has been added to the pizza. 05:39.540 --> 05:46.420 Finally with the onion type let's see the console output of this test with our current implementation. 05:46.650 --> 05:50.550 So open the terminal and run the test command. 05:50.550 --> 05:56.720 And here's the output the meat ingredient is exactly the same but we changed the type to meet. 05:56.790 --> 05:59.640 Instead of onion let's go to the test. 05:59.650 --> 06:05.870 Don't go and add the lines of code save the file and move back to the terminal. 06:05.940 --> 06:09.080 So the result of the tests must be similar. 06:09.120 --> 06:13.330 Let's run the test again. 06:13.340 --> 06:16.490 Finally we must check the full stack test. 06:16.490 --> 06:24.000 Creating a pizza with onion and meat must return the text pizza with the ingredients meat and onion. 06:24.110 --> 06:25.960 Go back to the pizza decorator test. 06:25.990 --> 06:30.560 Don't go and add the code for full stack test. 06:30.560 --> 06:38.090 Our test creates a variable called Pizza which like the mattress Goodall's embeds types of the ingredient 06:38.180 --> 06:45.200 add method in several levels calling the add ingredient method executes the method at the Onion level 06:45.410 --> 06:52.280 which executes the meat one which finally executes that of the pizza decorator struct after checking 06:52.280 --> 06:54.000 that no error has been returned. 06:54.050 --> 06:58.640 We check whether the returned text follows the needs of the acceptance criteria. 06:58.640 --> 06:59.510 5. 06:59.780 --> 07:04.610 Now save the file and let's go back to the terminal type at the command. 07:04.610 --> 07:08.000 Go test hyphen v hyphen run equal to test. 07:08.000 --> 07:15.680 Pizza decorator underscore a full stack enter cool from this output we can see that the tests now return 07:15.770 --> 07:18.720 an empty string for our decorated type. 07:18.740 --> 07:22.090 This is of course because no implementation has been done yet. 07:22.100 --> 07:26.300 This was the last test to check the fully decorated implementation. 07:26.300 --> 07:29.920 Let's look closely at the implementation then. 07:30.050 --> 07:34.100 Now we are going to start implementing the pizza decorator type. 07:34.100 --> 07:38.180 Its role is to provide the initial text of the full pizza. 07:38.210 --> 07:44.210 Open the pizza decorator dot go file and now let's replace this piece of code. 07:44.240 --> 07:50.870 Now a single line change on the return of the added ingredient method was enough to pass the test save 07:50.870 --> 07:53.300 the file and go to the terminal. 07:53.430 --> 07:58.400 Let us run the test as you can see we have successfully passed the test. 07:58.490 --> 08:01.350 Moving onto the onion struct implementation. 08:01.490 --> 08:08.030 We must take the beginning of our ingredient and return string and add the word onion at the end of 08:08.030 --> 08:08.240 it. 08:08.270 --> 08:14.480 In order to get a composed pizza in return let us modify this code with the return string. 08:14.480 --> 08:22.310 Also don't forget to define f empty in the import checking that we actually have a pointer to ingredient 08:22.390 --> 08:29.840 ad first we use the contents of the inner ingredient ad and check it for errors if no errors occurred. 08:29.840 --> 08:36.890 We receive a new string composed of this content space and the word onion and no errors. 08:37.040 --> 08:43.260 Looks good enough to run the tests save the file go to the terminal and run the test. 08:43.290 --> 08:43.770 Onion 08:46.310 --> 08:49.560 implementation of the meat struct is very similar. 08:50.000 --> 08:52.580 Let's open the pizza decorator and modify the meat. 08:52.580 --> 08:56.350 Function take care of the brace brackets. 08:56.350 --> 08:58.930 The proper opening and closing. 08:58.930 --> 09:04.650 Okay save this file and here goes there test execution. 09:04.730 --> 09:07.770 So we have again passed the test. 09:07.790 --> 09:11.320 Okay so now all the pieces are to be tested separately. 09:11.420 --> 09:12.700 If everything is okay. 09:12.770 --> 09:16.870 The test of the full stacked solution must be passing smoothly. 09:16.940 --> 09:25.760 Let's run the test for full stack also with the decorator pattern we could keep stacking ingredient 09:25.880 --> 09:30.680 ads which call their inner pointer to add functionality to piece a decorator. 09:30.680 --> 09:36.860 We aren't touching the core type either nor modifying or implementing new things all the new features 09:36.950 --> 09:40.360 are implemented by an external type. 09:40.380 --> 09:44.160 Let me share a few words about ghost structural typing. 09:44.370 --> 09:50.840 So go has a feature that most people dislike at the beginning that is structural typing. 09:51.000 --> 09:55.540 This is when your structure defines your type without explicitly writing it. 09:55.560 --> 10:01.230 For example when you implement an interface you don't have to write explicitly that you're actually 10:01.230 --> 10:02.290 implementing it. 10:02.430 --> 10:09.090 Contrary to languages such as Java where you have to write the keyword implements if your method follows 10:09.090 --> 10:13.260 the signature of the interface you are actually implementing the interface. 10:13.260 --> 10:19.350 This can also lead to accidental implementations of interface something that could provoke an impossible 10:19.350 --> 10:22.960 to track mistake but that is very unlikely. 10:22.980 --> 10:27.210 However structural typing also allows you to define an interface. 10:27.210 --> 10:29.380 After defining their implementers. 10:29.520 --> 10:33.320 Imagine a my printer struct as this one. 10:33.390 --> 10:39.630 Now imagine we have been working with my printer type for a few months now but it didn't implement any 10:39.630 --> 10:44.400 interface so it can't be a possible candidate for a decorator pattern. 10:44.400 --> 10:46.650 Or maybe it can. 10:46.680 --> 10:50.250 What if we wrote an interface that matches its print method. 10:50.250 --> 10:54.540 After a few months consider this piece of code that I'm about to add. 10:56.780 --> 11:04.130 It actually implements the printer interface and we can use it to create a decorator solution structural 11:04.130 --> 11:07.720 typing allows a lot of flexibility when writing programs. 11:07.760 --> 11:13.100 If you don't know whether a type should be part of an interface or not you can leave it and at the interface 11:13.100 --> 11:15.880 later when you are completely sure about it. 11:16.040 --> 11:23.270 This way you can decorate types very easily and with little modification in your source code you might 11:23.270 --> 11:29.570 be wondering what's the difference between decorator pattern and the proxy pattern in the decorator 11:29.570 --> 11:32.450 pattern with decorator type dynamically. 11:32.450 --> 11:39.200 This means that the decoration may or may not be there or it may be composed of one or many types. 11:39.260 --> 11:46.520 If you remember the proxy pattern wraps a type in a similar fashion but it does so at compile time and 11:46.520 --> 11:51.070 it's more like a way to access some type at the same time. 11:51.120 --> 11:58.050 A decorator might implement the entire interface that the type it decorates also implements or not. 11:58.050 --> 12:03.450 So you can have an interface with 10 methods and the decorator that just implements one of them. 12:03.510 --> 12:09.420 And it will still be valid a call on a method not implemented by the decorator will be passed to the 12:09.420 --> 12:11.190 decorated type. 12:11.190 --> 12:17.560 This is a very powerful feature but also very prone to undesired behaviors at runtime. 12:17.580 --> 12:23.940 If you forget to implement any interface method in this aspect you may think that the proxy pattern 12:23.940 --> 12:30.780 is less flexible and it is but the Decorator pattern is weaker as you could have errors at runtime which 12:30.780 --> 12:34.790 you can avoid it to compile time by using the proxy pattern. 12:34.830 --> 12:40.500 Just keep in mind that the decorator is commonly used when you want to add functionality to an object 12:40.620 --> 12:43.440 at runtime like our web server. 12:43.470 --> 12:50.250 It's a compromise between what you need and what you want to sacrifice to achieve it in this video. 12:50.270 --> 12:54.490 We dived into the decorator design pattern in the next video. 12:54.530 --> 12:57.410 We will learn about facade design pattern.