MARTIN:
And in honor of Katrina, we also have to remember to refer to Charles as Chunk for the entire episode.
[Laughter]
[This episode is sponsored by Rackspace. Are you looking for a place to host your latest creation? Want terrific support, high performance all backed by the largest open source cloud? What if you could try it for free? Try out Rackspace at RubyRogues.com/Rackspace and get a $300 credit over six months. That’s $50 per month at RubyRogues.com/Rackspace.]
[This episode is sponsored by Codeship.io. Don’t you wish you could simply deploy your code every time your tests pass? Wouldn’t it be nice if it were tied into a nice continuous integration system? That’s Codeship. They run your code. If all your tests pass, they deploy your code automatically. For fuss-free continuous delivery, check them out at Codeship.io, continuous delivery made simple.]
[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York, and L.A. bid on Ruby developers, providing them with salary and equity upfront. The average Ruby developer gets an average of 5 to 15 introductory offers and an average salary offer of $130,000 a year. Users can either accept an offer and go right into interviewing with the company or deny them without any continuing obligations. It’s totally free for users. And when you’re hired, they also give you a $2,000 signing bonus as a thank you for using them. But if you use the Ruby Rogues link, you’ll get a $4,000 bonus instead. Finally, if you’re not looking for a job and know someone who is, you can refer them to Hired and get a $1,337 bonus if they accept a job. Go sign up at Hired.com/RubyRoguesPodcast.]
[Snap is a hosted CI and continuous delivery that is simple and intuitive. Snap’s deployment pipelines deliver fast feedback and can push healthy builds to multiple environments automatically or on demand. Snap integrates deeply with GitHub and has great support for different languages, data stores, and testing frameworks. Snap deploys your application to cloud services like Heroku, Digital Ocean, AWS, and many more. Try Snap for free. Sign up at SnapCI.com/RubyRogues.]
CHUCK:
Hey everybody and welcome to episode 178 of the Ruby Rogues Podcast. This week on our panel, we have Avdi Grimm.
AVDI:
Hello, hello.
CHUCK:
We have a brand new Rogue, Jessica Kerr.
JESSICA:
Good morning.
CHUCK:
I’m Charles Max Wood from DevChat.TV. And we also have a special guest, Martin Fowler.
MARTIN:
Hello from Boston where the leaves are turning yellow, red, and gold.
CHUCK:
Now Jessica, do you want to introduce yourself really quick? You’ve been on the show before, but it might be good for folks to remember who you are.
JESSICA:
Sure, right. My name is Jessica Kerr, better known as jessitron on Twitter and everywhere else. I’ve been a developer for 15 years, mostly Java, more recently Scala, and now Clojure. In my spare time I do some Ruby work mostly because I like to speak at Ruby conferences, which is because Ruby people are the most awesome. Ruby conferences are by far the most fun and the most meaningful conferences I’ve been to. And that includes the Ruby Rogues. So, I’m thrilled to be here.
CHUCK:
Awesome. And Martin, do you want to remind people who you are as well?
MARTIN:
Yeah. I refer to myself as a loudmouth in the programming space. I’ve written a few books. I’ll speak at some conferences and I have a website at MartinFowler.com that gets a surprising amount of traffic.
JESSICA:
Loudmouth. I like that a lot better than thought leader. [Chuckles]
MARTIN:
Oh, I can’t stand it when people use the term thought leader. It always makes me think of some kind of head of the thought police kind of thing. So, I’ve never used that for myself. Loudmouth I feel is much better.
CHUCK:
I was going to use the words legend and superhero. But I guess that applies to Jessica as well, so we’ll just spread it around.
JESSICA:
Ha! Legend I would think definitely applies to Martin.
CHUCK:
Yeah. So, this week we’re doing our book club on Refactoring: Ruby Edition. And we announced it four months ago and so I read it three months ago. So, I’ve done some refreshing but it might be a little bit rusty for me [chuckles]. I am excited though. I’m a little bit curious as we get started, what part of the book or what principle of refactoring do you think is the most important?
MARTIN:
I think the most important thing about refactoring is making very, very small changes that don’t affect the overall behavior of your system, which in practice mean you can run the tests and they will still pass. And doing that a lot so that every time you run into code and it’s not quite right, you’re always in this constant state of improving it a little bit, because with refactoring, it’s all about doing it all the time. You never want to build up a whole load of work so that you have to spend a lot of time refactoring. You want to always be doing little bits of improvements so that the codebase is kept nice and healthy. The healthy is [inaudible] metaphor. You don’t want to get yourself really unfit and then after spend ages getting yourself fit again. You have to do your exercises every day if you’re going to stay healthy.
AVDI:
Can we back up a little bit? Because I think there are probably a few people out there that have maybe heard the term refactoring but aren’t entirely sure what it means.
MARTIN:
Ah. Avdi plays the Josh Susser card.
[Laughter]
MARTIN:
Okay, yeah, definition of what refactoring means. I actually prepared for this. I’ve even got the necessary bits of the book in front of me, although rather cleverly I didn’t put my reading glasses on so I have no idea what they say.
[Laughter]
MARTIN:
But yeah, I actually define it in the book in two ways. One is a noun and one is a verb. The noun definition is a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior. So, that’s the noun form. So, actually you carry out a refactoring. So, an example of refactoring is extract method where you take some lines of code within an existing method and you extract them into their own method that’s called by the original place. And the point is you do this because it makes the code more understandable and therefore easier and cheaper to change in the future. And it doesn’t affect anything else. Anything calling that method, anything anywhere else still works as a result of extract method.
Then there is the verb form of refactoring which is to say to restructure software by applying a series of refactorings without changing its observable behavior. So, the verb form of refactoring is just to say you do a whole series of individual refactorings. And so, at every time the software still works the same as it did before. All you’ve done is make that internal structure different in order to improve its clarity.
AVDI:
Wait, wait, wait, wait, wait, wait. Now, when I got into software development and particularly into agile work, I distinctly recall that refactoring was the word for the thing that happens when the team doesn’t produce any new deliverables for a month.
CHUCK:
[Chuckles]
MARTIN:
Yeah, that’s a common error of the team.
AVDI:
[Laughs]
JESSICA:
Refactoring as boogie man.
CHUCK:
Yeah, the other thing I remember about refactoring is that I didn’t need it when I was a brand new programmer because all my code I knew was great. So, I’ve just gone downhill from there. So, now I have to refactor. [Chuckles]
AVDI:
I kid, obviously. But these are also definitions, folk definitions that float around out there.
CHUCK:
Yeah.
JESSICA:
Yeah. I like…
MARTIN:
Oh yeah. I make a strong distinction between refactoring and restructuring.
JESSICA:
Ah.
MARTIN:
Where restructuring is any change you make to your code, system, to alter its structure. But refactoring is the particular discipline of doing it through this series of individual very small refactorings. Because when you’re refactoring you never break anything. That’s the definition of it. And as a result, you can restructure, it feels like it ought to be slower because every change is tiny. But the sequence of the changes, the composability of the changes means you end up going much faster. But it’s a particular way of doing restructuring. One that I think is particularly efficient.
JESSICA:
Does restructuring then also not change the functionality, the outward appearance of the code?
MARTIN:
I use restructuring as a very general term, so it might. It might not.
CHUCK:
So, from now on I’m going to tell people that I did some effective restructuring. And then they’ll ask, “So, you didn’t refactor it?” and I’ll say, “No, because I broke it.”
AVDI:
[Laughs]
JESSICA:
Right.
AVDI:
You mentioned it being a particular set of steps. And I think that’s for me one of the most interesting parts of reading this book, is just realizing how granularly these individual refactorings are broken down. Not just that the refactorings as a whole are relatively short changes, but also that they’re broken down into very small steps. I wonder if you could just step us through the individual steps involved in one of the refactorings to get an idea of this.
MARTIN:
Okay, yes. I could do that, because extract method is actually a very good example of it. The granularity is really one of the striking things. When I was first shown this technique, I was shown by Kent Beck. He refactored some of my Smalltalk code. And I was just taken aback by how small each change was that he made. And this notion of we’re running the tests after every change kind of thing. And it was really so tiny and yet it was so fast because the thing that kills you when you’re restructuring badly is you make a mistake that forces you to debug. And as soon as you go into debugging, that’s it. And in fact that’s part of one of the advice with refactoring is if you ever break anything, you rollback. You don’t attempt to debug your way out of it. You just roll back to the known state. And then usually smaller steps. And that’s how you actually make progress.
JESSICA:
I liked that part of the book where it talked about we’re tempted to go to the debugger when there’s a problem. But if you go into the debugger, you don’t know how long it’s going to take to find the problem. But if you back up, you know exactly how much time it’s going to take to back up. And the time you put in is the maximum time you can lose. So, the time lost is constrained by backing up.
And it’s completely open-ended if you get into the debugger.
MARTIN:
Yeah. In many ways, I think as refactoring and test-driven development which obviously goes very close with refactoring, is all part of the plot to make us no longer use debuggers.
JESSICA:
Yay.
MARTIN:
Because as soon as you use a debugger, you’re in this whole world of difficulties. And so, you’re trying to keep yourself out of it as much as possible.
AVDI:
Oh my god. Finally, I can tell people Martin Fowler agrees with me on my opinions of debuggers.
CHUCK:
[Chuckles] So, I have to ask then. Are there circumstances under which you use a debugger? Not necessarily in refactoring, but do you just roll back your code if you’re writing new code as well?
MARTIN:
No, there are cases where I use the debugger. I actually don’t use debuggers very much because I’m so old-fashioned I use print statements instead.
CHUCK:
[Gasps] No.
[Laughter]
MARTIN:
Yeah.
CHUCK:
I do too.
MARTIN:
But the thing is, I always ask myself, “Now, come on?” I mean, I always know that there’s a real question mark over that. Often, a better way is writing fine-grained tests for instance, to try and, if I’m getting into difficulty with something. Can I write a smaller granularity test that will get me there? Rolling back is often a really useful technique as well. So, to me the debugger is a tool. I do have to use it but I don’t like using it, as it were.
CHUCK:
Yeah, I also want to point out that most of the time when I need the debugger, it’s because there’s enough going on that I can’t see where the problem is. And so, it’s also to borrow a term, code smell. And it’s an indication that my code might be a little bit too complicated if I can’t just see what’s going on and see where the problem is with a couple of print statements.
JESSICA:
Functional programmers talk a lot about reasoning about code. And I’m still not entirely sure what they mean by that, but I’m pretty sure using the debugger is the opposite of it. [Laughter]
CHUCK:
It’s unreasonable code, meaning you can’t reason about it.
JESSICA:
You’re not reasoning about it. You’re just watching it to see what it does.
CHUCK:
Please work. Please work. Please work. Please work. Yes!
JESSICA:
Or if you’re debugging production, please fail. Please fail. Please fail, so I can see it.
CHUCK:
[Chuckles] There you go. Prayer-driven development.
[Laughter]
MARTIN:
Okay. So, I really ought to go back to Avdi’s question. He wanted me to walk through the mechanics of one of the things. And I’m using extract method because it’s simple and yet quite intricate to do the extract method properly. So, it’s a good example. So now, the idea of extract method as I said, is you’re taking, say you’ve got a method that’s got 10 lines in it. That’s a horribly long Ruby method. I don’t think I’d every write one with 10 lines in it. But imagine I have and I want to take 6 lines out to make its own method because I think it makes more sense. So, the basic steps look like this. I’m reading off the mechanics section of in fact the original, the Java book rather than the Ruby book, because it’s more familiar to me. But you can forgive me for that, I’m sure.
So, the mechanics say the first step is you create a new method, naming it after the intention of this new method. So, this is an important point about naming of course. We always want to name methods after the intention that we have, naming being very important and of course one of the two hard things. Then you copy the extracted code from your source method into the new target method. So, in this step, notice nothing has actually changed in the existing software because it’s still running the original copy.
You then scan your extracted code in the new method for references to variables that are local in scope to the source method. That is, a local variable that’s in the other place, or a parameter coming into the method. You look to see if any of the temporary variables are used only within this extracted code. If so, you declare them in the target method as temporary variables. You look to see if any of these local scoped variables are modified by the extracted code. If one variable is modified, see whether you can see the extracted code as query and assign the result to the variable concerned. If this is awkward or if there’s more than one such variable, you can’t extract the method as it stands. So, you’re going through all the variables that are in scope here and looking at them individually to say, “Okay, what can I do about this?”
You take any variables that you only read from and you pass those in as parameters, adding the parameters to the parameter list for the extract method. And so, you do all of this intricate playing around with variables, which is why by the way it’s a little bit more complicated to do an automated refactoring for extract method than you might initially think. And then when you’ve done and it’s all there, you can then replace the original code with a call to the extracted method, compile, and test.
So, it’s a lot of very small intricate bits to this. And that’s why the actual description of the refactoring uses several examples to do it. But it is also automatable. So, in some places you have got, for instance the Java world, pretty much any decent Java IDE will automatically extract method for you. And they’re pretty much reliable. But I must admit that when I’m programming Ruby, I don’t use any of those. I just do it myself in Emacs. But that’s also partly because my methods are so small that when I extract methods I don’t tend to get into trouble. And also, I don’t tend to use variables a lot. And I certainly don’t tend to update variables. I tend to treat them as let where you define it and use it and don’t change it. And that reduces the pain of doing any refactoring.
AVDI:
And so, you said compile and test, or just I guess test in Ruby, at the end. Is that the one place where you test? There wouldn’t be tests along the line for these steps?
MARTIN:
For extract method you can really only do it at the end.
AVDI:
Right, okay.
MARTIN:
But for other refactorings, again if you’re looking in my mechanics, you’ll see compile and test several times inside them. If you’re moving the method from one class to another for instance, there are several intermediate points you can compile and test. Basically, you want to compile and test as soon as you possibly can.
JESSICA:
Martin, you mentioned some things that you do now, some code styles that you use, that make this particular refactoring easier than it used to be. How has all of this refactoring practice affected the way you write code in the first place?
MARTIN:
That’s an interesting question and a very difficult one, because it’s so long ago when I really started doing this. And I was very much affected by particularly Kent Beck’s Smalltalk practice. Going back to when I was starting doing it in those days, one certainly big effect was dramatic reduction in size of methods. We used to joke on the C3 team that a method that had three statements in it was probably getting a bit long. And we weren’t really kidding. So, very short statements was something that I really got into in those days. And that’s true of my Ruby as well. I haven’t actually run any stats over my Ruby code, but it certainly would be surprising if I have any methods that are more than a few lines.
JESSICA:
That’s a good example. Coming from the Java world, Martin is definitely an iconic figure because your book in 1999 was one of the early, basically it became a style guide for Java. The places where I worked, our coding conventions were: make it look like ‘Refactoring’. Is there anything going back that you would do differently for this book that’s been so incredibly influential?
MARTIN:
Ooh, yeah. That is a question on my mind from time to time. What would I look at differently? It’s hard to say. I’d have to go through it and really think about that. A lot of it is about the emphasis of the choice of refactorings that I’ve described. So, certainly Java has changed a lot, which is a factor. So, this book is so old, the Rubyists won’t understand what I’m saying here, but this is so old that I’ve got references to java.util.Vector in there.
JESSICA:
Ah.
MARTIN:
It’s ancient. But one of the big shifts that have occurred recent with Java is the use of lambdas and the ability to form collection pipelines in your code, which you could not do in Java for a long time. Of course in Ruby, we’ve been able to do this forever. We can use map and inject, reduce, those kinds of operations. And that’s really, really handy because we had that in Smalltalk as well. But in Java, that’s a big jump and a big shift. So, I think that’s one of the things that I might try and do, is nudge people to using that style of programming more.
Another area that’s I think quite important is increasing the emphasis on treating things as immutable as much as possible. I made the comment that when I use temporary variables, I assign to them once and never change them, almost all the time. The only exception will be some kind of accumulator. And that is a practice that I’ve done, again since Smalltalk days. And of course in Java, you can actually annotate the variable as final to make the compiler enforce that.
Oddly enough, in my personal code I never bother doing it because I do it all the time. So, it ends up being the noise word, if you see what I mean. But I would much rather actually be able to follow the convention of it. Some languages [inaudible] says variables are assumed immutable unless explicitly marked as mutable. And I think that style, which obviously is encouraged by functional programming, that would suit me very much because that’s how I tend to think.
JESSICA:
That’s helpful. Thank you.
AVDI:
I have a question about tools and refactoring. As listeners of the show know, I spend a lot of time in Emacs. These days, I also split my time a bit with RubyMine which is a bit of a departure for me. For a long time I was IDE-free. But I’ve noticed that my development practice differs a little when I’m working in RubyMine. It does have some built in, some of the simpler refactorings are built in. And it actually does a very good job of things like, it’s not just pulling out a chunk of text if you want to extract method, but it’s actually finding all those local variable references and making sure that they’re accounted for in the parameter list.
And I find that I refactor more when I’m using this IDE than when I’m just using Emacs, because there is a lower mental barrier. It feels like less work, so I’m taking a lot of smaller steps. And I think it has some wider ranging effects, like there are certain things that I just feel more brave about changing because I know that the refactorings it might cause are going to be really quick and simple. I’m curious if you’ve experienced differences in how you code based on tool support, or if you look for tool support at all, and also if you customize Emacs at all to make refactoring easier.
MARTIN:
That’s a very interesting one. When I started refactoring consciously back in Smalltalk days in the late 90s, we were doing it without any specific tools initially. And I did most of my learning of refactoring in that situation. And then of course, the very first refactoring tool that became available became available for Smalltalk, the refactoring browser that was written by John Brant and Don Roberts. And it was really wonderful to be able to, “Oh, I can extract method and it just does it. Or I can rename the method.” That was one of the most powerful ones, just renaming. You didn’t have to click, find all the same [inaudible] and click through. It was a huge plus. But of course, that was at the time that I would stop using Smalltalk. [Chuckles] And then I spent a while in Java land and it took a while before Java tools got caught up.
Now, it’s intriguing because if I’m going to do anything more than a trivial, really trivial Java or C# program I’m going to fire up IntelliJ, because that’s my preferred tool for that, or ReSharper in the C# world, because I want the IDE. And a large part of why I want it is because its refactoring support is awesome. In Ruby, I’ve actually, it’s weird. I keep intending to try RubyMine for a while, but I’ve not got around to sitting myself down and doing it, because I’m very used to working in Ruby in Emacs. And of course, I don’t have much tool support at all. I do kind of miss it. And it is interesting to say, “Would it lower the activation energy of doing some refactorings?”
Extract method for me, as I said, isn’t too hard because of the way I construct my methods. Actually, I haven’t even bothered making a macro for it. I have a macro for extracting variables. I find I do that more often. And so, I actually got around to writing a macro for it. But it is interesting the degree to which tools might make a difference.
The renames I found were the most, really made the biggest difference, because when you’re in your refactoring browser in the Java world and you said, “Oh, that name isn’t quite right,” you just hit it and be really confident that it gets it right. And of course, that’s where static typing is a big advantage, because with a dynamically-typed language you haven’t got that degree of confidence when you rename something.
AVDI:
Right.
JESSICA:
Absolutely. Switching from Java to Ruby, that was one of the things I missed. Static typing and tooling go beautifully together. And I can rename a field and be confident that IntelliJ has renamed it in every file in this project that uses that field. I don’t have to go searching for it and it’s never going to rename something that just happened to be the same name but was actually a different type. All of these, I think it’s interesting that we’re starting to talk about tools, because each of these refactorings is itself a tool. And then we have tools that help us use these tools. And then we write macros to improve our tools to help us use the refactoring tools to make our code better.
CHUCK:
Oh, I so wanted you to keep going.
[Laughter]
JESSICA:
Well, in the end our software is a tool to help someone accomplish something. It is. It’s really all the way down. It’s we’re working to make some other work faster. That’s software itself and it’s our refactoring and it’s everything we do to make refactoring faster. So, given that we’re in Ruby and maybe we’re in RubyMine but even so, there’s a limitation to how much we can automate these refactorings. And even if they are automated, I think they don’t become tools in our toolkit until we practice. Do you have any recommendations Martin, about how to practice using these tools so that you become comfortable with them? The refactorings in particular.
MARTIN:
Yeah. Well, one of the best bits of advice that I got from somebody using the book was they would go to the code smells chapter which talks about all the bad indicators that you tend to see in code. And they would do something like pick a code smell for the week and say, “Let’s really focus on say, long methods. Or on middle men, or on data classes,” or whatever smell you pick up on. And then let’s really concentrate on identifying them and fixing them. And each code smell leads you to various refactorings that are the typical ones that you use to address that problem. And so then, you’re building up the practice in refactorings. But of course, in many ways the more important skill is that of identifying code smells and learning to become intolerant of them, because that will drive the desire to learn to refactor. And that’s really critical on keeping a codebase healthy, because you got to keep whacking these smells all the time.
JESSICA:
Wow. That sounds like a really fun idea. Smell of the week. It could be a game. Pick one at the retro.
CHUCK:
[Chuckles]
JESSICA:
And at the next retro you can say, “Oh, I totally found that smell and here’s what I did to fix it.”
MARTIN:
Exactly. And for people who are less experienced, as long as you can spot the smell, it’s less important that you know how to fix it, because if you can spot the smell you can always go to somebody more experienced and say, “This thing is really bothering me. How do I fix it?” And that’s a great opportunity for mentoring.
AVDI:
Definition time again. Can we talk a little bit about what exactly a smell means?
MARTIN:
Okay. So, the story behind code smells was I was visiting Kent. And at the time he was living in Switzerland, which isn’t actually at all relevant to the story but it’s part of a scene setting. And at the time he was working at this insurance company for incredibly rich Swiss people. And it was actually the first time I saw a project that did continuous deployment. They were deploying to production every night. This was in ’98 or something, ’97, ’98. So, it was a really early example of doing this work. But anyway, he was looking at the book and saying it was good. But he said, “There isn’t much guidance here as to when to refactor, when to do these things.” And we were bouncing around ideas. And there may have been some scotch involved.
[Laughter]
MARTIN:
And this idea of smells came up. And the point of a code smell is that it’s a very surface, easy to spot thing that usually implies a real problem. Doesn’t always, but usually does. And so, long methods are a great example of this. If I see a 30-line method, sometimes that’s okay, but very, very rarely. Usually it’s a sign that there’s stuff missing there. And so, I want to poke around and look at it more. Another great example is the data class. If you’ve got a class that’s only getters and setters and no behavior in it, it’s just screaming for, “Oh, I’ve got to do something. What’s happening here?”
And the point is that when you detect a smell, then that is a trigger to investigate to see, “Okay. For a start, is this actually a real problem or is it one of the rare cases that you allow it?” And then it’s the trigger to say, “Okay. How can we do something about that?” And the fact that it’s easy to detect is important. This may also come from the consulting background we had. You’ve got to dive into an unfamiliar codebase and you’ve got to make an impact rapidly. And so, you look around for the bits that you can spot, “Oh, well that’s a problematic area.” And you get a certain amount of experience at finding where those spots are and where you can make a difference quickly.
AVDI:
One of the smells you talk about in the book is comments. When is a comment smelly?
MARTIN:
Well, I actually say in the book, at least in the Java one. I assume they kept it for the Ruby one. But a comment is actually a deodorant.
AVDI:
[Chuckles] Oh, okay.
MARTIN:
So, it’s covering up a bad smell. And what you do is you look to say, “Can I refactor the code to make that comment completely superfluous? If so, then I can get rid of the comment.” And so, the classic example for this is a badly named method. The method has an awkward name and you put in the comment what the method actually does. And that was of course common practice. In fact, it was many places I went to, it’s effectively mandatory practice. And the point is you say, “Okay, how can I name that method in such a way that the comment is just irrelevant duplication? And then I can get rid of it.” And that’s really what I aim for it.
Now, of course that doesn’t mean you should never use comments. There are times when a comment is necessary, because you just can’t think of how to remove it. And particularly comments that say why you were doing something a certain way, fall into that category. But look at my code, look at the code of people who do this kind of stuff, you tend to see comments are relatively rare because we put the energy into the structure and the naming to convey most of the meaning.
JESSICA:
Speaking of structure, I was wondering. I find myself using a lot more comments in Ruby than in Java or Scala because I don’t have the type there to tell me what this input is and what output I’m expecting. When you move to a dynamic language, how do you make it expressive enough that you don’t need comments to tell you what that method’s going to give you back?
MARTIN:
Interestingly, the habit in Smalltalk, the convention that Kent also talked about in his books, is to always name your input parameters based on their type. So, if you’ve got an operation that extracts information from an XML element, you would call the input parameter an_element or an_xml_element, depending on the context and how much information you want it to convey. The name of the method should give you a clue as to what kind of thing it returns, though that seems to be less important to really have a typing there. But the type was really quite important for parameters. And I continue that Smalltalk naming habit in my code, even though it sometimes leads to slightly longer parameter names than needed.
JESSICA:
That’s interesting because in Java, the correct practice as far as I know it is to name a variable according to its role. But that implies that there’s a type that says what it is and then you get to name it according to why it’s there, what its purpose is.
MARTIN:
Yeah, the role should be part of it as well if that’s important. But a lot of that depends on the context. Of course, in Smalltalk we had keyword parameters, so the keyword could indicate the role a lot of the time. In Ruby I find that, I’ve usually not got very many parameters of course, so that’s another thing. We tend to avoid lots of parameters in a method. And so, that helps avoid that. And of course, now with keyword parameters in Ruby and of course even before that, by using passing in dictionaries, you could use that trick if you’ve got anything longer in terms of parameter list. But of course any method that’s got more than two or three parameters is suspect. That’s smelly right there.
CHUCK:
Yeah, one thing…
AVDI:
I think there are…
CHUCK:
I want to point out too is that a lot of times I’m not putting in there that it’s an integer or string or whatever but just that it’s blah_blah_blah_name indicates that it’s a string or blah_blah_blah_multiplier. So, you’re talking about that role and that role is usually something that only one specific type can use. And so, indicating the type is a lot of times, it’s duplicative there as well.
JESSICA:
I like that because when you say multiplier you’re being more specific, integer or double. When you say name you’re being more specific than string. So, there’s some flexibility there on how specific your descriptions are.
MARTIN:
Yeah, [inaudible]…
CHUCK:
Well, and the other thing is when you name the parameter, it doesn’t have to be the same name of whatever it was that was passed in. You’re just talking about the role within the very narrowly defined context of your method.
MARTIN:
Yeah, and I often combine the two. So, if I’m passing in a string that’s there as a name, I might well call it name_string. If I don’t think it’s completely obvious that name would imply a string, then I’ll add the type as well as the role and combine the two together. Again, it depends a lot on the context of where it is, as to what provides that clarity. And it also affects the audience. And I’ve got out of touch a little bit because most of my programming is solo these days. So, I’d get a bit sloppy because I know who my reader is.
AVDI:
Yeah, I’ll do that occasionally, especially in cases where I’m transforming data. So, a weird example but if for some reason I was transforming things from symbols into strings, then sometimes I’ll have an intermediate variable. If there’s an input that’s just name but it might be a symbol, then there might be another variable called name_string which is at the point where I know that it’s definitely a string. But that’s usually only if the next logic really, if I need some way to differentiate.
But I definitely agree with having conventions that indicate the role of variables that are sort of vaguely indicative of their duck type. And I think it’s really important to have consistent conventions in a project. If you’re representing counts of things, numbers of things, you might decide that they’re all going to be called num_something or you might decide they’re all going to be something_count. You know, foo_count versus num_count. But pick one and then stick with it across the project.
MARTIN:
Yeah, that kind of consistency is really important. That’s another reason of course to keep refactoring, because if you see some code that’s inconsistent then… The general test was best, I think, visualized to me by Ward Cunningham. And he said that if you’re ever in a situation where you’re trying to figure out what some code is doing and you spend some time, what’s happening of course as you’re doing that is you’re building up some understanding of the code in your head. And at some point, you’ll get the understanding. And it may mean that you’re not going to actually use this code or touch it in what you’re doing at the moment because you’ve realized, “Oh, it’s doing blah, blah, blah. I don’t need to touch that.”
But because you’ve built up this understanding in your head that wasn’t immediately obvious in the code, before you’re done you have to move that understanding out of your head and push it back into the code. And that’s part of this need to refactor all the time. You build, any time you spend some time puzzling out something, you’ve got to figure out, “Okay, how do I put it into the code so that next time I come through or next time somebody else comes through, they don’t have to spend that time puzzling it out?”
JESSICA:
Because the fact that you sat there and puzzled it out is a smell.
MARTIN:
Exactly.
AVDI:
Yeah, that’s something that I always ponder. I always think, “Should I keep some sort of development journal here or is there some way of pushing this understanding into the code?” And sometimes I do wind up writing some… it seems like every project has at least one treatise in the comments. Usually I don’t comment anything, or very rarely. But then I’ll have some treatise somewhere that’s three or four paragraphs of why I did this one crazy thing that makes no sense.
JESSICA:
We have a development journal. It’s called Git.
AVDI:
[Laughs]
CHUCK:
Oh, don’t start. I’m just kidding.
AVDI:
Yeah.
JESSICA:
Oh, totally.
CHUCK:
[Coughs]
JESSICA:
Those why treatises totally belong in the commit message. And the reason is because the commit message, if it was true when you put it in there, it never becomes a lie because it’s attached to the code at a particular time.
CHUCK:
So, Git commit –m “wrote code” bad?
AVDI:
[Laughs]
JESSICA:
Forget the minus m. Open your editor and type a story.
CHUCK:
[Laughs] I love it.
AVDI:
Yeah.
CHUCK:
That’s so true.
AVDI:
Well, that’s true. If your editor isn’t popping up when you do Git commits in order to edit the message, then… well, I’m not going to say you’re doing it wrong, but…
CHUCK:
But you’re doing it wrong. It’s fine.
[Laughter]
JESSICA:
No, no. You’re totally doing it right. Just rebase it later and add the story.
AVDI:
Okay, yeah. I just can never remember how to do that.
CHUCK:
[Laughs]
MARTIN:
It is one of the interesting changes actually, over the last 20 years, is the role of the version control system as part of the documentation of the codebase. That’s not something 10, 15 years ago that I tended to see people even considering. But now, the pendulum has swung in my feeling a little bit too far in that direction. People are making it so that it’s like you shouldn’t be able to understand the codebase without also looking at its history.
MARTIN:
And I think…
CHUCK:
Yeah, you have a point.
MARTIN:
My feeling is a Git comment in the commit message is kind of like a comment in that if you can think of a way to structure things in the actual code itself so that what you need in the commit message is just superfluous because it’s blindingly obvious then you should try to do that. But having said that, just like with comments often you can’t. And then putting something in a commit message can be an extremely valuable signal as to what the hell was going on.
CHUCK:
The other thing that I like in comments over commit messages, I think it’s important to put this stuff in commit messages. But there is a barrier between the code and the commit message. I have to go open up Git and look at the Git log to see it, or go to GitHub to see it, whereas if the comment’s there, it’s right where I’m working.
JESSICA:
Yeah, and the really crucial comments need to be that.
AVDI:
Are you using that?
CHUCK:
Yes.
JESSICA:
Yeah. The tools are there, too, to bring those commit messages much closer to you. It’s another thing that you’ve got to practice with in order to use. There are so many.
AVDI:
I wish there was a way to put a little footnote in that just said, “See Git commit.” [Chuckles] AVDI:
But that didn’t somehow become old and lost…
JESSICA:
I totally put that in my comments sometimes.
AVDI:
Oh really? Okay.
JESSICA:
Oh yeah. I’ll delete a bunch of stuff and be like, “Okay, this documentation was out of date so I deleted it from the readme. If you want to see it, do a blame on this line right here and go for it.”
CHUCK:
Well, one other thing you can definitely do is you can put a link in there. And if you’re using GitHub or any of the other Git hosting services, you can link directly to the commit so that people could see it. So yeah, I think it just takes practice and some mindfulness in order to get it right.
JESSICA:
And in the end, there is no right. There’s only subjectively better.
AVDI:
Oh.
CHUCK:
Oh, I quit. No right, I quit.
JESSICA:
[Laughs]
MARTIN:
But it’s right, what’s right for your team, isn’t it? The team has to figure out what works for them, because they’re your audience. And that’s one of the things of gelling with the team, is figuring out, “Okay, what does the team like to work with? How do they like to express things?”
CHUCK:
Well generally, I’m working solo too. So, my audience is an idiot. [Laughter]
JESSICA:
Martin, what else has changed over the last 20 years?
MARTIN:
[Laughs] Oh dear, we have the internet now. [Laughter]
CHUCK:
I love it. [Laughter]
CHUCK:
20 years ago, I was in junior high and writing Pascal on some dumb little computer.
MARTIN:
Well, that’s just going a long way off the subject of the book.
[Laughter]
MARTIN:
I know this show. I enjoy the tangents on this show. But sometimes, they can be a little bit wild.
JESSICA:
Oh, come on. You can come up with something totally relevant to the book that’s changed in the last 20 years.
MARTIN:
Well, certainly there’s a lot more recognition of not just refactoring but a lot of the Extreme
Programming practices. That’s where refactoring as described comes out of. It’s out of Extreme Programming. The idea of writing self-testing code and test-driven development that follows from that, that’s another thing that’s become much more common. Continuous integration, continuous delivery, again straight out of the Extreme Programming playbook. They’ve become much more common now.
Of course, I’m saying this because most of my inputs for information are people working at ThoughtWorks. So, of course ThoughtWorks tends to work this kind of way. So, it’s easy to assume the world does when of course it doesn’t. But my sense is the Ruby community is very much affected by Extreme Programming thinking and that’s I think part of the reason that it’s such a good community to work in.
AVDI:
I think it’s interesting that most of the XP practices have experienced some amount of backlash at one point or another. Most recently, apparently we’re debating the goodness of TDD. Then there have been…
CHUCK:
That’s a debate though that will never end.
AVDI:
Yeah. But you know, there have been other ones about pair programming and stuff like that. But I don’t think I’ve ever noticed any kind of backlash against refactoring.
MARTIN:
Oh, yes.
JESSICA:
Well, [inaudible] the managers. You said it yourself at the beginning. Oh, refactoring is where you don’t do anything for a month.
CHUCK:
[Chuckles]
AVDI:
Well yeah, I guess except that one, except the calling restructuring refactoring and then…
CHUCK:
Yeah, but that’s as poor sales job on your part to management. You haven’t explained what you’re doing and so it feels like an excuse rather than an actual thing that provides value.
AVDI:
Yeah. Well, I think it’s a real and kind of serious issue in that sense and it just, in a sense that I think here’s the thing. I’ve been writing code for a very long, well what seems to me like a very long time.
JESSICA:
[Chuckles]
AVDI:
Well over 10 years now.
CHUCK:
[Chuckles]
AVDI:
And I’ve been blabbing on this, being a loudmouth on this show for a while, et cetera, et cetera. I
go and do talks. And I just read ‘Refactoring’ this year because of this book club. And that’s kind of the issue in a nutshell I think, is that as far as the misrepresenting refactoring is that I think there’s probably a lot of people who are in my position, who like the idea of refactoring but actually never read the ‘Refactoring’ book all the way through and so maybe had some kooky ideas about it.
JESSICA:
It’s the pendulum. Everything has to get way too popular before we can find the balance. The first time I heard a PM say, “I’m going to refactor the project plan,” [snaps fingers]
CHUCK:
[Laughs]
JESSICA:
I knew the word had jumped the shark.
[Laughter]
JESSICA:
Because that did not avoid changing the output of the project plan in any way. Now I know. He was restructuring the project plan.
CHUCK:
So, one question that I have is, and I think you kind of talk around it or the authors in the Ruby book talk around this a little bit, but the first question is how do you get people to embrace the fact that they need to refactor their code?
MARTIN:
Yeah.
CHUCK:
Especially on the team you’re working on where it directly, “Oh crap. I’m tired of fixing these things that don’t need to be fixed.”
MARTIN:
Yeah. Here, it really is about cultivating an understanding for how a healthy codebase allows you to keep going fast. And that you’re slowed down by having stuff that’s unclear. And a lot of people get used to the fact that, “Oh,” I remember that this was a part of the worldview in the early 90s that would say, “Well, code is just a big hunk of cryptography. And you never really understand it. So, that’s why we need design documents.”
AVDI: [Chuckles]
MARTIN:
And people have to get used to the fact that no, code can be made clear. The analogy is often made between code and writing. And of course, this is part of the theme of David’s RailsConf talk that was so controversial, is that he thinks of code not as mathematics but as writing. And I’m very much in agreement with him on this. But that then has a consequence which says that if code is writing, it means you have to put a lot of effort into making it clear.
And ask any good rewriter, [chuckles] I’ve given it away, any good writer what they do most of the time and it’s rewriting. This morning, I’ve spent this morning just rewriting something I wrote and have already rewritten once, because the clarity you have to be constantly working at. And with code it’s that same thing. And you have to develop this lack of tolerance for stuff that’s unclear. And I think that’s very much the harder things.
JESSICA:
Lack of this tolerance, or distaste.
MARTIN:
Yeah, yeah. You really have to go, “Oh, no, no. This is just not good, because it’s going to slow me down. It’s going to mean I’m going to be struggling every time I come through this piece of code. And so, therefore I need to do something to improve it.” And realizing that this is I think very important, realizing that this is an economic judgment. Several times, many times, I run into teams that say something like, “Oh well. Management isn’t allowing us to do a quality job here because it will slow us down. And we’ve appealed to management and said we need to put more quality in the code, but they’ve said no, we need to go faster instead.” And my comment to that is well, as soon as you’re framing it in terms of code quality versus speed, you’ve lost. Because the whole point of refactoring is to go faster.
And this is why I quite like playing a bit more with the metaphor as the health of a codebase. If you keep yourself healthy then you’ll be able to run faster. But if you just say, “Well, I want to run a lot so I’m therefore going to run a whole load all the time and not eat properly and not pay attention about this shooting pain going up my leg,” then you’re not going to be able to run quickly very long. You have to pay attention to your health. And same with the codebase. You have to continuously say, “How do we keep it in a healthy state? Then we can go fast,” because we’re running marathons here with codebases. And if we neglect that internal quality of the codebase, it hits you surprisingly fast.
JESSICA:
Very true.
CHUCK:
The next question I have that’s related to this is a lot of people, they pick up TDD and they do red, green, go to the next ticket, story, whatever. So, how do you get to the point where you actually have that as part of your workflow and make it automatic? Because it’s really easy to go, “Yay, it works,” and then move on to the next thing.
JESSICA:
Ooh, ooh, I have one.
CHUCK:
Go, go, go.
JESSICA:
One of the things that were in Martin’s workflow slides that he linked us to which we can link on the show was the workflow of preparatory refactoring. So, my strategy is before the red test when I know what change approximately I want to make, I’m going to go refactor the code while it’s still green under the previous test, refactor the code to make the change I want to make really easy. It’s like I want to go 100 miles east but instead of just traipsing through the woods, I’m going to drive 20 miles north to the highway and then I’m going to go 100 miles east at three times the speed I could have if I just went straight there. When people are pushing you to just go straight there, sometimes you need to say, “Wait, I need to check the map and find the quickest route.” The preparatory refactoring does that for me. And plus, it puts the refactoring at the beginning so it’s sure to get done.
MARTIN:
That’s a beautiful metaphor. I hadn’t come across that one before. But that really does capture it very well. And that’s of course a separate step to the TDD style use of refactoring, but it’s a very valuable one, because it asks you, “What would this code need to look like to make this change I’m about to make simple?” So, you ask yourself that question and then you say, “Well, can I refactor it to be like that?” and then make the change. And if you can do that, it’s almost always going to be faster because the refactoring step, you’re not going to be in debug land. It’s a relatively straightforward process. And then you’ve made the hard part, which is adding the new functionality, a hell of a lot easier.
JESSICA:
And then the next time you need to make a similar change, it will be easier again.
MARTIN:
Exactly. And that also gives you that sense I think of learning the fact that having code that’s clear is what makes you go quickly. And you begin to realize then the importance of doing that refactoring step in the TDD step to say, “Okay, I need to refactor it each cycle through the TDD loop to make sure that I’m keeping things clear for myself.” And I think once you begin to learn the fact that healthy code allows you to go faster, that’s the primary thing that will motivate you to do the refactoring and do everything else that is required to keep the codebase in good shape.
AVDI:
Well, I have a question about this. Back when I was a younger developer, by which I mean this morning…
[Laughter] AVDI:
I would often try to do exactly this. I would see a change I needed to make and I would decide to refactor things to make the change easier to make. And then two weeks later, when I had reinvented object-orientation…
JESSICA:
[Laughs]
AVDI:
I would finally get around to making the two-line change that I’d originally set out to make. [Chuckles] You may already see the question here. How long do you let yourself go?
JESSICA:
Until my pair gets bored. [Laughter]
CHUCK:
I like it. [Laughs]
MARTIN:
Well, that’s part of your judgment, isn’t it? You’ve got to judge, how far is this getting me to the highway? There may be another highway a bit further down the road, but this one is going to get me fast enough to my destination. And sometimes, particularly when you’re working on gnarly code, there’s always that sense of, “Well, I can’t fix the whole thing all in one go. So, I just have to make it a little bit better.” And you just want to make it step-wise better each time. And then over length of time, that will improve things.
There is there also the difference between working on a healthy codebase and working on an unhealthy one. With a healthy codebase, you get much more a sense of zero tolerance for anything that’s getting in the way. While when you’re working on an unhealthy codebase, you’re always looking to gradually ratchet things up and realize that it’s going to take a long time before it actually gets in the state where you can begin picking up that zero tolerance approach.
JESSICA:
That gradual part I think is really crucial, because that is the opposite of the, “We’re going to make zero progress for one month.” And it’s also really hard. Someone said these small changes, these small refactors that we make and these small features that we implement bit by bit, the smallness of it can feel slow. But small is smooth, and smooth is fast. That’s smoothness we’re aiming for with the healthier codebase. But it’s a real challenge to get there.
One of the things that I found in the book was about how when you want to make a bigger refactor, and you’re like, “Oh, I need three days to refactor this before I can merge it back in,” no, no. Don’t do that. Do partial refactors. And if you have to make some interface, throw away intermediate code to fit the smaller pieces in with the older stuff then do that. A lot of this is redefining, what is waste? Because driving 20 miles north to get to the highway doesn’t look like progress but it’s not waste. Do you have any techniques for, I think a lot of this, how do you convince people and yourself, what is waste? What is yak shaving that’s procrastination? And what is productive, eating healthy food, getting your code in better shape?
MARTIN:
Yeah, I don’t have some easy test answer for that. That’s part of what you learn from experience that’s rather difficult to bottle because it’s very context-specific. But it is one of those things you always have to be asking yourself, is this, am I making, recognizing what things lead you to progress and testing yourself with that. And realizing that you make mistakes from time to time, and sometimes experiments where you just try to learn something and it gets nowhere.
And interestingly, particularly to my point is I spent a good few days last week trying to refactor some code of my own that’s actually powers the Infodecks that the workflow slides come from, and realizing that I just couldn’t figure out how to refactor. The problem I was facing was it was in JavaScript and I was switching from, trying to switch from jQuery style promises to Q promises. And I just could not figure out any way to do it in small steps. Still can’t. I don’t know whether it’s just unsolvable. Fortunately, it’s only 400 lines of code. So, I’ll just rip it out and restart if I have to.
CHUCK:
Oh, is that all?
MARTIN:
Yeah.
AVDI: [Chuckles]
MARTIN:
So, it’s not a big deal. But in terms of a large project, yeah you can get situations where you can’t see how to make progress easily. And sometimes, you just got to try a few things. And it might take you half a dozen things before you finally hit on something that will work. And that’s again, part of exploring and experimenting with things.
CHUCK:
In a lot of the projects that I’ve worked on in the past, there’s this discussion of technical debt. And usually, most of it is stuff that we want to refactor because we hate working on whatever it is in the codebase. Now, what point though do you take it all and you say, “You know what? This thing is so burdened with technical debt that it’s not worth saving, and you go back and restart.” Is there a good way to know that, to measure that?
MARTIN:
That is an interesting question. But let me back a little bit to say the thing that I really like about the technical debt metaphor is it gives you a way of thinking about the cost of suboptimal design in your system. It’s basically saying that if you’ve got a system that’s got suboptimal design, it is like a financial debt. And as with a financial debt, there are two things you can do. You can either continue to pay the interest payments, which means the extra cost, the extra time, every time you have to do something. Or you can pay off the principal, which means cleaning it up and removing the problem. And neither of those two is always the best thing to do. You’ve got to make a judgment based on the circumstances.
So, an example where it’s okay to not clean up the code would be a situation where you’ve got a module that’s horrible but you pretty much never have to modify it. In that situation, you’re not actually paying much interest payment so you’re okay leaving it the way it is. But of course, if you’re constantly going through and paying lots of interest payments all the time, then you want to start working off paying the principal. And of course, it’s not an all or nothing decision. You can pay it off in pieces.
So, I wanted to say that first because that’s an important part of technical debt that a lot of people miss, is that tradeoff between interest payment and paying off the principal. But then that leads to your question. At some point, when do you say, “Well this lump of code is just such a mess. I can’t refactor it. I have to throw it away and rewrite it.” And that again is one of the hardest decisions in software development. I think at the time I wrote the book originally, people were a little too keen to throw away and start again, and not think about refactoring. And we’d run into a lot of projects that were rewrite disasters in their own sense. Interestingly, now we’re beginning to think about the balance, whether it’s shifted or whether the tradeoffs get more interesting.
And actually, the post I was working on this morning which hopefully will be out by the time this episode goes live, is on what I’m referring to as sacrificial architecture, the idea that sometimes it’s perfectly okay to say, “I’m going to build this system,” particularly in context of things like startups but I suspect in many other contexts as well, ”and I’m not going to worry about what happens if it gets 100,000 users, because I’m going to build it with the expectation that once it gets up to 10,000 users, I’ll throw it away and rewrite it from scratch.” And we don’t tend to think of software deliberately written to be thrown away once you get beyond a certain size.
But often, it actually makes sense because to build a system and try to put too much scale ability to it early on, that imposes a lot of extra baggage that is going to be a problem if you’re still trying to figure what on earth the system ought to be in the first place. And you look at a lot of successful website outfits, they did this scratch, rewrite, throwaway business multiple times. EBay is an example. Twitter’s an example. Amazon’s an example. It’s regular practice at Google. But what we’re not yet ready enough, not yet got enough, is that sense of when do I make that cut between rewrite and refactor. And unfortunately, it’s like so many of these things, it’s experience and it’s not something that I can find easy to describe at this point.
AVDI:
Do you think it’s time to start estimating at the beginning of a project what we intend the lifetime of the project to be? Not the project, but the lifetime of the codebase to be, and making some decisions based on that?
MARTIN:
I think it’s a good idea to sit down and say, “Okay, what are our expected parameters for what we think this codebase should be able to cope with? And what are the signals that indicate we should think about scrapping it?” particularly in situations where you have got a potentially high growth. I think that could be quite often a useful thing to do. I think it’s also worth saying that with almost any system, it’s worth putting a little bit to your mind to saying, “How would I get all the things that I can do that would allow it to be gracefully retired in the future? Because eventually this codebase is going to become, hopefully this codebase will become not capable enough because of all the load we’ll get. So, how are we going to deal with handling that when the time comes?” Those are things that we don’t tend to think about much with our code.
JESSICA:
That’s really interesting, Martin. What are some of the things that you can do to be like a polite legacy codebase?
MARTIN:
Well, I think one of the best things you can do is have a good modular structure. So that as a result, you can tear out and replace module by module rather than having to tear out a whole system. The problem of course with that is we historically have great difficulty in creating good modular structures. And of course, early on in the project you probably don’t really have a good idea what the modular structure ought to look like. It’s often a truism with software, is that you don’t know how it should be designed until a year after you’ve started programming it. And that’s true whether or not…
JESSICA:
And then you really keep…
MARTIN:
And that’s true whether or not you actually spent a lot of time thinking about the design in the beginning. It’s only when you’ve been programming it for a year that you’ve really got and you design what it should look like. And as I think you were starting to say and I cut you off, even that understanding is temporary.
JESSICA:
Exactly.
MARTIN:
Because over time you will learn more and more.
CHUCK:
I want to ask another question. And this was something that I was thinking of while you were talking. And that is, how much of the refactoring you do is related to this increase in knowledge that you get as you work on a project versus just learning better practices or better ideas about how to work nice code?
MARTIN:
Oh, a huge amount is based on learning about what your codebase is trying to look like. I think it was Kent who used a metaphor that you should always listen to your code and get that sense. And Kent’s one of the best programmers I’ve ever worked with, and was back when we were working together in the 90s. And he was always trying to understand what should this code look like? And it’s very dependent upon the situation on the local project that you’re working with. The experience helps you recognize things faster. It gives you more tools in your toolbox. You can see things a bit clearer. But there’s still a huge amount that you have to figure out by actually working at a problem and working it through. Even very best developers will run into this situation all the time of, now a year after starting programming this I now know how I should have done it. That’s a universal thing I hear from the very, very best developers.
AVDI:
Martin, lately you’ve been documenting some microservice architecture patterns, right?
MARTIN:
Yup.
AVDI:
I’m curious. When you talk about modularity, traditionally when we talked about modularity we’ve mostly been thinking about modularity within a single program, classes and modules and whatnot. Should we be thinking more about modularity in terms of separate services now? Is there a point at which or are there certain projects within which we should be thinking about modularity more in those terms?
MARTIN:
There are certainly projects where we should be thinking more in those terms. I’m still a little bit unsure about the whole microservices thing. I’ve written about it a fair bit and I particularly, the main reason I wanted to do this was because many of my colleagues have had quite a lot of success with microservices style. And I wanted to have a good definition of the term. And I want to increase the understanding and learning from it, because a lot of things get talked about and they don’t have a clear definition early on. And then it leads to all sorts of confusion. And so, I wanted to nobble that by saying, “Here’s a definition to work with that hopefully is as good as we can get it.” And that was the purpose of my main microservices article.
But exactly when you should do it is an interesting question, because there are a lot of benefits from having separate services. You can independently deploy the services. You can independently scale the services. You get an enforced modularity which most programming languages’ environments just don’t give you. You can really solidly say what your interfaces are. And you can make damn sure that you’re never passing mutable data across module boundaries, things like that.
But on the other hand, as soon as you move to a distributed design, distribution is a huge complexity booster. And in order to get distribution to perform effectively, you’re probably going to have to go to an asynchronous call mechanism. And asynchrony is a huge complexity booster. And so, you take on quite a price. And the tradeoff between those two things is really quite significant.
And this also plays into the sacrificial architecture idea, because your first, your early attempt, you probably don’t want to go down the microservices route because you don’t really know what your module structure’s going to look like. You’re still trying to figure out what on earth’s the system you’re trying to build from a user experience and from a functional sense. So, you want to be able to rapidly change things within the structure. And only when things begin to solidify is it a good idea to peel out things into separate services.
But this area is still very new. We’re still really getting only the first indications of what is a good and bad practice. So, the best I can do is listen to the people and try to pick up what I can and distill as much signal as I can from all the stuff I’m hearing.
JESSICA:
That is a fantastic description of the tradeoffs of microservices. In programming, it’s always great to break things apart. That’s ‘decomplexing’ and that’s almost always a win. But in order to break them apart, you have to glue them back together. And with microservices, what is that glue?
MARTIN:
Well, exactly. And the danger is that you’re shifting complexity from, yeah back up a little bit. But you’ve got your, you’re doing a good thing in that you’re breaking up your code into individual services, all of which can fit in your head and are easy to understand. But to what extent are you shifting the complexity into the interconnection between the services, which is much harder to reason about, because it’s separate service calls, separate requests. There’s a very interesting set of tradeoffs here. And we’re still in the early days of understanding where they’re going to fall out.
JESSICA:
Right. When you want to know what services connect to what, you wind up reading log files, which is basically using a debugger. You’re just finding out what happened rather than reasoning about what can happen.
AVDI:
[Chuckles] Even less static data available than in a Ruby program. [Chuckles]
CHUCK:
Alright, well I hate to do this but I have a time constraint that I have to meet. So, we’re going to go ahead and do the picks. Avdi, do you want to start us off with the picks?
AVDI:
Sure. I pick that we keep doing this for another hour. [Laughter]
CHUCK:
I have another show in a half hour. So, I’ll just bring those guys in and we’ll talk about refactoring Ruby and AngularJS.
AVDI:
Yeah, that sounds good. Nice big party.
MARTIN:
Well, the nice thing about refactoring is it does apply to pretty much any software you ever write. So, all languages, all platforms, refactoring is an important technique.
CHUCK:
Yup. So, everybody should read your book.
AVDI:
Alright. I know this one has been picked on the show before. But it was really, really good. I finally finished ‘Thinking Fast and Slow’. It’s been my most recent book to listen to while running. And I really can’t say enough good things about it. I think it’s one of the most important books I’ve ever read. There have been lots of books that I’ve read that teach me about, that teach me facts. ‘Thinking Fast and Slow’ is a book about questioning how I know the things that I think I know, whether I really know them, whether I am biased in ways that I don’t understand, understanding the fact that even professionals who are aware of biases are still biased, and just all those little mental bugs and flaws that we don’t think about and that screw up how we evaluate the world. So, as sort of a meta book on understanding all things that other books tell us, I think it’s really, really important. So, that’s ‘Thinking Fast and Slow’ by Daniel Kahneman.
MARTIN:
And your next task is to figure out who first picked that on this show.
AVDI:
Was it you?
MARTIN:
[Makes buzzing sound]
[Laughter]
JESSICA:
Is that a positive or a negative [makes buzzing sound]?
MARTIN:
I don’t know, but it’s fun. [Laughter]
CHUCK:
I so need a soundboard for this show.
[Laughter]
CHUCK:
Yeah, whenever somebody says something that’s a little bit, you know, yeah I’ll just play that back. You know what Martin Fowler thinks of that? [Makes buzzing sound] [Laughter]
AVDI:
Okay. Here’s a program-y pick. I just read this article on functional reactive programming last night. There are lots of articles about functional reactive programming, but this one was really good. It’s called ‘The introduction to Reactive Programming you’ve been missing’ by Andre Staltz I think. And it’s actually all just in a gist on GitHub. But it’s really cool. It basically explains functional reactive programming in terms of, it uses the JavaScript reactive extensions to explain it but it makes a very strong point of conveying the general ideas of FRP using that, rather than making it very specific to JavaScript. And it has diagrams which always make an article like this better. I think it’s definitely the best thing I’ve seen on FRP so far. So, check that out.
And finally, I’ll do an equipment pick. I have had my latest Rollaboard bag for long enough and taken it on enough trips now that I feel like I can recommend it. I did a ton of research before getting a new carry-on bag and looked at all kinds of bags that are $400 or $500. But I wound up going with the Travelpro FlightCrew4 Rollaboard. And it’s not the lightest or the most fancy or anything. But it’s the one that flight attendants carry. And if you go shopping for this, you got to be careful, because Travelpro has two lines. They have the consumer line which is just their Crew line which is confusing. And then they’ve got their FlightCrew line.
And you cannot get the FlightCrew line on Amazon or big retailers like that. You have to go look for a site that caters to pilots and flight attendants to get the FlightCrew line. But the FlightCrew line tends to be highly recommended by people who travel a lot. And I really like it. It’s just really sturdy. You can tell that the parts are well thought out and they’ve been refining the design for a while. You can tell that the parts are easily user-replaceable. Everything is user serviceable. It just reminds me of my ThinkPad. It’s just boring and ugly and really solidly built.
JESSICA:
Does the surface accept stickers?
CHUCK:
[Chuckles]
AVDI:
It’s sort of a semi-hard… it’s got nylon on the outside. I think you could put stickers on it. I think that would work. I haven’t tried yet.
JESSICA:
Any black bag can be fixed with enough stickers. [Chuckles]
AVDI:
Alright, that’s it for me.
CHUCK:
Alright. Jessica, what are your picks?
JESSICA:
One of my picks is a Bash program, or Linux. The other day, we’re parsing through log files and I learned about split, which does exactly what you think it would do. It chops my log files up into portions either by line or by bytes. And then I can check through a smaller log file rather than the two-gigabyte log file that I just downloaded from production. So, split is useful.
My other pick is a conference. So, 1DEVDAY Detroit is November 15th. And I’m not speaking this year but the last time they held it I did. And it was a really good, small conference. It’s one day. It’s a Saturday. It’s $80. Bruce Tate is doing the morning keynote, and that should be really good. If you’re in the Detroit area, it’s probably worth your time. That’s all.
CHUCK:
Alright. I have two picks. The first one is sleep. That is how I am surviving this cold.
And the other pick is I started playing another game on my iPhone. It’s called Farm Heroes. It’s like Candy Crush. It’s made by the same company. But anyway, you’re lining up vegetables instead of candies. So anyway, I’ve just been down for the last few days [chuckles] and that’s all I’ve been doing. Martin, what are your picks?
MARTIN:
Okay. So, I have two. And the first is technical. It’s slightly self-serving because it’s a link to something on my website. But it’s not, because it’s mostly featuring somebody else. And this came out of the ‘Is TDD dead?’ Hangout that I did with David and Kent. And I ended up having a conversation with my colleague, Badri Janakiraman who was on this show a couple of months ago. And we ended up having a very interesting set of Google Hangout discussions.
And what we talk about really is the attitude you have with Rails and particularly the idea of the Hexagonal architecture with Rails. So, we talk about what is a Hexagonal architecture, what it means in Rails context, whether you should use an Active Record or a Data Mapper approach for talking to the database with Rails, and fundamentally whether you should treat Rails as a platform or as a suite of components. And it’s primarily Badri based on his experience. But I think it really distills this stuff really well. And I’ll give you the link. There are two videos, each about half an hour long. But also, the link has a page with all the important stuff written down in text for people like me who can’t stand watching videos.
And then for my second pick, I’ll move nontechnical and I’ll be inspired by Badri, because not just is he an ace programmer but he’s also one of the leading experts on cocktails in San Francisco. And so, for my second pick I’m going to pick a book called ‘Imbibe’ which is a book about the history of cocktails that also talks about what cocktails are. There are lots of recipes and things in there. But what I like about it is the effort the author’s gone through to try and figure out where a lot of these cocktails have come from and the different variations they pick up with over time. And so, it makes for a very enjoyable read as well as plenty of opportunities for serious practical study of the subject.
CHUCK:
[Chuckles] Awesome. Well, one other thing that I want to announce really quickly. On the 30th, Jeremy Kemper and Eileen Uchitelle are going to be, we’re going to be doing a Google Hangout webinar and they’re going to be talking about the new features in Rails 4.2. So, if you want to go, I know that most of you are in the car with your phone or doing the dishes or something, so rather than have you go to a website, if you text “Rails” to 38470, then you will get details on that. And we’ll tell you how to join. You’ll get a little voice message from me about a half hour before and a text message reminding you about it about 15 minutes before. And we’ll get a website up for it, too. But for right now, that’s the best way to do it. So yeah, if you’re interested in learning what is new in Rails 4.2, then once again text “Rails” to 38470. And that’s it. That’s all I’ve got. So, we’ll wrap up the show and we’ll catch you all next week.
[A special thanks to Honeybadger.io for sponsoring Ruby Rogues. They do exception monitoring, uptime, and performance metrics and are an active part of the Ruby community.]
[This episode is sponsored by MadGlory. You’ve been building software for a long time and sometimes it’s get a little overwhelming. Work piles up, hiring sucks, and it’s hard to get projects out the door. Check out MadGlory. They’re a small shop with experience shipping big products. They’re smart, dedicated, will augment your team and work as hard as you do. Find them online at MadGlory.com or on Twitter at MadGlory.]
[Hosting and bandwidth provided by the Blue Box Group. Check them out at Blubox.net.]
[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit CacheFly.com to learn more.]
[Would you like to join a conversation with the Rogues and their guests? Want to support the show? We have a forum that allows you to join the conversation and support the show at the same time. You can sign up at RubyRogues.com/Parley.]