1 00:00:06,480 --> 00:00:07,960 - So I want to reiterate that 2 00:00:07,960 --> 00:00:10,140 I don't want to be using interfaces 3 00:00:10,140 --> 00:00:12,400 anytime we have to think about mocking. 4 00:00:12,400 --> 00:00:14,210 But I really want to show you some mechanics 5 00:00:14,210 --> 00:00:17,670 in Go about that convention over-configuration too, 6 00:00:17,670 --> 00:00:20,850 because it's really helped us have to write less code, 7 00:00:20,850 --> 00:00:23,789 and has taken the burden of testing, 8 00:00:23,789 --> 00:00:26,530 at least worrying about users' tests 9 00:00:26,530 --> 00:00:28,640 from that API developer. 10 00:00:28,640 --> 00:00:31,010 So let's start with this piece of code here. 11 00:00:31,010 --> 00:00:33,880 So imagine one day that, or I have a client. 12 00:00:33,880 --> 00:00:37,280 My client loves the PubSub type of strategy, right? 13 00:00:37,280 --> 00:00:39,070 We have a message bus in the middle, 14 00:00:39,070 --> 00:00:40,890 and what we do is all of our services 15 00:00:40,890 --> 00:00:42,490 connect to the message bus, 16 00:00:42,490 --> 00:00:43,920 and services talk to each other, 17 00:00:43,920 --> 00:00:46,120 we get service discovery through the message bus. 18 00:00:46,120 --> 00:00:48,620 It's a really nice starting pattern 19 00:00:48,620 --> 00:00:50,450 if you're trying to do micro-services. 20 00:00:50,450 --> 00:00:53,090 And what I've done here is my client has come to me 21 00:00:53,090 --> 00:00:53,930 and they said Bill, 22 00:00:53,930 --> 00:00:55,440 we have our own internal message bus, 23 00:00:55,440 --> 00:00:56,273 we've had it for years. 24 00:00:56,273 --> 00:00:57,430 We use it, we love it. 25 00:00:57,430 --> 00:00:59,060 We want to start writing code in Go, 26 00:00:59,060 --> 00:01:01,010 but we don't have a package 27 00:01:01,010 --> 00:01:03,000 or an API that lets Go developers 28 00:01:03,000 --> 00:01:05,180 connect to PubSub, all that good stuff, 29 00:01:05,180 --> 00:01:06,200 to the message bus. 30 00:01:06,200 --> 00:01:07,340 Will you write the package? 31 00:01:07,340 --> 00:01:08,240 I said absolutely. 32 00:01:08,240 --> 00:01:09,730 I'll implement the binary protocols, 33 00:01:09,730 --> 00:01:11,060 I'll do everything you need. 34 00:01:11,060 --> 00:01:13,490 But my question to the client is, 35 00:01:13,490 --> 00:01:15,660 how many message systems do I have to worry about? 36 00:01:15,660 --> 00:01:18,350 They said no Bill, just one, just this one. 37 00:01:18,350 --> 00:01:20,180 This is the only one that matters. 38 00:01:20,180 --> 00:01:21,740 So there's not a second one? 39 00:01:21,740 --> 00:01:23,350 No, no, no, Bill, just this. 40 00:01:23,350 --> 00:01:24,680 Look, I don't need interfaces. 41 00:01:24,680 --> 00:01:25,880 There's nothing to decouple. 42 00:01:25,880 --> 00:01:27,810 There's not multiple implementations, 43 00:01:27,810 --> 00:01:29,610 and I don't need anything for my user. 44 00:01:29,610 --> 00:01:32,940 So I design an API entirely in the concrete, 45 00:01:32,940 --> 00:01:35,220 and I come up with this type PubSub, 46 00:01:35,220 --> 00:01:38,240 it's got other fields like host connectivity information. 47 00:01:38,240 --> 00:01:40,370 I've got my factory function returns, 48 00:01:40,370 --> 00:01:42,180 a pointer of the concrete type, 49 00:01:42,180 --> 00:01:44,570 and then we implement our API. 50 00:01:44,570 --> 00:01:47,980 Now we can pretend this is a 10 method set API. 51 00:01:47,980 --> 00:01:49,870 It's a method based API, 52 00:01:49,870 --> 00:01:52,360 because PubSub has state connectivity issues, 53 00:01:52,360 --> 00:01:53,410 things like that. 54 00:01:53,410 --> 00:01:55,760 So we've got here publish and subscribe. 55 00:01:55,760 --> 00:01:58,370 We pretend that we've implemented that, brilliant. 56 00:01:58,370 --> 00:02:00,170 Now, I implement this, 57 00:02:00,170 --> 00:02:01,910 and now it's time to write tests. 58 00:02:01,910 --> 00:02:04,330 I'm not gonna add an interface to write tests, 59 00:02:04,330 --> 00:02:08,150 because I need to make sure that my binary protocol works. 60 00:02:08,150 --> 00:02:10,600 So what I'm gonna do is use Docker 61 00:02:10,600 --> 00:02:12,760 and I'm gonna put that message bus system 62 00:02:12,760 --> 00:02:14,100 that this client uses, 63 00:02:14,100 --> 00:02:15,970 I'm gonna put it into a Docker container, 64 00:02:15,970 --> 00:02:17,590 and every time I call Go Test, 65 00:02:17,590 --> 00:02:19,400 I'm gonna bring up the message bus, 66 00:02:19,400 --> 00:02:21,320 and I'm gonna make sure my entire API 67 00:02:21,320 --> 00:02:22,930 and all the binary protocols 68 00:02:22,930 --> 00:02:24,810 work as expected. 69 00:02:24,810 --> 00:02:25,850 Nothing's mocked. 70 00:02:25,850 --> 00:02:28,500 When this code is now ready for a user, 71 00:02:28,500 --> 00:02:32,020 I know everything absolutely works. 72 00:02:32,020 --> 00:02:33,360 So I finish the code, 73 00:02:33,360 --> 00:02:35,540 and I go over to somebody on the other team 74 00:02:35,540 --> 00:02:38,957 and I say, here is the PubSub package, start using it. 75 00:02:38,957 --> 00:02:41,110 And a couple days later they come over to me, 76 00:02:41,110 --> 00:02:43,070 maybe Jack, Jack comes over to me, 77 00:02:43,070 --> 00:02:45,770 and he says, Bill, Bill, come here, I got a problem. 78 00:02:45,770 --> 00:02:48,240 And I say, dude, you found a bug with the PubSub? 79 00:02:48,240 --> 00:02:50,670 He says, oh no man, I haven't even gotten that far yet, 80 00:02:50,670 --> 00:02:53,821 you know, I started realizing that I need to write tests 81 00:02:53,821 --> 00:02:55,510 against the PubSub, 82 00:02:55,510 --> 00:02:57,880 and I'm not gonna have a PubSub system to hit 83 00:02:57,880 --> 00:02:58,720 when I write tests. 84 00:02:58,720 --> 00:03:00,870 I need to mock the PubSub system. 85 00:03:00,870 --> 00:03:02,300 And I think about it, and I go, 86 00:03:02,300 --> 00:03:03,133 you know what, you're right. 87 00:03:03,133 --> 00:03:04,450 For your application, 88 00:03:04,450 --> 00:03:07,290 and for your application's tests, you need to mock. 89 00:03:07,290 --> 00:03:08,250 You should assume 90 00:03:09,160 --> 00:03:10,810 that the PubSub API works. 91 00:03:10,810 --> 00:03:11,840 So you should be able to mock 92 00:03:11,840 --> 00:03:14,020 if I subscribe to this, and publish that, 93 00:03:14,020 --> 00:03:15,230 I get everything back. 94 00:03:15,230 --> 00:03:18,450 I go you're right, you need to mock your tests. 95 00:03:18,450 --> 00:03:20,780 He goes great Bill, I appreciate that you understand 96 00:03:20,780 --> 00:03:21,730 what I need to do. 97 00:03:21,730 --> 00:03:23,950 You didn't give me an interface, so I can't mock it. 98 00:03:23,950 --> 00:03:26,230 Can you go back and add an interface to your package? 99 00:03:26,230 --> 00:03:28,460 And I say, dude, no no no no no no, 100 00:03:28,460 --> 00:03:30,640 I'm not adding an interface to my package, 101 00:03:30,640 --> 00:03:33,400 because I don't need the interface. 102 00:03:33,400 --> 00:03:35,880 I don't have a need to mock. 103 00:03:35,880 --> 00:03:38,160 My tests hit against the real system, 104 00:03:38,160 --> 00:03:39,300 thanks to Docker. 105 00:03:39,300 --> 00:03:41,990 My API is one and only one. 106 00:03:41,990 --> 00:03:43,820 I go, you need to mock, not me, 107 00:03:43,820 --> 00:03:45,860 so I'm not gonna provide you an interface. 108 00:03:45,860 --> 00:03:47,710 And he says, Bill, why are you being a jerk? 109 00:03:47,710 --> 00:03:50,190 You know I need the interface, just give it to me. 110 00:03:50,190 --> 00:03:52,010 And I say to him very quickly, 111 00:03:52,010 --> 00:03:53,010 I'm not being a jerk, 112 00:03:53,010 --> 00:03:55,550 what you're not understanding is this is Go. 113 00:03:55,550 --> 00:03:58,340 And Go says that I only have to worry about my tests, 114 00:03:58,340 --> 00:04:00,370 and I don't have to worry about your tests. 115 00:04:00,370 --> 00:04:05,370 Your code, your tests need this interface, not mine. 116 00:04:05,380 --> 00:04:07,990 So sit down, Jack, and I want to show you something. 117 00:04:07,990 --> 00:04:10,950 And I what I tell Jack really clearly is to do this. 118 00:04:10,950 --> 00:04:12,639 Jack, there is nothing, 119 00:04:12,639 --> 00:04:14,765 nothing stopping you 120 00:04:14,765 --> 00:04:19,030 from going ahead and defining your own interface. 121 00:04:19,030 --> 00:04:22,050 Remember Go's about convention over configuration. 122 00:04:22,050 --> 00:04:25,370 Isn't it true that if Jack implements this interface 123 00:04:25,370 --> 00:04:27,450 for the methods that he's using, 124 00:04:27,450 --> 00:04:29,480 because he might not be using all of them, 125 00:04:29,480 --> 00:04:32,749 then doesn't any concrete type that I've defined 126 00:04:32,749 --> 00:04:35,927 also satisfy this interface? 127 00:04:35,927 --> 00:04:39,295 Yes, think about how convention over configuration 128 00:04:39,295 --> 00:04:42,850 is helping us to reduce code and cognitive load. 129 00:04:42,850 --> 00:04:45,920 Jack can go ahead and define the interface he needs, 130 00:04:45,920 --> 00:04:48,940 write the entire application using his interface. 131 00:04:48,940 --> 00:04:50,620 I don't have to provide it. 132 00:04:50,620 --> 00:04:52,980 And yet any concrete piece of data, 133 00:04:52,980 --> 00:04:55,610 any value or pointer that comes out of my package 134 00:04:55,610 --> 00:04:58,350 can satisfy this interface for Jack. 135 00:04:58,350 --> 00:04:59,930 So Jack now in his tests 136 00:04:59,930 --> 00:05:02,590 defines a concrete piece of data called mock. 137 00:05:02,590 --> 00:05:05,100 He implements the API that he needs, 138 00:05:05,100 --> 00:05:06,900 and now he's able to mock, 139 00:05:06,900 --> 00:05:09,100 and then when his application comes up, 140 00:05:09,100 --> 00:05:11,170 he either calls pubsub.New, 141 00:05:11,170 --> 00:05:13,450 he gets the concrete data from my package, 142 00:05:13,450 --> 00:05:15,140 or when his tests start to run, 143 00:05:15,140 --> 00:05:17,750 he just creates his own concrete data. 144 00:05:17,750 --> 00:05:20,340 But his entire application is built, 145 00:05:20,340 --> 00:05:22,200 not on the concrete, 146 00:05:22,200 --> 00:05:24,950 but on this value-less interface. 147 00:05:24,950 --> 00:05:27,420 And Jack doesn't need me. 148 00:05:27,420 --> 00:05:29,430 My code is clean, streamlined, 149 00:05:29,430 --> 00:05:31,500 and Jack's code that needs the decoupling, 150 00:05:31,500 --> 00:05:33,090 defines the interfaces. 151 00:05:33,090 --> 00:05:35,660 This is what's beautiful about Go 152 00:05:35,660 --> 00:05:38,100 and this idea of convention over configuration, 153 00:05:38,100 --> 00:05:41,620 that we've now shifted this idea of responsibility, 154 00:05:41,620 --> 00:05:43,370 that if you need to worry about tests, 155 00:05:43,370 --> 00:05:45,270 you worry about your own tests. 156 00:05:45,270 --> 00:05:47,277 I don't have to do anything special in my code, 157 00:05:47,277 --> 00:05:49,480 because you have to test. 158 00:05:49,480 --> 00:05:52,503 This is brilliant, brilliant stuff coming out of Go.