1 00:00:06,580 --> 00:00:08,970 - So let's really look at how composition 2 00:00:08,970 --> 00:00:11,170 works in Go with this example, 3 00:00:11,170 --> 00:00:13,200 and I want to give you some guidelines, 4 00:00:13,200 --> 00:00:15,890 around doing this and writing code in Go. 5 00:00:15,890 --> 00:00:17,780 It's probably a little bit against, 6 00:00:17,780 --> 00:00:18,700 what you're used to doing. 7 00:00:18,700 --> 00:00:20,060 A lot of you have been taught, 8 00:00:20,060 --> 00:00:21,290 to start with the interface, 9 00:00:21,290 --> 00:00:22,630 start with the behavior, 10 00:00:22,630 --> 00:00:25,060 try to figure out what those contracts are. 11 00:00:25,060 --> 00:00:26,290 I don't want you to do that. 12 00:00:26,290 --> 00:00:27,590 That is guessing. 13 00:00:27,590 --> 00:00:28,640 I don't want you to do that. 14 00:00:28,640 --> 00:00:31,160 Remember, the problem is solved in the concrete, 15 00:00:31,160 --> 00:00:33,050 not in the abstract. 16 00:00:33,050 --> 00:00:34,780 So we need a concrete influenced, 17 00:00:34,780 --> 00:00:36,650 implementation solution first, 18 00:00:36,650 --> 00:00:38,600 in order to know how to decouple. 19 00:00:38,600 --> 00:00:40,840 This is going to simplify your code, 20 00:00:40,840 --> 00:00:42,380 and allow you to focus on what's important, 21 00:00:42,380 --> 00:00:43,640 which is the problem, 22 00:00:43,640 --> 00:00:45,620 and remember, the problem is the data. 23 00:00:45,620 --> 00:00:47,450 Now, there's a couple of things here also, 24 00:00:47,450 --> 00:00:48,500 that I want to talk about, 25 00:00:48,500 --> 00:00:50,360 before we get into this example. 26 00:00:50,360 --> 00:00:52,460 Things that I see, that are missing, 27 00:00:52,460 --> 00:00:53,630 and one of these things, 28 00:00:53,630 --> 00:00:55,470 is the idea of done. 29 00:00:55,470 --> 00:00:57,990 How do you know when you're done with a piece of code? 30 00:00:57,990 --> 00:00:59,320 And if you manage people, 31 00:00:59,320 --> 00:01:01,940 how do you know that they are done? 32 00:01:01,940 --> 00:01:04,660 This is a really big, important question, 33 00:01:04,660 --> 00:01:08,020 and for me, done comes in two different answers. 34 00:01:08,020 --> 00:01:09,010 The first one is, 35 00:01:09,010 --> 00:01:09,990 you're really got to make sure, 36 00:01:09,990 --> 00:01:11,620 that you have your unit tests, 37 00:01:11,620 --> 00:01:14,190 and you got to have some level of test coverage. 38 00:01:14,190 --> 00:01:17,400 For me, I want to see anywhere from 70 to 80 percent, 39 00:01:17,400 --> 00:01:19,000 of code coverage on tests, 40 00:01:19,000 --> 00:01:20,060 before you can come to me, 41 00:01:20,060 --> 00:01:21,550 and say you're done. 42 00:01:21,550 --> 00:01:24,330 It's really hard to get above that sometimes in Go, 43 00:01:24,330 --> 00:01:26,620 because we focus on so much error handling, 44 00:01:26,620 --> 00:01:28,040 and a 100% code coverage, 45 00:01:28,040 --> 00:01:30,070 really doesn't add value to you, 46 00:01:30,070 --> 00:01:32,830 it just means that you execute every line of code once. 47 00:01:32,830 --> 00:01:35,930 I would like to a 100% code coverage on the happy path, 48 00:01:35,930 --> 00:01:37,870 but overall, 70 to 80 percent, 49 00:01:37,870 --> 00:01:38,820 and I'm good. 50 00:01:38,820 --> 00:01:40,120 The other part of this question, 51 00:01:40,120 --> 00:01:42,260 which really relates to me is, 52 00:01:42,260 --> 00:01:45,010 is the code decoupled from the change 53 00:01:45,010 --> 00:01:47,260 we expect to happen? 54 00:01:47,260 --> 00:01:49,440 Now, we might decide that we know 55 00:01:49,440 --> 00:01:50,940 what the decoupling is required, 56 00:01:50,940 --> 00:01:51,920 but we don't need it today, 57 00:01:51,920 --> 00:01:53,330 because we don't have 58 00:01:53,330 --> 00:01:54,910 multiple implementations with something. 59 00:01:54,910 --> 00:01:56,410 We don't have to need today. 60 00:01:56,410 --> 00:01:58,360 Remember, you're writing code for today, 61 00:01:58,360 --> 00:02:00,750 we're designing and architecting for tomorrow. 62 00:02:00,750 --> 00:02:02,810 So, deciding to decouple, 63 00:02:02,810 --> 00:02:04,850 may or may not happen immediately, 64 00:02:04,850 --> 00:02:06,050 but I want to ask the question, 65 00:02:06,050 --> 00:02:07,690 do we know what has to be decoupled, 66 00:02:07,690 --> 00:02:09,220 and do we want to do that? 67 00:02:09,220 --> 00:02:10,270 And I can do this, 68 00:02:10,270 --> 00:02:11,140 and I can ask this question, 69 00:02:11,140 --> 00:02:14,280 because decoupling is part two of everything I do. 70 00:02:14,280 --> 00:02:15,890 It is a refactoring. 71 00:02:15,890 --> 00:02:17,850 We solve problems in the concrete first, 72 00:02:17,850 --> 00:02:21,640 we refactor into the decoupling. 73 00:02:21,640 --> 00:02:22,770 There's a couple other things, 74 00:02:22,770 --> 00:02:25,680 that I see on that developers have problems with. 75 00:02:25,680 --> 00:02:28,690 They have a real problem breaking problems down. 76 00:02:28,690 --> 00:02:29,940 I'm not talking about tasks, 77 00:02:29,940 --> 00:02:31,920 or GitHub tasks or Jira tasks., 78 00:02:31,920 --> 00:02:33,370 I'm talking about looking at a problem, 79 00:02:33,370 --> 00:02:35,040 and saying, I've got to solve this, 80 00:02:35,040 --> 00:02:36,000 and I've got to solve that, 81 00:02:36,000 --> 00:02:37,040 and I've got to solve this, 82 00:02:37,040 --> 00:02:38,490 and it has to be in this order, 83 00:02:38,490 --> 00:02:39,390 and if I don't solve this, 84 00:02:39,390 --> 00:02:40,850 and the other problems don't matter, 85 00:02:40,850 --> 00:02:42,270 and these are little, these are large, 86 00:02:42,270 --> 00:02:44,820 and these can be multiple tasks to solve a problem. 87 00:02:44,820 --> 00:02:47,200 We're going to go through that exercise as well. 88 00:02:47,200 --> 00:02:50,160 One of the very last things that I see quite a bit, 89 00:02:50,160 --> 00:02:52,440 is software developers don't really understand, 90 00:02:52,440 --> 00:02:54,793 how to create a layered API. 91 00:02:55,760 --> 00:02:59,970 And this is really going to help you with a codebase, 92 00:02:59,970 --> 00:03:02,230 instead of you trying to solve every problem, 93 00:03:02,230 --> 00:03:03,820 in a few functions. 94 00:03:03,820 --> 00:03:05,280 What we really want to do, 95 00:03:05,280 --> 00:03:07,770 is find a layered approach, 96 00:03:07,770 --> 00:03:10,250 then initially just three layers, 97 00:03:10,250 --> 00:03:11,690 is all we're going to need. 98 00:03:11,690 --> 00:03:15,490 We can have what I call our Primitive layer, 99 00:03:15,490 --> 00:03:18,120 and this layer knows how to do one thing, 100 00:03:18,120 --> 00:03:20,080 and one thing very, very well. 101 00:03:20,080 --> 00:03:22,600 We're always focused on what is that one thing, 102 00:03:22,600 --> 00:03:24,250 and one thing very, very well. 103 00:03:24,250 --> 00:03:25,740 We write out the code for this layer, 104 00:03:25,740 --> 00:03:28,620 we write our unit tests for this layer right, 105 00:03:28,620 --> 00:03:30,290 and we write this layer, 106 00:03:30,290 --> 00:03:32,540 so it is testable. 107 00:03:32,540 --> 00:03:33,820 Now, when I say testable, 108 00:03:33,820 --> 00:03:35,220 this doesn't mean it interfaces, 109 00:03:35,220 --> 00:03:37,940 remember, I'm working in the concrete, 110 00:03:37,940 --> 00:03:40,880 interfaces, decoupling happens through a refactoring, 111 00:03:40,880 --> 00:03:43,910 and yet I have to already start writing unit tests. 112 00:03:43,910 --> 00:03:44,883 Unit tests, 113 00:03:45,870 --> 00:03:47,080 code that is testable, 114 00:03:47,080 --> 00:03:49,350 usually means that the data, 115 00:03:49,350 --> 00:03:51,820 that we're passing in is reproducible, 116 00:03:51,820 --> 00:03:53,450 and the data coming out, 117 00:03:53,450 --> 00:03:55,010 okay, is testable. 118 00:03:55,010 --> 00:03:56,780 So, I'm always going to be telling you, 119 00:03:56,780 --> 00:03:57,613 over and over again, 120 00:03:57,613 --> 00:03:59,420 testability is about the data, 121 00:03:59,420 --> 00:04:00,690 the code we're writing is about the data, 122 00:04:00,690 --> 00:04:02,370 decoupling is about the data. 123 00:04:02,370 --> 00:04:05,130 The problem you're trying to solve is about the data. 124 00:04:05,130 --> 00:04:07,600 So, when we're think about unit testing here, 125 00:04:07,600 --> 00:04:08,890 I want you to think about, 126 00:04:08,890 --> 00:04:11,320 can I write a function in the primitive layer, 127 00:04:11,320 --> 00:04:13,550 where I can give it a set of data, 128 00:04:13,550 --> 00:04:15,140 get a set of data back out, 129 00:04:15,140 --> 00:04:16,950 and we can validate it and test it. 130 00:04:16,950 --> 00:04:20,850 Now, your next layer, I would call the Lower Level, 131 00:04:20,850 --> 00:04:22,280 the Lower Level layer, 132 00:04:22,280 --> 00:04:25,730 and that's the layer that sits on top of the primitive API, 133 00:04:25,730 --> 00:04:27,690 that does maybe some raw things, 134 00:04:27,690 --> 00:04:30,030 a little higher level than the primitive layer, 135 00:04:30,030 --> 00:04:32,870 and again we're going to write those unit tests, 136 00:04:32,870 --> 00:04:34,320 and this layer to, 137 00:04:34,320 --> 00:04:37,110 should be testable in its own right. 138 00:04:37,110 --> 00:04:38,650 We should be able to test everything coming in, 139 00:04:38,650 --> 00:04:40,220 and everything going out, 140 00:04:40,220 --> 00:04:41,370 and a lot of time, 141 00:04:41,370 --> 00:04:42,560 this layer and these layers, 142 00:04:42,560 --> 00:04:45,170 are probably unexported, they could be, 143 00:04:45,170 --> 00:04:49,200 but sometimes it's nice to export the Lower Level, 144 00:04:49,200 --> 00:04:50,540 the Lower Layer API, 145 00:04:50,540 --> 00:04:52,870 because it's very usable if you write it correctly, 146 00:04:52,870 --> 00:04:55,450 and it gives the developer, the users, 147 00:04:55,450 --> 00:04:57,700 maybe more control over the things they need. 148 00:04:59,109 --> 00:05:00,230 And then you're going to have your, 149 00:05:00,230 --> 00:05:02,600 High Level API. 150 00:05:02,600 --> 00:05:03,790 This is where you're trying to do 151 00:05:03,790 --> 00:05:06,340 as much as you can for the user, 152 00:05:06,340 --> 00:05:07,930 to make their life better. 153 00:05:07,930 --> 00:05:10,310 You get it sitting on top of the Lower Level, 154 00:05:10,310 --> 00:05:12,340 which is sitting on top of the Primitive Level. 155 00:05:12,340 --> 00:05:14,320 Since every one of these levels have been coded, 156 00:05:14,320 --> 00:05:15,153 and unit tested, 157 00:05:15,153 --> 00:05:16,450 by the time you get up here, 158 00:05:16,450 --> 00:05:18,100 we're really just thinking about, 159 00:05:18,100 --> 00:05:20,540 an ease of use for the developer, 160 00:05:20,540 --> 00:05:22,020 and we're going to be able to hopefully 161 00:05:22,020 --> 00:05:23,890 unit test this as well. 162 00:05:23,890 --> 00:05:25,880 Sometimes these higher level functions, 163 00:05:25,880 --> 00:05:29,580 require more kinda integration kinds of tests, 164 00:05:29,580 --> 00:05:30,700 but we want to think about, 165 00:05:30,700 --> 00:05:33,000 how we test every layer all the way up. 166 00:05:33,000 --> 00:05:35,490 Eventually, your higher level tests 167 00:05:35,490 --> 00:05:38,200 might be able to replace some of your lower level, 168 00:05:38,200 --> 00:05:39,400 and primitive unit tests, 169 00:05:39,400 --> 00:05:41,950 because they cover those test cases for you, 170 00:05:41,950 --> 00:05:43,170 and so there are times, 171 00:05:43,170 --> 00:05:44,860 where I'm even writing unit tests, 172 00:05:44,860 --> 00:05:47,670 that I know aren't going to exist forever, 173 00:05:47,670 --> 00:05:51,010 because as I move up these levels of API, 174 00:05:51,010 --> 00:05:52,860 I'm getting the same code coverage 175 00:05:52,860 --> 00:05:54,610 on the tests that I've written here, 176 00:05:54,610 --> 00:05:55,500 and that's okay, 177 00:05:55,500 --> 00:05:57,070 I cannot stress enough, 178 00:05:57,070 --> 00:06:01,120 that I don't want you to be throwing code away, 179 00:06:01,120 --> 00:06:02,890 don't, I mean no, I'm sorry, 180 00:06:02,890 --> 00:06:04,040 I don't want you to be worried, 181 00:06:04,040 --> 00:06:05,760 about throwing code away right, 182 00:06:05,760 --> 00:06:08,870 refactoring is about making something work, 183 00:06:08,870 --> 00:06:10,530 and looking at how we make it better, 184 00:06:10,530 --> 00:06:11,930 how we make it more readable, 185 00:06:11,930 --> 00:06:12,890 how do we do things, 186 00:06:12,890 --> 00:06:16,210 and the best days are when we actually remove code, 187 00:06:16,210 --> 00:06:18,010 so don't get hung up that I might be writing 188 00:06:18,010 --> 00:06:19,420 some unit tests here, 189 00:06:19,420 --> 00:06:21,430 that eventually we're going to delete, 190 00:06:21,430 --> 00:06:22,807 because we're going to get some better coverage here, 191 00:06:22,807 --> 00:06:24,290 and writing those tests right away, 192 00:06:24,290 --> 00:06:26,810 because I want to make sure these layers are working. 193 00:06:26,810 --> 00:06:28,700 So this stuff is very, very important, 194 00:06:28,700 --> 00:06:31,650 and we want to have these things in our head, 195 00:06:31,650 --> 00:06:33,430 as we move forward okay, 196 00:06:33,430 --> 00:06:35,800 and as we start really starting to write more code, 197 00:06:35,800 --> 00:06:37,040 you're going to see me focus on, 198 00:06:37,040 --> 00:06:39,230 what are the real problems in front of us? 199 00:06:39,230 --> 00:06:41,080 How do we layer this API? 200 00:06:41,080 --> 00:06:42,940 Not only so it's usable, 201 00:06:42,940 --> 00:06:45,850 but it's testable and it doesn't mean we need interfaces, 202 00:06:45,850 --> 00:06:47,750 it means that we need strong 203 00:06:47,750 --> 00:06:50,060 inputs and outputs around the data, 204 00:06:50,060 --> 00:06:51,880 that we can test against, 205 00:06:51,880 --> 00:06:54,420 and then how do we refactor code, 206 00:06:54,420 --> 00:06:55,470 to then deal with change, 207 00:06:55,470 --> 00:06:58,093 once we have a concrete solution.