1 00:00:07,260 --> 00:00:07,680 Hello. 2 00:00:08,550 --> 00:00:15,390 In this video, we're going to talk about Question 45, what is the composition of our inheritance? 3 00:00:15,390 --> 00:00:22,980 Principal composition of our inheritance is a design principle stating that we should favor a composition 4 00:00:22,980 --> 00:00:24,300 of our inheritance. 5 00:00:24,690 --> 00:00:32,370 In other words, we should reduce the code by river containing objects within other objects, then inheriting 6 00:00:32,370 --> 00:00:33,780 one from another. 7 00:00:34,350 --> 00:00:36,330 Let's see a practical example. 8 00:00:36,990 --> 00:00:42,810 These grass roots people's data from a database and formats it as a single string. 9 00:00:43,290 --> 00:00:49,800 It's obviously breaking the single responsibility principle, but that's by now not focus on that. 10 00:00:50,340 --> 00:00:56,760 One day the business requirements change, and we are told that sometimes the people information will 11 00:00:56,760 --> 00:01:01,020 be read from the database, but sometimes from an Excel file. 12 00:01:01,590 --> 00:01:04,530 We wanted to be able to make this decision at runtime. 13 00:01:05,190 --> 00:01:13,050 We can solve it in two ways by either using composition and injecting an object, implementing some 14 00:01:13,350 --> 00:01:17,890 people data reader interface, or we can use inheritance. 15 00:01:18,480 --> 00:01:21,180 First, let's solve this with inheritance. 16 00:01:21,630 --> 00:01:25,260 I will make the personal data for motocross abstract. 17 00:01:27,480 --> 00:01:33,240 The rich people mattered must also be abstract so it can be overridden inheritance. 18 00:01:56,170 --> 00:01:56,770 Great. 19 00:01:57,070 --> 00:01:58,810 We achieved what we wanted. 20 00:01:59,260 --> 00:02:04,930 We can now format the personal data sourced from both database and excel files. 21 00:02:05,440 --> 00:02:11,830 We don't have an account applications and we can decide the type at runtime using some factory. 22 00:02:13,410 --> 00:02:20,100 Here is the factory, as you can see, it takes the source in, and based on that, it creates a proper 23 00:02:20,100 --> 00:02:20,790 object. 24 00:02:21,150 --> 00:02:23,250 It returns it as a base type. 25 00:02:43,220 --> 00:02:43,960 All right. 26 00:02:44,240 --> 00:02:45,470 Seems to be working. 27 00:02:45,860 --> 00:02:47,990 Everything looks great, doesn't it? 28 00:02:48,530 --> 00:02:50,510 Well, not so fast. 29 00:02:51,230 --> 00:02:56,780 Let me tell you why using inheritance in this case wasn't our brightest idea. 30 00:02:57,320 --> 00:03:04,070 Now, the personal data for Masterclass is tightly coupled with its inheritance, and the turned in 31 00:03:04,070 --> 00:03:07,130 the base class will affect the child classes. 32 00:03:07,550 --> 00:03:10,010 We can't really use any of those types. 33 00:03:10,040 --> 00:03:11,750 We found that the others provide that. 34 00:03:12,350 --> 00:03:19,370 So if I wanted to use the rich people method and where else I would not be able to without engaging 35 00:03:19,430 --> 00:03:26,270 this entire hierarchy of classes, you can learn more about coupling in the what this coupling lecture. 36 00:03:26,990 --> 00:03:30,770 The relation between those particular classes is reduced. 37 00:03:31,070 --> 00:03:33,080 It is defined at compile time. 38 00:03:33,740 --> 00:03:40,460 Also, we have all the limitations of inheritance, especially the fact that we can only inherit from 39 00:03:40,460 --> 00:03:41,720 a single base class. 40 00:03:42,320 --> 00:03:48,440 This example is simple, but if we need that some other changes that would make those classes different, 41 00:03:48,650 --> 00:03:52,640 we would have the inheritance hierarchy growing really fast. 42 00:03:53,030 --> 00:03:59,630 For example, if the way of formatting the final string would also need to be configurable, we would 43 00:03:59,630 --> 00:04:02,420 need to create even more classes like this. 44 00:04:04,090 --> 00:04:11,380 Such hierarchy would soon become unmanageable if we wanted to create unit tests for those classes. 45 00:04:11,560 --> 00:04:12,580 It would be tricky. 46 00:04:13,240 --> 00:04:20,740 They are two approaches for testing abstract classes and their inheritors, both with their own disadvantages. 47 00:04:21,250 --> 00:04:28,330 We could test only the inheritors and for both of them, would also test the common part belonging to 48 00:04:28,330 --> 00:04:29,320 the base class. 49 00:04:29,800 --> 00:04:33,190 This way, our tests would be partially duplicated. 50 00:04:33,730 --> 00:04:40,870 Alternatively, we can test inheritors ignoring the logic belonging to the base type as much as possible. 51 00:04:41,320 --> 00:04:46,960 Then we can test the base class logic by creating only for the testing purposes. 52 00:04:47,230 --> 00:04:54,280 A special dedicated concrete type derived from it in the tests of this class would focus on testing 53 00:04:54,280 --> 00:04:56,200 only the base class logic. 54 00:04:56,770 --> 00:04:59,440 This is even worse than the first solution. 55 00:05:00,070 --> 00:05:07,060 If we need to create a special inheritors classes for testing purposes only, it means we must our design 56 00:05:07,150 --> 00:05:08,020 really badly. 57 00:05:08,920 --> 00:05:14,560 Another disadvantage of inheritance is that we often inherit more than we actually want. 58 00:05:14,830 --> 00:05:19,390 The base class is exposing the implementation details to inheritance. 59 00:05:20,050 --> 00:05:26,620 There is one more reason for avoiding inheritance that is not really related to this example, but I 60 00:05:26,620 --> 00:05:28,120 want to mention it anyway. 61 00:05:28,540 --> 00:05:35,800 If we use inheritance in the hierarchy of objects that we intend to store in a database using some object 62 00:05:35,800 --> 00:05:42,130 relational mapping tools like Entity Framework, it may be a challenge to store those objects properly. 63 00:05:42,580 --> 00:05:50,410 Databases don't really understand inheritance, so mapping the shop's hierarchy of inheritance into 64 00:05:50,410 --> 00:05:56,920 a flat structure of tables is tricky and often leads to over complicating the model in the database. 65 00:05:57,430 --> 00:05:59,230 Well, that's a lot of issues. 66 00:05:59,470 --> 00:06:01,210 So how can we solve them all? 67 00:06:01,690 --> 00:06:07,030 In this case, we should definitely apply the composition of our inheritance principle. 68 00:06:07,450 --> 00:06:09,220 Let's refactor this code. 69 00:06:09,550 --> 00:06:12,700 First of all, we will introduce an interface. 70 00:06:21,340 --> 00:06:24,070 We will have two classes implementing it. 71 00:06:38,840 --> 00:06:45,590 Instead of using inheritance, we compose the personal data for formatter with any type implementing 72 00:06:45,590 --> 00:06:47,810 the open data reader interface. 73 00:07:01,270 --> 00:07:04,030 Finally, we will adjust the factory. 74 00:07:16,670 --> 00:07:18,530 Let's make sure everything works. 75 00:07:20,840 --> 00:07:21,530 Great. 76 00:07:21,920 --> 00:07:25,910 Everything works as before, but no problems that we mentioned. 77 00:07:26,000 --> 00:07:30,020 OK, you now the glasses are now loosely coupled. 78 00:07:30,320 --> 00:07:35,390 They live in complete separation and they only communicate over an interface. 79 00:07:36,110 --> 00:07:39,620 The relationship between glasses is not rigid anymore. 80 00:07:39,860 --> 00:07:44,060 It is defined at one time when we actually inject a concrete people. 81 00:07:44,090 --> 00:07:50,270 They trigger the personal data for motor object, which deconstruct constructor before the relation 82 00:07:50,270 --> 00:07:52,190 was defined at compile time. 83 00:07:52,760 --> 00:07:57,620 If we needed to add more changes, the inheritance hierarchy wouldn't grow. 84 00:07:57,980 --> 00:08:02,300 We would only add a new interface and classes implementing it. 85 00:08:07,070 --> 00:08:15,140 For example, some oh person formatter interface implemented by person showed data for motor and person 86 00:08:15,140 --> 00:08:18,860 full data for motor testing would be simple. 87 00:08:19,250 --> 00:08:26,600 We would test each class in separation and no tests would be duplicated when testing this class would 88 00:08:26,600 --> 00:08:30,410 simply inject a mark of a pupil data reader interface. 89 00:08:30,950 --> 00:08:36,020 Lastly, no class exposes and implementation details to uncover class. 90 00:08:36,590 --> 00:08:37,370 All right. 91 00:08:37,640 --> 00:08:44,390 I hope you see now that in this case, composition of our inheritance was a rule who are following. 92 00:08:44,960 --> 00:08:51,110 I would say that in the majority of cases, you should follow their composition, design rather than 93 00:08:51,110 --> 00:08:52,100 inheritance. 94 00:08:52,550 --> 00:08:57,530 To be honest, at my everyday work, I almost never use inheritance. 95 00:08:57,950 --> 00:08:59,810 One more thing before we move on. 96 00:09:00,320 --> 00:09:05,060 If you know the breed design pattern, this all may sound very familiar to you. 97 00:09:05,390 --> 00:09:11,420 This is because the bright pattern is simply a way of implementing the composition of our inheritance 98 00:09:11,420 --> 00:09:12,110 principle. 99 00:09:13,010 --> 00:09:13,820 All right. 100 00:09:14,180 --> 00:09:20,750 We said that having a composition instead of inheritance has a lot of benefits, but it doesn't mean 101 00:09:20,750 --> 00:09:24,020 that inheritance should be avoided at any cost. 102 00:09:24,410 --> 00:09:26,510 Let's take a look at the person type. 103 00:09:26,990 --> 00:09:31,850 Now, let's say we wanted to introduce an employee type to the product. 104 00:09:32,360 --> 00:09:39,140 An employee is still a person and it should have first name, last name and year of birth properties. 105 00:09:39,590 --> 00:09:42,980 Additionally, this type should have a position in property. 106 00:09:43,580 --> 00:09:50,120 Let's say we are so excited about using the composition of our inheritance that we decide not to use 107 00:09:50,120 --> 00:09:54,530 inheritance ever again and that this is the code we create. 108 00:09:56,020 --> 00:09:57,550 Is this design good? 109 00:09:57,970 --> 00:10:03,310 Well, I wouldn't say so what looks a bit fishy are the forwarding methods. 110 00:10:03,670 --> 00:10:08,560 So the methods that only exist to call methods from some inner object. 111 00:10:08,980 --> 00:10:14,770 In our case, those methods are the first name, last name and year of birth properties. 112 00:10:15,130 --> 00:10:18,850 Remember that properties are like special kinds of methods. 113 00:10:19,300 --> 00:10:23,980 Now let's see how this court would look like if we used inheritance. 114 00:10:25,190 --> 00:10:27,590 Well, I think it looks much simpler. 115 00:10:27,890 --> 00:10:34,340 The forwarding methods are not there as the properties we want to have in the employee class are simply 116 00:10:34,340 --> 00:10:41,330 inherited from the person class or we need to define is the new position property that actually makes 117 00:10:41,330 --> 00:10:48,290 the employee different from a person, how to decide whether to use composition of our inheritance. 118 00:10:48,800 --> 00:10:54,570 Well, first of all, you need to answer this question when thinking about your types. 119 00:10:54,590 --> 00:10:57,830 Can you say that one of them is the other one? 120 00:10:58,280 --> 00:11:04,820 Do they have the same structure and similar functionality with only some extended behavior in the draft 121 00:11:04,820 --> 00:11:05,330 type? 122 00:11:05,870 --> 00:11:08,990 If so, inheritance can be the right choice. 123 00:11:09,380 --> 00:11:12,380 Otherwise, you should rather opt for composition. 124 00:11:12,920 --> 00:11:19,160 When in doubt, go for composition, and in the worst case, you will adjust your design if it turns 125 00:11:19,160 --> 00:11:24,140 out it's not working out in the document attached to the structure. 126 00:11:24,170 --> 00:11:30,800 I linked an interesting article about making the decision whether to choose composition or inheritance. 127 00:11:31,370 --> 00:11:37,940 Let's summarize Composition of our inheritance is a design principle stating that we should favor a 128 00:11:37,940 --> 00:11:40,070 composition of our inheritance. 129 00:11:40,370 --> 00:11:47,270 It means that we should reduce the coat by containing objects within other objects rather than inheriting 130 00:11:47,360 --> 00:11:48,450 from one another. 131 00:11:49,220 --> 00:11:55,670 When discussing this topic during the interview, you can be asked What is the problem with using composition 132 00:11:55,670 --> 00:11:59,900 only if we decide not to use inheritance at all? 133 00:11:59,930 --> 00:12:06,500 We make it harder for ourselves to define types that are indeed in an ISA, a relation. 134 00:12:06,680 --> 00:12:10,190 So correlation when one type is the other one. 135 00:12:10,640 --> 00:12:15,950 For example, a dog is an animal or an employee is a person. 136 00:12:16,460 --> 00:12:23,180 When implementing such a hierarchy with the composition, we create very similar types that wrap over 137 00:12:23,180 --> 00:12:29,240 types, only adding a bit of new functionality, and they mostly contain forwarding methods. 138 00:12:29,900 --> 00:12:32,390 So what are forwarding methods? 139 00:12:32,840 --> 00:12:35,750 There are methods that don't do anything else. 140 00:12:35,930 --> 00:12:42,980 Then calling almost identical methods from some other type for working methods indicate a very close 141 00:12:42,980 --> 00:12:49,370 relationship between types, which may mean that perhaps one type should be inherited from another. 142 00:12:50,030 --> 00:12:50,720 All right. 143 00:12:51,200 --> 00:12:53,570 We learned a very important principle. 144 00:12:53,990 --> 00:12:57,350 Thank you for your attention, and I'll see you in the next lecture.