NOEL: Hello and welcome to Episode 54 of the Tech Done Right Podcast, Table XI’s podcast about building better software, careers, companies, and communities. I'm Noel Rappin. On this episode, we've got Sam Phippen and Justin Searls back for their third round on the show. Both of them have been working on new Ruby tools to better standardize your team's style and code formatting. We talk a lot about why they've decided these kinds of tools are important and what their philosophy of coding style is and how they evaluate code when given a code sample to look at. It's an interesting deep dive into code style and Ruby formatting and how Ruby teams work. We'd like to hear from you. How does your team handle differences of opinion in code style? Let us know at TechDoneRight.io/54 or on Twitter at @Tech_Done_Right. Before we start the show, one quick message. Table XI offers training for developer and product teams. If you want us to come to your place of business and run an interactive hands-on workshop, we would very much like to do that. Topics range from testing to Rails and JavaScript to Agile estimation to taking money via Stripe, all kinds of things. Also, if you're in the Chicago area, be on the lookout for monthly public workshops starting in early 2019. For more information, email us at Workshops@TableXI.com or hit us on the web at http://TableXI.com/Workshops. Now, here's my conversation with Sam and Justin. Sam and Justin, would you like to remind people who you are and why you are here? SAM: Sure. My name is Sam Phippen. I'm one of two lead maintainers of the RSpec testing framework in Ruby on Rails. NOEL: And Justin? JUSTIN: Hi. My name is Justin Searls. I'm a co-founder at a software agency called Test Double. We do a lot of Ruby and JavaScript work with companies all around the world. It's been my goal since this podcast started that I could have a one-on-one session with Noel but he keeps inviting Sam. NOEL: Ha-ha! We could do a one-on-one. JUSTIN: I don't know what we'd talk about at this point because I think Sam and I have so tangled up our Ruby identity. NOEL: Yeah, which one of you is which again? Which one of you has the British accent? The last couple of times you've been on, we've talked about testing which I don't think we're going to, at least start with at this point. We're here because both of you separately went on and on with me at RubyConf about Hash Rockets and various and sundry and other Ruby formatting and structural things. Justin, I think you have announced a public project on that. Do you want to talk about that? JUSTIN: Yeah, let's talk a little bit about style. I need to kind of come clean and out myself as like the worst person on every team that you've ever been on when it comes to nit-picking about aesthetic choices for things like code style, like liking how code looks this way versus that way and bringing it up at the worst possible times. NOEL: So, you're the guy doing the whitespace commits? JUSTIN: Yeah, sometimes. Or at least it is in my past and I recognized, even I think at the time that it was often unproductive. It was difficult for me to overcome because to me, consistency is really, really important in a codebase to accomplish a lot of other downstream goals and it's very difficult, I found in a big, monolithic codebase that's highly inconsistent or high entropy, so to speak, to accomplish things like broad based refactors or just like swoop in and understand any given unit on what it does. In the interest of consistency, I have always carped on and cared a lot about code style and from formatting all the way to which method we use in which case and so forth. But recently, I think I have learned that the best way to tamp down or suppress that instinct for myself has been to have a tool that just enforces something -- some set of rules, basically, take the gun out of my hands and force myself and the team that I'm working with to just follow a prescribed approach. I learned this about myself when I adopted StandardJS after meeting Feross Aboukhadijeh who's the author of it and what Standard is is it's a rule set that set stands on top of ESLint for JavaScript and its only noteworthy feature is that it is not configurable, so Standard comes with a set of rules and you follow those rules and if you don't like those rules, tough. Because it's an external thing from the team, the team spends no time bikeshedding about those rules and additionally, it's sort of like eased my apprehension about specific quibbles that I really care about, about things like whitespace because it was out of our hands anyway. I could just hate the tool as opposed to other people on my team. I really like StandardJS for that reason and because I see a lot of our client teams really struggle with bikeshedding around RuboCop configurations or particularly onerous RuboCop defaults, that I would endeavor, with Feross' blessing to create a standard gem for Ruby that was very similar. The gem Standard, which has a binary `standardrb` and some Rake tasks and stuff to run, stands on top of RuboCop and it has a very -- NOEL: Define what a RuboCop is. JUSTIN: Oh, sure. RuboCop is the most popular linter and style guide tool for Ruby and it is noteworthy for a couple of reasons. SAM: I think parenthetically, it's probably the only one. JUSTIN: There is a tool called Rufo, R-U-F-O, which purports to do the same thing and there's a handful of other, I think smell tests like Reek, for example. It's a really cool tool for identifying different code smells and there's a lot of overlap in terms of where the style format ends and lint starts. NOEL: Right. RuboCop is notable for its voluminous number of options, you were about to say. JUSTIN: Yes and also, the unpalatability of its defaults. I think that regardless of intent -- you know, I don't have a personal bone to pick on this. I don't really know anyone who's been a heavy contributor to RuboCop, especially early on but while it's a very popular linting tool and definitely the most well-adopted in the Ruby community, I felt like its defaults don't really reflect very much of Ruby code that I actually see day-to-day. A lot of our client teams seem to agree because all of them customize this thing out of the wazoo. Because every team seems to be dissatisfied with the defaults, customization goes way up, which increases the amount of bikeshedding that you see in RuboCop way above and beyond what you see in other languages like JavaScript with ESLint, for example, so it felt like a really pressing issue to address and that's why, I think the Standard gem, if we can just get some adoption behind it, it could help resolve that for teams. NOEL: So you're trying to create, I think a low configuration -- I don't think there actually no configuration options on Standard Ruby -- a low configuration set of defaults. JUSTIN: Yeah, right. The configuration that's available is mostly quality of life like how am I running the thing, as opposed to customizing the rule set, per se. NOEL: All right. I have a couple of things I want to say but Sam, I will give you a chance to talk about this first, if you have something to add. SAM: Justin and I went back and forth fairly heavily while he was spinning up Standard. I think that Justin has made a lot of good choices but also, he involved me in a number of the making choices about what configuration defaults on top of RuboCop make sense. In particular, and I think nobody in the Ruby community was very surprised by this is that the day before RubyConf, I dropped my 'Hash Rockets are good actually' blog post, which is an opinion I've held for a really long period of time. I think it's one Justin agrees with and we were sort of trying to reinforce the case for using hashrockets as an enforced thing in Standard. Now, both Justin and I, I think have since come down from that hill but as a sort of reasonable sets of configuration defaults that you can't change, I really do like a lot of the choices Justin has made in Standard. Even if they're not the ones I would've made, they are at least quite defensible. I think Justin's doing some great work with that tool. NOEL: I've had sort of an interesting change of heart on this. Justing, I also was always the person on a team who is making weights-based comments and was super fussy about a particular method of indentation that made a lot of sense to me, that I could only marginally articulate to other people. Especially over the last two or three years, I've really moved away from that, at least in the sense where I'm able to give other people grief about it. A code that's not formatted that I want still kind of bothers me a little bit but I'm able to sort of deal with it more. SAM: I think the difference is between code being formatted the way that any particular individual or set of individuals wants and that being complete, well-enforced consistency across a codebase, right? NOEL: Yeah. I think that what I've seen is the value of having consistency even if it's not necessarily my consistency and some of that has come from language tools like elm-format that formats things completely differently than I would normally but which is consistent and fine and so well-integrated that it actually like I'm sloppier in my typing because I know the formatter will clean it up. SAM: Right. Exactly and I've been programming a lot of Go recently and Go has `gofmt`, basically everyone has set up to the moment they save a file, all the code just snaps into place and that's been in place since Go 1.0. I think part of this as well is that there isn't a single source in Ruby where we can all just agree that code looks like this and I think that's really the high level problem that Justin and I aiming down solving. JUSTIN: I don't think it's an accident that Ruby has either of these problems. First, Ruby attracts a lot of people, especially people who've been around Ruby for 10 years or more, like ourselves, it attracts a lot of people who are opinionated about aesthetics on code. Ruby, a big reason people came to is it's a beautiful language. You can do a lot of things, you can express yourself in a lot of different ways in Ruby and so, I think we have a high population of people with strong taste around how they like code to look. But then we have another problem which is at the same time, Ruby is an incredibly expressive language and we diverged in so many different styles. We talked about Seattle style and it conjures like a very specific look to how code is formatted that might differ dramatically from somewhere else, that certainly differs in various enterprises, maybe where they don't have quite as strong attachment to the community. Figuring out how to build a custom rule set that is simultaneously fostering consistency without kneecapping what is really awesome about Ruby which is it's highly expressive and you can express yourself in lots of different ways and establish a particular aesthetic, that's been probably the primary challenge in figuring out the right rule set for Standard. NOEL: Yeah. I think that also sort of some of Ruby's like Perl heritage shows up here, where there's the sense of it's a positive good to have multiple ways of doing things. I remember seven or eight years ago, I used to work at a consulting company called Obtiva. We had hired Michael Feathers, author of Working Effectively with Legacy Code, who had not, to that point, done a whole lot of Ruby and so, I wasn't exactly teaching him Ruby -- that would be presumptuous -- but I was showing him what Ruby aesthetics were and when he found out that you could leave off the parentheses in the method argument of a method definition -- the 'def methodName()' that you could leave off those parentheses, I said, "You can leave them off but I find it really ugly," and it really tickled him that you could do that and I think it also tickled him that it bugged me, so he would write all his code in what is effectively Seattle style just because he thought it was cool. I hate to lose that exactly, although that particular point of style still bugs me but here's a thing that is a little bit related. For many times over the last 10 years, I have popped on to Twitter and asked the question, "Would you hire an otherwise qualified Ruby developer if their code sample -- their incoming code sample -- was otherwise a reasonable but was indented four spaces." I don't know if my answers have diverged over time but to me they gets the question of like, "How important style is and how important community standards for what code looks like are?" SAM: To me, the answer to that question would depend on what that person's background was. If I was hiring someone who had 10 years of experience writing say, Java into like a senior Ruby engineer job but was confident they could pick up Ruby and they'd done that, I would be fine with it. If this is someone who is claiming to have a significant amount of Ruby experience coming in and then, I think no. It really depends on the person's background. JUSTIN: You know, I agree with everything Sam said. I think that the interesting thing is that in a broad sense, as technologists who also care about the social and interpersonal aspects of this industry, we talk a big game about how writing code and software is a very human act. It's a creative thing. It's about writing code that communicates to other developers well in the present and in the future. If that's true, then when we are evaluating other people's code, we need to be able to detangle several qualities of it. For example, does it literally do the job? Does it automate the computer to do the thing requested correctly? That's just one aspect of several. I think that if I were to get that code sample and evaluate that, I'd start looking for other indicators. For example, is it factored in small simple units? That tells me something about what they value. Is it tested? And when I see a style that's highly divergent from what the community does, I think what it tells me is some level of connectedness to the community at large because four space indents is so unusual in Ruby that it probably tells me that their experience writing Ruby is, to Sam's point, either limited or maybe, it's just cloistered off and in a sense, isolated. I think community involvement is super-duper important to being a successful programmer, especially in a highly dynamic language where there's a lot of tribal knowledge necessary to be productive but it's not the only thing. It's just something that I would probably dig into next. NOEL: Yeah, I think that was always my argument. That was that indicated a lack of community engagement and it was therefore, a valid data point. I think maybe, there would have been a time where I would have been harsher on it but I think now, I would just consider a data point to follow up on. SAM: Yeah. When I'm interviewing candidates, that's very rarely single points of elimination anywhere. I know this is a tangent but rather, you amass a bunch of signals to make a decision. NOEL: I actually think this is interesting. I would be very curious to know what either of you, because both of you I assume have evaluated code samples, as have I, for developer positions and I'd be really curious to know what kinds of things you look at. I think this is adjacent to the style question. SAM: I'm happy to take this left turn if you are, Justin. JUSTIN: Yeah, sure go for it. SAM: When I've looked at people's code homework submissions, usually a few things I have looked for and most of my recent hiring experience has been with more senior engineering roles and so, that certainly colors the evaluation criteria a little bit but one of the things is like, "Is it functionally correct did they actually do the thing the exercise was asking for without necessarily breaking any of the functionality?" and did they prove it? Can I understand? Have they written an appropriate amount of codes for the problem? Too much or too little can often be an indicator of stuff. Justin gave a bunch of really good sort of code level things but then, also in the code homework that I was evaluating most recently, we had a bunch of required communication pieces, including write some documentation about the code that you've written but also, write a sort of design rationale for why you solved the problem the way that you solved it, like why you made such an architectural choices and what the tradeoffs were? That is actually where I got the overwhelming majority of my sort of opinion formed, is how the candidate was talking about architectural tradeoffs. Because some people were like, "We just used threads because threads is the obvious way to solve this problem," and I'm like, "That's not a design rationale. You're just saying things." I actually like how people talk about that process of designing software. At least for me, it was one of the more interesting evaluation points in the exercise that I used most recently. I don't know if that's helpful. NOEL: Yeah. My most recent experience is on entry level coders and we used one exercise at Table XI for entry level and senior level and I found that it is somewhat hard to calibrate your expectations to have a similar rubric for both entry level and senior level. One of the ways we get around that is we would consider certain things very damaging for senior level submission but wouldn't worry about them tremendously in a junior level submission. But I agree that the extent to which people are able to talk about and write about the rationale is very interesting. Sometimes, there's a little bit of ambiguity in our codebase. Certainly in our code sample, you could certainly interpret in different ways and I like it when people either ask questions or say in their comments that they have made an assumption about that ambiguity, rather than just sort of not showing any evidence that they thought about it all. SAM: It's actually pretty amusing to me. I think most everyone on the internet knows at this point, I recently went through a round of interviewing and I won't say which company is this is their coding homework but the company set me the Gilded Rose Kata as their interview homework and I think -- NOEL: Sure. A famous code problem -- SAM: Right, so -- NOEL: -- to be found in the internet. SAM: It turns out this is been sort of beaten to death in the Ruby community but in communities with other programming languages, it's not actually necessarily so well-known. I promptly break out the very standard and well-known path amongst our Ruby friends at this point. I get to my sort of review interview and the guy is like, "Oh, yes. Sometimes, people interpret it to mean this completely a different thing." I was like, "Okay, that's amazing," because we've been talking about this problem for literally, maybe five years in our community and I don't know that I've seen anyone ever take it that way and I was like, "Ah! Huh? Interesting," and so, it's really fun to me to think how we even have these well-established problems that can have ambiguity in them. Let alone, something that you've concocted for your own interviewing purposes. JUSTIN: I guess all that I have to add to this, because you both covered it pretty well. At Test Double, we also offer up to candidates a what we call a take home exercise and we're careful to not just make that something where somebody with a ton of privilege and spare time can really show off and somebody with more limited resources would struggle and so, we have like a lot of clear direction. For example, it's time boxed. We only want to see how much you can do in two hours and honestly, we don't disqualify people for a single reason very often but it's definitely not a good look if it's obvious that the candidate spent six or seven hours on this thing because it's just a basic follow directions aspect. But every now and then, there's the obvious stuff. We've had submissions to that where a person implements like all five of the stories of the problem in like one 1000-line long method and it's easy to point to that and be like, "Well, that's not good," or they'll go really, really afar and not write and any single tests. All that's interesting but it's really doesn't tell you very much, especially if they're somewhere in some acceptable range of solutions, until you talk to them. The first interview following that take home exercise is actually a talk through review of that code, where the candidate is in the driver's seat. They're talking you through their design, how they approached it, and we have a kind of a guided path of different challenges and without, I guess sharing the rubric, a lot of them are based on the presumption of let's push back, let's challenge, let's ask hard questions and just see how thoughtful the person was about those decisions, as well as whether or not it triggers any sort of defensive reactions because as consultants, we have to make peace with a whole bunch of different teams and we're not always going to get our way, so I found that to be a really great overall exercise but you walk away with a much more holistic measure than a person that can't code good. SAM: Yeah, for sure. NOEL: Our next step, similarly is a pair exercise using that sample as a basis and for much the same reason, we want to talk to person about it, we want to give them feedback, and see how they react to feedback and refactoring suggestions and things like that. That's often a much richer source of information than just the code. JUSTIN: If we were to take a right turn back on to our original topic of linters and formatters and the Ruby community, what else is there to talk about, other than to pour one out for our poor Hash Rockets? SAM: I am happy to go into a little bit of what I've been working on recently, which I think will be relevant and interesting to the folks at home. Basically, Justin and I have been texting about this probably, on and off for... What? Like a month now? Justin was like, "I want to build my thing on top of RuboCop because it's quick and dirty and I can do it," and I was like, "Yeah but I don't want to put RuboCop in my editor save hook. I just don't," and as I said, I've been programming a lot of Go recently and so, I sort of endeavored to start building a tool which is significantly faster than RuboCop, specifically for the formatting piece with a view to implementing most of the opinions in Standard, in sort of a new formatter that I'm lovingly calling `rubyfmt` for the moment because why not. And yeah, it's going really well. It's round tripping large files in like 50 milliseconds, which is just a little slower than I would like but it's acceptable, so I'm working on that. NOEL: What's involved in building something like that? How would you go about? What are you actually doing? SAM: Basically what Ruby Format does is it loads your file, it invokes Ruby's built-in parser in the standard library, which is Ripper, runs Ripper over your file, builds a syntax tree and then basically, walks the syntax tree like re-emitting all of the code from your file just, like, formatted. The idea here being that once this tool is complete and it's nowhere near complete yet, you'll sort of be round tripping files through it in the save hook, on your editor, to auto format them and run it over all the files as a CI check but unlike RuboCop, this tool is deliberately never going to know enough about the semantics of Ruby to do linting and there are some sort of questions about where that boundary is. I think Justin and I are somewhat aligned on the existence of this being a good thing, simply because then you'll have like a real, honest to god, zero configuration formatter that is separate from RuboCop and it's really fast. That's kind of where I'm at. JUSTIN: Sam and I, we have, I think a very healthy working relationship as two randos on the internet who, I think we generally share a value system and we're sometimes so well-aligned that we tend to overlap and so, if anyone is listening to this, wondering does that mean that Sam's thing and Justin's thing are going to be competitors and we're going to fight to the death? I regret to disappoint you that we're in cahoots. There is another analogy that's super-duper useful, I think to understand where this all fits in. First of all, one of the things that Standard does is it tries to play nicely as a minimal UNIX tool that is when you run it, it doesn't output anything by default, unless there's a problem and just exits cleanly. That makes it easy to chain and throw into scripts and so forth, because frankly, if there's no failures, you shouldn't really care about the output of your linter. Similarly, it tries to be a single-purpose as possible but right now, it is sort of stuck in this no man's land of like some things are layout in formatting and some things are genuine, like, linting and like, "Hey, don't invoke a method this way," or it might be ambiguous, that sort of thing and so -- NOEL: Yeah and unused variables. JUSTIN: Yeah, exactly. When you look at again, using a StandardJS and ESLint as the comparison of what's popular in the JavaScript world right now, it's actually a little bit more colored than that. Standard focuses primarily on linting rules but the most popular formatting tool in JavaScript is currently Prettier and so, what we're starting to see is a lot of teams just use plain old UNIX pipes and run their code through Prettier and Standard as part of their build and so, my hope is that Sam publishes Ruby Format. He and I kind of work together through any quibbles that Standard and Ruby Format currently have and then, I summarily cut out of Standard anything that Ruby Format can do and what's left behind is a smaller, faster subset of the linting rules that we selected out of RuboCop so that teams can just as Day 1 of their project, pull in Standard, pull in Ruby Format and then they're off to the races with a consistent configuration with fast save hooks and consistent linting. SAM: Yeah. I very much agree with Justin's position there and mine is more taken from sort of my experience in the Go world where almost everyone runs Go format on every single one of the Go files every time they save it but then they save all of their linting passes for CI or a pre-push hook and so, if you sort of think about RuboCop, it's good at a lot of things but its execution time, especially with bundle exec in front of it is always going to be too slow for you to put it in your editor's save hook. And so, my sort of single... Well, there are a couple of motivations here but the big one is a tool like this really does not exist in Ruby and also, no one's really ever taken the time to sweat the small details of Ruby formatting. It's funny, Noel. I know you mentioned like 'def methodName' with no parentheses and then an arg's list and because I've been heads down in Ruby auto-formatting for the past three days, I'm like, "Well, actually, a method name can be literally any Ruby expression, so how do we reconcile that?" Well, not quite but you can do like -- NOEL: No, I – SAM: -- Thing.thing.thing.methodName, right? And so, like how do you reconcile that. I think frankly, a lot of the built-in RuboCop rules make an assumption that you will never hit these edge cases and sweating all of these small stuff is something, I definitely want to do in a pass before we sort of put a 1.0 on `rubyfmt`. I want to take a lot of input from, not just Justin -- sorry, Justin -- but the community as well. I'd really, really like to get the input of some people who have never seen Ruby versions below 2.2 or 2.3 because I think they will have very different opinions to me and Justin on how Ruby is supposed to look. I'm going to be doing a very open RFC-style process and we'll see where it goes. It's early days right now. It's like, I'm just about able to round trip a single large file out of RSpec through it and not break RSpec CI which will be a huge crowning achievement and that will give us the basis of this platform for then to start the infinite bikeshed but I am really hoping to have the last bikeshed on Ruby style ever and then, we just have a tool that once its 1.0, people just use and that's it. JUSTIN: I guess what we're actually advocating is two medium-sized bikesheds and one lives at GitHub Test Double standard and one lives at GitHub Sam Phippen Ruby Format and we've successfully externalize this really, if you want to look at it a little bit more generously, Sam and I are just sort of shouldering all of the caremad about this on behalf of the community and while I applaud Sam's adoption of an RFC process right now, Standard is also pre-1.0. I don't really know when the right time to call it 1.0 is. It's changing of course, quite a bit as we go but -- NOEL: It doesn't work with my editor yet, so you can't make it 1.0 JUSTIN: Well, it works with Vim. Do you use Vim? NOEL: No. JUSTIN: Well... NOEL: See you weren't at my RubyConf talk which was all about how I don't use Vim. JUSTIN: Oh, right. NOEL: You guys talk about sharing a common philosophy about how to structure this stuff and is there some principle to that beyond like this is the idiom that seems most familiar or most readable to me? How do you describe the way that you are picking rules for Standard or picking the formatting set up? SAM: I think the answer to that last part of your question is probably a little premature. For me, I have a few sort of guiding principles. One is that I really want to minimize git churn. If a formatting rule will minimize git churn versus not minimizing git churn, it's one that I'm likely to want to pull for. I want things to feel consistent with how people are already writing Ruby. If Standard or Ruby Format significantly churn files out of RSpec or Rails or something, that's a point to pause and then I guess, Justin maybe also has some strong opinions that he might want to interject here. NOEL: Yeah. I was just going to say that that's one of the criticisms with the RuboCop defaults, which is that the RuboCop default language structure doesn't feel like Ruby anymore, if you've been programming in Ruby for a long time. JUSTIN: Well, there are a couple of things that have been sort of guiding lights to the rules that I've selected for Standard and several of them like for example, I caved on trailing commas in Hash and Array literals to reduce git churn, which isn't the most common way for people to format Ruby but the people who believe in it are the loudest and I gave up, so -- SAM: Hi, hi -- JUSTIN: Yeah, you're one of them and that's okay because I think ultimately, since it's an auto-formatter, like it has an auto-fix ability -- we haven't talked about auto-fix yet but that was one of the things is that in general, favor auto-fixable, especially safe auto-fixable rules over ones that can't be safely auto-fixed. Because if it can't be auto-fixed, then there's some amount of judgement or deviation in behavior or maybe, even performance between one option and the other and in general, I'll disable those. SAM: Yeah and actually, if I may interject here, Ruby format, as a strictly as an auto-formatter intends to never change the semantics of your Ruby program. It's just moving like characters around and will not actually significantly alter the semantics of your program. JUSTIN: And Ruby is pretty darn forgiving about moving characters around too. So that's great. The other one that I think about it a lot is people proposing rules and then, me looking into them and playing with them and the longer the conversation goes, very often it's a sign that we should just disable the rule entirely as opposed to pick one side or the other because like if a rule can't be applied close to 100% of the time, then it's probably unfair or inappropriate to say that that rule must be enabled 100% of the time in my unconfigurable linting tool and so, in general, whether or not you agree with a particular rule, they must be agreeable in the sense that it is fine to use Hash Rockets 100% of the time or 0% of the time, for example. NOEL: Yeah, that sort of makes Standard something to build on because a team might have additional configuration -- not additional configuration of Standard but additional consistency at things that they might want -- SAM: I guess we should maybe make this explicit because I'm not sure that we did but both Justin and I have fully climbed down from the always Hash Rockets hill. It turns out to be wildly unfeasible with keyword args and Ruby... It's going to break real hard in Ruby 3.0, so as much as Justin and I love the Hash Rockets, we are not going to be enforcing them. JUSTIN: In fact, I'm actually enforcing people not use Hash Rockets. Once again, I encourage Sam, "Hey, we believe in this very niche thing. Please write a blog post about it." Sam writes a terrific blog post and then two days later, I cave and I'm like, "Sam, I just killed Hash Rockets." SAM: And then four weeks later, I caved while having a completely different conversation with somebody else. NOEL: I'll just say there isn't a major Ruby consulting company named, like, "Colon" SAM: Yeah. It's really interesting, actually. The thing that changed my mind is that I had a conversation with someone where I came to the conclusion that as long as a construct is not obviously broken, single quotes is kind of the straw example that I'm using for this, like the auto-formatter should not try and replace it. Hash Rockets and new syntax will probably come out of Ruby Format until Justin and I suspect he's going to try and talk me down from that one but yeah, I'm replacing single quotes with double quotes everywhere as an example. Because the cost of churning those and to add interpolation, to me is not worth the potential differentiation between non-interpolating and interpolating strings. JUSTIN: Right. I'm not going to try to talk you down because I assume everyone running Ruby Format should also be running Standard and that one will make sure that all of the elements in a Hash are consistent but I think it's a completely valid point. There's a fundamental, I think, ideology behind why we even invest time in tools like this and I remember the first time when I first befriended Aaron Patterson like six or seven years ago, one of the first things he told me is the reason he worked on Ruby open source is because he wanted to use Ruby at work and he wants to keep it that way, so people can use Ruby at work. I have been kind of chewing on that as a sort of operating thesis for my time in Ruby open source for years. I come and go because I don't think that the language is necessarily the hill that I want to die on. But one of the things that stands out to me about Ruby in this day and age is that auto-formatters are really common. Linting and style tools are really mature including through RuboCop as being mature but there's a certain level of expectation, I think out there that these tools be available and conventional and Ruby talks a big game. We've been very successful in socializing lots of valuable ideas about design, about testing, about expressiveness and code, about putting into practice extreme programming and agile principles and stuff but we are way behind the eight ball in these sort of bikeshedding arguments and so, having tools that make our code just as consistent and carefree as are available in other languages, seems like it's becoming table stakes and I want Ruby to be able to compete. SAM: Yeah. I don't know that I could put this anymore eloquently than Justin just did. NOEL: One place where I see the coding rules really, really break down is in Rails view template files, whether they're Haml or ERB or something like that. My experience is people are much sloppier in those small Ruby snippets that they write in that. I mean, the Haml lint tool which backs onto RuboCop does not autocorrect at all, which is a pain in the neck but I have taken to using it on my projects, specifically because I find that that code gets really sloppy and I don't know whether you guys see that or whether you have any feelings about that. SAM: I have definitely experienced both Haml and ERB templates that follow none of the same styling rules as that parent projects. I would say that's an extreme stretch goal, at least on my part, like getting all of Ruby, like formatted correctly is going to be a big enough lift on its own to then do Haml and ERB as a second pass. NOEL: Yeah. That's why the Haml lint tool actually doesn't auto correct because it was something about it being very hard for it to hold on to the syntax tree of the internal Ruby via the auto-correct. I don't remember the details, something like that. SAM: Nervous laughter. JUSTIN: This is one case where I'm glad that I am just some bozo picking out linting rules and not reimplementing RuboCop from scratch because it is a super hard problem but I will point out though that what is best for a Ruby code listing, in terms of style and format and rules of the road, might differ a little bit from best practice for writing a template clearly. It's maybe a trite example but the kind of iteration that we see in a very side effect-y way as you like to iterate over the items in a list, for example to print them out in a template, that's a really, really common thing to do but I tend not to write '.each' ever when I write in Ruby because I'm almost always returning a value. I think the mode that you're working in is different enough that I'm not so eager to jump in and say that the rules that are good for a Ruby file listing is necessarily apply to a template. SAM: I also say that I think I've had fewer bikeshedding conversations about those things. I don't know that anyone has ever really started a flame war on the internet about how ERB files are supposed to be formatted in the same way. There are a lot of discussions about how our core Ruby files need to look. NOEL: Which is weird because I think that the ERB and Haml files on most Rails projects, including my own, are a mess. A mess in ways that could be fixed. A really trivial example is about a year or two ago, I started actually parenthesizing the Rails helpers in a Haml file as though they were actual method calls and it actually made a surprisingly huge difference in how readable I found the files and so, I kept doing it but a lot of people don't or a lot of people are just really inconsistent about it. SAM: I think a little bit of my take on that might be a kind of like a broken windows theory, like we tend to think of our Ruby files as being nice or at least, 'possible to make them' nice. I don't know that anyone is madly in love with the templates. NOEL: Yeah, I think that's true. I think that's to some extent, a different conversation about why the markup part of that is you're essentially interfacing with a whole other system that has a weird -- SAM: Yeah and you're effectively writing a programming language inside of another programming language, so you're always going to have some tradeoffs there. JUSTIN: I genuinely am curious, I think about the extent to which tools like these will be adopted and how much of that is going to rest on our shoulders as people building those tools. By the way, Sam and I have not explicitly invited others to collaborate and contribute to these projects but please know that all are welcome and we would love your help and I am sure, Noel will have links in the show notes -- NOEL: I will. I've definitely been following the Standard's development pretty closely. I haven't watched Sam's as much. SAM: Well that's because right now, it only exists on my laptop. Basically, as soon as I'm able to demonstrate that it doesn't immediately break Ruby files, my thesis is that I could just write a Ruby auto-formatter that formats Ruby exactly how I want it to be and then, have it for myself and no one would adopt it and that would be a huge waste of my time. This is A, why I'm collaborating with Justin because he's already done a lot of the legwork but B, I'm also very deliberately going to be soliciting feedback for as many people in the community as I can, as to whether or not they think the rules are good or bad because this is a tool I would like to see heavily adopted because I think it genuinely does fill a need that doesn't exist at the moment. It is a materially different thing to what RuboCop does, even though a lot of the behavior overlaps. At least from my perspective and Justin, this is a great way that you sort of posed it, is that like, I don't want Ruby Format to end up as a tool that no one adopts, even if it is useful and so, that's why I'm going to be doing wide feedback cycles and it will be a long time before we see a 1.0. JUSTIN: I guess my question is if this failed to get... Well, first of all, if they're successful, the answers to all these questions are obvious but if they're not successful, I am really going to be genuinely curious as to the cause. Is it because Ruby is a more mature language and people are set in their ways? Or is it because most projects are with existing codebases supposed to new codebases? Is it that the implementation sucked or that we fail to socialize it successfully or that we picked bad rules and bad style? I actually think that's probably a less likely reason that they might not take off but in general, this sort of feeling that the one ideological thing about Ruby that has always stood out to me, starting with 'why's (poignant) Guide' all the way down is like, "Ruby is great because you can just do whatever the hell you want," and here we are, years and years later saying, "Ruby is great, do it this way, and let's all do it this one way," and that tension is going to be hard for us to deal with. But the fact is lots of people use Ruby at work and lots of people get tripped up over overly expressive and overly creative of Ruby code and I think having some guardrails can be useful. NOEL: Yeah. I think that four or five years ago, I would have been really skeptical about a tool like this in Ruby but two things have happened since then. One is I have had the experience in other languages: using Elm format and using Prettier and I found them to be perfectly fine experiences and I have also seen the effect that using a tool like that has on code review, which is it focuses code review on stuff that actually matters. SAM: I will say parenthetically that the first time I wrote some Go code and I hit the save button in my editor and all the code just snapped into place, that was an incredible experience. NOEL: Super-satisfying. Again, I see it in Elm more than the Go but it's incredibly satisfying if you're me. I think that one of the things that RuboCop did that made its adoption much, much easier was the ability to grandfather in all of your existing code, which made it much more feasible for a large existing project. You didn't have to change everything, you could just start from a fresh slate, and keep track of things as you wrote new code and I think that was tremendously valuable in its adoption. I think that how will a large legacy codebase incorporate these tools, the tools that you two are both writing, is going to be a big feature. SAM: Yeah. I think from my perspective, it's the one ginormous PR which reformats everything and then you just go from there, right? NOEL: Yeah. I mean, for both of your tools, that's possible and at RuboCop, you can't really do that because there's a lot of things that aren't auto-correctible. SAM: Yeah. My tool, obviously, literally the whole point of it is auto-correction. The way it checks if a file differs from its formatting is by literally, running and then diffing them. That's the whole point of my tool and Justin and I think is only enabling auto-correctable Cops anyway. JUSTIN: That is unfortunately false because this was a debate in Test Double like we kind of trialed the tool internally before we published the gem and some people, were of the opinion is like, "We should make it only auto-correctible," but then when we started looking at what that would mean turning off, there are actually a lot of valuable rules where maybe, it's just for implementation reasons are not auto-correctable in RuboCop and sometimes, they are judgment calls but they're important to point out. For example, assignment in conditionals. I personally really like the if-foo equals as an assignment this expression, then route this way in the controller, else route that way but it trips people up and often causes enough bugs that RuboCop has a rule that says, "That's cool. If you were meant for that to be assignment, then you must wrap that expression in parentheses. If you didn't, then you might have just screwed up a Boolean statement," so that's an example of one where because the linter is pointing out, you need to make a judgment call, it's not auto-fixable. As a result, when I think about adoption, I'm actually going playing with repos like Nokogiri to see just how much damage I'm in for in terms of how much manual work it's going to be to get over the hump. NOEL: Actually, I ran standard on a long-standing side project of mine that's not on GitHub or anything but I haven't touched, or reformatted the code in years and years just to see what it would do and it did pretty well. SAM: Yeah. NOEL: We are super tight on time right now, so if you could just remind people where to reach you online, if they want to continue this conversation. SAM: Yes. I am @SamPhippen basically everywhere on the internet. JUSTIN: And because this is a JavaScript podcast, you can npm install me at `npm install Searls`. Fortunately, I am also the first person with my last name on every social platform so far and so, if you find me on GitHub or Twitter or Gmail, you can pretty much guess my username based on that. NOEL: Okay. Well, thanks both of you for being on the show and I'm looking forward to seeing how these projects turn out. Tech Done Right is a production of Table XI and it's on the web at TechDoneRight.io and on Twitter at @Tech_Done_Right. You can find Table XI on the web at TableXI.com or on Twitter at @TableXI. Tech Done Right is hosted by me, Noel Rappin and edited by Mandy Moore. I'm on Twitter at @NoelRap and Mandy is on Twitter at @TheRubyRep. If you like the show, please tell a friend or a colleague or your social media network or a relative or a pet or just tell me, all of those will be very helpful and if you'd like to leave a review on Apple Podcasts, it really does help people find the show. Table XI is a UX design and software development company in Chicago, with a 15-year history of building websites, mobile applications, and custom digital experiences for everyone from startups to storied brands. Find us at TableXI.com where you can learn more about working with us or working for us and we'll be back in a couple of weeks with the next episode of Tech Done Right.