Code Reuse6:12 with Craig Dennis
Let's dive into a couple of ways to reuse code. Should you use inheritance or composition?
That's right, it's a queue. 0:00 Thanks for reminding me. 0:01 So let's think about those bins. 0:03 When you have existing code like we do, like the queue. 0:04 We for sure want to reuse it, right? 0:07 Well, in practice, 0:09 when you decide to reuse code you have a couple of options of how you use it. 0:10 Namely, you have to decide between inheritance and composition. 0:14 Now our bin is basically a queue. 0:18 It's got a couple of ways in which it works differently. 0:21 Well first off, there's a maximum number of items that we can put into the bin. 0:23 So we need to limit the total number of items that can go in there, so 0:27 that when we add to the queue, we need to check a limit. 0:30 And secondly Tex is pretty particular about the placement of the bin and 0:33 the grids. 0:37 And one thing is certain. 0:38 He doesn't want to mix items. 0:39 If the bin has pretzels when it's restocked, pretzels should be there. 0:41 So people know they love B1 and they habitually press B1. 0:45 Consistency, my boy. 0:48 He shouted on the plane and slapped on the shoulder and guffawed. 0:50 So both inheritance and composition will work to solve our problem. 0:53 Let's walk through both options here briefly and 0:58 understand the benefits of each. 1:00 So first let's explore our inheritance option. 1:01 Let's create a new class called bin. 1:04 So we'll have it extend and existing Queue implementation. 1:07 I popped over to the Queue interface documentation and 1:10 after bouncing around a bit, 1:12 I found an implementation that limits the total number of elements allowed, sweet. 1:14 Let's have it extend that implementation. 1:18 It's called ArrayBlockingQueue. 1:21 So we'll extend an ArrayBlockingQueue of a class called Item, 1:23 where Item is something, you know, like freedoms. 1:27 So remember what that does is that our bin will inherit 1:29 all of the methods from ArrayBlockingQueue. 1:33 That means methods like add and add all will show up in its API and that's great. 1:35 But all the methods are here. 1:40 Poll. 1:43 That's a little strange for use of our API, right? 1:44 We would want them to know how to release the item from the bin so 1:47 we could do something like this, we could just create a synonym. 1:49 But see how polluted our API is? 1:53 It has a contains method, but that's not really important. 1:55 Is it? 1:59 You know that all the items in here are basically the same. 1:59 We probably never want to call this. 2:02 Oh man, that reminds me, too. 2:05 We would need to make sure that the add method doesn't allow you to add any item. 2:06 We need to fix that by overriding add and adding proper blocking. 2:11 Something like this [SOUND]. 2:15 See how we're able to block if there's already something in the bin, 2:19 just like Tex wants. 2:23 And if there is, we throw an exception if there are any different types of items. 2:24 Otherwise, we call the parent add method defined in the superclass 2:29 ArrayBlockingQueue. 2:32 This is how you modify how inherited methods work. 2:34 It's called polymorphism, and it's pretty powerful. 2:36 Now we've talked about this before. 2:40 And remember it roughly translates to, to "many forms". 2:41 But the different forms here being the classes that extend the parent. 2:45 Each child class can use inherited methods and or 2:49 change them as needed by their modified class or form. 2:52 But if we think about this, we are going to have to do this overwriting for 2:56 every exposed public method that adds or changes items in the queue. 3:00 So we covered add, but we need to do addAll and put as well. 3:05 This is gonna get time consuming, right? 3:09 It feels like inheriting all those methods means that I'm responsible to make sure 3:11 that code I didn't write works the way that I want it to. 3:15 Now because it's exposed publicly anyone could use any of these methods, right? 3:19 And because we explicitly said that we want all the methods exposed through 3:24 inheritance, we have to make sure that they work the way that we want them to. 3:29 After looking at this in more detail, I'm not sure we want all this stuff exposed. 3:34 So let's take a look at the composition approach. 3:38 The basic concept is just to re-use code that you need and 3:41 encapsulate the fact that you're using it at all. 3:44 Here, let's take a look. 3:46 So first we create our class. 3:48 It doesn't extend anything, it's just a normal class. 3:49 it's going to have a private field that must implement the blocking 3:52 queue interface of items, we'll call it items. 3:55 Blocking queue is the interface that helps us keep track of the max number of items. 3:59 Now, remember we want to declare with the interface so 4:04 that we can choose whatever specific implementation we want later. 4:07 So now we'll add our constructor. 4:11 And here, 4:14 we want to choose the implementation for the [SOUND] blocking queue. 4:14 Array blocking queue. 4:18 In the constructor, 4:20 we'll require the creator to specify the maximum number of items. 4:21 Then we'll use that to instantiate the instance and 4:26 choose the implementation array blocking queue. 4:29 And pass in the max items allowed. 4:32 Note that I used the diamond operator, 4:35 no need to redefine that it's a blocking queue of items. 4:37 So, we know that we want to be able to check the bin as empty. 4:41 So let's do it. 4:45 See how we're only exposing the methods that we want, and 4:46 we can also name them any way we want. 4:49 So we can add specific terms too, right? 4:52 Like so each of these spaces in the bins are called slots. 4:54 [SOUND] So, why not get available slots? 4:57 But check out this restock method. 5:01 [SOUND] This replaces the add method that we had from the inherited stock. 5:03 See how that bins API is pretty much exactly what we mean, 5:07 while using basically the same tricks. 5:10 And remember, because we've encapsulated our queue by making it private, 5:13 we can swap that out whenever, as long as the public methods still do and 5:17 return what they're expected to. 5:20 So there you go. 5:23 Best practices are always going to tell you to favor composition over inheritance. 5:24 And I hope you can start to see why. 5:28 Inheritance is basically saying bin is a queue, and 5:31 composition is saying the bin has a queue. 5:35 In my experience, I'd suggest that you start by composing and 5:39 move to inheritance if you end up writing all of the methods. 5:43 So you might be wondering, this is all great Craig, but 5:47 what does this have to do with testing? 5:50 Well, remember that mantra of testing that I keep repeating? 5:51 Testing enforces best practices. 5:55 Composition is one of those best practices. 5:57 Let's take a quick break and 6:00 I'll show you why composition is a great testing solution and how it helps solve 6:01 another programming problem and helps bring forward another best practice. 6:05 The single responsibility principle. 6:09
You need to sign up for Treehouse in order to download course files.Sign up