Join author Christian Clausen as he goes through key topics from the book together with Kevlin Henney. "Five Lines of Code is a fresh look at refactoring for developers of all skill levels. In it, you’ll master author Christian Clausen’s innovative approach, learning concrete rules to get any method down to five lines—or less! You’ll learn when to refactor, specific refactoring patterns that apply to most common problems, and characteristics of code that should be deleted altogether." – © Book description by Manning
Five Lines of Code is a fresh look at refactoring for developers of all skill levels. In it, you’ll master author Christian Clausen’s innovative approach, learning concrete rules to get any method down to five lines—or less! You’ll learn when to refactor, specific refactoring patterns that apply to most common problems, and characteristics of code that should be deleted altogether.
Book description by Manning.
Kevlin Henney: A good morning or good afternoon or good evening, depending on wherever you are and whenever you're listening to this. My name is Kevlin Henney, I'm here doing a GOTO Book Club, and the book that we're going to explore and we're gonna go further than just the core book, we want to explore the world around it as well, is by Christian Clausen and it is "Five Lines of Code." And I'm gonna say, books with hard coded numbers in their title is something that I'm familiar with, as the editor of "97 Things Every Programmer Should Know," and "97 Things Every Java Programmer Should Know." And the goal of the book, just kind of a subtitle on the cover, how and when to refactor. This is a topic close to my heart and one of the reasons I was very keen to talk to Christian about this. Christian, hello.
Christian Clausen: Hello, Kevlin. Thank you for that introduction.
Kevlin Henney: Let's talk about this one. There's a lot going on here. This book was published two years ago at the time of recording, we're in 2023, year of publication is 2021. Kind of right in the pandemic. We'll get to that one in a moment. I'm presuming it was written mostly over the pandemic. But I suspect this origin story goes far further back. Christian, if you could just tell us a little bit about, you, what you do, and then we'll dig into where did this book come from?
From Teenage Programmer to Agile Guru
Christian Clausen: Sure. After university, or during university, I used to study programming. I've always loved programming, I learned programming at a very young age, and it was sort of the way that I explored the world was automating things and building these little prototypes. And when I got to the teenage years, I started selling these small website solutions that you could do back in the day. Now, of course, the CMS systems are too good to write your own. But back then, we could still do it. During university, I got more and more into this programming thing and how can we make code easier to work with. Is there, like, such a thing as perfect code that never breaks and never...like that's so resilient to change? And I also...the other thing I really loved was teaching and working with people. And obviously, those two go hand in hand because humans build the software, so you need to understand how humans think and build and make mistakes, and then also how the programs make mistakes or what computers are vulnerable to.
And I used to do a lot of teaching during university. I used to host a talk two hours every Friday for 60 weeks in a row or something like that on different topics. And after I was done, I went into consulting and did hands-on solutions for big industry customers and stuff, where the systems ranged from doing a small plugin to some big, huge system or writing, the entire architecture of a multi-million line code base. And I started thinking about when the code bases grew too large for one person to fix, I started thinking about how can I get my team go in the right direction without having to give them the whole five years education I've had in programming theory.
I started trying to, fake it till you make it kind of, dress for the job you want. I was like, "Here's a rule, it's super easy to understand, just do this, it'll be better than before. It might not be perfect, but it will go in the right direction." And I've fully embraced this agile way of living where I only think about the next step in the right direction, and then we'll adjust from there. That was sort of the thing, I started coming up with a few rules and stuff. And eventually, I had this catalog of small rules that sort of helped each other and build on each other, and I knew that it was something really important or it really useful because the improvements we saw were real. I decided to write them down, and then compile them into a set of things, a small catalog of 100 pages in the beginning.
Unleashing the Power of Small
Kevlin Henney: That's where it grew from. And to hint at something that you're describing, so you're talking about the small things, the small stuff matters. That idea that, we build big systems, big systems are built out of smaller pieces, and those are built out of smaller pieces still. Therefore, the small stuff matters. What's interesting about the way that you present the refactorings in the book is I think, one, is a general observation and one is an observation from, I say, the 2020s. First of all, the general observation, my first proper introduction to refactoring was around the XP era, Martin Fowler's refactoring book, that's kind of helped popularize it, brought it to the surface, if you like, as a first-class practice.
And Martin's first edition book and then the second edition, they deal with kind of like a middle range, a range that many people who tend to think about and talk about design patterns be very comfortable with. But also, we head into the code but often with bigger implications. It feels like your book kind of picks up...it overlaps with some of this kind of the more fine-grained things. For example, switches into polymorphism. That's a kind of a classic, where you start with a little piece of control flow and end up with a changed structure that is first-class visible to anybody opening the file. But you also go into much more detail that kind of in some ways picks up where Martin left off. You're dealing with, I don't know, the small change, if you like, rather than the bigger amounts.
Christian Clausen: It feels like or it felt like to me...I'd read, obviously, the "Gang of Four" book, and then right when I got it, actually, I was super excited because it was a book referred by everyone and I was super awestruck. And then I showed it to one of my professors and he's like, "Oh, that's not the one you should be reading, you should be reading Martin Fowler's book instead." I went home and order Martin Fowler's book, and it changed my life completely. It was like this idea that instead of trying to figure out everything from the start, you instead do this small, incremental work on a codebase and you start from a mess.
And I'm like, "Obviously, this is way more applicable because I always have a mess." Whether I start from something somebody else built or something I built six months ago, it's always a mess. It's way more stable to be able to handle that. But then I started realizing as I was talking with people and seeing people in the real world that the smells were sort of the unexplained sort of thing. Where do you get started with the smells? That was the next, frontier.
Kevlin Henney: I think there's a couple of things. First of all, let me just jump back from that to that idea, the second idea, the perspective from the 2020s. Now, many people are now more familiar with refactoring. It's now in people's vocabulary, possibly to the point that they overuse it sometimes just to mean, "I'm changing something," and it's strictly not a refactoring in the sense of preserving existing behavior. But when Martin's book came out, he was building on a whole movement there that had kind of been growing. And he kind of categorized it, cataloged it, presented it in a way, and he was a popular author, really nicely presented, it's just like you're going through and go, "Oh, okay, this is what people mean when they talk about incremental development, this is how they talk about iterations, everything else fell too big."
But what I find interesting is that a lot of people now assume this is a solved problem, because we have tools which have automated refactorings. And, I mean, obviously, that's not a solved problem. What I find is that people have all of those issues in their code that, honestly, they had 20 years ago, that hasn't changed. They've just now got a tool that they don't use. But also, your book actually gives people the raw recipes and low-level ingredients, and just saying, "Don't worry about the tools, I'm going to show you what this is, just imagine the only tool you have is a compiler." Now, I like that approach. What inspires you to kind of pursue that one? Because it goes back to this idea of detail, doesn't it?
The Power of Effective Programming
Christian Clausen: I guess, obviously, I started coding back before I knew IDs were a thing. I coded in straight notepad, no ++, no fancy things, just save the file and edit the file, you have to do your own line breaks and no syntax highlighting. I got all these very hard habits or hard-learned habits where it's like I always put the end parenthesis when I put the beginning parentheses because, otherwise, I'm going to have to sit down and count them. There was no highlighting, right? All of these things that I'm hoping people don't deal with when they learn programming nowadays, but I learned all of these things.
And also debugging with just printf instead of using a complicated debugger with all of these extra things, it's always been about sort of the purity of, like, "What's the least amount of things I need to learn to be able to work effectively?" And then learn those really well. Like, I always advocate people learn Git, for instance. We all have Git somewhere in our stack. Learn it, like, use it. It's a super powerful tool. I always advocate learning fewer things better, at least in a professional setting. It's like I would really go that way.
And it's very much that you are looking to get that message out and you're going to choose that common subset. You're not going to rely on somebody working with just, say, " I'm assuming that you are working with IntelliJ and that you're doing this, so therefore, I'm going to lean on that." You're just saying, "No, here is what's happening to the code, and perhaps you can automate it, but let me just show you the real deal."
The Pitfalls of Automation
Christian Clausen: And it comes especially out when it's talking about something like renaming something or extracting a method. Whenever people have looked in the book, they're like, "Why do you do this by hand? Why don't you just use the automated tool, the ID, to do something like this?" And I'm like, "If you feel comfortable with that, that's fine, I don't mind. But I really want to be able to do it without the tool." Right? If I find myself in a situation where I'm in a new team, for instance, a new organization, but they don't use the same editor, I don't want to have to rely on a tool that isn't necessarily there. Fewer dependencies.
Kevlin Henney: Fewer dependencies is a really good point and that idea of having a portable skill.If you've got a tool that does it, reach for it. But if you don't, you still know how to do it. You're not without that. But I also think that having...in fact, you pick on rename, which I think is probably the most common refactoring that people apply. But if you ask them, "How would you do it if you didn't have an automated refactoring?" They probably wouldn't know. And what you're describing...and you actually go through the mechanics of it, in a way that I found very comfortable. But also, if somebody's just doing something with a scripting language that doesn't have any ID support, they're just messing about, actually, they can still do this, which I think is quite nice. This is very much like that kind of like minimal toolset.
Christian Clausen: I remember having to do some of these renamings in languages that weren't compiled, and I would do it with Search and Replace, right, because it's a big codebase, maybe a few thousand lines, it's too much for me to read by hand. Search and replace, and of course, what happens then? You break something else because that name was part of another name somewhere else in the codebase that you didn't...? It seems like a trivial thing but it can go wrong, so can automated refactoring tools, by the way, also, which also scared me off because I was using Eclipse a lot back 10-15 years ago.
And I had the Save actions to just auto format, auto make everything nice whenever I saved. And then one day, I hit save, and it put in all of the line breaks after the if before the parenthesis or it should have. Instead, what it did was it moved it to just one character to the left everywhere.Instead of if, it was now "i space if" and then parenthesis, so the whole codebase was corrupted. It was horrible. Tools can help you fast, but they can also break things very fast.
Kevlin Henney: I think that idea that it's that idea of they allow us to amplify the speed at which we can get things wrong. They allow us to amplify the speed at which we can get things right, but there's the other side to it as well, I think, that's quite important.
Strategic Copying: Maximizing Codebase Agility
Christian Clausen: And that's super important, actually, also for the book because it's something that I often discuss with people. Whenever they say, "You copy code so much, why do you do that? Why don't you just...what about dry? What about this stuff? What about unifying everything?" And I'm like, "Well, whenever you unify things, you can now change twice as much code in the same time, right?" Virtually, you're gearing up your codebase for faster change. And if you're in an environment where you have good test coverage, you have good types or formal proofs or whatever you have, sure, you can do that. Just gear it up as much as you want to, and then just go really, really fast. But for a lot of people where test coverage is a problem, it might not be a good idea to be able to change twice as much code very quickly. Maybe you want to change it a little bit slower, right? I'm really...I've been fighting a lot to make dry sort of a conscious decision instead of just a catch-all, "Everything should be dry."
Kevlin Henney: That was something for those of you listening who have not come across the book, the book goes through a number of different examples. It's got one core example through the first part, but it also has some side quests thrown in. And the transformations, typically left to right page, are shown before and after, which is nice...which makes it very easy for direct comparison. But also you get that progression over time and you notice the copy. And I was actually quite glad of this because I did a talk recently where I found, exactly as you're describing, I had to have a whole couple of slides justifying why, and the talk was on a refactoring.
And I went and duplicated a whole bunch of stuff in order ultimately to cook it down to eliminate it, but it's kind of the whole idea of like, "If I'm going to tidy my room, I don't immediately put things in other rooms, I don't immediately extract. What I do is I kind of put the whole mess in the middle of the floor. Now I can see what I need to tidy, I can shuffle things around. Now, I can classify, I see it all in one place." And in code, some of that is throw things into a method until it gets painful but more obvious, you see the patterns. But the other thing is copying. That's one of the things that we do. And it's just like there's a benefit to that.
Once you've added that, the stuff works. If it's not doing anything extra, then it works, and now you can start knocking out the bits with diligence and care by inspection. It was nice to see that made first class because I don't think that's...when other people talk refactoring, I don't tend to see them...no, they say it sometimes, but they don't show it and I think there's a difference. And as you say, people are noticing it. And that idea that perhaps dry is what you want, at the end of the day, when you put your clothes on, but while you're washing your clothes, it doesn't have to be dry, it can be as wet as anything.
Christian Clausen: That's a very nice way of putting it. I think also something that people miss is whenever you try...if you try to do some of these refactorings or some of these major changes to code that is shared by multiple things, you're gonna have to do everything a little bit slower because you have to check, "Did I break either of the places? Did I consider..." Like, you're putting more stuff into the head of the developer, which is the opposite of what I'm trying to do. And I'm trying to make it simpler, to make it easier to do these things and to make it safer. By duplicating something, "I'm not going to do side effects, I'm not going to affect anything that isn't in front of me right now."
You can go a little bit faster and you can do a little bit more reckless things, and then it's easier to revert it. If you've already started unifying it, you have to mess about with a bunch of stuff. And again, if you're good at using your Git history, then maybe you can get back fast if you need to roll it back. But if not, you're just totally screwed.
The Art of Doing One Thing at a Time
Christian Clausen:It ties into another thing I wanted to mention in the book but I ended up cutting it. It was in the initial plans was a chapter called "Do one thing at a time." Because I see so many people just stacking on extra thing, taking on extra things while they're working, and during a refactoring, that refactoring could get really complex. If you get distracted and do something else in the middle, it's gonna go wrong. Both things are gonna go wrong, probably.
Kevlin Henney: That was something else I noticed that it was actually more visible in the second part of the book where you kind of pull back and zoom out, kind of look at slightly the bigger picture, the implications, more about working with other teams, diving into some of the coding habits, talking a bit more about architecture, a bit more about the whys and the wherefores, and tackling various topics, including threading, which we know TypeScript doesn't support but you're there going like, "Here's how to think about this stuff." You also touch on a lot of workflow things. Although you didn't end up with that chapter, I think I was really interested that you actually went much further into the workflow than I initially expected.
It was kind of hinted at in the first part of the book. You talked a lot more about...and this idea of doing one thing at a time, I think, is, curiously, one of the hardest things for us to do and it perhaps needs to be made more explicit. I think that's what...it is a thing, it's like people go like, " I'm going to fork across all of these things. I have 10 things I could be doing. Rather than doing them one at a time, I will start all of them simultaneously." And then each one of those, kind of like a hydra, springs up a couple more things that you hadn't accounted for and as you say, you end up with you're not doing one thing well, you're doing two things really badly. And that's such a common thing. I'm presuming that's something you see but I think it's interesting. Apart from just recommending that people do one thing at a time, what do you think the bigger impact is across large code bases of not doing one thing at a time?
Christian Clausen: First of all, I think when you're doing something and you're deep into changing something, making something more readable, whatever you're doing with the code, and you didn't notice something else that's broken or something else you could be fixing or something that's really ugly or whatever it is you want to do, and you start fixing that, you'll be doing that while retaining the momentum of the thing you were doing. It will sort of put you in a frame of mind of, "Now we have sort of two things," and your brain will force them or try to force them to be the same sort of thing or one coherent thing and you'll struggle either to make a red sort of line between those or you'll find one and then you might see this thing in a completely different light.
It gets really weird. When you start unifying or when you start...also, sometimes, it's the same with DRY, right? If you try to unify things that coincidentally look similar, these will now have to have a method name like something-handler or something-general, and I know you hate suffixes that don't mean anything, but that's how you end up with them, right? It's because you are in a case where it's so general, you don't know where to go, right? There is no connection between these things, but you're trying to force it onto them. It actually gets worse than just having two copies.
Kevlin Henney: There's something really subtle in what you're describing that I think deserves to be brought out, because you're saying, you're effectively...accidentally, you can end up projecting an opinion, an accidental momentary opinion onto the code, rather than the deliberate approach that you take in the book of trying to, as it were, find the design, sense the code, kind of feel your way through it, and as it were, figure out what does it want to be as opposed to what am I going to impose on it.
And I think we're very...it's exactly as you described, it's very easy to just kind of go with something and go like, "I'm going to push this onto the code and it will fit this shape," and I don't know that I'm forcing it into a shape that it doesn't want to be and I don't know that I am driving together things that are coincidentally similar but have no deeper meaning. And then I'm left with this thing or this imposition rather than that slowness that you talked about of like, "Let's just feel our way," it's just like, "Make sure we don't break things, but feel our way, find out what the code wants to be."
Christian Clausen: And the "make sure we don't break things" is also super important because what I learned from the industry and from bitter experience is the code that's running in production works right now, right? It's running. That's what they have now. It might be wrong, it might have errors in it, but it is at least good enough to run right now. I really, really strive towards having people just follow the thing it's already doing. If you don't know that it's wrong, don't question it right now, right? You can fix something after. Also, fixing wouldn't be a refactoring anyway. But, like, it already has some structure, it's doing something. Make that structure appear, make that more clear what it's doing right now, more so than what you can imagine it will do in two years or in three years because we might bet wrong. Actually, we usually bet wrong when we try to go far out in front of us.
Is Automating Refactoring a Mistake?
Kevlin Henney: That sensing approach...and again, let's go back to that idea of senses. I mean, senses, we use sensors all over the place very figuratively and smells being the one that we often gravitate towards when we talk about refactorings. And you highlighted this issue that for some people, that's actually more of an obstacle that there is and I was thinking when you said that in the book, I was thinking, "There's a kind of a notion of to have a refined sense of smell, you don't get it for free." You've got to learn how to do this, whether it is the kind of the aroma of a perfume, the bouquet of wine. Or if anybody's seen the film, "Ratatouille," you've got one rat there that has an incredible sense of smell, very sophisticated, the other rats don't have it, and he's trying to educate the other rats and it's hard work.
And that's kind of the issue here is that smell, although a very potentially potent metaphor, there's a lot of learning there. If you're trying to get to the simpler message of refactoring, there's a lot of refinement that you have to do to be able to...from a standing start. And that's the goal of the book is pretty much to take...that's what it felt like, to take people who perhaps hear this word thrown around, refactoring. They see the shortcut key, they know how to do a rename maybe, they know a couple of other things, but it's not in their spine. It's something Joe Armstrong used to say, "You just got to program your spine so that it becomes automated." They don't think in those terms. And throwing smells in is perhaps simpler for some people, but for a lot of people, it's actually the obstacle. And that I find really interesting, I don't think I've come across anybody else point that one out and I think you're right.
Christian Clausen: I think the thing that I saw was that many programmers like knowing what to do when they get a task? It's nice and it's comforting to be like, "Oh, you have to do this, this, and this," or, "You have to solve this problem." "Okay, fine, I can maybe write a test," or at least I can imagine what I wanted to do when I'm done with this thing. But when it's like, "Make this code better," people always almost get scared because like, "What if I make it better in a way that the rest of the team don't agree with?" Like, what if I do something wrong? What if there is no universal truth here?"
And also, what I advocate more than anything is that your team sits down and has a conversation about where do you want this code to go and how do you want to get there? If you don't have anything else, then I recommend, obviously, starting from the rules that I've come up with because they seem fairly solid. But I'm not religious about them. They're not lost. They're a starting point for collaboration more than anything, right? So that people can get started and feel comfortable. We should feel comfortable going to work. Working with code should be a nice experience, and it can be, but it isn't for a lot of people and that's sort of the fundamental pain that I try to alleviate.
Kevlin Henney: And I think actually, it's something else, there is...as you sort of said, "What if I want to make the code, better in a way that other people don't agree with it?" I think the secret fear probably many of us have is, "What if I don't know how to make it better? What if what I think is better is actually worse?" It's that kind of imposter syndrome, there's a fear there, that I think many people hold themselves back. And this kind of speaks to this idea of..., first of all, picking up on what you were saying earlier about teaching and communication, but also what you've just said, very much this kind of more communal approach to programming and socialization of code. It's just like, "Make sure that we're all happy and comfortable with it."
This very much speaks to the human dimension and I find it interesting that there's a really nice connection here between the detail mechanisms, the kind of recipe-like approach that is offered in the book, but also kind of there's a lot of stuff on other people and this is really important. I think it's very often overlooked and perhaps because many people in their minds already put refactoring in the...it's a technical tool corner rather than actually it's a people thing corner. And that, I'm more...I'm interested to hear what your thoughts are on this because I think this is probably one of the more interesting areas that is overlooked in refactoring.
Christian Clausen:Sure, it's also the reason why I think automating refactoring is a mistake is that it's a human discipline. It's like saying, "Text is a solved problem." It has to be read by humans, and if a human has to convey...or wants to convey something, some intention, or some feeling, or something like that, it needs to be a human with us with a lot of different skills, actually, in grammar and syntax and stuff like that to get that out, and metaphors and knowledge about the domain and what the common knowledge of the two people or multiple people interacting is. All of these are not things that you can automate. I think, actually, it will be one of the last barriers of AI and of all these tools will be the highly social aspect of this because it doesn't...you can't code yourself out of that situation where two humans tried to share some sentiment or some emotion in some way.
And I think code is the same. Code is trying to model some part of reality in a language that both the computer can understand and then humans can work with. We have to take it down to the lowest common denominator of computer and human. Maybe you could think of AI as sort of removing the human part of that equation and the lowest denominator is now just a bunch of random if statements and weights on neural nodes, I don't know, something like that. But for most programmers, they still work in a lowest common denominator between human and computer. That means you need a human to go in and explain some of the intentions to the other humans or themselves later with good naming and with good structure in the code and a good architecture that makes errors harder to make instead of...you know? And that communicates an intention behind some of the things, "Why are these things grouped? Why are they not grouped?" More likely.
Kevlin Henney: And that notion...again, going back to the sensing of the code, these things want to be grouped. Sometimes you kind of look at stuff and you'd start looking at things and you go...you move things around, and it's very much, "These clearly want to be together," or, "These clearly don't belong together," whichever conclusion we reach about whatever we're talking about and sensing our way through it. There's a lot here very much about this idea that the workflow is not simply a mechanical thing, it's a cognitive thing, it's a message between people.
And there are a number of points in the book, you are kind of keen to emphasize,, "Hey, I want to pay a programmer or ensemble a program on this." And although that's not what the book is about, it connects really strongly to that, which it kind of suggests, again, that the refactoring message is very much about our collective understanding and refining. It's not just for the runtime of the code. The idea is that collectively as a team, we are learning what's there.
Christian Clausen: You're modeling the domain and you'll learn more about the domain and you'll learn more about computers with most projects also, apparently. It's like things always fail in new and interesting ways as you also famously mentioned a lot of times. And revealing new structure, either about sort of the language or the thing you're implementing the model in or something new about your model that you didn't anticipate. We're learning constantly. The trick is...I think refactoring to me is a lot like deformatting your computer, right? If you just learn stuff all the time, you put all these little pieces back-to-back in your head, and then sometimes you invalidate some learning and you forget something. You create all these holes. Sometimes you need to go in and just collect all of it, tie a nice bow around it, and be like, "Okay, this is the current truth." You're removing all this gunk and you're making it nice again. It will invalidate over time, all software does.
Kevlin Henney: And I think, again, the idea that this is ongoing, again, just to fit back to a smaller detail, is very much...as you're talking about with copying, it's a transient state. It's just like, "It's fine not to have this little bit of duplication here, it's a temporary measure." Everything is about change and the idea that you're not going to reach a final state unless until somebody decommissioned the software, there is no final state. You will naturally always end up in the flow. There will always be some bad code, but that doesn't mean there can't be better code. There will always be some duplicate code and some of that will be accidental, but some of it will be quite intentional.
It's just like, "This is only a duplicate for a moment, this is fine." We're on route, that's absolutely fine, that this state of change is a normal thing. You're not actually looking for a...in fact, this book is very much the opposite of books that I certainly read 30 years ago, looking back to kind of like the earlier design books, which were very much about, "Okay, we're going to reach a state of perfection before we've even built it. "The book goes the opposite way. It's very much embracing the idea of like, " Stuff happens, and not only that, but it continues to happen and you won't stop it happening. Here's how to ride the wave rather than pretend there are no waves."
Christian Clausen: And I actually write my own code and build my own systems in that way too where the most recent code, I just write it one pass without thinking about it. No nice styles, no design patterns, just get it out any way you can make it work, put it into production, see what happens to it, how it's used if it's used at all. If it's not used at all, it's easy, delete it. If it's used, then you can go back and fix it? Once you have some experience about, "What changes did I need to make?" Like, when you do something new, you have no idea what the structure should be of that thing. You can do sort of guests and you can sort of do these things. But for most of us, those guesses are not great. And whenever it meets real users, it's going to have to change in some weird ways. Communication is hard.
Communication is Hard, Do it more often
Kevlin Henney: You've highlighted a number of cases, that kind of DevOps mantra, "If something is hard, do more of it, do it more frequently." And that, I think, probably applies to communication. I think perhaps in software development, we become very good at erecting barriers to communication, whereas your book is very much about, "No, let's do more of this." It's not simply about refactoring and touching the code, it's this idea of, "Whether it's naming or structuring or articulating what the goal of a piece of code is, that's hard, therefore, do it more."
Christian Clausen: For the longest time, while I've been a DevOps consultant, I used to explain it to executives and management, DevOps is a commitment that whenever you have a problem, your first thing is to ask, "Which two people or multiple people can I put in the same room so this problem will just go away?" Because whenever people get together, they solve problems. Like, that's our entire job is solving problems. If you have all of the right access code you need and, all the right skills and competencies and you're allowed to explore this thing and to go to another team and say, "Hi, we need someone in the room right now," you're gonna solve all the problems.
The worst debugging tasks I've ever had were the ones where I was told, "Something in this code doesn't work," and I'm like, "Okay, who reported it?" "Some user." "Okay, well, it has to do with the database and an integration to a third-party thing, can I get...like, I need some people from there." "No, you can't interrupt those, those are busy." And I'm like, "Perhaps, but, like, it's gonna take me 10 times as long if I have to go and ask them each question instead of just sitting in the same room and take 10 minutes and then we're done."
Kevlin Henney: Again, it's a communication thing. It's the bringing people together thing and, having people understand that that's actually what drives this. It's this really strong kind of human element. But I think one of the recognitions of the human element, and you highlight it in the book, is this idea of it's not enough. And actually, you highlight it in the talk as well in GOTO Copenhagen last year. This idea that you can't simply present people...although you have a series of rules, you've distilled it down to a series of rules, it's not simply enough to present people with these.
Overcoming Barriers in Software Development
Otherwise, this problem would have been solved and we'd all just be sitting there and be like, "Read Martin Fowler's refactoring book, and that's it, that's everything you need to know. Here is information, here are facts, go forward and create good systems." Just as providing everybody with automated refactoring, again, that doesn't seem to move the needle far enough. How did you come to realize because you have a background and outlook that is, I think, in some ways, very similar to mine and other developers that it's a case of there's a little rational view that says, "All I need is the right information and suddenly everything will work."
And then one day, you hit a wall or a series of walls and you go, "Wait a minute, everybody has the information they need, we've said this, why do we still have the problem? Perhaps we're not as rational as we thought we were." What's your journey been on this one? Because I think that's one of the really interesting ones because I think that was ultimately the cause of writing the book, wasn't it?
Christian Clausen:It comes from this. I've always tried to follow these strict guides or guidelines and stuff as if they were rules. Like the smells and stuff like that, try to really internalize and be like, "Okay, what is the actual truth?" I'm really into distilling things into these little tiny pieces of information that are super deep and condensed, and then you need weeks to sort of understand or sometimes years. And I was thinking about this thing, "Why do we always come up with these bad names and all these horrible things? And code always seems to tend to get more and more dilute over time?" And eventually, I started realizing this thing, it's because we tried to try to unify things too early and stuff.
And that gives all of these bad namings we've talked about, it gives this abstraction...it makes everything sort of a flat hierarchy, where you have one file with a main method that calls another method, and then it's just big methods one after the other in some large sequence or sometimes packed into a loop or two. But the control flow is entirely obscured through this, I don't know, attempt to unify everything immediately, and do the right thing the first time. And whenever we do that and try to take a too-big bite, it's just like, "This doesn't work." And then at university, I learned functional programming and I was like, "This is amazing, I do the opposite of what I would do in an OO language because I make these tiny little functions that are just a few lines big," right?
One match and then a recursive call and you have those recursives or most functional methods are just like that, and then you just compose them together in some weird chain and you're like, "Here it is, your program is just the composition of these five standard library things, so it would be an Haskell." It's such a weird style and it has all of these weird effects, and I was like, "Why does functional programming not have errors in it when the same program written in OO would have a bunch of errors in it?" And just reflecting over this, "What is the difference? And if we know that functional programming has fewer errors and is not, like, significantly slower anymore, why do people not use it? Like, what's the reason people haven't switched?" And I find, again, of course, there are some mental barriers there, you have to learn a lot of stuff for functional programming.
It seems a lot of people have tried to move people towards a more functional style and try to explain, "Here's FP for OO people, and here's these things," really good books, also really good blog posts, it just hasn't moved the needle, as you say. It's hard to figure out.I started thinking, "How can I get the same advantages that I would in a functional language in OO and then, started getting these?" That's sort of my design principle is, "How would I write this in functional programming? How would it not be vulnerable to the same things?" Or, "Why is it not vulnerable and can I sort of replicate that or simulate it?"
TypeScript, getters and setters, code quality and code visibility
Kevlin Henney: In the book, you use TypeScript, and you very much kind of focus on resolving in the object dimension through the use of classes and interfaces, many of the things, depending on the language. But as you mentioned, Haskell, many people in the functional space would more naturally revert to a pattern-matched approach perhaps to resolve that rather than, say, kind of inclusion polymorphism. But you mentioned in a few places, I noticed, in the book of not just the discussion on getters and setters, but you talked about reducing mutability. You don't lay it on too heavily, but I kind of noticed that. I was reading the book and go, "Good, I was hoping this would appear."
Christian Clausen:Again, as you said earlier also, it's about finding a common ground with as many people as possible. I don't want to be scary in any way. And as I said, if you feel comfortable with it, feel free to do all of these things, that's fine. I also note in the final chapter that a lot of the objects that we've created could be replaced by a lambda, and then you'd save a little bit of space because you don't need the interface to be implicit in the signature of the parameter or something like that. That's fine, I don't mind. But to me, it doesn't actually change anything whether you use lambdas or objects.
When you become fluent in the style where , you're pushing things around, you're making things small, and you're localizing the invariants, you're sort of hiding away stuff that doesn't need to be there. I would say one of the bigger steps towards FP that I took in the book is eliminate all the getters and setters. That is a big step towards functional programming for people used to OO. And I remember being super confused by getters and setters when I heard about it for the first time in introductory programming. It was like, "So you have to use these field variables and you have to make them private." I'm like, "I need to change them." "Well, easy, then you just make these public getters and setters."
And I'm like, "Why did I make it private then? What's the point?" And obviously, the historical point is that you can change the getters and setters, and then you can change the internal structure, and then the getters and setters would pick that up, right? And they would sort of hide or abstract away the changes, and they would still be invariant under change. But what happens in practice is people make new getters and setters, right? And then they propagate the change out. Then, there's no point in doing getters and setters. Like, there's a complete misunderstanding or misuse of the whole concept of...
Kevlin Henney: For me, that's the thing, and I get that conversation with many people and when they make a complaint about object orientation, they talk about the getters and setters. I said, "Well, that's not really object orientation. What do you think object orientation is about?" I was dealing with a group this morning and it was just like they had public data and all the rest of it, they had the class keyword in there. But if that's what you think objects are, I understand your pain. I can see where your pain is coming from. Object orientation was never about getters and setters. Getters and setters is what, if you like, the procedural people did when they got to objects. They said, "I don't understand objects. Tell you what? I'm going to make it much more like just, standard records and structs that I find in Pascal and C. And there we go, fine, getters and setters, we're done."
That's a massively oversimplified history, but it feels like the deeper idea of distributing your behavior across a group of entities that kind of know what they're doing and do it well and keep it small. That small message, I mean, literally small talk, the word small is in there, was kind of part of the original idea. And a lot of the original OO books were very clear on this, but that message got lost. It feels to me like your book is trying to reclaim that territory. But without sort of saying, "Hey, I went via the functional route to kind of learn the lesson of smallness," it's just like, "Hey, small is its own virtue in this case." If you can put it in your head, if you can understand it, you can change it and you can work with it.
Christian Clausen: I’m actually inspired by one of your talks where you talk about testing and structure of your test cases, and how test naming should be, that you have all these great points. The test naming doesn't need to be short because you only never call them actually, they're just used for communicating to the programmer. Make them long, and then make them something descriptive. And then you have this thing where you notice that two or multiple of your tests start with the same thing, and then you just use that thing as they're described for that portion as a suite name so to speak. I'm like, "That's exactly it," and that sort of what inspired Chapter 6, I think it is, where we do the thing where I say, "Don't have common prefixes and suffixes, they should be an outer sort of packaging thing for this thing, and then do the same thing for packages after you've done it for methods, classes, and packages."
Kevlin Henney: In fact, use that duplication as a driver for, "Oh, there's a commonality here, I should move it to the next level, I should move it out."
Christian Clausen:Exactly. These are more related than the rest of the things in this file. I can make that relation more explicit to the compiler by making it a class because it understands class, it doesn't understand method names.
Kevlin Henney: And that point, it also relates interesting enough, that idea of trying to make things more visible. I really like the bit where you're talking about, "Make bad code look bad." I like this because this is something that I've often talked about in the past. But I've never made it perhaps as explicit but the idea of like...I remember talking to somebody about both IDEs but also how they wrap something up. And I said, "I don't want this to look nice because it's really ugly and I want to know that it's a problem and I want to make sure that I see that it's a problem, and then one day, I or somebody else will recognize I understand what's going on here." There is a simple solution, but it's not hiding it under the carpet.
The idea of ‘make the bad code look bad’ so that you can obviously see that there is something that wants to be done. I don't mean you make it very clear in the book, you're not trying to trash a piece of code and go like, " I'm just gonna make a complete mess of it." But something that is not satisfactory that is clearly a long way from where it wants to be, but you don't yet recognize or have the opportunity to improve it. You go like, " I don't want this thing to look pretty, I want it to stand out for what it is, and then the more obvious we can make it, perhaps somebody will pick it up."
Christian Clausen: A lot of the things as I hope is evident in the book are about making things more immediately visible. I should be able to look at the code and know that it's wrong or know that it's good, without having to think. If I have to start up my cognitive processes, I'm not going to do it. I'm especially not going to do it because I'm super busy with the 30 other tasks that are on the backlog that we'll never even get to. I need to be able to, like, just look at it and be like, "Oh, this is better, this is good." And it also helps prevent this gradual slide over time where the code just gets...you admit a little bit worse and worse and you put some bad code here because you're super busy, you're fixing something in production, you didn't really come back to fix it. Maybe that's the new standard now, right? And then the code just slowly degrades over time.
And I'm saying put a trench there, right? Have this code that's really bad and the code that's decent, and don't make them mix. And so, as you say, to put little things that make yourself or the other programmers, like, instead of putting math.pi, put the actual number pi, because immediately, you'll be like, "Why is this number here?" It'll catch your eye immediately, "Oh, it's to signal that the rest of this thing is probably also bad." But it's easier to see it now, it's easier to spot it. I just read a really interesting article from "Harvard Business Review," where they're like, "The cognitive thing of the environment around you shapes how you make decisions," and then like, "Put bad things further away and then bring good things closer." And I'm like, "That's sort of the point I was also trying to make, make it feel annoying so you'll do something about it."
Kevlin Henney: I read the very same article. It's a good one. But it is that idea of making a distinction and that idea of separation, and as you say, actually, adding a trench so that you don't get one mixing with the other so that you can advance that over time. But also, you have a clear idea, this is the geography of the code because where you stand. Literally, you're looking at this and you go like, "Okay, I understand this code is less mature than the code over there that I was working on this morning." But I understand that and it's a conscious thing that I'm aware of and I can see the opportunities for improvement, "Perhaps this is where we move to next," or I treat it in a different way and there's a very kind of situational aspect to that.
Building Better Code with Invariants
Kevlin Henney: But I want to draw you back to something else because you kind of mentioned it a couple of times and I think it's quite important because, again, this is something that I noticed. You emphasize invariance a lot and you actually did so very early on in the book. The idea of an invariant is something that I think perhaps people who have studied logic or are very familiar with, say, programming by contract, programming proofs, and certainly, functional programming, there's this idea of an invariant, which doesn't get talked about enough in the mainstream. I kind of liked that you talk about it and make it first class.
Christian Clausen:It's very central. I think, actually, it's the first thing I actually say after the introductory chapter is, "This is what an invariant is, this is what it's all about. It's about the things that I can keep in my head and I can know about the code, but I haven't checked them explicitly in the code or in the type system or tests are something like that." It's something I have to remember and I have to keep track of, which is why, of course, it's the source of most problems is because I lose track of these things. I'm a human and I'm fallible, so I forget things over time and I misunderstand things, and again, if you mix communication in, I also miscommunicate them to other people.
It's like I may know that this thing can happen, but then I might forget to say it to the other guy because I'm thinking, "Reasonably, he won't do it." But when you do that, just six months, let's say, in a row, all these things start breaking down, falling apart. And I think also, perhaps it was you who said that assumptions are like Legos, you don't know they're there until you step on them." Same thing with invariants.
Kevlin Henney: In fact, that's what I was thinking. The way you describe invariants...because normally, people open with a formal description, but I like that idea of like, "It's the stuff that I know that I haven't told the compiler, it's not sitting in the code in code form." Maybe somebody put it in a comment but guess what? We don't read those and neither does the compiler. It's the things that we know or assume and those assumptions get lost, and other people also have different assumptions and all it takes is a collision of assumptions to get a bug. This tells us, again, another place where bugs come from, but I think it's a very important one.
And I liked that it was presented in a way that is non-threatening, non-formal because I guess I tend to think about them in very formal ways. If somebody asked me what is that, I probably start from a formal perspective. I don't think I've come up with anything that was quite as direct as basically saying, "Hey, stuff I know that I haven't told the compiler," is a very simple way of...kind of, again, it goes back to this idea of distributing the knowledge and it goes back to communication. That's a piece of knowledge that remains within my head, but it doesn't flow out to my fingertips into the keyboard to be shared with other people necessarily. And that becomes a really important idea and that's how we build, that's how we build this stuff. We either build through invariants or we build through assumptions, and I think the first one sounds a little safer.
Christian Clausen: I remember reading Dijkstra's book, "A Discipline of Programming" back when I was at university, and it was so hard to get a foothold, and when you said like, "What is an invariant? What's the least precondition we can have here?" And it's like, oh, God, the formal definition of these things and the way that he pulls them up through the method as if it's something natural to do, but it's so hard to do. And that's sort of what I'm...like, I'm trying to bring it back down to earth and be like, "You know it intuitively, like, what it is that about the code, just make them explicit or at least limit their scope." Right? So that you encapsulate these things. They're almost always tied to some data in some way. Just encapsulate the data and make sure that at least it's in this file so it's more likely you'll spot the same thing.
And actually, the common thing you mentioned is also very important, that neither us or the compilers read them. Because my approach to that, like, the thing with making bad code look better, is to make comments much less common. Because then perhaps we can get people to actually read the ones that matter and get rid of all the ones that don't, again, trying to hack this cognitive thing. Now, if you see a comment and you haven't seen one in two months, then probably you'll read it. But if you see them every day and they're mostly outcome of the code or, whatever, you start ignoring them.
Kevlin Henney: It's a value of something one of the ways we define value is in terms of scarcity, and if comments are everywhere, then they're not worth much. There's a kind of a currency, there's an economics of, if you like, of comments. I think that's very true and that a more practical way of expressing invariants or dealing with them, is this idea of locality, as you say. Because if I can put it in a block, whether that block is tied to a class, whether it's tied to a function, then I basically say, "Inside this, there's a bunch of truth, and you can see it and it's visible there." It's contained in here, it doesn't leak out, and then we can manage that." I think it's perhaps a way that people are not taught to think about their code or when they are...exactly as you say, the Dijkstra example. I've read that book, the reader has to put in a lot of work. You know? He doesn't say anything wrong, but perhaps he doesn't communicate in the way that we've been talking about.
Christian Clausen: It's one of the hardest books I've read and it's also one of the shortest, so it's amazing how much is packed into that little thing.
Kevlin Henney: I think it's a mercy that it wasn't any longer. Picking up on something else that you mentioned. You mentioned about, the cogs of a hack. In some ways, there's a lot of that in the way that you describe workflow practices, the way that you crystallize various rules, the way that you are, as it were, inviting the reader to think about certain things is that...and again obviously, the smoothness of communication is important to this, but there's something else going on here. The idea of you're trying to make sure that there is an idea that perhaps would be a lesson that would be lost if you made it more formal and more complete, that you're trying to reduce it to the size that it will slip into somebody's head, is that an accurate description?
Christian Clausen: That's exactly right, and I know you're interested in linguistics as well. I would talk about myself as a descriptive linguist and not a prescriptive linguist. I don't want to tell people what to do, I want to observe what are they actually doing and how can I take advantage of that. How can I sort of make these small things change, and then they'll do the right thing in the end, right? I want to create...as Woody Zuill says, "It's not about creating great software, it's about creating an environment where great software is inevitable." And, like, I'm just trying to hack everything around people so that they'll get where they want to go, but might not even know they want to go. As I also see from a lot of the people who are critical of the ideas, they're like, "I don't think I want to go there." It's like, "Have you been? Like, it feels nice. Maybe you should want to go there."
Into the danger
Kevlin Henney: That's very much the kind of nudge theory. It kind of moves us into that space. When thinking about all of these things, there are a number of ideas. And I think, again, this idea of trying to reframe things, there's a lot of common ways that we try and reframe things for people to make them look at code differently. But I was quite like the...you mentioned one in the book, a couple of ways of looking at things, so I hadn't thought about it. First of all, describing the kind of classic procrastination of waterfall or anything like waterfall as being like coding stage fright.
I thought that was a lovely way of putting it, definitely what I'm going to steal because I think that's just such a lovely way of looking at the whole coding stage by deliberately putting off the moment of performance as if the moment of performance is something that's only going to happen once, as if it's a big deal. And yet, we know that code is not something that happens just once and that it's as easy to change as it is...in fact, it's as easy to change as it is to not write it. And yet, we've put so much effort into not writing it and creating vast, complex technical stacks, when actually honestly, you just need a Hello World at this point. " But what about the CI/CD pipeline for this?" Honestly, you don't need a pipeline for Hello World.
The idea that if we're not lost and I think many people would be surprised or shocked by being told, "Hey, this is waterfall thinking," "No, no, this is an agile thing." It's like, honestly, you've managed to avoid writing code and creating your technical stack, you've managed to avoid, you put off actually doing even the simplest thing, or even talking to the product owner or the customer. There's clearly a fear somewhere that you need to embrace, which leads to this other improv advice that you have in the book, "Into the danger." That's a great way. Do you want to describe that for listeners? Because I thought it was just such a lovely way of pulling that one into the book in the context of programming, I never thought about that.
Christian Clausen: It started when I was at university, and I heard this fun little joke about functional programmers versus object-oriented programmers. And I just started identifying myself as a functional programmer, and then there were like, "An object-oriented programmer gets a task, sits down, autocompletes the first thousand lines, and then write the two important lines, and then they're done." But a functional programmer, he would get this task, he would sit down and he would think for three days, and then he would write down the two lines, that was the minimal program you could write, and it was perfect, right? It was just the right thing.
And I'm like, "That sounds like functional programming is slower," which might be true in some cases but it wasn't in my experience with functional programming, you know? I'm annoyed by that. I started thinking about, "What's the reason that functional programmers tend to start by thinking and not by writing code?" And it led to this talk that I gave at university where I basically told people that we were being taught all the ways we could be wrong, which made us scared of writing code. We've been taught all the things that the algorithms could be slow or the wrong data structures or we could be breaking the types, we could be doing all these things in a bad way, and I'm like, "Shit, programming is really dangerous, like, of course, I'm going to sit down and think for three days for all the ways that I could be doing this wrong."
But what it also meant was that before I started university, I could write thousands of lines of code per day, like, no problem. Because it was PHP, I didn't really care, I was young, just go or just write something and see what happens. I was way more productive because at the end of university, I was like, "I have to write something, what I'm gonna do? I need to set up some CI/CD, some testing frameworks, I need to research first." Obviously, I need to pick the right front-end language or framework, I can't get started without a front-end framework, you know? And then I just put off starting, which is exactly the opposite of this, "Just get coding and see what happens." Eric Meyer has a lot of talks where he talks about, stop all the planning activities, stop all the scrum, stop doing all these things, just sit down, open up an editor, and start typing."
That's how you start a project, that's how you start solving a task, just open an editor and code. And I found there was some very profound truth in that. And when I started writing for what would eventually become the book, I also experienced the same thing with the writing of the book. It's like I put so much thought into trying to make this perfect in the first go, which really is a less effective way of spending my time than just writing something and then iterating. And we've heard that time and time again, but the best way I've heard about it was in the movie, "Finding Forrester" where he says, "Just pick up something and start typing. The first time you type with your heart, and then you go back and you rewrite it with your head," right? First, you make it work, then make it pretty. Like, just write something, I don't care, just get it out there, it's infinitely more valuable when it's written down, even if it's wrong, than when it's just an idea that you have.
How to Fear-Proof Your Code and Overcome Challenges to Deliver Exceptional Software
Kevlin Henney: There's a lot of truth there. It's a funny thing because it's like we've almost taught ourselves to be...by being cautious, we've taught ourselves to be fearful. And when we are fearful, we're actually less effective. And exactly what you described, it's kind of like, before I knew stuff, I'd write loads of stuff, and then I started learning things and now I'm afraid to write because I know there are so many things that can go wrong or so many considerations and so many parts into the future, what I would naively once have thought, "I can do this," and it's a straightforward path, and I might discover I'm wrong, but I would still set out on that path.
Through a process of education and experience, we've ended up preventing ourselves from walking down any paths, but standing around talking about the paths, it's this whole fear that we've accidentally created. And for something that is, given the software is supposed to be soft and, refactoring is a mechanism for doing so and ensuring that, we've made it harder than hardware. That's how it feels, at least to me some days.
Christian Clausen: And then as you said, it comes from...also, I have a bit of a background in theater, where when you want to create something that's emerging in this way, the improv theater is very much an emerging thing between the people and what you can get out of the few props you have or the few situations, whatever you can create there. There is a very important rule that if you start saying no to things because, those are not appropriate or this is going to be harder, if you start saying no, you're gonna take it down. Like, you're gonna actually destroy the creativity of that forum and everything just goes wrong from there. There's this, "Yes, and," idea, you have to always build on whatever is there.
And it's the same thing with consulting, especially management consulting I've found is if you actively avoid all the things that are going to be hard and scary, you're going to be a worse consultant and you're probably not going to change anything because you need to make hard choices sometimes, and you need to have hard conversations and stuff. The same with code, you need to sit down and do whatever you're scared of because otherwise, you're just going to never do it. And usually, just writing the first few lines will get you sort of into some sort of a groove. And it might not be perfect, but it doesn't matter because you can fix it. Like, just go back into the danger, just do whatever you're scared of to un-scarify it, to take away the fear.
Kevlin Henney: As you're describing earlier on, there's that notion of like the knowledge that, whatever you knew at the beginning is not going to be what at the end. But if you don't get to anywhere near the end, you don't make any kind of progress, you're not going to learn anything. It remains as dangerous and scary as it was before. And I think that it also speaks to that notion of trying to anticipate and plan things, and then something unplanned comes along. And it reminds me of...again, you talk about theater, and that just reminded me, there's a little snippet of Michael Caine talking to an interviewer.
And he talks about using the difficulty and that early in his career, he tried to do a stage entrance and there was something in the way and, he kind of explained it, "Oh, I can't do this," and he was told, "Use the difficulty. If something's in the way, then use that, make that part of the scene, make it part of your progress, and make it part of the story." In other words, he quite literally improvised at that point, even though it's not an improvisational context. It's a reminder, everything is an improvisation context, and code and software is not necessarily something that respects plans. In fact, it tends to laugh at them quite loudly.
That kind of idea, again, that kind of brings us full circle to, sort of what I felt to be one of the underlying messages of the book and that this idea that the fact that not everything is going to be perfect and not everything can be planned is not a problem. Here are the ways of dealing with stuff. Things might look big and scary but, it all comes down to the small stuff. If you can do lots of small stuff, then that's good, that's fine. And you don't even have to be...you don't even have to bring your best game to the keyboard to be doing this. Here is how to do it in its simplest level, you can be doing your worst day and still make progress, which I don't think you say in the book. But certainly, the message that I got is just like, "Here's how to make progress even when you're having a terrible this is not your best week, this is not your best year," whatever. There are so many other difficulties, you're being pulled in other directions, or,it's a technology that you don't know, you can still make progress.
Christian Clausen:There are so many reasons to not write code today. Picking tools, doing all these things that's scary, all of this, but ultimately, coding and building software is a creative process and it's a learning thing. You have to play with these things to get a deeper understanding of the domain, of the language of your tool, of everything. You have to be in the mode where you can take all these things in. And I think it's Cleese who has this management talk, actually, where he...he's also very funny, but where he talks about making space for creativity, making space to be open-minded, we're in the open state.
And I also tried to emphasize that by, "Before you start writing your real code, then do a spike," right? The old XP spike. Do an explorer thing. Just promise yourself you're going to throw it out, and what you'll most often find is it's a lot easier to write it if you have to throw it out. And then the second time is easy to write because you've done it before. Just hacking these things. I find that spikes have been really difficult to get into the industry and I'm hoping I did a little bit for it, but still seems like there's a far way to go.
Kevlin Henney: I think on that note, and that's a wonderful unifying note given we talked about unification, but this is bringing many of the threads together and bringing them back to a joint. I'd like to thank you, Christian, for your time, your thoughts, and your book. And where can people find you online?
Christian Clausen:I'm on Twitter, I'm on LinkedIn. Again, another one I stole from you is I tried to be easily stackable and very public. I'm always the same handle on all of the things that I'm on, whether it's YouTube or GitHub or whatever. I'm everywhere. I'm also doing a company where I'm trying to build the next cloud, which is going to be huge and a lot easier to work with, like the refactorings, you know? It has to fit on the head of a programmer. They can also find me there.
Kevlin Henney: Right, brilliant. Thank you very much for your time.
Christian Clausen:Thank you very much.