1 00:00:00,610 --> 00:00:02,960 Looking back over the code we've just written, 2 00:00:02,960 --> 00:00:05,640 I can see some improvements we could make. 3 00:00:05,640 --> 00:00:08,560 The first thing I see is that we have two lines 4 00:00:08,560 --> 00:00:10,260 that are identical to each other here. 5 00:00:11,330 --> 00:00:14,700 A common saying coders use is keep your code dry. 6 00:00:14,700 --> 00:00:17,660 Dry stands for don't repeat yourself. 7 00:00:17,660 --> 00:00:18,600 Having duplicate or 8 00:00:18,600 --> 00:00:23,090 even similar code like this is one example of what's known as a code smell. 9 00:00:23,090 --> 00:00:27,320 A code smell is something in the code that indicates that there's a potential problem 10 00:00:27,320 --> 00:00:29,520 with how the software is designed. 11 00:00:29,520 --> 00:00:32,790 Let's look at why having these duplicate lines might be a problem for 12 00:00:32,790 --> 00:00:35,110 us and then see how we can fix it. 13 00:00:35,110 --> 00:00:37,570 Let's take a closer look at these lines. 14 00:00:37,570 --> 00:00:38,760 In both lines, 15 00:00:38,760 --> 00:00:43,490 the location property is being set to the location on the path at this _pathStep. 16 00:00:43,490 --> 00:00:47,530 In the case of constructor the _pathStep is zero. 17 00:00:47,530 --> 00:00:51,380 And in the move method, the _pathStep is just the next step on the path. 18 00:00:52,410 --> 00:00:53,560 In either case, 19 00:00:53,560 --> 00:00:58,160 the location property is being set to reflect where the invader is on the path. 20 00:00:59,270 --> 00:01:04,360 So whenever _pathStep changes, the location must also change. 21 00:01:04,360 --> 00:01:07,190 This can be problematic as we add more to this class. 22 00:01:07,190 --> 00:01:11,690 You see, these two places might not be the only places we'll want to change 23 00:01:11,690 --> 00:01:13,780 the _pathStep in the future. 24 00:01:13,780 --> 00:01:16,420 If we ever add code that touches the _pathStep field, 25 00:01:16,420 --> 00:01:18,240 we'll need to be sure to update the location. 26 00:01:19,620 --> 00:01:22,400 What if someone who doesn't know this code as well as we do 27 00:01:22,400 --> 00:01:24,170 wants to make some changes? 28 00:01:24,170 --> 00:01:27,690 They'll need to know this very obscure piece of information. 29 00:01:27,690 --> 00:01:31,470 So the root cause of this code smell is that we have a property that must be 30 00:01:31,470 --> 00:01:34,550 updated every time another field changes. 31 00:01:34,550 --> 00:01:38,700 We can fix this by computing the location every time it's requested, 32 00:01:38,700 --> 00:01:42,290 instead of storing it every time the _pathStep field changes. 33 00:01:42,290 --> 00:01:43,830 This is a good solution, so 34 00:01:43,830 --> 00:01:48,270 long as computing the new location isn't a really expensive operation. 35 00:01:48,270 --> 00:01:52,370 We know that computing the new location is just an array lookup inside the path class 36 00:01:52,370 --> 00:01:55,750 and array lookups are not expensive operations. 37 00:01:55,750 --> 00:02:00,060 To do this, we need to introduce the idea of a computed property. 38 00:02:00,060 --> 00:02:04,780 A computed property is a property that doesn't wrap an actual field. 39 00:02:04,780 --> 00:02:08,700 Remember, this property, as it's written right now is really a field, 40 00:02:08,700 --> 00:02:11,230 a getter method and a setter method. 41 00:02:11,230 --> 00:02:15,010 Let me rewrite this property so that it's computed each time the getter is called. 42 00:02:16,480 --> 00:02:17,690 So we'll get rid of the setter. 43 00:02:20,710 --> 00:02:22,170 And now expand this property a little bit. 44 00:02:25,500 --> 00:02:29,199 Now in here, we'll just return the location that the invader's at, 45 00:02:29,199 --> 00:02:30,462 given the _pathStep. 46 00:02:48,497 --> 00:02:52,150 We no longer need to update the location anymore. 47 00:02:52,150 --> 00:02:57,830 Now, no matter what _pathStep is set to or when and where it's set, the location 48 00:02:57,830 --> 00:03:01,430 property will always accurately reflect the location of the invader. 49 00:03:02,470 --> 00:03:05,556 Now instead having a property that’s a field, a getter and 50 00:03:05,556 --> 00:03:09,480 a setter, we now have what looks a lot more like a simple method. 51 00:03:09,480 --> 00:03:13,120 In fact, we could have coded this up as a method too. 52 00:03:13,120 --> 00:03:16,690 But this is actually a very good case for a computed property, though. 53 00:03:16,690 --> 00:03:21,080 You see, the user of this class doesn't need to know that the location property is 54 00:03:21,080 --> 00:03:24,600 actually computed from the _path and _pathStep fields. 55 00:03:24,600 --> 00:03:28,370 All they need to know is that they can type invader.location and 56 00:03:28,370 --> 00:03:29,970 get the location of the invader on the map. 57 00:03:31,060 --> 00:03:33,920 This is an implementation detail that's best hidden. 58 00:03:33,920 --> 00:03:36,890 And because we did proper encapsulation with access modifiers and 59 00:03:36,890 --> 00:03:40,180 properties, we were able to make this change without changing 60 00:03:40,180 --> 00:03:42,410 anything about the way this class is used by others. 61 00:03:44,060 --> 00:03:49,090 It can sometimes be difficult to decide whether to write a property or a method. 62 00:03:49,090 --> 00:03:52,950 There is sometimes a tendency to turn every method that doesn't have parameters 63 00:03:52,950 --> 00:03:54,080 into a computed property. 64 00:03:55,290 --> 00:03:59,720 Properties intentionally look like fields because they should be used like fields. 65 00:03:59,720 --> 00:04:02,060 They should do simple things related to getting and 66 00:04:02,060 --> 00:04:04,680 setting data that's stored in the object. 67 00:04:04,680 --> 00:04:08,880 That's a general guideline for deciding whether to write a property or a method. 68 00:04:08,880 --> 00:04:12,190 There's also an expectation when using a property that it's going to be 69 00:04:12,190 --> 00:04:16,180 a reasonably inexpensive operation and return quickly. 70 00:04:16,180 --> 00:04:18,940 Just keep this in mind when writing properties and you'll be all right.