← Back to episode

Transcript: Teaching and Learning with Sandi Metz

Tech Done Right, Episode 69

NOEL: Hello and welcome to Episode 69 of the Tech Done Right Podcast, Table XI’s podcast about building better software, careers, companies, and communities. I’m Noel Rappin.

We are currently running a brief listener engagement survey. Unlike most of these surveys, this one has nothing to do with advertising. We’re just trying to see what kinds of shows and guests you like so that we could do more great shows. Fill out the survey at bit.ly/TechDoneRightSurvey, all one word. And if you want, we’ll send you some Tech Done Right stickers and you’ll have a chance to win a deck of the Table XI Meeting Inclusion Cards. That’s bit.ly/TechDoneRightSurvey. And thanks.

If you like Tech Done Right, I think you will also like our new podcast Meetings Done Right. Meetings Done Right is 12 episodes with communication and culture experts all focused on how to improve your meetings using the new Table XI Inclusion Meeting Deck and other tips and techniques from our experts. For more information about the podcast and to learn how to buy a meeting deck of your own, go to MeetingsDoneRight.co or search for Meetings Done Right wherever you listen to podcasts.

Today on the show, we have Sandi Metz, author of Practical Object-Oriented Design in Ruby and co-author of 99 Bottles of OOP. I’ve literally been trying to get Sandi as a guest since we started recording this show and I’m thrilled that we have finally been able to connect. We have a long conversation about OOP and TDD, maybe going a little bit too much down the test of a rabbit hole for a while and we also talk about what it’s like to teach and coach about OOP and TDD. I really enjoyed this talk and I think you will too. So now, here I am with Sandi Metz.

This week on the show, we have Sandi Metz. Sandi, would you like to introduce yourself to our audience? Hi, Sandi.

SANDI: Hi, Noel. How are you?

NOEL: This is great. I haven’t seen you. I’ve literally been trying to get you on the show for about two years. So, hi.

SANDI: Hi.

NOEL: And you’d think that I would have a lot of questions built up.

SANDI: I know. You can either think of us as having done no prep or having always been prepped.

NOEL: Yeah, that’s it. Always been prepped.

SANDI: I prefer that.

NOEL: Yeah. That’s good. So, what’s on your mind? What are you finding exciting in the coding world these days?

SANDI: Oh my gosh, that is such a broad question. How can anybody answer that? I mean, like all of us. I feel like I’m just trying to surf the waves and there’s too much going on and too many new things all the time and we’re all trying to like get our jobs done, but also make sure we don’t become obsolete and also make sure we have fun along the way. And I feel like I’m just fighting a rearguard action against all of those things all the time.

NOEL: So, how do you do that? How do you surf the waves? What catches your attention? What makes something stand out?

SANDI: Okay. So, I’m a woman of a certain age. It does feel like I ought to know the answer to that question. And also I’m here now, like I started 40 years ago writing Cobol on a mainframe and I have to admit, I don’t know what all the people that I was writing Cobol with 40 years ago are doing now. I suspect some of them are still maintaining Cobol programs.

NOEL: Yeah, there’s one or two of them who are probably still working on Cobol.

SANDI: Gosh, Noel, I try to pay a little attention, but I’m very bad at paying attention. So, really what I have is friends who pay attention that I talk to on a regular basis. And I do, I rely on the kindness of strangers to sort of filter. Think about this, the news, if you think of every piece of information you would get about what’s going on in programming development land that we live in, it’s impossible to keep up with it all. And I used to be really stressed by that because we really do want to pay attention and make good choices about how to have fun and how to manage our futures so we can make a living later. We want to make good choices at that boundary, but it’s impossible to do it all. And so, how do you navigate those waters? Someone once told me it’s just news and it’s true that you can ignore most of it on a day-to-day basis, right? You can just wait and see what floats to the top.

NOEL: What people continue to talk about.

SANDI: Yeah. What stays on. I mean, I have to say like many people have already caught the functional boat. I mean, I’m definitely watching that craft to the point where I’ve done a little functional programming intentionally. And boy, is that hard for a crusty old OO type. Oh, my gosh. What are you doing?

NOEL: What am I doing? Well, I find people to have as guests on podcasts and they tell me what I should be looking at.

SANDI: See? So, that’s a form of having a friend who keeps up.

NOEL: Yeah. So we’re in a weird loop here if we’re expecting the other person to be telling them what’s going on. That’s kind of problematic. One thing that I did want to, you talk about the functional paradigm versus OO. As it happens in somewhat coincidentally, somebody at Table XI is organizing, we’re in the middle of a book club on 99 Bottles of OOP. One of the things that is interesting to me about it is that most of us here, strictly speaking on a day-to-day basis, our object oriented developers, because most of us are writing Ruby, but I don’t really hear that’s it’s kind of like object oriented triumphalism, they’re like full-throated, this is the way to program, the way that I used to. Sandi, by the way, you can’t see her roll her eyes impressively. That’s the kind of cue we wouldn’t have if we were on a video chat. And interestingly because the previous guests I just interviewed, Dave Thomas and Andy Hunt, about pragmatic programmer 20 years on and Dave was talking about how he is thinking about testing too, which is another thing, that test driven development is another thing that you don’t really hear like full blown defenses of these days. First of all, do you agree with me? Does that make sense? Does that match what your friends are telling you?

SANDI: Are you asking specifically about TDD or the more broader question about OO?

NOEL: Let’s talk about OO first.

SANDI: I mean, here’s what I’ll tell you about OO. Some problems are really suited to that style of solution. And if you have a problem, our job is to save money. Our job is to produce software, the best software we can for the least cost possible. And there’s a place where there’s categories of problems where OO is a really good fit, and there’s categories or problems were dynamically typed OO is a really good fit. I happen to love those problems because I love that way of thinking about the world. But I would never argue that everything is an OO problem. Just like I would argue with you, you know how these people learn a thing they learn and then you get really comfortable with it. And then it feels like every problem is a nail because you got a hammer. And I feel like I have to be really careful about saying some things probably should be solved functionally, some things maybe or some teams would be the argument I would make, like some problems need enough speed or have teams that need enough management that you should probably be in a statically typed language. OO is not that. The answer to every question is it depends.

NOEL: Right. But that’s [inaudible].

SANDI: I wrote a little Elm last summer and it was super interesting how you had to test it, like the effect that using a functional language had upon my confidence level about how many tests I needed in order to write that code.

NOEL: That’s kind of interesting because I have also played around a little bit with Elm and with Typescript.

SANDI: I haven’t used Typescript but I am totally aware of it. How could you not be?

NOEL: Yes. But specifically Elm, since I have also done per-project where I had to write, where we’re testing Elm, as a [inaudible] side project. And one of the things that I said to Dave two weeks ago on this podcast was that static type checking was replacing some of the tests that I was writing, and Dave did not buy that at all. Dave, it’s not like he writes tests.

SANDI: So wait, I just want to confirm that I heard this correctly.

NOEL: Okay.

SANDI: You said Dave Thomas is not writing tests or he writes tests in a different way?

NOEL: Okay. At the risk of making this entire podcast a recap of the previous podcast, Dave Thomas has a long section in the new version of Pragmatic Programmer about how he decided to try not writing tests for a while because he was really comfortable with writing tests and he just wanted to see what would happen. And what happened to him, at least in the short term, was nothing. He felt like he was writing the same code he was going to write anyway. He just wasn’t writing the tests. He didn’t see a change in his bug rate and he didn’t see a change in his designs. Eventually, he started writing tests again because he wanted the communication factor and the regression things, but in the immediate term, he didn’t see any benefit. And what he took from that, and I am paraphrasing the arguments of people who are smarter than you is always dangerous, but what he took from that was that the reason he had been writing tests was to help him think about his design and that he had been doing that for so long that he had internalized it and therefore did not need to write the tests again. When I suggested that I was writing tests that would get replaced by static typing, Dave said that that was not why he was writing tests and therefore static typing didn’t help him in writing tests. So for more information about that, you can touch the last 20 minutes of episode 68 of this show. Sandi is frantically looking for a pen and paper.

SANDI: I’m just looking for a piece of paper here.

NOEL: Okay.

SANDI: Did you say four things? I know that I’m going to lose three of them. So, one was about like why do we write tests? Right? Let’s just talk about that for a minute.

NOEL: Yeah.

SANDI: I have this weird life now. For 40 years, I went to my desk every day where I wrote code all day long. That was what I did. And now I travel and teach. And so, instead of writing my own tests, I go to business after business after business. And one of the questions I ask them right away is, how’s your test suite? Do you like your tests? Do you hate your tests? When do you write tests? Are you writing tests first? Are you retrofitting tests around things afterwards? And I can report from my very unscientific sample that there’s a huge number of shops out there, most of them are not doing test first. They’re all writing tests, but they’re doing tests afterwards. They’re afraid to delete their tests, but they hate them all. That’s the state of the universe. They don’t have a lot of practice doing design. They’re not skilled OO designers. And so, here’s what their code looks like. It is a tightly coupled ball of muddy objects that are linked. The dependency chains go from the sinner, the main class in their app, whatever it is, product, contract, whatever they do, there’s a huge big app in the middle and it knows about everything else. If you were to draw a graph of every object and every object it knows about, their apps are big interwoven mats. So they write tightly coupled code because it’s easier to do if you just sit down to do it without tests. And it makes all of their code unusable. They can’t reuse anything they’ve written because all of it requires the entire context of everything that they have. And the fact that their stuff is tightly coupled is reflected in the enormous amount of setup they have to do in order to write a test, which they do afterwards.

And so, the thing I tell them, I just want to lay a suggestion on the table about what a good reason to write tests might be for people who aren’t Dave Thomas or Kent Beck, even though I think Kent probably does write tests first. If you write tests first, what you’re saying is every object in my app is used by two unrelated things. I need reuse from day one. It’s used by the production parts of my app and it’s used by the testing parts of my app. If you find it, it’s really hard to use it in a test. It means you can’t reuse it. And so, that extreme pressure that gets put on you if you try to write tests first serves a purpose of motivating you to decouple your code. And that has enormous value. And I know that people who are really good at design don’t need that pressure. Like if you routine injecting all your dependencies, if your stuff decoupled anyway, that probably has no value for you. But for the vast majority of normal folk who live out in the world, they could really use some of that pressure and it would be a good reason to write tests first.

NOEL: What I think I see, one of the things I see, and I alluded to this before, was a couple of years ago I gave a talk at RubyConf and did a quick show of hands about how long people’s test suite was. And a lot of them were effectively infinite. And what I heard when I went around and asked people about it was, “We don’t care, the CI server handles it. We never run our tests locally.” So, you’re in a situation where there is no particular like social pressure to write fast tests or write unit tests and therefore nobody does. And it just all gets sort of taken care of it. There’s a certain boiled frog quality to it because the tests will get slower and slower slowly and the problem gets worse slowly enough that you don’t notice it. One of the things I always say about OO and TDD is that they all seem like total overkill until you suddenly realize you should have been doing it six months ago. And I think that this is a problem. One of the reasons why OO and TDD, one of the similarities that I see there is that both of them have the problem where toy problems do a particularly poor job of showing them off because a toy problem in TDD, which is the thing that I spend more time coaching, it’s hard to come up with a toy problem and TDD that a competent programmer couldn’t solve without it.

SANDI: I face the same problem when I teach because I have three days, I have to introduce a domain that you could frankly just grok in your head and write the whole thing down. And I’m trying to use those 99 Bottles or scoring bowling as a proxy for these techniques, which are very clearly overkill for the size of those problems. I mean, here’s the thing, everything I just heard you say, it feels like it’s an indictment of us. It’s an indictment of you and me. It’s a failure of teaching.

NOEL: Completely agree with that, actually. I really do.

SANDI: And so then, if we have, like I distinctly remember going to a vo-tech school and learned to write Fortran a million years ago, they teach you syntax. That’s what everybody out there, all the new people learn language, syntax. And then people like you and me, we just like – how did you learn TDD? How did you learn to do TDD?

NOEL: I learned to do TDD, I was a grad student in computer science, which is not where I learned how to do TDD. I came into early projects that were painful for various reasons. And at the end of a painful project, I picked up Kent Beck’s Extreme Programming Explained book. And I was like, “This makes a lot of sense to me.” Because I had been doing object oriented stuff. Actually, my graduate work was about teaching object oriented development. I taught small talk to college sophomores at Georgia Tech.

SANDI: How cool is that.

NOEL: It was really interesting because they really, really wanted to be learning C++, and they could not figure out why we were teaching them this weird language that nobody used. At the beginning of the semester, by the end of the semester, most of them figured it out. But yeah, I taught even before Squeak. This is about the time Squeak came out. So we were using IBM object works, which was a pile. Anyway, digression on top of digression, the Digressions Done Right Podcast.

So yeah, I picked up Kent Beck’s book and I was like, “This makes a ton of sense.” This is very consistent with the way I was teaching OO but not the way I’ve been programming professionally. I was really upset that I feel like I was not doing a good job of coding professionally the way that I had been teaching people to do. That and the Pragmatic Programmer both gave me a vocabulary to think about what I was lacking. And so from that, I sort of intuited, I never formally learned TDD aside from that and from like the test infected essay and a couple of other things. I started to do it myself and I probably read a longer one of Kent’s other books about it to start to pick it up.

SANDI: The fact that you say like you didn’t formally learn it, like I don’t know where you would formally learn it. Of course, I don’t have a computer science degree, so I have no idea whether you could be taught this as part of an academic program.

NOEL: My impression right now is that the academic programs don’t teach those kinds of methodologies.

SANDI: They don’t seem to teach you OO.

NOEL: It depends on where you are and what you were doing because like the programs that I was familiar with, we were teaching OO.

SANDI: When I have people in my class, like very often they have computer science degrees now because kids do. And I asked them what their OO look like, what their OO courses were like. And they tell me nothing like what I’m teaching. Like it was, again, syntax.

NOEL: It’s a syntax of Java.

SANDI: Right.

NOEL: Specifically.

SANDI: It’s a syntax of Java. What I just heard you say was you taught yourself TDD.

NOEL: Yes.

SANDI: And were you good at it, to begin with, when you first started teaching yourself? I’m wondering now if you had a different experience than I did because you are perhaps smarter than I am.

NOEL: So the follow-up question is, am I good at it now?

SANDI: Yeah. Are you good at it now? Start there.

NOEL: So, okay. Was I good at it? Was I good at it when I started? Let me say that I felt like when I started TDD that it was improving my coding.

SANDI: Really?

NOEL: Maybe not. The thing I can definitely say is it felt like it was improving my experience of being a coder. That splitting things up into small pieces and getting that red green hit was improving my experience as a coder when I first started learning it. That’s why I kept up with it. It took stuff that hadn’t been fun to me and made it more fun.

SANDI: That seems great though. Before you go on, can I just jump in with my initial experience with TDD?

NOEL: Go ahead, please.

SANDI: I sucked at it and it made everything I did – I was a pretty good programmer that had – I was the go-to person in my shop. I was the person that was thought of as someone that could solve any problem. And I read on the Internet about TDD, and so I tried to go because people that were clearly smarter than me were saying it was a good idea. And I went and tried to get some information about it and tried to do it. It took my productivity from like a hundred to zero pretty much overnight. My initial experiences were not positive. It was hard. The only reason I persisted was it felt like people smarter than me were saying that it was going to ultimately be a good idea. But I worked in a shop where no one else was converted but me because everybody’s experience was bad.

NOEL: When I started doing TDD for real, I was in a shop where I was largely working on stuff that I was doing myself. We were doing internal projects and it did not have to integrate with other people for the most part. Shortly after that, went to a larger team that had built up this huge crazy ball of Java code without TDD-ing that had like five layers of architecture where in order to get an object to put in the interface, you had to get a database object and convert it to a business logic object and convert it. And that I crashed and burned on testing. Had that been my first experience, it would have been gone much differently I think because that was a setup where it had not been built for testing and you had to like, it was a hundred lines of setup toward a unit test.

SANDI: I just want us to talk about this using slightly different language. It was not set up for reuse.

NOEL: I think the architect who built it said it would have thought would have said it was built for reuse.

SANDI: Yeah, they thought that. But here’s the thing, if it’s really built for it, if it’s reusable, you can test it without a hundred lines of set up. There’s a way in which that canary in the coal mine, which is how hard it is to write a test is a sign, like that whole test driven design. What is test-driven design for people that really don’t have enough experience with the design to know what they should do? I mean, that’s a group of people I talk to all the time. Like, if there’s a failure of teaching and we’re trying to solve it, then how do you give people enough experience so that they can do the right thing? The thing I tell them is just like if it’s hard to test, it’s not designed well, and to think about what your test would look like if it worked, if you could get into the object that you’re trying to test. And basically, usually that means having less set up. Here’s what it means. Don’t commit Demeter violations, like don’t have multiple hops where you jump to the ring of your collaborators and then jump from there to their collaborators. That’s one thing that causes testing to be hard. And the other thing is, and in some ways it’s the same thing, like don’t send messages to the objects that come back and don’t hold on to lots of objects and hold onto the objects that they hold on to. It’s just a different way of thinking about the world. I can only talk to my immediate collaborators and I can talk directly to them and no one else. Then your set up gets easy. And then the design problems become, how will I make objects that only know about adjacent thing? Like how do you do that?

NOEL: How do you do that? So what I find in my day-to-day Rails development is that I have settled into a structure which is comfortable for me and probably in a somewhat generic and probably not optimal, where the bulk of my code, the bulk of my business logic goes into this layer, which I sometimes call workflow and sometimes call service. So the controller talks to that object and that object talks to the Active Record model objects. And therefore most of my testing happens on objects at that layer. And sometimes it feels like that is a lot of setup because it requires a bunch of database pieces, of model pieces to be there. And sometimes it’s easier to do that setup than to fix the design issue, at least it feels that way in the short term.

SANDI: What you just said was you’re pushing the edges of the frame [inaudible] and letting it deal with unwrapping an http request and giving you [inaudible] hash and telling you what the session looks like and waken some point in your code up for an incoming request.

NOEL: Yup.

SANDI: And on the other side, there’s that bag of persistence where there’s some object that has attributes that I want to change and have them be here when I come back later. And I think of both of those things. I’ll say this and then I’ll qualify it. Both of these things are commodities. Any framework will do it. We would expect any modern framework to be able to take an incoming request from the browser and wake us up and also to have some sort of object to relational database mapping so I can create an object that has attributes that get saved, then I’ll come back later. And I am so deeply grateful to Rails because it does those things which means I can write all of my business logic in Ruby but my business logic isn’t part of having a route wake up a place or having a bag of persistence to be there when I come back later. It’s all that stuff that you just said in the middle, whatever you want to call that layer. So when I teach, mostly almost 100% Ruby classes, probably 50% of those classes are for shops that are using Rails and they want me to tell them how to architect a Rails app and I give them the same kind of advice to do what you said basically in the simple form. But I give them a few other pieces of advice like one is to make a folder under model called AR and put everything that’s a subclass of Active Record in there. And just strictly through the power of naming, it starts feeling like those bags of persistence are not your business objects, but people want to make other things.

I also ask them this question: are you going to be using Rails in five years? And they all say, “Yeah, probably.” And then I say, “10 years?” And they start looking a little confused and concerned. And I say, “15 years?” And here’s the thing, there’s so many folks out there working on apps where their first programming job might’ve been in Rails. And so they haven’t had the leisure in their lives yet to consider – actually the very first question you asked me in this podcast, “What comes next?” Because I’m in line of a certain age and frameworks come and go, like window shades going up and down. And there’s a day like all those apps where you’re putting those objects in the middle, some day you’re going to want that logic out in some other language, in some other framework and separating it from, not letting it get entangled into the logic of the framework you’re using is really important now. And so, if you think your business is going to survive, like I’m all for you, Noel. If you think your businesses can, if you’re going to stay in business, you’re going to – it’s worth the trouble to isolate your stuff from the framework.

NOEL: Yes. The thing that I think where I get a little challenge with what I do regularly is that I often don’t take – so I often wind up with a lot of objects that are just sort of generic workflows that basically are just, essentially they’re functions.

SANDI: Are they little procedures?

NOEL: Essentially they’re procedures, yeah. They’re classes that essentially they get called with their run method.

SANDI: Yes.

NOEL: And I know or at least I believe that in most of these cases, there is a design step where I have things that are sort of more domain-y objects. And I often wonder whether I would be better served by doing that, thinking of having those middle objects be more domainier, or whether it’s okay to just have like, here’s my void order class as opposed to having like an order – my void order procedure as opposed to having an order of [inaudible].

SANDI: I know. Yeah. Here’s the thing, when a user hits enter and the request gets to you, they’re asking for a procedure. Like they want all the thing, they want A, B, and C and D and E and then to get an answer. And so, some place in your app has to represent that. The question is if you have lots of those, do they share some underlying more object demodeled underneath that’s different than sub-classes of Active Record?

NOEL: Yeah. They often share a certain structure.

SANDI: Yeah. But here’s a thing I tell people, either we know in advance what our apps do and what our architecture should be, which has never been true for me, or we write a bunch of procedures. We have the controller actions jump to some kind of workflow-y object that represents the procedure and we make a bunch of those and then we just watch when the system changes. We see every time they ask me to change idea X, I have to go make a change in 14 places. That’s probably an object. And so, if you start with that simple thing, I don’t want to put business logic in my subclasses of Active Record because I don’t want to have to get it out later. I want that bag of attributes to be something that some other object holds onto. Well, here’s the thing, now we’re talking about how much trouble do you go to, to have some pre-considered architecture to impose it on an application when you don’t know what’s going to happen. Because now we’re saying I’m going to spend money to put that middle layer in. And if it never changes then I’ve wasted my time. But then like you say, if you make too big a mess six months down the road, it’s hard to get back.

And so, it feels like what I have and what you have is a lifelong of experience with things going badly wrong. I mean, that’s all I got. I know. I’ve seen tons and tons of failures. And so, the things that I’ve seen go wrong over and over again, I’m going to roll the dice and place a bet that ultimately, it will be better for me. I will save money by making those objects that sit in the middle right from the get go. And I’m going to do that because more often than not, I save money rather than lose money by making that bet. But it is a bet. We’re just making an arbitrary decision based on past experience about what future costs are likely to be.

NOEL: Yeah. What I’d say I have a lifetime of is the feeling that I’m slowly getting into quicksand and things get more and more complicated and you think I should have done something better. Yeah, I should have made a better choice in the past.

SANDI: So many apps that I see, it’s a whole thing, like 20% of the code causes 80% of the pain. And so mostly we just have to ignore the mistakes that we made that led to code that we’re embarrassed by because if it never changes to shut the door and walk away, you just have to. For my own personal hobby projects, then of course I can try for perfection. In real life at a business – okay, I taught a class in place where they have code that produces sheet music. It’s actually visual sheet music from some markup, and it is the worst code. It’s astonishing. It is impossible to follow. But sheet music doesn’t change that much. Yeah, it has a really bad code climate score, but it never gets touched. All we can do is like write code and let change tell us where we should do a better job of design. But that thing, that quicksand, it doesn’t mean we should put all our logic in controllers. Like putting the logic in the framework is a separate problem of its own that can be absolutely intractable, like if I want to test it without spinning up Rails. I might want to take small parts of it and write in some other language for some other app. And that’s a lifetime of, like I’ve touched the hot stove of having to change frameworks so many times over 40 years of coding. And I think people who haven’t had that experience repeated over and over again don’t realize how daunting, costly, and business harming it can be to get your code out of framework. That’s a bet. My bet is that later that’s going to pay off if you keep your code untangled from that.

NOEL: Right. And I think that there are cases where you don’t care about 15 years down the road because it’s going to be somebody else’s problem.

SANDI: Right. I mean, I realize my view of the world is skewed because, like who calls me? It’s the business that’s won in their domain. And what that means is congratulations, they have a huge mess and they won by making those messes maybe. And that’s like, “Hey, good on them.”

NOEL: I will say that one thing that is definitely more true of me now than I was at the beginning of my career is I have much more respect for working code that is messy than I think I would have had a bit of a chip on my shoulder about it 15 or 20 years ago.

SANDI: Yeah. I feel like I am better than I used to be about having heuristics. I have little internal rules that let me make decisions in the face of uncertainty. And it would be something like, “Should I inject this? Should I take an argument and inject this dependency?” Even if I set a default to the thing I could know in the class. Am I going to routinely inject dependencies or not? I’m biased toward doing that. Am I biased toward not knowing about my friends’ friends? Yes, I am. There’s a whole bunch of rules that I would apply to my code right off the bat. If you do it from the beginning and everybody is aware of that style that your team – if your whole team is using a style where you say, “Okay, we’re going to inject dependencies,” then it’s effectively free. It’s not more expensive to do it than not do it. It’s just different. And so, there’s a whole bunch of decisions I want to make. There’s patterns of coding I follow from the beginning where I’m willing to – I hesitate to say this because I’m afraid people are going to – like I am super practical and I’m all about the money, but there are some things where for a tiny increase in the level of abstraction, you can get huge amounts of flexibility later. And that’s really what I’m looking for. A flexibility to be able to easily adapt to unforeseen change requests. That’s all I want.

NOEL: The long-term cost of change.

SANDI: So, I want to go back to my list.

NOEL: Yeah. We’re now going to pop this stack and go back through other – we were talking about testing at one point.

SANDI: Yeah, CI. I don’t know if Jim Weirich is a name that everyone still knows. You certainly know him.

NOEL: I do. Yes. Jim Weirich was a long time Ruby developer and teacher, and also the creator of Rake as tool.

SANDI: And terrifyingly brilliant while being the most generous, open- hearted nice man you could imagine.

NOEL: One of my favorite things that ever happened to me as a speaker, there’s a video of me telling a joke that only Jim in the room got and there’s this big booming laugh and then everybody else laughs from his laugh.

SANDI: Okay. So, he was super, super, super famous and should have. I was intimidated by him, but it wasn’t because he was anything but sweet and endearing. I was sitting next to him at a conference five or six years ago and someone was on stage giving yet another one of those talks about doing something to spin up multiple servers, parallelize testing so that the suite could run in a normal manner, in an acceptable amount of time. It was that. And I was totally convinced by the talk. I was sitting there, little Sandi, beep, beep, beep, beep. I was like, “Okay, sign me up. I’ll do it. It sounds awesome.” And Jim looked at me and he said, “This is a terrible idea.” And this is a man who would never say a bad thing about anything. And I was just stunned. I looked at him and I said, “What?” And he said, “It just enables bad testing. We should not be putting time and energy into making test suites run faster, we should be putting time and energy into making testing faster, making people get better at tests instead of doing things to overcome bad tests.” And I was really struck. Obviously, I remember that to this day. And so, earlier when you said something about CI, doing things with CI, CI is an enabler and it will not save us. And I know there’s some businesses where they have enough money, like it’s possible in some places to just throw money at the wall and solve the slow test problems. And maybe if they have a bunch of money, maybe that is the right solution at some places for some time.

NOEL: I think it becomes the right solution when you find yourself already having a super slow test, where then it becomes much, much cheaper to throw money at servers than it does to fix all the tests.

SANDI: Here’s the thing, if you have tests that run that slowly where you have to throw money at them to do it, then what you get is like safeties against regressions. Those test suites can serve the purpose of proving-ish the correctness of your application, but what they don’t do is help you write code. They don’t give you any safety while you’re writing code. And I want my test to do that too. Like I want them to run, I want the test for the object I’m working on to be separable from everything else and to run in milliseconds. And that implies a whole bunch of stuff about how I write code, not just how I write tests, but how I write code.

NOEL: I think that there are a couple of things. One is that what I find actually is that a lot of the places with these really long test suites, it doesn’t give them a whole lot of confidence in regressions either, which becomes the problem. The tests become sloppy, and then nobody really trusts their aggressions, especially if it’s a Ruby-developed project and the JavaScript, like nobody including myself, is probably doing a fantastic bang up job of testing their JavaScript side. So anyway, most Ruby developers. So, one of the things about Rails particularly is that Rails was not written with unit testing in mind, although it was written in with testing in mind. But one of the things about Rails is that it suggests that you can write unit tests to hit a database, which I think is a very standard thing for Rails developers to do.

SANDI: It’s very hard to decouple yourself from the database, if you put business logic in sub classes of Active Record.

NOEL: I think the way Active Record is structured, it’s very hard to decouple. In my experience, it’s very hard to decouple the database no matter where your business logic is, specifically because Active Record associations are very hard to mimic without an active database. And because of that, my experience is that there are a lot of Rails developers that have never had the experience of working in a system that has sub second unit tests. They’ve never had the experience of sitting in a small talk system and having things just like turn green when you hit the test button and there’s no discernible wait. If you’ve had my experience and your experience I think of having had that happen, and then the way that we talk about TDD is completely separate from the experience of most Rails developers…

SANDI: You and I are having a completely different conversation. And it’s probably one that across this gap people can’t even understand. Like my notion and your notion about what it should feel like to sit down and write code and test first and the lived experience of most people using Ruby on Rails is really different. Yeah, I totally agree with that. And so, it becomes a thing that is difficult to imagine if you haven’t had it. But if you’ve had it like you and me, it’s a thing I’m absolutely unwilling to do without. I don’t know how I would write code. It seems insane. It seems costly and so costly as to perhaps not be worth it to write tests the other way. And that’s a state that most people are in, which is why they’re not doing TDD.

NOEL: Right. Because when I come to this and I say the way that I would approach TDD, the way that Kent, the classic XP Style, the actual execution of the tests is a footnote. It’s happening almost in the background, if not actually in the background.

SANDI: Actually in the background and under the window below the window you’re working on and they’re just running as if by magic.

NOEL: Yeah, and in a small talk environment, that actually can happen. But in a Rails environment, it’s very tricky to do that. And because of that, when you start talking about taking these small steps and running the tests after every step, my experience is that people get really skeptical about that because they see that as a huge drag because in most cases, in most Rails environments, it’s going to be a huge drag.

SANDI: When I go and teach that style as you’ve seen in 99 Bottles book, then we have to have a long conversation after. The thing I tell people because their initial reaction is like, “We can’t do this.” And I have to say, “I know you can. First I want you to want it. I want you to see the power and the freedom of writing code using this style because I know it means changing how you write code. You’re going to have to nibble away at your current code base to gradually shape things from the way they are to the way they could be if you are going to have this sort of initial safety net instead of the sort of crappy post code safety net.”

But yeah, it’s really two lessons. One is how to do it, which is a thing people don’t know. My experience is that people are familiar with the word refactoring but they can’t tell you the name of three refactoring recipes. The global ideas are out there, but the people are generally unaware of how specific you can get with those techniques. And so, there’s a whole body of skills that most folks don’t have or a full body of ideas that people don’t really know exist that would prevent them from doing it anyway. Because right now, the state of the world in programming as far as I can see it is that, this is how we work. Somebody tells me something to do and I go and I find some place in the code that does something like it and I sit and I try to imagine what code I would have to write in order to do it. And then I throw all the pickup sticks up and make all the changes that I need. And then I try to get the test run when I’m done. And that’s a very inefficient way to write code. But it’s what we’ve taught people. It’s what they learn in school. It’s what their peers teach them. And I find when I go try to teach people to do TDD and to do refactoring style of TDD, they find it almost impossible to just try a one-line change out. People will sit with their hands near their keyboards and try to imagine a solution to the whole problem rather than make a single line change that they think is a step in the right direction that might keep the test running green. There’s no process that we know. All of us programmers feel like we have to sit and solve the whole problem in our heads and then we write it down. That’s the way programming works when I go look at it. And it means I have to be able to hold the whole problem in my head and write it all down and get everything to work before anything works. And that can be really hard.

NOEL: Right. And that was always one of the benefits of TDD specifically for me was that it really minimized the number of things I had to care about at a time.

SANDI: Yes.

NOEL: In a way that was really valuable to me, and that is sometimes hard to like rework myself into.

SANDI: I’m a little worried that people are going to listen to this and think the whole conversation was about TDD.

NOEL: I’m a little worried that people are going to listen to this and think we’re just cranky people talking about [crosstalk] today.

SANDI: Here’s the thing, TDD is good. I mean, what is the meta thing here? I learned things because I heard that people who were smarter than I thought they were good ideas. I’ve learned refactoring because of that. I learned TDD because of that. And then I was really bad at all the new things I tried when I first tried them. Attempting to do TDD made my goad velocity drop to zero. And so, there’s a way in which everything that we’ve learned, we learned sort of by accident and then we turned it up to [11]. People tell me, “Don’t talk to people about patterns because they’ll overuse them.” What do you expect them to do?

NOEL: The only way to find the edge of a technique is to overuse it.

SANDI: Yeah, I totally agree.

NOEL: A useful step towards figuring out when a technique is appropriate is trying it in places where it’s not appropriate.

SANDI: Every time I give a talk, people will come to me afterwards and say, “You shouldn’t tell people about because they will overuse it.” And that seems insane to me. It’s like, of course they will. I did. We’re not going to deny them the right to learn the same way we learned. That’s crazy talk. Now I’m wishing we had a theme. What has the theme of today been? Not cranky people, not cranky old programmers.

NOEL: Well, you’ve got a few minutes here. What do you want the theme to be? We got a couple of minutes.

SANDI: It feels like when you and I talk, the theme always turns into about teaching and knowledge sharing. Now, I want to ask you a really big question that’s probably too big for the time we have remaining.

NOEL: Go ahead.

SANDI: What ought we be doing as a community? Either we’re right and these ideas would help if other people knew them. And yet they don’t. And it’s very hard to get this information. Should they have to suffer 30 or 40 years of pain?

NOEL: The short answer is I don’t know and we’re out of time.

SANDI: Cheater.

NOEL: I actually don’t know. I definitely have gone through, and maybe not completely gone through certainly in the wake of like the ‘TDD is dead’ conversation. A lot of thought about what I had and hadn’t done to contribute to the ideas that made TDD painful to people, and started to think about how to do a better job of explaining it. Whether I came down to useful conclusions, I don’t know. But certainly a thought that I had was that it was a failure of like the TDD advocates to make their case effectively.

SANDI: Yes, agree.

NOEL: Sorry, I don’t want to keep pulling this TTD, but that’s my knowledge transfer.

SANDI: I mean, it’s a whole thing about like it is – here’s a thing. This is a conversation I’ve had with a bunch of people. Is TDD a bad idea or you’re just bad at TDD?

NOEL: Or is TDD so hard that it only becomes a good idea if you’re really, really good at it?

SANDI: I don’t think it’s hard. There is a way in which you can infer that it’s hard because it was so hard for all of us. Yet now, it seems simple to me. Does it not seem simple to you now?

NOEL: It seems simple to me on a wide range of problems and complicated demand has slightly large different set of problems.

SANDI: Yeah. Okay.

NOEL: If it’s like an algorithm where there’s input and output, then I find TDD very easy to do on it. If it is something where there’s more of a display component and it’s harder to say what the right output is, then I find TDD can be challenging.

SANDI: If I’m following a refactoring recipe, I don’t TDD it. Those recipes work. I might put some post hoc tests around them to explain to other people what it does to solve the communication problem. But if I’m going step by step through a recipe, I have so much confidence that those recipes work that it feels like it makes it more complicated to write the code, to TDD it. But there’s plenty of times…

NOEL: I don’t know. So what do you do as a teacher and as a coach? What’s your answer to that question? What should we be doing?

SANDI: As a coach or a teacher, my job is to give people very explicit concrete advice about what to do, not hand-wavy ideas. But here’s the thing, when you see this, you test it this way. When you see that, you test it this way. And to give them a very small number of when you seize so that they can do the right thing. So, I set up problems that forced them to write the kind of – I tell them how, “There’s like six categories of things you might test,” and then I set up problems so that they have to choose what category the thing they might test is in and go test it. And that every rule is meant to be broken. They can break them all later once they get some experience doing the very sort of straight forward initial things. I gave a talk about testing a couple of years ago and it was really right out of the chapter in POODR that’s about testing, which I was very uncertain about writing because I’m not that testing guy. That chapter and that talk, the talk that came from it, probably I get more feedback about those two things than anything in POODR. And it’s because it’s a sign that people are really suffering for how to think about doing TDD. I don’t know. We should shut up about it because it’s not worth it or we should make it more clear how to do it in a way that’s worthwhile.

NOEL: That seems like a good outnote. Sandi, if people want to talk to you more or see other things that you’ve done, where can they go to find you online?

SANDI: You could go to my website: sandimetz.com. If you just Google my name, I have a bazillion talks. They’re all on like YouTube or Vimeo or something like that. You can find many of these things out there. I’m also on Twitter at @sandimetz and I sometimes actually look at Twitter. So, there’s some small chance that…

NOEL: [Laughs]

SANDI: Can’t spend too much time there.

NOEL: Sandi, thank you so much for being on the show. I’m really glad to finally get a chance to talk to you again and hopefully, I will see you around soon.

SANDI: It was a pleasure, Noel.

NOEL: Tech Done Right is available on the web at TechDoneRight.io where you can learn more about our guests and comment on our episodes. Find us wherever you listen to podcasts. And if you like the show, tell a friend or your social media network, or your friend’s social media network, or your pet, or your boss. Or tell me, I really like it when people tell me they like the podcast. Also, leave a review on Apple Podcast, that can people find the show.

Tech Done Right is hosted by me, Noel Rappin. Our editor is Mandy Moore. You can find us on Twitter @NoelRap and @TheRubyRep.

Tech Done Right is produced by Table XI. Table XI is a custom design and software company in Chicago. We’ve been named one of Inc. Magazine’s Best Workplaces and we’re a top-rated custom software development company on clutch.co. You can learn more about working with us or working for Table XI at TableXI.com or follow us on Twitter @TableXI. We’ll be back in a couple of weeks with the next episode of Tech Done Right.


Subscribe to the Dynamic Rubyist Newsletter

Subscribe to the blog via RSS

RSS Feed