 Your name is Justin, feel free to call me either. This is what my face looked like in 2011, and thanks to how social media branding works, I'm now stuck with it forever. I work for a company called TestDouble. We're a software agency who's on a mission to improve how the world writes software. You can learn more about us up at that URL. The title of this presentation is How to Program. And it's a rumination on a word workflow, two-part word, work being what programs are, their structure and behavior, flow being how we program our thoughts and actions. And when I look back on my experience learning as a computer science student, they taught me things like data structures and P versus NP and big O analysis and cryptography and not very much about how to think or how to work. And boot schools nowadays are actually analogous even though they're more market practical skills like web standards and system tooling and languages and frameworks, not so much how to think through problems and solve stuff and really write code. And you might think that's the job of thought leaders because the word thought is right there, but really thought leaders, when they're talking about design patterns or solid principles, even when they talk about agile and test driven development, those are nice because they describe work activities, but it's pretty discreet and mostly about how people interact, not so much how to think through things. So it's reasonable to ask, when do we actually learn flow as programmers? Who teaches us how to think? And if you're lucky, 10 years into your career, you'll stumble upon or somebody will show you the only productivity tip that any of us have ever been taught. The convoir technique. Where you work for 20 minutes and take a three minute break, it's really awesome. But honestly, it kind of feels like you put 10 years of hard service in to get a $4 plastic pin. It's kind of insulting that that's the best that we have to offer. So sure, somehow we all learned what programs are, but I hazard a guess that most of us, nobody ever really taught us how to program. Look no further than a Google search, how to program. And you get a whole bunch of terrible results starting with the traditional way of teaching people how to program. You start with nothing and then somebody shows you a completely finished example, finished product, what the program should be. And then as for connecting it, it's good luck, have fun. And every single computer science assignment that I had in college really resembled the how to draw an owl comic. Where you start with two circles and then go draw the rest of the owl. And I spent entire weekends cooped up in a lab trying to figure out, look staring at a blank editor, no idea how to write code. And it was that moment that I realized that programming is almost a philosophical activity that happens mostly in our heads. Of course, we've now innovated quite a lot in programmer education since I was in college. Now we, instead of just one big finished example, we've broken it up into two or three steps over the course of a book or a screencast. But very rarely does the pros or the explanation actually explain the thinking of how to make that thing more real. It might take years before you're able to imitate even an example application from a book. But that word invitation stands out because I think that most of us are just imitating other programmers. We see somebody successful or well known and we just try to do things like they seem to be doing things and that's how we kind of learn and get by. You can see that this is endemic in our society as programmers because we're really bad at how questions. If I ask, how do I know when to create a new method? When should I break this thing up into more than one thing? You know, you get really unsophisticated responses like method should be about three lines long. My wife, she likes telling the story, when she was in first grade, Becky, she was told by a teacher that sentences were two lines long and so then dutifully for the next several years until she was corrected, she just stamped a period at the end of every other line and that's funny because she's not an adult and yet here we are with these unsophisticated ideas like a method should be about three lines long and no ability to communicate above and beyond that. But let's say in spite of all of this, somehow you write a really good program one day and you're really proud of it and really happy and I ask you, okay, so what actions were productive or unproductive that led you to that point? Or what thoughts led you there? Which thought processes were successful or unsuccessful? Would you be able to answer those questions and most of us wouldn't be able to and it leads to rampant insecurity from how we educate programmers to the work that we do, to the colleagues that we keep in the overall industry. Now 99% of the work that I've done as a professional programmer could be boiled down as a business person trying to get a spreadsheet onto the internet. And yet it's taken me 10 years or so to even become a nearly competent programmer and that's clearly something's wrong and how we teach people to program. And this industry is 60 or 70 years old but we're still searching for silver bullets. We always are externalizing the problem and hoping the next language or framework or library or process is going to suddenly make programming explicable and it never works out. And think about that situation, you know, where everyone's either making stuff up as they go or pretending they understand it. Who's going to succeed in that environment? It's genuinely brilliant people and people with the overconfidence of having been told that they're brilliant their whole lives. So imagine that you don't look like other programmers and you walk into a room and you lack that privilege of having been told that you're brilliant by society. This is a terrifying line of work to walk into because no one can actually explain how to program. And I think that if you want to make programming a more diverse and inclusive industry we really need to solve this. And it's obvious that the industry has no idea how software works because they're constantly analogizing it to literally any other industry like construction or like design or manufacturing. Because of that they control the handful of things that they do understand like estimates and when people work and where they work instead of like the true none of it which is like how we think as software developers and how we solve problems. So how do we fix it? Well, fortunately yesterday at the keynote DHH offered us one solution but I'm going to talk about a different one. I'm going to talk about feedback loops because programmers through compilation and through testing were used to establishing feedback loops to make forward progress. And we can do the same things inside of our heads improving as developers. We're going to practice this today by reflecting on the actions we take and whether they're successful or not and how to improve our actions. You can do the same thing for feelings and actually reflect on your emotional state so that you can reinforce positive emotions or mitigate negative ones. And spoiler alert you can actually think about thinking and produce better thought processes that turn out to be more productive. This is really the path to programmer enlightenment but I realized that we're starting from scratch here. We got to walk before we can run and ask yourself what do we do with teams that are so kind of emotionally immature they struggle to even talk about feelings? Well, we hand them crappy personality tests like the Myers-Briggs type indicator. If you're not familiar with the Myers-Briggs just know that it's the worst type system. The reason we rag on it is because it puts people into these silly buckets like ENTJ and ISFP and the implication is that there's only 16 types of people out there but we know that there's much, much more. But when you're starting from zero, 16 start sounding pretty good. So that's why today I'm pleased to announce the Searles-Briggs type indicator. And instead of pontificating to you today about how to program and dictating that this is the magical way, this is the silver bullet, instead I'm just gonna humbly take my own test, show you how I feel and my inclinations and my personality and what I've done over the course of my career to reflect and improve and result in better outcomes as a programmer. To do that we need an example feature so let's make one up. Like I mentioned, I work at a company TestDouble and we have always been a distributed company but we're still learning that that does not mean evenly distributed. So if you've got a flat organization you might think that there's all these spontaneous relationships that form but of course that's not accurate. We all have our assigned pairs and we all phone home to an account manager. Our org chart looks like one of those 1980s suction cup ball things. But there's nothing wrong with that per se and let's say two people on the team both really wanna learn Elm but there's nothing systemically that's gonna get those two people talking together necessarily. So somebody raised the idea, why don't we have virtual coffee dates on the team and just randomly assign people to talk to each other that otherwise wouldn't be. It's actually an expression from math that it's called the handshake problem which just calculates the number of potential relationships of any group of people and you see that there's just tons of them and so what the system should do is just send an email every week to pair up people who might not otherwise be talking to one another and tell them go spend 15 minutes on this Google hangout URL and chat about something doesn't have to be about work. And so we're gonna put my test to the test and build this feature together this morning as a group and the first bucket that I'm gonna put us in is sensitive versus fearless and the first question is, I prefer hearing all requirements up front even if I can't tackle them all right away. I strongly disagree with that. I get overwhelmed really easily. Two, adding to a long function feels like more code just won't fit. Absolutely, once I hit a certain amount of complexity I can't imagine adding another pace. Three, I look forward to being assigned to new projects and teams. No way, new projects give me night sweats. Four, I often feel paralyzed while staring at a blank editor screen. Yeah, I already admitted to that. So does that make me sensitive or fearless? Pretty obvious in this case, I'm sensitive. A big part of being sensitive is that I get overwhelmed easily. So think about this feature and all I've gotta do. Create pairs, great, that's not so hard but I do have to go and send the email and I also have to look up all these people from a database but I gotta be careful not to repeat so I gotta randomize the pairings and I gotta not repeat week to week either which means I also have to persist them. So there's a lot of work. So I don't wanna think about all that. I just wanna focus on the core problem. So my inclination is to just do that, put a unit around it, think hard about the problem. I can do my little test-driven development thing and I'm feeling really good about that unit of code. So then I go to the controller that's gonna call it and I realize that the method signature doesn't quite line up. Or somebody else might say, hey, this unit you just made is doing all this extra redundant work that's actually handled elsewhere. My inclination was to overcome that paralysis that I felt and find some productivity by just putting on blinders and I fell into that rabbit hole often enough that I had to think and reflect and actually have inverted how I work as a programmer. So what I just showed you is often called bottom up programming but now I practice top down, it works better for me. You might also call it outside in where I think from the perspective of the controller or the top level entry point and I start there and I ask, what do I need? Why do I need something to create these pairs? And when your brain is focused that way, the caller knows exactly what inputs are available, what output it's gonna want and it's also a way to minimize like waste because it has the broader context in terms of what guard clauses need to be inserted or can be omitted. The other aspect of being sensitive is that I'm really afraid of failure and when you work outside in, you do have to juggle all these different concerns at once which can again be overwhelming and so what I try to do is just rush into solving it. Like my inclination is just to like open up an editor and prove that I can write this code. So I start with a module and I make a method, I go load up a bunch of users, I loop over them, I skip anyone who's already had their handshaking and otherwise I'll go and add a tuple of like a, you know, represent the pairing and then I'll go and slam it through some mailer and now I feel really good because I just proved I could do it and someone will remind me, you remember you gotta randomize it and you don't wanna leave out the 15th person every week and you've also gotta prevent repeats from happening week to week and now I'm terrified because I can, this is already really dense, I don't know how I'm gonna make it more complicated and I'm very familiar with this corner of the room as a result so I keep paying myself into this corner and the root causes fear, I'm afraid of failing, I'm afraid of big things that I don't know how to break down so my solution is avoid that fear by breaking things down in a systematized way, give myself some help and I've been practicing over the last few years iterating on an approach to test-driven development that I call discovery testing and it's really an effort in breaking big, scary problems into smaller, more manageable ones. It works with, I start with just a test of that top level thing so I write a single test case, I invoke the thing and then I ask myself a crucial question, what's the code that I wish I had that I could defer and hand this work out to? Well, something to find these hands, something to determine who shakes whose hand, something to mail them and then persist them. Then I use my test double library, which in Ruby is gimme so it creates these four fake things and I set up a stubbing so I say, hey, when finds hands is called, it gets you this thing to symbolize the hands and if I pass that to the thing that determines the shakes, another stubbing will give me these handshakes. This is all the tests that I need to be able to actually assert that I mail out all those handshakes and that I persist them. Now this is an unusual looking test to a lot of you I'm sure but what it does is it perfectly specifies the behavior of that top level unit. And so I get this test to pass and I never have to worry about that top level again. In fact, if you list out all the files that shake out from just getting that test to pass, now I have a pretty clear work cut out for me. I know exactly what I need to do. I can start making forward progress. So I start off with a big scary thing but as I build that test, I identify the units that I would need to actually carve out the work and instead of one big scary thing, I now have four more digestible problems that I can focus on and if any of them are scary, I now have in my back pocket a tool that I can use to like reduce and break things up even further. The second bucket I'm gonna talk about is inventive versus aesthetic. So there's some quiz questions to determine my type. Question one, it's more important to build the right thing than to build the thing right. These are both important but I'm more implementation focused. Question two, I love experimenting with new tools, frameworks and build systems, not at all. I do spend a lot of my time in open source here but it's expressly so I don't have to worry about it at work. Question three, I strive to write visually appealing code down to syntax and symmetry. Absolutely, I don't know why but I really like pretty symmetrical code. Question four, it's boring when all the code in a project is structured similarly. I disagree, I really like consistency in code. So does that make me inventive or aesthetic? Well I think it makes me a little aesthetic and one part of being aesthetic is I have refined taste. Now the problem with taste is that nobody knows what it is. Until somebody on your team says, you know what, I'd prefer a 300 line function to all these well named little small units that you keep creating and then my face looks like this, that's taste. Quiet programmers develop taste while it's obvious. When you're staring at a blank editor screen there are infinitely many ways to solve any given problem. We need something to constrain ourselves, some patterns to follow to just not be stuck in analysis paralysis forever. And that's why I think that pros is a much better analogy to writing software than construction is. In fact, I think of programming as just communication to the next developer who's gonna pick it up and it's just hard because it has to happen through this filter that's just formal enough for an interpreter or a compiler to understand and so when I hear this feedback, I reflect and I take it to mean it as a critique that maybe I'm writing code that's meant to be read by myself as opposed to another human because the other developer they're not in the room so I tend to write code that I think that I would wanna read and this leads to self-centered design. So if I just write a book on design patterns I'm gonna create a bunch of units like services and factories and repositories and I'm gonna feel really brilliant having done all this but then somebody else could list out all of the files I just created and one big listing from their perspective it's gonna be impenetrable complex it's a forest of all these objects no idea how things are gonna work and so now when I hear that critique they've got a pretty good point and I found this happen on team after team and what I really realized is I've gotta start working differently to make my code more discoverable and approachable for other developers and now I do things much differently. It started with realizing programs are directed graphs so all of these units are really kind of nodes in this graph and all of the edges and vertices are function calls. So the locator calls the service which calls this repository which calls this mapper which instantiates hands service also calls this factory which calls that thing and that thing and we already, cause we think of programs this way we have some tastes we have some constraining principles that we share like for instance if this repository were called this service we would all wait a second that's a dependency cycle we'd realize there's a risk of an infinite recursion or like a stack overflow there and so most of the programs that we write as developers try to be acyclic digraphs and remember my purpose here is just to prove that I'm right I wanna tell this person no small units is better than 300 lines objectively and to do that I thought maybe there's a liberating constraints maybe if I refine my tastes further I can solve this problem and where I landed was I want to express all of my features not as just general graphs but as trees because a tree is just a special subtype of a graph you can take this exact same menagerie of units and organize it in a tree shape where you have your value objects on the left and then function future behavior on the right and now if it's true that I have any needless indirection it stands out in a tree cause it's just got one child so that service locator yeah I can probably get rid of that and if somebody asks what they're looking for is how to compare two hands they can search the tree much more easily and quickly than just a gigantic directory of files and find what they're looking for so it's more discoverable the other aspect of my aesthetic is I'm a minimalist so when you look at our app and you see it's a car it drives you think about what its function is and why it exists when I look at our app all I see is the clutter and the mess and as a minimalist my productivity goes up when things are tidy and symmetrical and terse and it goes down when things are cluttered or inconsistent and what the software is supposed to be doing is it's essential complexity everything it actually does is it's incidental complexity the other stuff think of everything that goes into writing a program you're writing deploy tooling and app config and dependencies and framework appeasement then of course there's whatever the app was supposed to do there's style rules continuous integration build systems and then of course unnecessary stuff as a minimalist I'm the person on the project who's always chiseling away to try to minimize the amount of incidental complexity in the system and trying to maximize the time that the team spends on whatever is really important that means I'm always tweaking my code style like maybe I'd start writing feature behavior inside of my model objects but then separate them out into separate units but then maybe make them callables but maybe ultimately land at module methods these are all fine you can debate the finer points but at the end of the day there are really six of one half a dozen the other kinds of arguments and they represent a sort of trap because earlier I said like style rules debating style is a type of incidental complexity because style is subjective and so it changes around arbitrarily and arbitrary decisions breed inconsistency and oh it turns out that inconsistency is another form of incidental complexity and so oops because I thought Monday I organized code this way and on Tuesday this way and Wednesday that way and then by Thursday I've decided this is the best way to organize code everyone's gonna get mad at me because I've just littered 36 custom little styles all throughout the system so my temptation to continuously be improving stuff actually breeds inconsistency and creates bigger messes elsewhere so I reflected on how I think what would happen is I'd chase the local optimization at the expense of like the global optimization of what's best for the overall project and I had to learn to avoid this oscillation in my design and it really required me to just realize I'd spend the entire project spinning my tires and so instead I decided I need to just lock in these decisions and say we're just gonna do things this style whether or not it's better or worse it doesn't matter so we can try to carve out time to be productive and as I got better at that at flexing that muscle I could recognize where I'm spinning my wheels earlier and spend more of my time being productive it was a way for me to both be minimalist but also really consistent in my applications even when it meant hewing really strongly to arbitrary decisions of things that didn't really matter and when you do that especially with your incidental complexity it brings the essential complexity into sharper relief so you can all as a team really just focus and spend more time on what your app really needs to do the third bucket is naive versus leery question one publishing metrics like code coverage is always a good idea and I think radical transparency often backfires question two writing good commit messages today will pay off in the future secret I don't actually read commit messages so three software teams will make smarter use of time under pressure disagree I think pressure kills cognition four software is generally improving over time and we are not doomed so does that make me naive or leery I'm starting to realize this is a pretty obvious test in my case I'm leery it all starts with my distrust of all of you because most teams operate in a pressure cooker they're under pressure to get as much stuff done as fast as possible and as a result their brains turn off and it results in really really bad outcomes in fact it's not very fair to pressure cookers because pressure cookers serve a useful purpose so I'll find another analogy where we're just being squeezed for all of the Ruby and JavaScript that we're worth and again not being creative not resulting in good code one person on teams I don't trust is I don't trust product owners I love them but I don't trust them back in the waterfall days product owner would be able to specify 300 bullet points of everything that they ever wanted and then foist them upon us and we'd say hey this is awful but in a way at least it was honest they got to articulate everything that they wanted up front it was just us who didn't know how to handle that much complexity Scrum and Agile's stuff kind of gave us a little bit of a backbone and we said no sir you only get one index card at a time and in fact that's gonna be 20 points and I made up what points mean and so naturally then it becomes a debate of no I think it's five points and any system can be gained and really savvy product owners I know are really good at this and you're like oh you know this is not that complex it's just a little cartoon whale you guys can do that right you have time and we'll say oh yeah sure we can do that and then we realize it's much more complex than we really thought and by then they're out to lunch and we're left holding the bag so I don't trust product owners for someone I trust even less than product owners as other developers and it's because on day one of a feature we neglect to realize a very basic fact our brains can only hold so much stuff in them at once and so I think the developers have this bias towards sizing features to just whatever number of things they can hold in their head at a time and naturally the conclusion that we draw about how big our objects and methods should be is the same size because then that way we can just put all the things in one place it seems like the simple solution but then a month passes and somebody says hey you need to add a couple additional aspects to this feature you know it has to do this and this as well well that means that the other stuff like our brain is finite we can't you know keep it all in our heads at once anymore but units we can make files as long as we want so we just even though we're incurring a paging cost we can slam in those additional attributes to the feature but it creates a blind spot for us where you know now that we're not thinking about the persistence you know bugs can creep in through that door and if you work this way a year passes and pretty soon your units are just gigantic and they look like this and they're riddled with bugs and normally day 400 is the day that I get a phone call saying hey can you help improve our tests of course this isn't a testing problem right it's like a complexity management problem and it's hard for me when I see this cycle repeat over and over again to let that distress kind of like grow into cynicism and that's not good and in fact if I'm empathetic I realize that at the root of this industry all of us really struggle to predict how complexity is gonna change and to guess the complexity of stuff and I do it too and so what I wanna do is change the question and instead focus on how to prepare myself and other people for the inevitable increase of complexity because on any maintaining system almost any of them they're gonna complexity is gonna go up over time it's just a matter of what that graph looks like and so like Pascal I made up Searle's wager in my head where sure complexity might remain constant or it might go up and yeah we could keep writing these brain-sized units or much smaller ones and if complexity doesn't change you know no harm no follow it doesn't really matter how we factor our code but if it goes up we have a lot of evidence that these larger units cause problems and the nice thing about small ones is that they can actually accommodate some additional complexity without too much pain and that's why in day one of every feature I break things up into itty bitty tiny units to the point where people criticize me and you know if you think that my units are too small don't worry because I trust that you're gonna go and make them bigger later it'll work out it's a great way if you struggle with like trying to follow the single responsibility principle I'd have every object do one thing this makes it really really easy in fact this is what the tree of functionality kind of shook out as in this example and every single unit serves exactly one purpose and they all follow one of three roles that I've kind of observed over the years of practicing this the parent nodes are delegator objects they don't really have any logic or branching maybe just like one if condition or something they mostly just break up the work and hand it off to other things and the way that I happen to do that is I use this test driven design where I use test doubles to identify and think up what's the code I wish I had that would actually do the real work what you want to try to maximize is these leaf nodes so this is where the core logic of the application is it takes inputs and transforms it to some kind of output these are pure functions so you don't need test doubles you just are actually testing real logic these are the kinds of unit tests that everyone likes to write and it's sort of like functional programming for people who don't want to think too hard about functional programming it makes it very accessible because you can still do it in Ruby you don't have to change languages or something on the left are my values and value objects they just wrap a little bit of data maybe they just hold on to a hash or an array and the methods on them are only allowed to elucidate the data and answer questions about the data as opposed to doing feature work they're not there to actually build features instead I think of them as the sludge that flows through the pipes of my feature code they're the types in those method signatures and even if all of this abstraction doesn't ultimately pay off and even if that feature doesn't change a lot in the future the very worst case I've got a very discoverable system of carefully named things that are obvious and small and comprehensible so it's not the worst outcome in the world the third aspect here is that I distrust myself even more than all of you it's because I worry about the future and even though I'm not super confident in today's skills I'm even more worried that my future self won't be able to program either for some reason and so when I'm writing a feature somebody says build this thing I'll think about how to build it and then I'll build kind of a message in a bottle for myself in the form of better tests and documentation and commit messages things to try to help and my future self who's wearing sunglasses is told to change that feature he gets really frustrated because what those tests mean is now he's got a bunch of other stuff to do every time he wants to make a change and my future self would much rather just start fresh and be able to write new code and so I kept trying to do myself favors by writing a lot of extra tests and adding in all this quality at the beginning but it would actually tie my hands and so I had to reflect how do I bake quality into my applications without creating an undue burden for my future self and so I started working a little bit differently because if this is our tree of functionality and our manager comes in and says new requirement like thanks to some HR fiasco all handshakes have to happen between three people the traditional way to solve this is to carefully read the existing code add, remove, change, test, change the code and then try to make as small of a mess as possible and I say small mess because any time the purpose of a piece of code has been two things whenever we change a unit it kind of carries with it technical debt it confuses the story of why it existed because it's changed over time so instead I've been trying to make my code disposable and what that means is that when I look at this tree I search for all of the affected units by the change these are two units they're gonna change and so then I find the smallest subtree that encapsulates that change and so there it is right there and then I do something unusual I blow it all out I just knock it out because I trust that my future self is gonna be able to see that top level thing and understand what the contract is so there he is he's gonna drive out a new solution and as opposed to just changing these old units that implemented via Lodge of the Old Way and thus rack up technical debt so I trust him to drive out a new solution and in fact the future us is gonna have more experience than present day us they'll probably have a better understanding of the business they'll be able to write better units in the future than a week ever could hope to today so this is a healthy way to work it does mean that I try not to reuse code too much in my future code because any code reuse like if you have a method that's called in nine places it's really hard to change that method because you have to consider nine different place callers and what they need it's also really hard to throw it away and replace it so I try not to reuse too much code and it also forced me to let go of this idea that maintainable code has to live forever in fact, you know, as opposed to that this incremental rewrite in the small as part of your process is a way to pay technical debt without saving a rainy day fund for when you finally get to refactor and in doing that I actually made myself happier because future me does not want his job to be fixing all of Justin's old janky tests every time that he changes something wants to be able to write code for a living and so this process by making like, you know death a part of life while we're working through features is a great way to keep your teams happy at found the last bucket here is economical versus throw the question one better to ship code quickly than wait until everything is tested and I feel like I just be bailing out water in that case to design principles are useful but most teams waste too much time on them it's possible for sure but few teams are at risk of this three most teams lack a sufficient understanding of their dependencies absolutely, you know 90% of us have no clue how most of our code works in our applications and four it's okay for everyone on a team to maintain separate coding styles I actually strongly disagree because this leads to silo development it's kind of like a Conway's law of style so does that make me economical or thorough well of course it makes me thorough some of you are noticing that this spells salt that's because when you make up the quiz you can make it spell whatever you want it's going to surprise a few of you to learn today I have a confession to make I'm a bit of a control freak and that means I'm dubious of free stuff so when you see a sign that says free puppies all I read is extra work and another thing in our industry that makes me think extra work is open source and so just keep that in your head next time you're on GitHub asking for free labor from an open source maintainer imagine you're yelling at a puppy instead because who yells at puppies you jerk open source isn't free because just like puppies we have to learn how to use it we have to learn how it's changing and follow it and it's not just this panacea that we can pull off the internet and instead of having to build stuff ourselves and if that open source has a bug in theory sure we can fix it ourselves but in practice we're not going to understand all that stuff we're probably going to have to rely on a maintainer or an expert to come and fix it later and finally like if we have like let's say that this is our graph of objects and it's all very consistent everywhere and we slam in some third-party API that's going to create a certain amount of friction and pain because it's not going to look like all of our other objects in fact third-party dependencies have this really nasty habit of leaking references all over our code base which makes it really hard to change or replace or upgrade those third-party dependencies over time. So my temptation of all these negative things about open source and puppies is to well I don't have a puppy first of all again much to my wife Becky's consternation but two I try to like avoid using open source and that's what my gut tells me to do but that's increasingly untenable these days because I'd be reinventing wheels constantly so I had to change how I thought about open source instead to maybe protecting myself from its blast radius as opposed to avoiding it entirely. The way that I do that is I write wrappers of all the third-party code that I write in fact we already have one up on this tree it's that finds hands unit on the left so this is a wrapper object and it starts as just a well-named delegator no off it doesn't do anything interesting but it comes to encode all of our understanding of that dependency it is the carpet under which we sweep all of the stuff that we have to do to make that third-party dependency happy and I integration tested but only in proportion how suspicious I am of it breaking otherwise I trust that it itself has tested well and it might feel like needless in direction but I need you to trust me that it's not of course this is where we're calling finds hands in our top level code and I just told you not to trust other developers so you don't trust me you assume that like that wrapper is unnecessary let's say and instead of using that call we're just gonna call a user.all instead that way it's much more direct we got rid of that needless in direction which means we have to update our test so this is our original test we can get rid of that fake finder and instead have an array of real users that we create in the database of course validation failed so now I have to add like a birth date some incidental other arbitrary thing to make this work but I can also get rid of the stubbing here and pass real users into the other stubbing and I gotta make an integration test as opposed to a unit test and ask yourself now what do we just do because the value of this test used to be crystal clear its purpose was to break the work up into four clear responsibilities and now what is it? It's calling through to the database so it's making sure that the thing works but only when three quarters of the code pads are fake like that doesn't seem right that seems wrong to me and it's really becomes obviously wrong when this becomes more complex because if we add a couple of scopes like only search for full-time and active employees then our test isn't enough anymore because those scopes are like branches and now we need two or three test cases to cover everything and now it's abundantly obvious that we sliced things wrong so when I hear teams complain you have too many abstractions or too many objects typically I think that's it's not wrong it's not that you're making not too many abstractions or that no abstraction is somehow better it's that you're probably mixing the levels of abstraction in your system because life with wrappers is much easier if I look at that same thing and dive into what that wrapper looks like yes on day one it looks like needless in direction but on day two when it gets more complex there is a it's easy to write a test for this there's a place for that complexity to go and over time you know it might become a little bit more complicated as you distance yourself further here with like a transformer to a type that you own as opposed to you know an active record user so let's say our boss comes in and says we're gonna change from active record to the sequel gem traditionally this would really panic everyone in the room because it didn't have a billion references to active record all over your system but when you're writing wrappers carefully of your third party dependencies you're actually preparing for yourself an adapter interface that's minimal and specifies exactly how you use that dependency so you can even answer questions like would it be possible to switch to this third party thing and if you did you could create an alternate implementation and run both in parallel for a while it's a much much better way to work and what I found is it's a way to maintain still have all that convenience of open source and sucking in these useful libraries while maintaining control over how you work so when you're as introspective about this stuff as I am you run the risk of explaining the universe through yourself in fact if you ask anyone who's ever worked on a project with me what my favorite way to write code is it's my way and I'll fight you for it so my inclination is just to work really hard to convince you all that my way is best and I'd love to say that that's an altruistic thing and I want you all to be better programmers but it's not it's selfish what it really is is I'm afraid I'm gonna have a manager someday tell me that I can't write code my favorite way anymore and when I reflect on that even if I were to come up with the perfect way to write code and hand it to you I would run the risk of robbing you of that same autonomy and so that wouldn't be good either and so that's why I'm getting out of the silver bullet business so even though I talked a lot today about how I program I'm not here to sell you on that I mean I hope you find some of it useful but what I really am here to sell you on is the idea of pausing and introspecting about how you act feel and think while you're programming so that it becomes more explicable to you and then you can articulate it to other people and improve and share and you might ask yourself hey if we all start thought leading ourselves won't that just create chaos on our teams and I think that's actually a valid concern so let's spend a minute to talk about that because earlier I said if you lock down all those arbitrary decisions upfront you can spend more time being productive that's true individually but it's also true as teams and that's why when you have disagreements with other people on teams you should aggressively pull those forward because the earlier you have that discussion and say okay you know we'll use these semicolons or we'll follow this style if you can agree to that stuff early and lock it in you'll as a team be more productive and in fact if you look at the average team remember what I said earlier we're all just imitating other programmers so most teams actually like the idea of normalizing in fact some of them like it too much where if you have a creative idea of doing things differently I don't want to rock the boat you know I don't want to like do my own thing off here or go off the reservation quote unquote so instead we tend to just gravitate towards the lowest common denominator on a lot of teams and that's not good but that's not new anymore right because after today you're gonna be thinking about how the actions you take could be improved your feelings improving your thought processes and on your next team when you join a team of all enlightened Hugh Jackman's some of whom will be salt and some of whom will be fine which is literally what the other portraits spell some will be sale and some will be fault when you look at this team yeah sure they all have very strongly held opinions of different ways of doing things but the one thing they have in common is when they're approached with a new idea they have a system for testing it and figuring out whether to adopt or reject it and so they're not afraid of trying new things and that's why I think that really introspective developers when they're on a team they might just look like they're talking at the whiteboard all day but they can actually have a multiplicative impact on each other as they grow and that's really my dream today is that if we can as an industry normalize the concept of metacognition and a self improvement so that we can explain how to program this whole place might start making a whole lot more sense and that is how to program so I appreciate your time here today if you're looking for a company to work with that's gonna support you on this kind of journey I hope you'd consider checking us out that's our page explain what it's like to work with us at Test Double and if you're a company that is looking for additional developers on your team I hope you'd consider working with us we join other teams just as additional developers with an interest in helping everyone get better as we go and you can learn more about us on our site by the way I really made this quiz it's a real thing I actually printed out like a hundred copies and I have it in my bag so you can get a special commemorative edition today if you come up and say hi to me I'll hand you one I also have a lot of Test Double stickers if you don't want to say hi to me in person you can actually go to testdouble.com slash salt and fill it out we made a Google form and then two of our agents yesterday actually figured out how to automate Google form so it'll calculate your programmer type and email you right away so I hope you'll check that out too but most importantly of all I'm really thankful for this opportunity and for your time this morning thank you