1 00:00:00,480 --> 00:00:03,480 foreign 2 00:00:12,980 --> 00:00:16,379 giving a talk on the complexity of 3 00:00:15,120 --> 00:00:21,060 simplicity 4 00:00:16,379 --> 00:00:23,279 uh Chris used to run pycon IU and um 5 00:00:21,060 --> 00:00:24,600 has passed those rains over well as he 6 00:00:23,279 --> 00:00:26,820 has moved to the U.S he is the director 7 00:00:24,600 --> 00:00:28,320 of the Python software Foundation a 8 00:00:26,820 --> 00:00:31,880 contributor to pants which we're all 9 00:00:28,320 --> 00:00:31,880 wearing of course wait what 10 00:00:32,300 --> 00:00:36,899 and um yes probably the person one of 11 00:00:35,820 --> 00:00:38,219 the people at the conference needs the 12 00:00:36,899 --> 00:00:40,559 least amount of introduction because you 13 00:00:38,219 --> 00:00:43,379 all know him so well please help me give 14 00:00:40,559 --> 00:00:44,879 a warm welcome to Chris oh no an 15 00:00:43,379 --> 00:00:47,340 audience 16 00:00:44,879 --> 00:00:49,320 I was fearing this 17 00:00:47,340 --> 00:00:51,360 um hi everyone 18 00:00:49,320 --> 00:00:53,100 um this is another one of my talks about 19 00:00:51,360 --> 00:00:55,739 how pythonisters think about software 20 00:00:53,100 --> 00:00:57,780 engineering I've been giving talks in 21 00:00:55,739 --> 00:01:00,079 this vague direction for like five years 22 00:00:57,780 --> 00:01:00,079 now 23 00:01:01,260 --> 00:01:04,799 um and because I've been doing this for 24 00:01:03,000 --> 00:01:07,200 five years things are now starting to 25 00:01:04,799 --> 00:01:09,479 get scarily abstract which I apologize 26 00:01:07,200 --> 00:01:11,460 uh there is less code in this talk than 27 00:01:09,479 --> 00:01:13,500 my talk tomorrow will have 28 00:01:11,460 --> 00:01:15,180 um unfortunately uh for those of you 29 00:01:13,500 --> 00:01:17,460 seen other talks where I make old 30 00:01:15,180 --> 00:01:19,320 versions of python do weird things I'm 31 00:01:17,460 --> 00:01:20,580 not doing any of that today I I 32 00:01:19,320 --> 00:01:22,680 apologize 33 00:01:20,580 --> 00:01:24,180 um but you're here anyway um thank you 34 00:01:22,680 --> 00:01:26,280 so much for coming along 35 00:01:24,180 --> 00:01:30,180 Shall We Begin 36 00:01:26,280 --> 00:01:33,060 so here is a value of pythons simple is 37 00:01:30,180 --> 00:01:35,340 better than complex and what better way 38 00:01:33,060 --> 00:01:37,140 to demonstrate Python's Simplicity than 39 00:01:35,340 --> 00:01:38,460 with the first python code that most 40 00:01:37,140 --> 00:01:40,860 people write 41 00:01:38,460 --> 00:01:43,979 let's talk about print 42 00:01:40,860 --> 00:01:46,259 uh print it is the first function I see 43 00:01:43,979 --> 00:01:49,020 introduced in most introductory python 44 00:01:46,259 --> 00:01:52,020 textbooks understanding print is very 45 00:01:49,020 --> 00:01:54,479 very simple you call it unlike on this 46 00:01:52,020 --> 00:01:56,399 slide you normally give it an argument 47 00:01:54,479 --> 00:01:59,759 and then some text gets displayed to the 48 00:01:56,399 --> 00:02:02,820 screen uh wonderful but what does print 49 00:01:59,759 --> 00:02:06,259 do who here knows what print does 50 00:02:02,820 --> 00:02:08,340 print does a lot of error checking 51 00:02:06,259 --> 00:02:10,020 here's the actual implementation of 52 00:02:08,340 --> 00:02:12,780 print it's taken from the very source of 53 00:02:10,020 --> 00:02:15,120 C python the function is called built-in 54 00:02:12,780 --> 00:02:17,040 print impul which is complexity that you 55 00:02:15,120 --> 00:02:18,480 didn't need to know about that's the 56 00:02:17,040 --> 00:02:20,280 function that actually gets called it's 57 00:02:18,480 --> 00:02:23,459 quite long there is a lot of error 58 00:02:20,280 --> 00:02:24,959 checking here is the line somewhere in 59 00:02:23,459 --> 00:02:27,120 it that actually takes an argument 60 00:02:24,959 --> 00:02:28,400 writes it to what will usually be 61 00:02:27,120 --> 00:02:31,500 standard out 62 00:02:28,400 --> 00:02:33,780 and the bit that's really important is 63 00:02:31,500 --> 00:02:36,080 this bit here the bit that says Pi file 64 00:02:33,780 --> 00:02:38,760 underscore right object 65 00:02:36,080 --> 00:02:41,040 which itself has a whole world of 66 00:02:38,760 --> 00:02:44,220 implementation details to to worry about 67 00:02:41,040 --> 00:02:45,599 and you're looking at this and what's 68 00:02:44,220 --> 00:02:47,459 actually important about this is not 69 00:02:45,599 --> 00:02:50,599 none of none of what you're reading 70 00:02:47,459 --> 00:02:56,459 the important thing is that this is C 71 00:02:50,599 --> 00:02:58,800 and this is a python conference and so 72 00:02:56,459 --> 00:03:01,200 for you and me as python people 73 00:02:58,800 --> 00:03:02,879 understanding the C API is this going to 74 00:03:01,200 --> 00:03:04,560 add an undesirable amount of complexity 75 00:03:02,879 --> 00:03:05,280 to this talk 76 00:03:04,560 --> 00:03:06,599 um 77 00:03:05,280 --> 00:03:08,340 but I'd like to take a moment to point 78 00:03:06,599 --> 00:03:10,440 out here that this is already complexity 79 00:03:08,340 --> 00:03:12,540 that's inherent in doing something very 80 00:03:10,440 --> 00:03:14,159 very simple in Python rather than just 81 00:03:12,540 --> 00:03:17,519 executing some code that's written in 82 00:03:14,159 --> 00:03:20,340 Python we are executing C code python 83 00:03:17,519 --> 00:03:22,620 needs to allow you to run C functions 84 00:03:20,340 --> 00:03:24,239 and to keep that overall Simplicity it 85 00:03:22,620 --> 00:03:26,159 needs to prevent uh present these C 86 00:03:24,239 --> 00:03:27,900 functions to the rest of the language 87 00:03:26,159 --> 00:03:30,120 runtime in exactly the same way that 88 00:03:27,900 --> 00:03:31,980 presents your python functions and the 89 00:03:30,120 --> 00:03:33,659 CIA API that's needed to facilitate all 90 00:03:31,980 --> 00:03:35,760 that is complex you saw all that error 91 00:03:33,659 --> 00:03:37,500 handling but this is a python talk so 92 00:03:35,760 --> 00:03:40,379 let's talk about python 93 00:03:37,500 --> 00:03:42,980 print to a python developer has a 94 00:03:40,379 --> 00:03:45,180 complex interface with complex behaviors 95 00:03:42,980 --> 00:03:47,220 that really depend on how you specify 96 00:03:45,180 --> 00:03:48,599 these keyword arguments at the end and 97 00:03:47,220 --> 00:03:49,920 that's complexity that I don't want to 98 00:03:48,599 --> 00:03:52,440 touch so we're going to narrow the scope 99 00:03:49,920 --> 00:03:56,040 even more let's talk about printing just 100 00:03:52,440 --> 00:03:58,140 one thing just a single argument 101 00:03:56,040 --> 00:04:00,599 so what we're going to do is we're going 102 00:03:58,140 --> 00:04:01,680 to Define a variable and then we're 103 00:04:00,599 --> 00:04:04,140 going to print the value of that 104 00:04:01,680 --> 00:04:07,140 variable and if we set the value of our 105 00:04:04,140 --> 00:04:07,680 variable to a string like Hello World 106 00:04:07,140 --> 00:04:10,260 um 107 00:04:07,680 --> 00:04:12,180 this is very simple uh how would print 108 00:04:10,260 --> 00:04:13,980 work well we can we can iterate over 109 00:04:12,180 --> 00:04:16,380 each of the characters in The String we 110 00:04:13,980 --> 00:04:18,720 can write each character to a file stand 111 00:04:16,380 --> 00:04:20,100 it out in sequence 112 00:04:18,720 --> 00:04:21,540 um it doesn't actually work like this 113 00:04:20,100 --> 00:04:23,040 under the hood you saw that earlier 114 00:04:21,540 --> 00:04:25,199 there's some complexity that involves 115 00:04:23,040 --> 00:04:27,180 block i o which becomes more efficient 116 00:04:25,199 --> 00:04:29,759 if you transfer in larger blocks across 117 00:04:27,180 --> 00:04:30,900 the the API boundary but event there's 118 00:04:29,759 --> 00:04:31,919 eventually there's something that's just 119 00:04:30,900 --> 00:04:34,380 going to go through every single 120 00:04:31,919 --> 00:04:36,240 character and put them onto some sort of 121 00:04:34,380 --> 00:04:38,520 buffer somewhere so there's already a 122 00:04:36,240 --> 00:04:40,919 whole bunch of complex conceptual 123 00:04:38,520 --> 00:04:41,880 complexity here but it's it's not too 124 00:04:40,919 --> 00:04:44,759 bad 125 00:04:41,880 --> 00:04:46,680 as a python person what if we want to 126 00:04:44,759 --> 00:04:50,340 print an integer 127 00:04:46,680 --> 00:04:52,500 well this code is going to it's going to 128 00:04:50,340 --> 00:04:55,380 throw an index error because you can't 129 00:04:52,500 --> 00:04:57,300 iterate over an in object this code this 130 00:04:55,380 --> 00:04:58,680 code won't work 131 00:04:57,300 --> 00:05:00,360 um 132 00:04:58,680 --> 00:05:02,820 so what you need to do is you need you 133 00:05:00,360 --> 00:05:05,460 need to stringify the the parameter that 134 00:05:02,820 --> 00:05:07,620 we pass in to print 135 00:05:05,460 --> 00:05:09,380 and under the hood what stringification 136 00:05:07,620 --> 00:05:11,639 will look something like this you you 137 00:05:09,380 --> 00:05:13,139 dereference the type of the object and 138 00:05:11,639 --> 00:05:15,240 you call the dunder string method that's 139 00:05:13,139 --> 00:05:16,199 on that type pass in the parameter that 140 00:05:15,240 --> 00:05:17,940 was part 141 00:05:16,199 --> 00:05:19,320 and with that you know you can print 142 00:05:17,940 --> 00:05:22,560 anything you can print anything recently 143 00:05:19,320 --> 00:05:24,240 but in reality this this stringify code 144 00:05:22,560 --> 00:05:25,919 is probably provided us to the C library 145 00:05:24,240 --> 00:05:28,440 but if we're not going to use that and 146 00:05:25,919 --> 00:05:29,820 to deal with this complexity we're going 147 00:05:28,440 --> 00:05:31,199 to write our own string of fire which 148 00:05:29,820 --> 00:05:33,419 which needs a bunch of knowledge of 149 00:05:31,199 --> 00:05:35,160 ASCII and stuff and 150 00:05:33,419 --> 00:05:37,259 that's before you even get to that 151 00:05:35,160 --> 00:05:38,699 implementation of this put C function I 152 00:05:37,259 --> 00:05:39,840 didn't even talk about which is 153 00:05:38,699 --> 00:05:41,100 underpinned by a whole bunch of 154 00:05:39,840 --> 00:05:43,139 sophisticated software and Hardware 155 00:05:41,100 --> 00:05:45,120 Concepts that'll eventually give you the 156 00:05:43,139 --> 00:05:48,170 ability to see the text that will you 157 00:05:45,120 --> 00:05:51,629 asked to be displayed on your screen 158 00:05:48,170 --> 00:05:51,629 [Applause] 159 00:05:55,759 --> 00:06:01,199 nobody sets out to write complex code 160 00:05:59,639 --> 00:06:02,639 there's two things that you should have 161 00:06:01,199 --> 00:06:04,680 learned from that discussion of print 162 00:06:02,639 --> 00:06:06,300 here the first is that we should all 163 00:06:04,680 --> 00:06:08,400 want to interact with the simplest 164 00:06:06,300 --> 00:06:09,780 interface possible and the second is 165 00:06:08,400 --> 00:06:11,940 that even the simplest thing you can 166 00:06:09,780 --> 00:06:13,860 teach someone about programming hides a 167 00:06:11,940 --> 00:06:15,539 lot of complexity under the hood I I 168 00:06:13,860 --> 00:06:17,580 don't think that anyone would disagree 169 00:06:15,539 --> 00:06:19,620 that the best most maintainable code is 170 00:06:17,580 --> 00:06:21,240 the simplest code that you can write 171 00:06:19,620 --> 00:06:22,259 under the constraints that we have to 172 00:06:21,240 --> 00:06:24,780 operate in 173 00:06:22,259 --> 00:06:26,520 with software it exists because there is 174 00:06:24,780 --> 00:06:28,080 complexity inherent in the world and if 175 00:06:26,520 --> 00:06:30,240 we can model that complexity then then 176 00:06:28,080 --> 00:06:31,919 we help people navigate that complexity 177 00:06:30,240 --> 00:06:33,840 and by helping people navigate 178 00:06:31,919 --> 00:06:36,120 complexity if we do it right things 179 00:06:33,840 --> 00:06:38,580 become simpler for them now looking at 180 00:06:36,120 --> 00:06:40,860 print is is instructive it only appears 181 00:06:38,580 --> 00:06:43,080 uh simple whatever that is because we 182 00:06:40,860 --> 00:06:44,880 wrote building blocks and with each tool 183 00:06:43,080 --> 00:06:47,039 you're from the LCD elements in our 184 00:06:44,880 --> 00:06:49,560 projector here right up to the python 185 00:06:47,039 --> 00:06:52,319 interpreter itself more complexity gets 186 00:06:49,560 --> 00:06:54,000 modeled and simplified for us which is 187 00:06:52,319 --> 00:06:55,979 leading me to some indisputable facts 188 00:06:54,000 --> 00:06:58,680 here the first is that complexity exists 189 00:06:55,979 --> 00:07:00,600 that it will be experienced by somebody 190 00:06:58,680 --> 00:07:02,160 on a project of some description it 191 00:07:00,600 --> 00:07:04,199 could be an end user it could be you as 192 00:07:02,160 --> 00:07:06,419 the programmer and on a systems design 193 00:07:04,199 --> 00:07:07,740 level complexity is either modeled or 194 00:07:06,419 --> 00:07:10,139 ignored 195 00:07:07,740 --> 00:07:12,900 and more importantly that Simplicity 196 00:07:10,139 --> 00:07:15,660 usually belies some level of complexity 197 00:07:12,900 --> 00:07:17,639 on some level within a system 198 00:07:15,660 --> 00:07:19,440 put another way anyone who is 199 00:07:17,639 --> 00:07:21,360 experiencing Simplicity is doing so 200 00:07:19,440 --> 00:07:24,440 because complexity has been dealt with 201 00:07:21,360 --> 00:07:24,440 in some sort of way 202 00:07:24,780 --> 00:07:27,960 so with that in mind 203 00:07:26,460 --> 00:07:29,520 I used to think about how to build the 204 00:07:27,960 --> 00:07:32,039 simplest possible solution to a problem 205 00:07:29,520 --> 00:07:34,080 which which raises the question of what 206 00:07:32,039 --> 00:07:35,759 we might think is simple and I don't 207 00:07:34,080 --> 00:07:38,400 think this is a good question anymore I 208 00:07:35,759 --> 00:07:40,259 I don't think it scales well 209 00:07:38,400 --> 00:07:41,759 um instead if we accept that Simplicity 210 00:07:40,259 --> 00:07:43,919 will usually belie some sort of 211 00:07:41,759 --> 00:07:46,139 complexity within a system then the 212 00:07:43,919 --> 00:07:48,120 questions we should be asking is who 213 00:07:46,139 --> 00:07:49,199 should be experiencing Simplicity within 214 00:07:48,120 --> 00:07:51,360 a system 215 00:07:49,199 --> 00:07:52,440 which parts of our system should be 216 00:07:51,360 --> 00:07:54,240 simple 217 00:07:52,440 --> 00:07:55,919 and where should Simplicity be 218 00:07:54,240 --> 00:07:57,780 experienced 219 00:07:55,919 --> 00:07:59,220 and the main thing that I want to convey 220 00:07:57,780 --> 00:08:01,919 is that the answers to these questions 221 00:07:59,220 --> 00:08:04,620 are in flux python is an evolving 222 00:08:01,919 --> 00:08:06,419 ecosystem and as new problems arise and 223 00:08:04,620 --> 00:08:09,599 new tools make different problem domains 224 00:08:06,419 --> 00:08:13,520 easier to navigate our Focus changes and 225 00:08:09,599 --> 00:08:13,520 our Focus will continue to change 226 00:08:18,120 --> 00:08:23,340 um so the first idea that I want to 227 00:08:21,120 --> 00:08:25,860 explore is the idea of internalized 228 00:08:23,340 --> 00:08:27,720 versus externalized complexity which is 229 00:08:25,860 --> 00:08:30,900 one where python has really changed its 230 00:08:27,720 --> 00:08:32,880 tune over the last 10 13 15 years 231 00:08:30,900 --> 00:08:35,159 thereabouts there used to be this idea 232 00:08:32,880 --> 00:08:37,680 that python would come with everything 233 00:08:35,159 --> 00:08:39,180 that you needed to solve most problems 234 00:08:37,680 --> 00:08:40,919 you might ever encounter out of the box 235 00:08:39,180 --> 00:08:42,659 and this idea was prevalent back around 236 00:08:40,919 --> 00:08:44,159 the time the Zen of python was actually 237 00:08:42,659 --> 00:08:45,899 written 238 00:08:44,159 --> 00:08:47,580 is actually less relevant for these days 239 00:08:45,899 --> 00:08:49,560 for a number of reasons that's but not 240 00:08:47,580 --> 00:08:51,660 particularly important right now 241 00:08:49,560 --> 00:08:54,480 um who's seen this thing 242 00:08:51,660 --> 00:08:57,300 right firstly like you know ignore this 243 00:08:54,480 --> 00:08:58,920 a joke at the expense of pearl 244 00:08:57,300 --> 00:09:01,080 um this line was written as a joke 245 00:08:58,920 --> 00:09:04,019 there's still enough people uh in the 246 00:09:01,080 --> 00:09:06,360 python Community who take this seriously 247 00:09:04,019 --> 00:09:08,640 um and so python had this idea that if 248 00:09:06,360 --> 00:09:10,440 if it made the big decisions for us 249 00:09:08,640 --> 00:09:11,820 about how you'd solve your problems then 250 00:09:10,440 --> 00:09:13,260 everyone would have the same version of 251 00:09:11,820 --> 00:09:15,000 python and you could read another 252 00:09:13,260 --> 00:09:16,080 person's Python's code and that would be 253 00:09:15,000 --> 00:09:18,180 great and everybody could understand 254 00:09:16,080 --> 00:09:20,580 everyone's code so we're going to talk 255 00:09:18,180 --> 00:09:22,640 about a thing called URL lib2 256 00:09:20,580 --> 00:09:22,640 um 257 00:09:24,120 --> 00:09:28,140 so that that that two there that two 258 00:09:27,300 --> 00:09:30,779 there 259 00:09:28,140 --> 00:09:32,220 um that's entirely down to python not 260 00:09:30,779 --> 00:09:34,620 addressing the complexity of name 261 00:09:32,220 --> 00:09:36,600 spacing in the standard Library which 262 00:09:34,620 --> 00:09:38,640 they fixed in Python 3 they called it 263 00:09:36,600 --> 00:09:40,019 urlab dot request and and that 264 00:09:38,640 --> 00:09:41,640 introduced complexity and reading 265 00:09:40,019 --> 00:09:44,040 documentation which I'm not going to get 266 00:09:41,640 --> 00:09:46,320 into but that that's the thing as well 267 00:09:44,040 --> 00:09:47,820 um eurolib 2 was built around the idea 268 00:09:46,320 --> 00:09:50,220 that your code could be simpler if you 269 00:09:47,820 --> 00:09:51,839 could just drop URL handling code into 270 00:09:50,220 --> 00:09:54,540 python code that dealt with other 271 00:09:51,839 --> 00:09:56,279 interfaces and so it did all this in 272 00:09:54,540 --> 00:09:58,800 what would be a relatively familiar way 273 00:09:56,279 --> 00:10:00,779 to you uh your request objects they kind 274 00:09:58,800 --> 00:10:02,640 of Quack Like files there's an 275 00:10:00,779 --> 00:10:05,279 object-oriented interface for installing 276 00:10:02,640 --> 00:10:06,720 handlers for more complex use cases and 277 00:10:05,279 --> 00:10:08,399 you could install these handers for 278 00:10:06,720 --> 00:10:11,040 authentication and redirect handling 279 00:10:08,399 --> 00:10:11,880 either with or without affecting Global 280 00:10:11,040 --> 00:10:14,459 state 281 00:10:11,880 --> 00:10:15,720 and so in doing so it let you do a 282 00:10:14,459 --> 00:10:17,640 reasonable job of modeling the 283 00:10:15,720 --> 00:10:21,540 complexity of working with perfectly 284 00:10:17,640 --> 00:10:24,660 specified HTTP but how does that look in 285 00:10:21,540 --> 00:10:26,640 practice so URL Ed 2 has a thing called 286 00:10:24,660 --> 00:10:28,200 authentication helpers 287 00:10:26,640 --> 00:10:30,420 um what you do is you create a password 288 00:10:28,200 --> 00:10:33,300 manager to associate some credentials 289 00:10:30,420 --> 00:10:35,519 with specific URLs that's this this HTTP 290 00:10:33,300 --> 00:10:36,300 password blah blah blah blah blah blah 291 00:10:35,519 --> 00:10:37,200 thing 292 00:10:36,300 --> 00:10:39,120 um 293 00:10:37,200 --> 00:10:40,800 and you can create an authentication 294 00:10:39,120 --> 00:10:42,899 Handler that supplies these login 295 00:10:40,800 --> 00:10:45,120 credentials and then you create an 296 00:10:42,899 --> 00:10:47,040 opener that knows how to open URLs with 297 00:10:45,120 --> 00:10:48,839 these auth credentials and you use that 298 00:10:47,040 --> 00:10:50,940 opener to open the URL and then you 299 00:10:48,839 --> 00:10:53,100 treat the response like a file and you 300 00:10:50,940 --> 00:10:55,079 hand them into json.load which I presume 301 00:10:53,100 --> 00:10:57,860 you've you've imported somewhere in this 302 00:10:55,079 --> 00:10:57,860 in this code before 303 00:10:57,899 --> 00:11:03,480 this this code becomes visibly simpler 304 00:11:00,779 --> 00:11:05,459 if you choose for URL lib2 to not manage 305 00:11:03,480 --> 00:11:07,680 the complexity of authentication for you 306 00:11:05,459 --> 00:11:10,680 as long as you know how to write this 307 00:11:07,680 --> 00:11:13,260 this header you can make a request with 308 00:11:10,680 --> 00:11:14,820 that header and with this you're forced 309 00:11:13,260 --> 00:11:17,820 to make a trade-off 310 00:11:14,820 --> 00:11:20,700 you either get simple code and you model 311 00:11:17,820 --> 00:11:23,279 the complexity yourself or you have the 312 00:11:20,700 --> 00:11:25,320 complexity handled for you but you spend 313 00:11:23,279 --> 00:11:27,060 a lot of time rigging up this reusable 314 00:11:25,320 --> 00:11:29,459 authentication handling infrastructure 315 00:11:27,060 --> 00:11:32,880 and so the alternative is that we use a 316 00:11:29,459 --> 00:11:34,440 different Library like requests the 317 00:11:32,880 --> 00:11:36,540 behavior and authentication is a lot 318 00:11:34,440 --> 00:11:39,060 more declarative requests you say you 319 00:11:36,540 --> 00:11:40,860 want better off you make a request using 320 00:11:39,060 --> 00:11:42,300 those declarations and as a bonus you 321 00:11:40,860 --> 00:11:44,579 don't need to think about file handling 322 00:11:42,300 --> 00:11:46,440 because it Imports Json for you and this 323 00:11:44,579 --> 00:11:49,040 is obviously much simpler code to 324 00:11:46,440 --> 00:11:51,480 interact with an authenticated HTTP API 325 00:11:49,040 --> 00:11:52,800 you can make use of the libraries work 326 00:11:51,480 --> 00:11:55,019 to model the complexity of 327 00:11:52,800 --> 00:11:56,880 authentication and you get short code 328 00:11:55,019 --> 00:11:59,399 you don't need to make these trade-offs 329 00:11:56,880 --> 00:12:01,760 within your code but what's particularly 330 00:11:59,399 --> 00:12:04,320 interesting about this is that 331 00:12:01,760 --> 00:12:06,779 requests chose to re-implement something 332 00:12:04,320 --> 00:12:09,720 that existed in the standard library and 333 00:12:06,779 --> 00:12:11,820 then it choose it chose not to be in the 334 00:12:09,720 --> 00:12:13,800 standard Library itself 335 00:12:11,820 --> 00:12:16,800 this was a very odd choice at the time 336 00:12:13,800 --> 00:12:19,740 but in retrospect this is how things 337 00:12:16,800 --> 00:12:21,000 tend to get done in Python these days by 338 00:12:19,740 --> 00:12:23,220 being out of the standard Library 339 00:12:21,000 --> 00:12:25,560 request was able to adapt as a broader 340 00:12:23,220 --> 00:12:27,480 web communities changed their attitudes 341 00:12:25,560 --> 00:12:29,700 changed particularly around things like 342 00:12:27,480 --> 00:12:31,440 security and it shows to model some 343 00:12:29,700 --> 00:12:34,019 complexity of interacting with HTTP 344 00:12:31,440 --> 00:12:36,180 services for end users and as a result 345 00:12:34,019 --> 00:12:38,040 the code that you need to write to 346 00:12:36,180 --> 00:12:42,660 interact with requests is much much 347 00:12:38,040 --> 00:12:43,980 simpler than interacting with URL lib2 348 00:12:42,660 --> 00:12:46,260 um 349 00:12:43,980 --> 00:12:49,320 so the question that that arises from 350 00:12:46,260 --> 00:12:51,480 this is what do you get for that gaining 351 00:12:49,320 --> 00:12:53,760 Simplicity is this absolute 352 00:12:51,480 --> 00:12:55,380 and the answer is no this this gain is 353 00:12:53,760 --> 00:12:57,240 not absolute you now you need to model 354 00:12:55,380 --> 00:12:59,519 dependencies you need to have a 355 00:12:57,240 --> 00:13:01,100 requirements.txt you need to write 356 00:12:59,519 --> 00:13:03,300 instructions on on which 357 00:13:01,100 --> 00:13:05,100 requirements.txt file to load with Pip 358 00:13:03,300 --> 00:13:06,899 you need to manage execution 359 00:13:05,100 --> 00:13:08,940 environments you need to keep things up 360 00:13:06,899 --> 00:13:12,360 to date and so there's now added 361 00:13:08,940 --> 00:13:14,519 complexity in maintaining a project 362 00:13:12,360 --> 00:13:15,839 so which is the right choice here or if 363 00:13:14,519 --> 00:13:18,959 you're making the choice you use 364 00:13:15,839 --> 00:13:21,360 requests or urlab 2 in 2011 the choice 365 00:13:18,959 --> 00:13:22,620 might not have been immediately clear I 366 00:13:21,360 --> 00:13:24,300 think people were still thinking about 367 00:13:22,620 --> 00:13:26,399 whether using virtual amp was the right 368 00:13:24,300 --> 00:13:28,620 thing to do or not and this was still 369 00:13:26,399 --> 00:13:30,959 fairly early in the trend of HTTP apis 370 00:13:28,620 --> 00:13:33,899 where you know everything is an API now 371 00:13:30,959 --> 00:13:35,700 it wasn't the case back then so maybe if 372 00:13:33,899 --> 00:13:37,860 your application needed to hit a number 373 00:13:35,700 --> 00:13:39,540 of services that look like GitHub and 374 00:13:37,860 --> 00:13:41,459 regular you might do that 375 00:13:39,540 --> 00:13:42,899 I mean if you are fetching packages of a 376 00:13:41,459 --> 00:13:45,660 Debian mirror or something like that 377 00:13:42,899 --> 00:13:47,279 that doesn't require authentication you 378 00:13:45,660 --> 00:13:49,139 you are a lib2 might have been simpler 379 00:13:47,279 --> 00:13:50,579 for you and so you'd have you'd have a 380 00:13:49,139 --> 00:13:52,680 bit more first party code wherever you 381 00:13:50,579 --> 00:13:54,060 needed to hit a weird API but your 382 00:13:52,680 --> 00:13:55,740 overall code base would be smaller with 383 00:13:54,060 --> 00:13:57,959 urlib too and you wouldn't need to track 384 00:13:55,740 --> 00:13:59,820 external dependencies and the 385 00:13:57,959 --> 00:14:02,339 alternative would be to have less code 386 00:13:59,820 --> 00:14:04,800 but more complexity in terms of the 387 00:14:02,339 --> 00:14:07,200 environment that you need to manage 388 00:14:04,800 --> 00:14:08,940 I think in retrospect this idea of less 389 00:14:07,200 --> 00:14:11,040 first party code and letting your 390 00:14:08,940 --> 00:14:12,480 dependencies do more of the work is an 391 00:14:11,040 --> 00:14:14,279 approach that is one 392 00:14:12,480 --> 00:14:16,200 and this is not because absolutely 393 00:14:14,279 --> 00:14:18,300 everything was in place 10 years ago 394 00:14:16,200 --> 00:14:20,339 it's because we saw this as kind of a 395 00:14:18,300 --> 00:14:22,560 good way forward and we built tools to 396 00:14:20,339 --> 00:14:24,360 help us manage complexity that arose 397 00:14:22,560 --> 00:14:26,820 from deciding to manage external 398 00:14:24,360 --> 00:14:29,399 dependencies and configuration we have 399 00:14:26,820 --> 00:14:31,740 things like GitHub and and git more 400 00:14:29,399 --> 00:14:34,019 generally to manage our configuration 401 00:14:31,740 --> 00:14:36,240 management we have reasonable tooling 402 00:14:34,019 --> 00:14:39,240 for managing execution environments and 403 00:14:36,240 --> 00:14:40,800 we have a quite good package index 404 00:14:39,240 --> 00:14:42,300 and so now we're in a place where our 405 00:14:40,800 --> 00:14:44,760 definition of Simplicity has actually 406 00:14:42,300 --> 00:14:46,860 changed for an identical problem a 407 00:14:44,760 --> 00:14:48,720 modern python code base is going to be 408 00:14:46,860 --> 00:14:51,120 smaller than one that we wrote 10 to 15 409 00:14:48,720 --> 00:14:52,560 years ago to solve the same problem but 410 00:14:51,120 --> 00:14:55,019 the trade-off is that we have an 411 00:14:52,560 --> 00:14:57,360 increase in complexity of configuration 412 00:14:55,019 --> 00:15:00,240 management so we have more dependencies 413 00:14:57,360 --> 00:15:01,980 but we have more rigid environmental 414 00:15:00,240 --> 00:15:03,660 requirements 415 00:15:01,980 --> 00:15:06,000 but those dependencies they model 416 00:15:03,660 --> 00:15:07,980 complexity themselves now we have 417 00:15:06,000 --> 00:15:10,320 configuration tools they modal 418 00:15:07,980 --> 00:15:12,360 complexity and so for the modern python 419 00:15:10,320 --> 00:15:14,579 developer it seems that we get 420 00:15:12,360 --> 00:15:17,760 Simplicity as a virtue of other people 421 00:15:14,579 --> 00:15:19,019 managing complexity for us and just as a 422 00:15:17,760 --> 00:15:20,820 thought like if simple is better than 423 00:15:19,019 --> 00:15:22,680 complex well what does it say about how 424 00:15:20,820 --> 00:15:26,240 good the code that we're using to manage 425 00:15:22,680 --> 00:15:26,240 our environmental complexity is 426 00:15:27,199 --> 00:15:32,579 so the second idea I want to talk about 427 00:15:29,699 --> 00:15:34,680 is one that's less conclusively answered 428 00:15:32,579 --> 00:15:36,899 in Python which is the idea of how we go 429 00:15:34,680 --> 00:15:38,760 about managing complexity in a code base 430 00:15:36,899 --> 00:15:42,360 and whether the tools that we have 431 00:15:38,760 --> 00:15:44,820 actually present us uh present us with 432 00:15:42,360 --> 00:15:47,339 Simplicity and specifically I'm going to 433 00:15:44,820 --> 00:15:48,660 talk about quality assurance which is 434 00:15:47,339 --> 00:15:50,519 the set of tools that we use to make 435 00:15:48,660 --> 00:15:52,139 sure that our programs do what we say 436 00:15:50,519 --> 00:15:55,740 where we'll do what they're meant to do 437 00:15:52,139 --> 00:15:58,139 but first let's talk about duct typing 438 00:15:55,740 --> 00:15:59,639 so duct typing is an idea that two 439 00:15:58,139 --> 00:16:00,959 objects are interchangeable if you can 440 00:15:59,639 --> 00:16:03,360 use them in the same place and not get 441 00:16:00,959 --> 00:16:04,740 interface related errors if you're a 442 00:16:03,360 --> 00:16:06,899 type theorist you would call it 443 00:16:04,740 --> 00:16:07,920 structural polymorphism I'm not so I 444 00:16:06,899 --> 00:16:09,959 won't 445 00:16:07,920 --> 00:16:12,240 um Python's use of duct typing is a very 446 00:16:09,959 --> 00:16:14,579 very simple type system both to 447 00:16:12,240 --> 00:16:16,440 implement and to understand firstly 448 00:16:14,579 --> 00:16:17,940 there's no syntax in the language that 449 00:16:16,440 --> 00:16:19,620 describes the types that exist on an 450 00:16:17,940 --> 00:16:21,959 interface just have functions and 451 00:16:19,620 --> 00:16:23,880 variables this is simpler than Java or C 452 00:16:21,959 --> 00:16:26,399 plus plus which require you to enumerate 453 00:16:23,880 --> 00:16:27,839 the types that an interface expects and 454 00:16:26,399 --> 00:16:29,459 then on the other hand there's no 455 00:16:27,839 --> 00:16:32,459 automatic coercion so the language 456 00:16:29,459 --> 00:16:34,320 doesn't do complex Behavior to make data 457 00:16:32,459 --> 00:16:36,540 behave in different contexts this is 458 00:16:34,320 --> 00:16:39,000 simple as a JavaScript or Perl or PHP 459 00:16:36,540 --> 00:16:42,300 this forces some complexity in terms of 460 00:16:39,000 --> 00:16:45,540 managing types onto you as a developer 461 00:16:42,300 --> 00:16:47,399 um so when faced with some Library code 462 00:16:45,540 --> 00:16:48,660 you may ask yourself well how do you 463 00:16:47,399 --> 00:16:51,720 make sure that your library code is 464 00:16:48,660 --> 00:16:53,759 correct and that normally comes down to 465 00:16:51,720 --> 00:16:56,160 two questions which is what does your 466 00:16:53,759 --> 00:16:57,779 code do and where should your code be 467 00:16:56,160 --> 00:16:59,699 used 468 00:16:57,779 --> 00:17:01,620 so let's talk about this first one or 469 00:16:59,699 --> 00:17:03,480 how do we solve this what does your code 470 00:17:01,620 --> 00:17:05,699 do problem from in terms of quality 471 00:17:03,480 --> 00:17:08,339 assurance perspective 472 00:17:05,699 --> 00:17:10,199 um it's it's to do things you know test 473 00:17:08,339 --> 00:17:11,459 you know do your numeric inputs work do 474 00:17:10,199 --> 00:17:13,500 your strings work do your valid 475 00:17:11,459 --> 00:17:16,260 non-numeric inputs work 476 00:17:13,500 --> 00:17:18,120 things that you write with tests 477 00:17:16,260 --> 00:17:20,400 so automated tests help us manage 478 00:17:18,120 --> 00:17:22,079 complexity of verifying Behavior by 479 00:17:20,400 --> 00:17:23,339 allowing us to automatically run code 480 00:17:22,079 --> 00:17:26,520 that will check the code that we're 481 00:17:23,339 --> 00:17:27,839 verifying under the test works and to go 482 00:17:26,520 --> 00:17:29,520 back to this talking about computer 483 00:17:27,839 --> 00:17:30,840 science terminology stuff I was doing 484 00:17:29,520 --> 00:17:32,520 earlier 485 00:17:30,840 --> 00:17:34,799 um what we're doing is describing a set 486 00:17:32,520 --> 00:17:37,320 of things called invariance and 487 00:17:34,799 --> 00:17:39,419 invariant is basically a specification 488 00:17:37,320 --> 00:17:42,780 of some behavior that a system should 489 00:17:39,419 --> 00:17:44,640 hold given a set of circumstances if an 490 00:17:42,780 --> 00:17:46,740 invariant stops holding then either the 491 00:17:44,640 --> 00:17:48,600 behavior is wrong or the specification 492 00:17:46,740 --> 00:17:49,860 is wrong and the more invariants you 493 00:17:48,600 --> 00:17:52,320 describe the narrower the set of 494 00:17:49,860 --> 00:17:54,120 behaviors your system can display 495 00:17:52,320 --> 00:17:55,380 which means that the more invariants you 496 00:17:54,120 --> 00:17:58,020 have specified 497 00:17:55,380 --> 00:18:00,600 the more your complexity is managed 498 00:17:58,020 --> 00:18:03,179 and a unit test is a way to specify an 499 00:18:00,600 --> 00:18:04,740 invariant an invariant the circumstances 500 00:18:03,179 --> 00:18:06,960 of this data that you provide to the 501 00:18:04,740 --> 00:18:08,580 function under test and the invariant is 502 00:18:06,960 --> 00:18:10,380 a set of assertions that are specified 503 00:18:08,580 --> 00:18:12,360 about the result 504 00:18:10,380 --> 00:18:14,039 and this is really familiar to us it 505 00:18:12,360 --> 00:18:15,720 gives us a simple code-based structure 506 00:18:14,039 --> 00:18:16,919 to reason with which is that 507 00:18:15,720 --> 00:18:19,080 functionality lives in the 508 00:18:16,919 --> 00:18:22,559 implementation files you have and in 509 00:18:19,080 --> 00:18:24,240 variants are specified in test files 510 00:18:22,559 --> 00:18:25,860 but what if we think about our simple 511 00:18:24,240 --> 00:18:27,299 framework for quality insurance well 512 00:18:25,860 --> 00:18:29,280 we've only really looked at one of these 513 00:18:27,299 --> 00:18:32,220 two questions the question of what our 514 00:18:29,280 --> 00:18:33,780 code actually does if we're thinking 515 00:18:32,220 --> 00:18:35,940 about these and giving them fancy names 516 00:18:33,780 --> 00:18:37,860 we can classify these two questions into 517 00:18:35,940 --> 00:18:39,720 functional styling variants which are 518 00:18:37,860 --> 00:18:42,600 the things that specify how the thing 519 00:18:39,720 --> 00:18:44,580 works and structural ones which is how a 520 00:18:42,600 --> 00:18:47,340 piece of software fits into a system 521 00:18:44,580 --> 00:18:49,260 around it and the tool that we have for 522 00:18:47,340 --> 00:18:50,820 describing functional invariants I don't 523 00:18:49,260 --> 00:18:52,980 think are very good at describing 524 00:18:50,820 --> 00:18:54,960 structural invariance we can describe 525 00:18:52,980 --> 00:18:56,580 where things will work but we can't 526 00:18:54,960 --> 00:18:59,039 really exhaustively describe where 527 00:18:56,580 --> 00:19:00,360 things won't work and in Python for the 528 00:18:59,039 --> 00:19:03,559 longest time we kind of solve this 529 00:19:00,360 --> 00:19:03,559 problem with documentation 530 00:19:05,580 --> 00:19:09,900 on the other hand 531 00:19:07,200 --> 00:19:12,059 we have types now and types are great at 532 00:19:09,900 --> 00:19:14,280 specifying structural invariants and 533 00:19:12,059 --> 00:19:16,919 recent versions of python can describe 534 00:19:14,280 --> 00:19:18,600 types for most reasonable python code 535 00:19:16,919 --> 00:19:20,039 as well as providing structural and 536 00:19:18,600 --> 00:19:22,260 variance you also don't need to write as 537 00:19:20,039 --> 00:19:23,820 many tests so if you can't specify the 538 00:19:22,260 --> 00:19:25,080 wrong type you don't need to enumerate 539 00:19:23,820 --> 00:19:27,660 all the cases where you might have a 540 00:19:25,080 --> 00:19:29,220 type error you can't specify the wrong 541 00:19:27,660 --> 00:19:32,160 type so you don't need to test those 542 00:19:29,220 --> 00:19:34,200 things but I'm not here to evangelize 543 00:19:32,160 --> 00:19:35,760 types to you I think they're great but 544 00:19:34,200 --> 00:19:38,100 they still aren't universally popular 545 00:19:35,760 --> 00:19:41,160 and they're really really good reasons 546 00:19:38,100 --> 00:19:42,780 for that firstly types are a tool for 547 00:19:41,160 --> 00:19:46,020 managing complexity that really only 548 00:19:42,780 --> 00:19:47,760 occurs in large code bases and it's not 549 00:19:46,020 --> 00:19:49,559 always clear when you've crossed the 550 00:19:47,760 --> 00:19:52,020 line of structural complexity that 551 00:19:49,559 --> 00:19:54,419 arises where you can no longer fit 552 00:19:52,020 --> 00:19:56,220 things entirely within your head I I 553 00:19:54,419 --> 00:19:58,200 don't even think it's always clear the 554 00:19:56,220 --> 00:20:00,360 code base will ever achieve the level of 555 00:19:58,200 --> 00:20:02,220 structural complexity where you need to 556 00:20:00,360 --> 00:20:04,020 have typing in place 557 00:20:02,220 --> 00:20:05,940 and generally it can be hard to judge 558 00:20:04,020 --> 00:20:07,799 when types are necessary and once you do 559 00:20:05,940 --> 00:20:09,840 you kind of have to learn to use an 560 00:20:07,799 --> 00:20:11,520 entirely new system which itself can be 561 00:20:09,840 --> 00:20:13,440 a complex thing 562 00:20:11,520 --> 00:20:14,940 and so you end up with a trade-off you 563 00:20:13,440 --> 00:20:16,980 can either have a simpler toolbox for 564 00:20:14,940 --> 00:20:18,960 managing quality assurance or you can 565 00:20:16,980 --> 00:20:20,640 have a simpler way to specify the 566 00:20:18,960 --> 00:20:22,200 structure of your code base 567 00:20:20,640 --> 00:20:24,299 and so you can either have more tests 568 00:20:22,200 --> 00:20:25,980 and more documentation or you can make 569 00:20:24,299 --> 00:20:27,660 your interfaces harder to read and 570 00:20:25,980 --> 00:20:29,760 harder to understand 571 00:20:27,660 --> 00:20:31,380 and so there isn't actually a correct 572 00:20:29,760 --> 00:20:33,419 answer here yet I don't think I think 573 00:20:31,380 --> 00:20:35,400 both approaches provide some sort of 574 00:20:33,419 --> 00:20:37,620 Simplicity depending on what sort of 575 00:20:35,400 --> 00:20:39,539 problem you're trying to solve but they 576 00:20:37,620 --> 00:20:42,900 both leave complexity elsewhere in a 577 00:20:39,539 --> 00:20:44,460 project depending on how big it gets 578 00:20:42,900 --> 00:20:46,620 so I'd like to finish up with a 579 00:20:44,460 --> 00:20:48,660 discussion of evolution of python itself 580 00:20:46,620 --> 00:20:51,059 because a common complaint I hear is 581 00:20:48,660 --> 00:20:53,640 that that python is becoming more 582 00:20:51,059 --> 00:20:55,559 complex with every single version and I 583 00:20:53,640 --> 00:20:59,179 think it's worth taking some time to 584 00:20:55,559 --> 00:20:59,179 examine whether that is the case 585 00:21:02,460 --> 00:21:05,460 laughs 586 00:21:09,179 --> 00:21:14,820 so python was for a long time a 587 00:21:13,080 --> 00:21:18,059 completely static language for a lot of 588 00:21:14,820 --> 00:21:19,919 us Python 2.7 was around for a very long 589 00:21:18,059 --> 00:21:21,660 time and that's kind of the time when a 590 00:21:19,919 --> 00:21:23,160 lot of the growth of of python actually 591 00:21:21,660 --> 00:21:25,559 happened and was only really around 592 00:21:23,160 --> 00:21:27,900 python 3.5 that the language started to 593 00:21:25,559 --> 00:21:30,360 become stable for people who needed to 594 00:21:27,900 --> 00:21:32,580 do python who needed to use Python 3 for 595 00:21:30,360 --> 00:21:33,900 things other than data science and the 596 00:21:32,580 --> 00:21:35,760 language is kind of been adding on 597 00:21:33,900 --> 00:21:38,820 language features very regularly with 598 00:21:35,760 --> 00:21:40,740 every single major release of python 599 00:21:38,820 --> 00:21:42,659 um but if you're used to python not 600 00:21:40,740 --> 00:21:44,880 changing on you for seven whole years 601 00:21:42,659 --> 00:21:46,620 then maybe you'd be asking yourself well 602 00:21:44,880 --> 00:21:49,140 what happened to this idea of of simple 603 00:21:46,620 --> 00:21:54,020 being better than complex 604 00:21:49,140 --> 00:21:54,020 um to which I would respond with print 605 00:21:54,299 --> 00:21:57,780 because python has always been a 606 00:21:55,919 --> 00:21:59,940 language that kind of tries to model 607 00:21:57,780 --> 00:22:02,460 complexity so that users can write 608 00:21:59,940 --> 00:22:05,460 simpler code and one thing that happens 609 00:22:02,460 --> 00:22:07,919 as more people from more diverse use 610 00:22:05,460 --> 00:22:10,140 cases decide to use Python to solve 611 00:22:07,919 --> 00:22:12,840 their problems is that we discover more 612 00:22:10,140 --> 00:22:13,860 cases where python is just not simple to 613 00:22:12,840 --> 00:22:16,620 use yet 614 00:22:13,860 --> 00:22:18,299 so python just models more complexity 615 00:22:16,620 --> 00:22:21,059 for us 616 00:22:18,299 --> 00:22:23,460 most of us really when we first learned 617 00:22:21,059 --> 00:22:25,980 python only really picked up a subset of 618 00:22:23,460 --> 00:22:28,799 python as a language and likewise as new 619 00:22:25,980 --> 00:22:31,080 features emerge we'll only ever need a 620 00:22:28,799 --> 00:22:33,419 new a subset of these new features as 621 00:22:31,080 --> 00:22:35,520 somebody who who writes apis for things 622 00:22:33,419 --> 00:22:37,020 I don't need a matrix multiplication 623 00:22:35,520 --> 00:22:39,059 operator 624 00:22:37,020 --> 00:22:40,440 but then again a data analyst is 625 00:22:39,059 --> 00:22:42,480 probably never going to need to write an 626 00:22:40,440 --> 00:22:44,280 async await Co routine in their Jupiter 627 00:22:42,480 --> 00:22:47,220 notebook 628 00:22:44,280 --> 00:22:48,780 um I was at kiwi pycon last year and I 629 00:22:47,220 --> 00:22:50,640 gave a talk there and I tried to make a 630 00:22:48,780 --> 00:22:52,919 point that Python's success was its 631 00:22:50,640 --> 00:22:55,200 willingness to support use cases from a 632 00:22:52,919 --> 00:22:57,539 diverse set of disciplines another talk 633 00:22:55,200 --> 00:22:59,580 called the when of python argued that 634 00:22:57,539 --> 00:23:01,500 you can very easily use a subset of 635 00:22:59,580 --> 00:23:03,059 Python's features and never need to 636 00:23:01,500 --> 00:23:05,880 think about the more complex features 637 00:23:03,059 --> 00:23:08,340 until you actually need to use them and 638 00:23:05,880 --> 00:23:10,320 they even proposed a model for it it's 639 00:23:08,340 --> 00:23:11,760 called The when of python I don't 640 00:23:10,320 --> 00:23:13,260 entirely agree with it but I think it's 641 00:23:11,760 --> 00:23:15,500 a good start and you should look it up 642 00:23:13,260 --> 00:23:19,860 and either adopt it or criticize it 643 00:23:15,500 --> 00:23:21,919 basically go to last year's kiwi pycon 644 00:23:19,860 --> 00:23:23,880 uh there are videos 645 00:23:21,919 --> 00:23:25,860 that's the secret like this this 646 00:23:23,880 --> 00:23:28,140 complexity is reasonably self-contained 647 00:23:25,860 --> 00:23:30,900 and it's optional until you need it and 648 00:23:28,140 --> 00:23:33,539 this stands in contrast to needlessly 649 00:23:30,900 --> 00:23:37,980 complex languages like Java or even 650 00:23:33,539 --> 00:23:41,100 necessarily complex languages like rust 651 00:23:37,980 --> 00:23:42,840 all right we we as programmers want to 652 00:23:41,100 --> 00:23:44,640 continue to model more things and then 653 00:23:42,840 --> 00:23:46,260 the question we have to ask ourselves is 654 00:23:44,640 --> 00:23:48,780 well do we want to have a simple 655 00:23:46,260 --> 00:23:50,400 language or do we want to write simpler 656 00:23:48,780 --> 00:23:52,880 code with the language that we end up 657 00:23:50,400 --> 00:23:52,880 using 658 00:23:53,159 --> 00:23:57,179 um right so now I ended at the end of 659 00:23:55,020 --> 00:23:58,679 the examples section of this talk and 660 00:23:57,179 --> 00:24:00,299 we're going to enter into the realm of 661 00:23:58,679 --> 00:24:02,220 commentary again 662 00:24:00,299 --> 00:24:04,620 um so when we started 663 00:24:02,220 --> 00:24:06,419 we had this proposition that that simple 664 00:24:04,620 --> 00:24:08,100 is better than complex and we went 665 00:24:06,419 --> 00:24:09,720 through a bunch of examples that show 666 00:24:08,100 --> 00:24:11,580 that when you are writing python 667 00:24:09,720 --> 00:24:14,400 somebody is going to have to model 668 00:24:11,580 --> 00:24:15,780 complexity for us and in the world of 669 00:24:14,400 --> 00:24:17,700 python we're really lucky that the 670 00:24:15,780 --> 00:24:19,799 language we use chooses to Model A lot 671 00:24:17,700 --> 00:24:22,320 of complexity for us and it provides 672 00:24:19,799 --> 00:24:24,240 tools that can model new and unexpected 673 00:24:22,320 --> 00:24:25,799 forms of complexity 674 00:24:24,240 --> 00:24:28,140 but I haven't really spoken about code 675 00:24:25,799 --> 00:24:30,179 that that we write ourselves which 676 00:24:28,140 --> 00:24:31,380 brings me to this thing that I said at 677 00:24:30,179 --> 00:24:33,299 the top of the talk which is that 678 00:24:31,380 --> 00:24:35,100 complexity exists 679 00:24:33,299 --> 00:24:38,159 it would be better if complexity didn't 680 00:24:35,100 --> 00:24:40,799 exist but it does and 681 00:24:38,159 --> 00:24:42,960 as developers we can choose to contain 682 00:24:40,799 --> 00:24:45,900 that complexity or we can choose to do 683 00:24:42,960 --> 00:24:47,820 not contain that complexity 684 00:24:45,900 --> 00:24:49,860 so what I hope I've conveyed today is 685 00:24:47,820 --> 00:24:51,659 that we should be thinking about who 686 00:24:49,860 --> 00:24:54,179 should be experiencing Simplicity and 687 00:24:51,659 --> 00:24:55,679 who should experience complexity you 688 00:24:54,179 --> 00:24:57,780 know we work in narrow domains as 689 00:24:55,679 --> 00:24:59,640 developers and so even as if we're 690 00:24:57,780 --> 00:25:01,799 working in a team on the same project 691 00:24:59,640 --> 00:25:03,380 different people focus on different 692 00:25:01,799 --> 00:25:05,400 things 693 00:25:03,380 --> 00:25:07,020 with each of us having a pretty good 694 00:25:05,400 --> 00:25:08,340 understanding of of the stuff that we 695 00:25:07,020 --> 00:25:10,080 work on ourselves and so it's probably 696 00:25:08,340 --> 00:25:12,299 best if we mod our own domains 697 00:25:10,080 --> 00:25:13,620 complexity so it's not complicated for 698 00:25:12,299 --> 00:25:15,960 other people 699 00:25:13,620 --> 00:25:19,320 and this is why you have a giant pile of 700 00:25:15,960 --> 00:25:21,900 C code that does a whole bunch of stuff 701 00:25:19,320 --> 00:25:24,299 and then present a coherent interface 702 00:25:21,900 --> 00:25:25,799 that is safe to give to new programmers 703 00:25:24,299 --> 00:25:27,600 is literally the first thing we teach 704 00:25:25,799 --> 00:25:29,640 them 705 00:25:27,600 --> 00:25:32,400 like that's the point our code has end 706 00:25:29,640 --> 00:25:34,860 users whether they're consumers or 707 00:25:32,400 --> 00:25:37,559 whether their other software developers 708 00:25:34,860 --> 00:25:39,480 on your own team your code is almost 709 00:25:37,559 --> 00:25:41,760 always going to be part of some bigger 710 00:25:39,480 --> 00:25:44,039 system and it will exist because it's 711 00:25:41,760 --> 00:25:46,500 modeling some sort of complexity better 712 00:25:44,039 --> 00:25:48,720 than a human could your code has 713 00:25:46,500 --> 00:25:50,640 dependencies each of these dependencies 714 00:25:48,720 --> 00:25:52,500 from the python interpreter to the 715 00:25:50,640 --> 00:25:55,080 packages your dependencies depend upon 716 00:25:52,500 --> 00:25:57,720 model some sort of complexity so you 717 00:25:55,080 --> 00:25:59,100 don't have to otherwise it just wouldn't 718 00:25:57,720 --> 00:26:01,620 be useful for you and it wouldn't need 719 00:25:59,100 --> 00:26:04,320 to exist and like maybe your own code is 720 00:26:01,620 --> 00:26:06,659 somebody else's dependency chain 721 00:26:04,320 --> 00:26:08,880 we've seen earlier in this talk that the 722 00:26:06,659 --> 00:26:10,559 things that may be simplest they can 723 00:26:08,880 --> 00:26:12,720 change as we get newer tooling that 724 00:26:10,559 --> 00:26:14,220 solves problems more repeatedly or if 725 00:26:12,720 --> 00:26:15,240 people's opinions about what is good 726 00:26:14,220 --> 00:26:17,100 changes 727 00:26:15,240 --> 00:26:19,140 we've seen that what's simplest may 728 00:26:17,100 --> 00:26:21,539 depend on a trade-off between more 729 00:26:19,140 --> 00:26:24,659 upfront work and deferring decisions 730 00:26:21,539 --> 00:26:26,400 until later I for me a guiding principle 731 00:26:24,659 --> 00:26:29,520 is that Simplicity can be a gift that 732 00:26:26,400 --> 00:26:31,200 you give to others if if simple is 733 00:26:29,520 --> 00:26:33,779 really better than complex then leaving 734 00:26:31,200 --> 00:26:35,580 your end users with a simpler experience 735 00:26:33,779 --> 00:26:37,320 in managing your own complexity is 736 00:26:35,580 --> 00:26:39,059 probably better because that means that 737 00:26:37,320 --> 00:26:41,520 you're the only person dealing with this 738 00:26:39,059 --> 00:26:44,419 dealing with complexity that you have to 739 00:26:41,520 --> 00:26:46,860 deal with also I lied 740 00:26:44,419 --> 00:26:49,860 this is a slide that suggests that you 741 00:26:46,860 --> 00:26:52,080 should definitely use types if only at 742 00:26:49,860 --> 00:26:54,179 your interface typeset your interface 743 00:26:52,080 --> 00:26:56,220 give your users less complexity to need 744 00:26:54,179 --> 00:26:58,200 to worry about because you've told them 745 00:26:56,220 --> 00:27:00,000 what things will never work with your 746 00:26:58,200 --> 00:27:01,919 code 747 00:27:00,000 --> 00:27:03,960 choose to model complexly for your end 748 00:27:01,919 --> 00:27:05,779 users and annotate your interfaces with 749 00:27:03,960 --> 00:27:08,220 types if nothing else 750 00:27:05,779 --> 00:27:09,960 more generally like simplify things 751 00:27:08,220 --> 00:27:11,400 appropriately because I think this is 752 00:27:09,960 --> 00:27:13,500 what you should take away from this talk 753 00:27:11,400 --> 00:27:14,640 the idea that simple interfaces are a 754 00:27:13,500 --> 00:27:16,740 thing that we should strive for and 755 00:27:14,640 --> 00:27:19,880 complex ones are not but if you simplify 756 00:27:16,740 --> 00:27:19,880 things in the wrong place 757 00:27:21,440 --> 00:27:26,480 you tend to remove so much complexity 758 00:27:23,940 --> 00:27:30,860 for us to be useless and inactionable 759 00:27:26,480 --> 00:27:30,860 and you get talks like this one 760 00:27:32,100 --> 00:27:39,769 foreign 761 00:27:33,260 --> 00:27:39,769 [Applause] 762 00:27:39,960 --> 00:27:43,740 okay apparently we have time for 763 00:27:41,760 --> 00:27:46,919 questions so jacinta is going to hand a 764 00:27:43,740 --> 00:27:50,000 microphone somewhere and we'll see if 765 00:27:46,919 --> 00:27:50,000 anybody has a question 766 00:27:54,240 --> 00:27:57,980 you can ask the obvious one as well 767 00:27:58,980 --> 00:28:01,700 yes Tom 768 00:28:02,700 --> 00:28:05,900 what's the obvious question 769 00:28:06,480 --> 00:28:10,400 uh do you have your laptop out yeah you 770 00:28:08,400 --> 00:28:13,559 just type import this 771 00:28:10,400 --> 00:28:16,140 into a python interpreter okay yeah and 772 00:28:13,559 --> 00:28:17,039 just read what it says there to yourself 773 00:28:16,140 --> 00:28:20,240 um 774 00:28:17,039 --> 00:28:20,240 I'll just give you a moment 775 00:28:20,400 --> 00:28:24,720 have you have you found it 776 00:28:23,100 --> 00:28:27,260 okay well do you want to ask what the 777 00:28:24,720 --> 00:28:27,260 question is then 778 00:28:30,360 --> 00:28:35,640 well I guess now the question is um 779 00:28:33,840 --> 00:28:38,000 how do you know if it's simple if you're 780 00:28:35,640 --> 00:28:38,000 Dutch 781 00:28:38,940 --> 00:28:42,000 and that wasn't the question I'm sorry 782 00:28:40,500 --> 00:28:45,080 does anyone else know what the question 783 00:28:42,000 --> 00:28:45,080 I've prepared for is 784 00:28:45,120 --> 00:28:47,299 foreign 785 00:28:48,840 --> 00:28:55,940 what is the question you prepared for 786 00:28:52,080 --> 00:28:55,940 no no you don't get that sorry 787 00:29:02,179 --> 00:29:05,419 thanks everyone 788 00:29:06,059 --> 00:29:10,159 um is complex better than complicated 789 00:29:13,799 --> 00:29:17,940 I'm not answering that 790 00:29:15,130 --> 00:29:19,260 [Laughter] 791 00:29:17,940 --> 00:29:20,670 all right thanks everyone for coming 792 00:29:19,260 --> 00:29:27,150 along 793 00:29:20,670 --> 00:29:27,150 [Applause]