**Update!** The Ruby Rogues Panel video can now be viewed on Confreaks! Check it out!
- Josh Susser (twitter github blog)
- Avdi Grimm (twitter github blog book)
- David Brady (twitter github blog ADDcasts)
- Charles Max Wood (twitter github Teach Me To Code Rails Ramp Up)
- Katrina Owen (twitter github blog)
- James Edward Gray (twitter github blog)
02:29 – Best Practice Patterns
03:24 – James Edward Gray: Why Best Practices?
06:58 – Katrina Owen: Naming Things
10:03 – Charles Max Wood: Best Practices and Style Guides
14:13 – David Brady: Code Readability
18:41 – Josh Susser: Aesthetics
23:00 – Avdi Grimm: Don’t Get Clever
28:26 – Questions From the Audience
Understanding Computation: From Simple Machines to Impossible Programs by Tom Stuart! He will join us for an episode to discuss the book on August 14th. The episode will air on August 28th. O’Reilly has generously offered our listeners a discount code. Use the code RUBYROGUES to receive 50% off the eBook and 40% off the print version. *Discount does not apply to the ebook + print bundle.
Accessibility with Brian Hogan
JAMES: I’m talking like I normally do.
[Hosting and bandwidth provided by the Blue Box Group. Check them out at BlueBox.net.]
[This podcast is sponsored by New Relic. To track and optimize your application performance, go to RubyRogues.com/NewRelic.]
[This episode is sponsored by JetBrains, makers of RubyMine. If you like having an IDE that provides great inline debugging tools, built-in version control, and intelligent code insight and refactorings, check out RubyMine by going to JetBrains.com/Ruby.]
[This episode is sponsored by Code Climate. Code Climate automated code reviews ensure that your projects stay on track. Fix and find quality and security issues in your Ruby code sooner. Try it free at RubyRogues.com/CodeClimate.]
JOSH: Hi. So we may not need an introduction, but I’m giving you one anyway. We’re the Ruby Rogues. I’m Josh. This is Avdi.
JOSH: David, Chuck, Katrina, and James.
JAMES: Hello everyone.
JOSH: We’re almost ready to get started here for slides, but I’m not going to wait for them because the intro here doesn’t really need them.
AVDI: Somebody might not know what the Ruby Rogues are?
JOSH: Hey, who listens to us?
DAVID: Welcome to our show.
JAMES: They are on our show right now.
JOSH: How many people here are on the Parley Email list? That’s really cool. I’m going to make the announcement now, rather than later. One of the things that we’ve been working on for a little bit is, we had Jeff Atwood on the show a couple of weeks ago, a month or two ago, something like that. And we talked about Discourse which is this really cool open source project they’re doing to reinvent forum groups.
AVDI: Built on Rails.
JOSH: Built on Rails with Ember is the frontend and we’re going to be moving the Rogues Parley list from a Google group Email list to a Discourse forum. We’ll have much more flexibility in how to manage conversations. We can plenty of off-topic stuff. There’ll be a place for recruiters to send their spam. It’ll all be wonderful.
Okay. So, we have slides up now. Now, I’ll talk about what we’re talking about today. I’m just going to do a quick intro then we’re all going to each take three minutes and tell you our position and then we’ll have a little fun debate and you can ask us questions too.
The topic today is best practices. Many of you may have heard of this book, ‘Smalltalk Best Practice Patterns’. We had Kent on the show quite a while ago now and talked about this book. Everybody says we really need a Ruby version of this book. So, we’re writing one.
JOSH: We’re going to be working with Pearson. They do the Professional Ruby Series, the books with the red covers. I’m sure you’ve seen a lot of them. Tomorrow, we’re going to be going down to the South of the River here in Austin and spending a few days in a house and having a retreat and starting the book. Sometime next year, you’ll be able to buy this book.
Now, we’re going to tell you why you should care about best practice patterns or best practices. So James, can you start us?
JAMES: Yes. But we have to switch slide notes [Chuckles] because there are a lot of us.
JOSH: By the way, how do you like the hats?
JOSH: Or headwear in general?
JAMES: That’s not the right question. Who wins best hat?
JOSH: Okay, that one can be at the end.
JAMES: I’m sorry. I’m sorry. Okay.
JOSH: By the way, I couldn’t bring myself to wear a hat. I spent too much money on this hair.
JAMES: Okay. If you listen to Ruby Rogues at all, you know I’m the super talkative one, which is why they made me put in this slide. I want to show you my one point. Here it is.
JAMES: If you can’t see that, it’s a period. Okay, so that’s it. Thank you. No, I’m just kidding. It does tell you a lot about my personality though, that they gave me a really tight time limit and I would still burn three slides on a joke.
JAMES: Alright. So, I’m going to tell you why you should care about best practices. To use an example, this is a discussion I had online recently with several people, when you gist and some comments. These are the different ways you can use Struct if you want to add custom methods. A lot of times, people use the top form where they just inherit from what Struct returns and put the methods in there. But you can also choose to pass a block to Struct and use that. I like the latter one, but that’s not the point. Try not to get hung up on that as we talk about this.
One of the reasons I do prefer the latter one is that if you use the latter one, then a Struct with custom methods looks similar to a Struct without custom methods. There’s this concept that Josh talks about a lot about code malleability where it’s easy to transform code. In this case, you can just add or remove the block to turn it into the opposite one.
The other complaint I have against the inheritance one is that it actually uses two classes, the one that gets returned from Struct and then the one that you inherited back from. This can cause problems if you’re using any kind of code reloading, because if this code gets executed a second time, you’ll get a different parent class and then Ruby will complain that the parent classes don’t match and you get an error.
But my way is not all roses. Aaron Paterson pointed out that if you do use the class inheritance one, then you have access to super. You can write methods like you always do because they’re at a higher level in the class hierarchy so you’re fine to super up to them or include some Mixin, the supers up to them, whereas if you use my way, you need to use this alternate syntax to access the hash version of it. Ruby 2.0 kind of solves the Mixin problem since we can just prepend it instead of include it.
The point isn’t that I’m trying to tell you the right way you should code your Struct. I’m just saying that this is interesting. There’s a lot of interesting concepts around this like code malleability and stuff like that. By having these discussions, we learn from each other and get to a better style of programming. To me, that’s the point. That’s all I have.
KATRINA: I’d like to talk about naming things. I started a project recently. Sandi mentioned it. It’s called exercism.io.
KATRINA: One of the first exercises there, the first exercise there, is a simple class named Bob. Bob is a lackadaisical teenager and he has a very limited set of responses. One of them is if you shout at him in all caps, he responds, “Whoa, chill out!” To everything else, he responds, “Whatever.”
The absolutely simplest form of this usually looks something like this. You get a string, you check whether or not the upcase version of that string is the same as the string, and if so it’s, “Whoa, chill out!” and otherwise it’s, “Whatever.”
I found that some people suggest that you should name this piece of logic, the s equals blah, blah, blah is implantation details. We can hide it. If we go back to the readme, it says that if the string is all caps then do the one thing. Some people then say, “Is it all caps?” and name that concept. I’d like to say that that is still an implementation detail.
What we’re actually talking about here is, “Is someone shouting?” So, shouting is interesting in this context because it’s telling the story of Bob and his interlocutor, however that’s pronounced. I’d rather see this thing called shouting.
There’s more here. This shouting, right now, we’re passing the message into shouting. Bob is determining whether he’s shouting or not. We can move this. We can say shouting is a phrase and we can check if the phrase is shouted. This leaves the logic of determining what is shouting, what is eventually then yelling or whatever, to the phrase itself.
There’s more. S is very, very generic. In this context, we’re actually talking about drivel. It’s a conversation. It’s meaningless. Choosing the name drivel will tell the reader that this is meaningless. This is drivel. This isn’t a serious conversation. So, this is a lot more complex than what we started out with, but there are names here that tell us the story of Bob and the person he’s talking to. And that’s all I’ve got.
CHUCK: Alright. Before I get going, I just want to give a quick shout-out to Mandy. She’s over there. She edits all of our shows. She writes up show notes.
CHUCK: She really does a lot for the show and a lot for me personally. In fact, before I came down, my wife told me that I had to tell her that she’s not going anywhere because my wife appreciates the time that she saves me. Anyway, I just want to give credit where it’s due.
Let’s talk for a minute here about best practices. One of the issues that I have a lot with some of the best practice discussions out there are the discussions where somebody says, “You should always do this,” “You should always do that.” There’s always a situation where, I just choose that word, there’s usually a situation with most of these best practices where there’s a tradeoff.
Now, the interesting thing, if you listened to Katrina’s talk earlier, was that she talked about the Dreyfus model and she talked about how with beginners, with novices, advanced beginners, a lot of times they just follow the rules. There are things that they do and they do it because somebody told them to. They don’t completely understand those tradeoffs.
I think it’s an important thing to consider with best practices because they don’t have the information to make the determination of what’s the best practice given a certain context. Under those circumstances, a list of best practices or a set of rules pulled together into a style guide can be really helpful for beginners. That’s a lot of what I think the book is about, when we start putting together a list of best practices. It’ll help people start the conversation if they have the experience to have that. But for beginners, it tells them where to start and how to avoid some of the issues they don’t even know they’re going to have.
I’ve started looking at the style guide for GitHub. GitHub has a style guide up for Ruby. I just picked a few examples that I like for various reasons. This example, you can see that the difference is just if condition then versus if condition and then the body. This isn’t a major thing, but if you’ve listened to — I keep talking about Katrina but she gave a talk a while ago about refactoring and she mentioned code junk. In this case, the then doesn’t mean anything. It doesn’t do anything. It doesn’t add anything to the conversation. It’s just clutter. Some of the best practices are simply about readability, about focusing on what’s important. You’re probably going to hear a lot of that as you ask questions and read the book and talk to us and hear us talk about these things on the show.
Some other ideas out there such as — and I’m not going to go into the why on a lot of these, but doing flow control with exceptions. How many of you have done something like the top example where you rescued some exception when really what it was, was a fancy else? I think we’ve all made that mistake. I’ve done it. Other people have done it. The other one that’s my favorite is where you do a rescue and then return nil, so you have rescue nil at the end of the line. Everybody wants flow control because you’re saying that you don’t care that something bad happened. It’ll save you these troubles and if you give them a style guide like this, then they won’t make this mistake. They’ll just do it that way because you told them to. Then as they move ahead, they can start to build context around why they should or shouldn’t do something. The single-quote/double-quote, how many of you have had that debate? That’s one of my favorites.
DAVID: It’s on Parley.
CHUCK: It was. It was on Parley. You can go look at the benchmarks, doesn’t make any difference. Anyway, GitHub’s recommendation is to use double-quotes because there’s no penalty for using double-quotes for a string. Those are all of my examples.
But the whole idea is that you can avoid some of these issues. You can make sure people are doing the right things, at least to start with, by giving them a set of rules to follow. Then as they gain experience, as they move up that Dreyfus scale, then they can start to use that experience and knowledge to actually make their own best practices and choose the things that they should be doing. That’s all I have.
DAVID: So, it’s just over this talk and ended up throwing everything out last night because I had this huge epiphany that — oh, that’s not good. Okay. We’re not dealing with slides because the disk appears to have corrupted them.
Awesome. Alright, less [inaudible]. I have three code examples and I have three minutes to give them and I was joking about how they needed to be so simple that I could give them without needing slides if I wanted to do this in three minutes. Alright, broken slide deck. Rock.
Okay, so I wanted to talk about patterns and why patterns and when you should and wherefore. What I realized was I wanted to talk about cognitive loads, the amount of crap you have to keep in your head when you’re trying to debug code and work and understand stuff. Then I realized late last night, no, what I wanted to do is just come up here for three minutes and just beg you to please write readable code.
DAVID: The first example I have is an array123.inject+. This is Ruby’s method if you’ve got a functional programming background, this is reduce. Or if you’re from Haskell, this is fold. If you’re from Ruby, this is going to add up all these things by injecting the plus thing. From a functional standpoint and talking about primitives, that’s great. But from an OO standpoint, what I really want to do is access array, “Please Mr. Array,” I love that phrase from Sandi, “Please Mr. Array, what is the sum of your elements?” I want to say write out sum. I would like that in code. The great thing is that if you’re new to Ruby, you’ll look at 123.sum and go, “Hey, that should be six.”
The problem is if you’re advanced at Ruby, you’ll go, “Wait a minute. There is no sum method on array. How do I debug this?” You can get into a big argument about what this is about. This is a monkey patch. I’ve inserted the sum method into array. Guess what? It’s self.inject+. If you work with me, you know that you can go to lib/patches/array, actually in this case, enumerable, en.rb, and that’s where you’re going to find the en patch. But if you don’t know this, you might go to Enumerable. So cognitive load. Where do we make things more readable? It’s a discussion. What I’m saying is it’s a tradeoff. It’s always a tradeoff. How about that?
JOSH: Except for when it’s not.
DAVID: Except for when it’s not. The second example that I had was I wrote this quick little bit of code of sell me this sandwich. It was like, if sandwich has bread, do this thing, if sandwich has mayo, do this thing. If vending machine includes sandwich, wait a minute, I was having a lovely conversation with this sandwich and now I have to talk to the vending machine.
There’s another monkey patch that I love to write, which is object.in?collection. And it just is collection.includeme. Again, an entry-level Rubyist will read through this and go sandwich.in vending machine, that’s really clear, makes total sense. But boy, if you don’t know what it does and you’re trying to debug it and you try to go to ruby-lang, or rubydoc.org, you’re not going to find this method. So, there’s cognitive load. You have to have this discussion with your teammates. You have to know where this stuff is coming from for this to work. This is great that I don’t have a slide for this.
The last example, you want to make intention revealing names, but this can go horribly, horribly wrong. One method, we had users in groups, groups have users to send a message to people that are in your groups. You can imagine the code. User.group.members, map, flatten, unique. So I had a coworker who wrote the method user.all_users_in_groups_this_user_is_a_member_of. I just want to point out that if your method name has a dependent clause, you are revealing your intent to violate the Law of Demeter. So, it is intention revealing, or as Josh said, it’s self-incriminating.
DAVID: Everything’s a tradeoff. I argued that this should be renamed to peers. I lost the argument. User.peers lost because that was not a domain name in our project and our designers were like, “What are peers?” So, it actually would have increased cognitive load across everything. Everything is always a tradeoff. Think about that tradeoff. Please, please, please write readable code.
JOSH: Hi. Best practices. We’ve been talking about style as a big part of that, code style. In any conversation about code style, somebody always plays the aesthetics card. Aesthetics. What are aesthetics? Aesthetics is a sense of beauty or the appreciation of beauty. But it’s not just something that’s a sense of something. It’s also a set of principles that underlie and guide either the work of an artist or an artistic movement, or in our case the style of code. But what that doesn’t mean is that you look at code and you say, “Oh, it just looks better.” Now you’re comparing a set of principles to evaluate something with your gut feel. A gut feel that develops over years or decades of experience, someone who’s that experienced can look at something and know intuitively, “Oh, that’s bad code,” or, “That’s good code,” because they have all this experience to draw on.
But for someone who doesn’t have that kind of experience, a gut feel is often misleading. It can be something that you’ve transferred from experience in another language that works somewhat differently or it could just be the result of inexperience or even lazy thinking. I think that when somebody plays the aesthetics card and says, “I think that code just looks better. I like the way it looks. It’s more pleasing to me. It’s more beautiful,” but they can’t back that up with an actual, rational, evidence-based justification for why it’s better, then I think that that’s a copout. I think that’s an excuse for not really doing your homework to understand why your code is doing what it’s doing and why you’re writing it that way.
So let’s get concrete a bit. In Ruby on Rails, the core team has a style preference to prefer symbols to strings. In almost all cases in the API, a huge set of cases, you can use symbols and strings interchangeably because they just send to_s to whatever you pass in and a symbol works just as well as a string. That can be really convenient in places. I can see there might be an argument for, “Okay, we have a string. A symbol looks a little better to some people maybe. One fewer character, it stands out a little bit in a different way.” But that can go wrong. Here’s a migration from Rails and this is the standard way that the Rails core team prefers migrations to be written. The generators work that way.
The schema.dump task unfortunately still uses strings so it’s not consistent and that got me in trouble in a bit of an argument recently. But this is how I prefer it, strings. I prefer it this way because you can actually tell that the strings have a different role than the symbols. The symbols are the names of options that you pass to the type methods, whereas the strings are the names of the things. Those strings don’t actually mean anything to the Ruby code. All they are is something that you pass to the SQL, DDL, and tells the database what to name the call up. You never actually care how that thing is spelled within the Ruby code. Okay, great. I don’t have to compare these things. The identity is not that important. It’s just a pass-through. I actually have some rational reasoning behind that.
There are also places where that can get, that style of not distinguishing between symbols and strings, can get you in trouble. Any Rails programmers here know what this does? How about this? If you’ve been using Rails for a while, you’ve been trained to think that symbols and strings are interchangeable. But when you use a symbol, it’s telling Rails, “Oh, call that method on me. Send that message to me.” Then the result of that method is what’s used as the [layout] name. This is an instance where the style can actually get you in trouble because it’s not well reasoned out. That’s all I got. Thank you.
AVDI: Hello. If you have followed my blog at all, you probably know that I get a kick out of clever solutions for things. It’s a hobby of mine, finding clever things to do with Ruby. I thought that my little addition to this would be talking about when it’s not such a good idea to be clever. Quick pop quiz. This code here uses standard libraries only. What does the true argument mean to transaction? If you’re like me and you use PStore all the time, you know that true there means read-only. I’m lying. Every single time I use that method, I have to look it up.
DAVID: Pop quiz?
AVDI: Pop quiz number two. Here’s something similar. In this case, what does the false passed to instance_methods mean? In this case, it means don’t include the super class methods. Again, I have to look it up every single time.
JAMES: Everybody has to look that up.
AVDI: So clearly, this is a style problem because those Booleans are meaningless to the reader. There’s a solution to this. There’s an approach to this that I’ve seen suggested by a number of people, including some of my fellow panelists. It’s this interesting solution that says symbols are truthy, right? Rather than passing a literal true to that method, we could just pass a symbol to stand in for that true value and we could give that symbol a nice readable name like read_only. Clever, right? This is a really clever solution. But unfortunately, there are some drawbacks to this approach. Frist of all if I didn’t know anything about PStore and I came to this code for the first time, I might look at that and I would think, “Oh, that’s interesting, read_only must be a special flag to that method. That method understands a read_only flag.” I might want to know more about that to find out what else I can pass in there. I might go searching through the documents or through the code for that string, :read_only. I’d come to a dead end.
AVDI: Because it’s actually not part of the API. I could just as well have passed :chunky_bacon in there and it would have worked the same way. It’s suggesting an API that actually isn’t there. Another little problem with it, at least in my opinion, is when we get to the negative case. Here’s the instance_methods where we want to pass false in. In this case, there’s no false version of a symbol. So to simulate that, we have to negate a symbol. I don’t know about you, but I’m not a fan of this !: business. It’s just not that readable to me. So there are some drawbacks to this clever solution. I want to suggest to you that the clever solution, not always the best solution. I want to show you an alternative here. This is very technical code, so I’m going to walk you through it one line at a time.
AVDI: On the first line, I assign a variable with a meaningful name called read_only and I assign it the value true. Then on the next line, I pass that variable in.
JAMES: Wait, can we go through that again?
AVDI: If you didn’t get that, I can go through it again. Here it is, the same technique, in case you didn’t catch that, applied to the other method call. This time I assign the false value to a variable with a meaningful name. Then I pass that variable in as the argument. Okay, it’s an extra line of code. But I feel like this is probably a better solution, even though it isn’t as clever. Now we can take this a little bit further, because we can actually do an inline assignment within that method call. We’re actually assigning the variable and then using the value right there inside the method call. But I think you know what I’m going to say next.
AVDI: Don’t get clever. I’ve actually watched programmers look at code like this or write code like this. The thing is, this looks like a keyword argument. I’ve watched programmers look at this and think that they were using keyword arguments, even in versions of Ruby that didn’t have keyword arguments. They were new to the language. So they had false expectations about the code they were writing and it was working by accident. Then when they try to change it, it didn’t behave the way they expected. So yeah, don’t get clever. Sometimes the simplest solution is the best solution.
JAMES: Can we talk about the actual problem there? If you define a method that takes one true/false flag, we will send David Brady to your house.
DAVID: I will sing Christmas carols at you.
DAVID: Actually, I want to know why you didn’t reopen the include_super symbol and have it return nil to be true.
DAVID: So that you could just say include_super and it’ll be false. It would be falsey.
AVDI: You cannot make arbitrary objects false in Ruby. It can’t be done.
DAVID: Oh, okay.
AVDI: Can’t be done. By the way, quick note. That whole problem is caused by APIs where a keyword argument would have been better.
JAMES: Yes. Okay. So we’re going to take some questions because we have lots of people here. We want to talk to you.
JOSH: Question time.
JAMES: Bring one. Good ones. Yes.
AUDIENCE MEMBER: In many ways, it sounds like the book that you’re planning to write, there’s some overlap in the conceptualization of the book that you’re talking about writing or at least [on the surface] it seems in a book like ‘Eloquent Ruby’ or other books that intend to teach beginners the usual patterns. How’s your book going to be different?
KATRINA: We actually figured maybe we could just take ‘Confident Ruby’, change the name and put all our names at the bottom.
AVDI: I was honestly hoping for a cage match with Russ, because I think I can take him.
JAMES: Josh describes this best.
JOSH: I actually have a serious answer to this. That’s that there are the things that you read and learn when you’re leveling up to master the language. Those kinds of things change as you get better. The kind of things that you do when you’re a beginner, you start doing different things as you become more proficient. The things in Kent Beck’s book, ‘Smalltalk Best Practice Patterns’, those are things that you do throughout your whole career and they’re things that you do multiple times a day whenever you’re working on code. When I work on code, I use intention revealing message names, intention revealing variables. I will extract method objects as a refactoring technique. Those patterns in Kent’s book are, in my opinion, they’re eternal. I will use them throughout my entire career of object-oriented programming. Russ’s book is a good book. I like it. But I think it has a limited shelf-life in terms of utility to me as a developer.
AUDIENCE MEMBER: If it’s more for a longer shelf-life and more career-driven approach, why would a Ruby-specific version help if they [value] ‘Smalltalk Best Practices’?
JAMES: That’s a really good question, actually. I learned Smalltalk to read ‘Smalltalk Best Practice Patterns’. Has anyone else done that? Seriously? Learning Smalltalk to read one book. Go ahead. Yeah, it works. I learned a lot and that was cool. But it would be even cooler to have one in Ruby not just because it saves you learning the other language, but it also gives us an opportunity to address Rubyisms. Ruby is not Smalltalk. It’s close in some ways and then different in other ways. One of the things we’ve been looking at is we take the table of contents and move it over. Ruby needs an entire section on its scripting capabilities, which Smalltalk doesn’t even have. It doesn’t work like that. It gives us an opportunity to address things that are specific to us.
AUDIENCE MEMBER: My question is actually a very good follow up to what you just said about having sections in the book to address things that are unique to Ruby. I think you have a really great idea and bringing over that book to an audience for whom Smalltalk isn’t really an option that they have the time to learn to go through. I’m in that group where I wanted to read it but I did not have time to pick up on the language to do so.
I think it’d be great if in the new version of the book you’re working on, you can include sections on using things like metaprogramming in dynamic languages and scripting in dynamic languages. As you said, you’re trying to make it so that it’s not just, “Here’s what I need to do as a Ruby developer, but here’s career things.” I think we’ve seen a lot of languages pick up on a lot of these features. I think using Ruby’s examples whether things work in every language or not, I think it’d be great to see examples of doing things like that that are practices that might not really have existed in that form back when the original book was written. I guess it’s not a question, that’s a comment. But what do you think about that idea?
JOSH: We do have a section in the outline on metaprogramming.
JAMES: So we agree.
AVDI: I think I’d like to point the conversation more toward just the general area of best practices, best practice patterns, rather than the book that we’re going to write because we can all discuss on Parley and stuff like that.
AUDIENCE MEMBER: Yes. There’s a case where you might have a conflict between your two different ideas. The gentleman with the red hat, the [Cable Guy]
CHUCK: I [inaudible] feel worse about myself now.
JAMES: It’s never getting old.
CHUCK: Nobody knows what I really bring to the [show]. [inaudible]
CHUCK: What was my question?
DAVID: It’s official. This is an episode now.
AUDIENCE MEMBER: It brings out the point, that there’s probably never ever any good answer, but your statement was with single-quotes versus double-quotes. I think some of the [inaudible] following that were the point was is to write code to show your intent. I’ve been following the theme lately to using single-quotes when I don’t do any interpolation. So that’s clear in my writing that it’s not going to be interpolated and can’t be interpolated. How does that bounce off you?
CHUCK: There’s a tradeoff, again. There is that intention, the string can’t be interpolated. However, if things change down the road and I do need to interpolate, it’s easier just to refactor something that already has double-quotes. I just add it in. Granted, it’s not a huge cost to change, but at the same time there is still a little bit of tradeoff. The other thing that’s interesting about style guides like the one that I was looking through is that it keeps things consistent. So if I’m looking for strings or if I am identifying strings, I can identify them by the double-quote and not have to worry about the single-quote case. There are the tradeoffs and it really just depends on what’s important to you.
JAMES: Your specific example, you say that using a single-quoted string reveals your intent there, which it does. The tradeoff is you’ve sacrificed some code malleability. If I need to use interpolation, now I have to stop and switch the string to double-quotes so that then I can include the interpolation. There are cases where you know that won’t happen. You’re pretty darn sure it’s not going to get interpolated, so it may make sense to make that tradeoff. If you’re asking me how I would handle that case, first I think it’s wrong to say always use double-quotes. I think it’s better to say, usually use double-quotes because. Then if you give the reason then you can go through the reasoning and when you reach the point where because doesn’t apply, you know that.
AUDIENCE MEMBER: And I agree. I’ve done a lot of single-quoting and have gone back to double-quotes on the same material.
AUDIENCE MEMBER: This is not about the book, but it’s going to sound a little bit like it, I think. You guys, you’re not all the same person. I suspect that you’re going to have differences of opinion.
DAVID: I also.
AUDIENCE MEMBER: I suspect that you have already had discussions about how to resolve differences of opinion for style guides. I’m interested in how you can take that discussion, whatever process you’re already thinking about for resolving the differences and talk about how other people can apply them back in their offices for the teams that they work on to resolve their style differences.
JOSH: We’ll let you know how it goes.
KATRINA: I think the first thing is to say that we know we have different opinions because we get into it all the time about it. The interesting thing is to discuss the reasoning behind it. This is what Josh was talking about. It’s not just a gut feeling. We have our reasons. Usually, I cede in this group. Avdi will always have a really good reason that I hadn’t thought about and I’ll just change my mind. You can do that, which is cool right? We haven’t discussed the strategy. Maybe it’s rock, paper, scissors, I don’t know.
JAMES: Rock, paper, scissors, lizard, Spock.
KATRINA: Of course.
JOSH: I like your strategy. Avdi’s always right.
AVDI: Well it works for me.
JAMES: Do they notice that Avdi’s slides could have also been titled ‘Why Josh and James are Stupid’?
CHUCK: I want to just add something to that. That is that we convoluted to it but we didn’t talk deeply about it. But there is also the conversation around context. Sometimes a best practice isn’t a global thing. It doesn’t always apply. In some cases, we’ll disagree because we have a different experience due to a different context. It’s possible that we’ll have conflicting best practices and we’re conflicting simply because under these circumstances, you’ll probably want to do A, and others you want to do B. There’s always a constructive discussion over when it applies, how it applies, and what our experience is. But everybody here is really good about explaining why and providing code samples and things like that. The discussions will be very well reasoned. I’m really excited about having those conversations.
JAMES: I think it’s actually a feature, not a bug. If half of us disagree, then there’s not really a good best practice. If we lock horns over it and we can’t bring the others around, and if we can then [all’s] the better. If we made a good argument like Avdi often does and sways the rest of us, then great. If not, then maybe that’s not a best practice or at the very least it’s a signal that we need to show it both ways and explain the tradeoff. Yeah, and we explain it to you. You have to have the because. It’s not, “Do this.” It’s, “Do this because.”
CHUCK: The book will be real short without the explanations, I think.
JOSH: I want to say real quick that the phrase best practices is a term of art in many professions. If you follow best practices, if you’re a lawyer or a doctor or an electrical engineer or a plumber, you do these things then to some extent it shields you from liability. You say, “I did the thing that everybody does and everybody expects or accepts as the proper thing to do.” Then if somebody sues you for malpractice you say, “But I was just doing the thing that my entire industry says we should be doing.” That’s from that perspective. I think it’s harder to come up with a baseline in what we do in engineering because the problems we solve appear to be much more varied. The whole point of best practice is I think it’s potentially a misnomer. We’re going with the name because there’s some tradition there. But because it’s a best practice doesn’t mean it’s the only practice.
JAMES: That’s great, yeah.
DAVID: I was talking to somebody yesterday. Forgive me, I can’t remember who. I believe it was one of the conference volunteers or organizers, about the book. He asked me, are you going to just take all six of your voices and just blend it into one homogenous thing? Because if you do, please god, I don’t ever want to read that book.
DAVID: Yeah, there’s going to be a time when five of us stand against Josh and Josh kicks our butt. Then there ends up, “Here’s the best practice. Here’s why we think it is.” Then there’s a crazy little sidebar from Josh that’s in his voice of the lone pariah crying in the wilderness. Actually, it’s probably going to be me in the sidebar most of the time.
DAVID: But if we can create a book with six different voices in it and still have a coherent narrative, I think we win everything. We win all things.
AUDIENCE MEMBER: Are you going to publish the Discourse in GitHub so we can for early and often on that Discourse? What are the mechanisms?
JAMES: Discourse is an open source project so you can already fork and contribute to it.
JOSH: The Discourse application is open source. The content is going to be private because we have the Rogues Parley list. Are you familiar with the Rogues Parley list? Okay, so for those of you not familiar, last year we set up an email list so that listeners of the show had a way to support the show production. So you can [anywhere] from $10 a year to what’s the top rate? $50 a month. [Chuckles] And we’ve had a few people do that.
JAMES: And then we leave your name on the show.
DAVID: Because you’re cool.
JOSH: And we love you dearly. So it’s a private email list. It’s very high signal to noise ratio. A lot of good content. All of the guests who come on the show get instant membership to the list and many of them come on the list and talk with us, from Martin Fowler to Kent Beck.
JAMES: Recently we did some episode and Martin Fowler chimed in about all the things we got wrong, which was awesome. It’s great. You can’t beat Parley. I have no idea how it happened but we actually own the best Ruby on Rails mailing list, not Ruby on Rails, Ruby.
DAVID: Rails, too.
JAMES: Yeah. It does have [inaudible].
AUDIENCE MEMBER: So I want to touch on what Avdi said about not being clever and ducktails off of what Steve Klabnik presented yesterday about using irresponsible Ruby to still be creative. I found myself in situations where I’m correcting people who are junior to Ruby. Maybe they’re experience developers. I’m like, “That’s not the right way to do it,” because they show me something that they’re excited about. They think it’s cool. I just wanted to ask you guys, how do you get people to use a best practice without squashing their spirit in the process?
AVDI: Alright, so the best way to avoid being clever is to be clever a lot.
AVDI: You’ve got to get it out of your system. If you’re anything like me and you enjoy that kind of thing, which hopefully a lot of you are. That’s a lot of why we get into this, awesome hacks. Steve nailed it. He said, “But don’t do it at work.”
JAMES: Or, “I will quit.” Or I will quit.
AVDI: You’ve got to have time and opportunities to do irresponsible coding and you’ve got to make time after hours. Honestly, I would hope that you have an enlightened enough workplace that you can have some hack nights or something where you just do fun stuff. I’ve definitely batted around crazy, crazy code in offices over the years. What I would hate to see is a culture of somebody says, “Hey, check this out,” and then the lead developer says, “That’s the worst thing I’ve ever seen. I don’t ever want to see anything like that again.” You’ve got to celebrate these hacks, but you also have to recognize that if you’re not sure what the implications are or something clever, then maybe it’s not time to put it into production yet. But by all means, foist it on an unsuspecting public on GitHub and watch what other people do with it.
CHUCK: One thing I want to add to that, and I’m just basically going to say the same thing in a different way, but it’s a different way of thinking about it. That is that best practices usually revolve around some commonly solvable case. If you’re out there writing irresponsible code like what Steve was talking about the other day, you’re probably going to transcend a lot of best practices by doing so. The idea, the crazy thing that you’re doing, there’s probably not a best case, best practice way to do it. You follow the ones that are idiomatic Ruby or what will help make exploring the idea easier but at the same time you’re probably going to go beyond what we’re talking about with how to solve a particular problem if that’s the whole point of your irresponsible code.
JAMES: Steve did also cover very well that there are two different modes of thinking. One mode has a time and a place and the other mode has a time and a place. When he engaged in app mode, he suspended the normal rules. Don’t do test unit. Don’t unit test. Change the rules.
JOSH: One of the things that I said in the panel we did at RailsConf last year, I don’t have the quote in front of me right now so I’ll paraphrase it. But it was Baudelaire said something about, be conservative in your daily life so that you can be daring in the things that are important to you. If you have a foundation of best practices that you follow, then you have a stable thing that you can rely on and have some confidence that that’s not going to be the thing that’s messing you up. Then when you want to take risks and do the irresponsible things or explore, then you know that that’s going to be the thing that you have to worry about breaking not everything else in your system.
SPEAKER: Thank you everyone. The LoneStar Ruby Foundation wants to extend our sincere gratitude for the Rogues coming here and having a panel. Thank you so much.
JOSH: Thank you. We are so grateful.
JOSH: We are really grateful for the opportunity. We don’t get to do this very often. Thank you.
CHUCK: Yeah, a big hand for the LoneStar Ruby Foundation.