Wednesday, January 14, 2009

Ruby Best Practices: mini-Interview 2

As Gregory Brown (@seacreature) and I discussed the Ruby Best Practices Contest, we also talked about the current state of Ruby Best Practices (or get the Rough Cut). You can read the resulting interview below.

Before we get to that though, we should announce the tow winners of the contest: Jamis Buck (actually entered by Daniel Berger) and Eric Hodel. Eric and Jamis both get free Rough Cut Access to Ruby Best Practices — who knows, they might even find some of their own ideas in there.


How is the writing process itself going? How are you dealing with feedback from readers/reviewers?

Gregory The process we've put together really seems to be working. When I first pitched the book, I set the pre-condition that we'd need to have a broad panel of advisers from the get-go. If this book is going to have the title "Ruby Best Practices", I want it to be able to stand on more than my own name, for sure. So I asked a few of my friends, a few of my students, and a few folks I think of as truly masterful Rubyists to be part of an active review process. So far, that has been working really well.

Every chapter gets two levels of review, at a minimum. I start by posting to our internal reviewers a plain text file and a PDF, and collect their comments. After a about a week, I make revisions based on their suggestions and send things off to O'Reilly for a RoughCut update. Usually within a day or so, the changes hit Safari and those who pre-ordered the book can comment on them. That group has already caught a couple problems and made suggestions, so it's definitely useful to have more eyes on the content. I think it's really important to release changes as often as possible, to encourage further review. Of course, we use some great tech to help us with that.

Because the book's sources are in Asciidoc, there is no separate typesetting process. My plaintext files are the same source that the PDF is generated from. This means I can make whatever revisions I want whenever I want, and I don't need to be worried about getting bogged down by the formatting. We can also go back and make changes to old chapters later on without much worry.

So far, O'Reilly has basically let me run things exactly how I wanted to, and it has been working out great. Fast, tight iterations will help make the book grow organically based on the input from our internal reviewers as well as the wider reader base. That's what I'm hoping for, anyway.

I hear that you're converting testing examples from RSpec to Test::Unit is pretty huge. Why are you making the change?

Gregory Oh, for the "Driving Code Through Tests" chapter? I just sent that out to the internal reviewers, so we'll see what they think. :)

But actually, it was their suggestion. The initial RSpec based chapter was meant to reflect the change in the tides in the Ruby community, but it wasn't too hard to convince me that I should reconsider things. I used to think RSpec was easier to teach than Test::Unit until I wrote a chapter about it, and found myself having to show reference implementations of how things like foo.should be_bar work, whereas assert foo.bar? needs no extra explanation. I had to explain what a proxy object was for folks to understand how to build custom matchers, and what a lambda was for people to know how to test their exception raising. I'll be blunt, that sucks.

But to be fair, I use RSpec for a good bit of my work, and I think it's okay once you get the hang of it. But the ideas I wanted to express in RBP weren't really tech-specific. I was mostly talking about overarching strategies like keeping your tests atomic, writing some helpers here and there, that kind of stuff. So some of the 'features' of RSpec were actually getting in the way. Test::Unit (well, now minitest/unit I guess), is standard Ruby, is dirt simple, and was able to demonstrate the strategies I wanted to share with folks with less magic.

So, maybe it's not such a big change. RSpec, Test:Unit, Minispec, Test:Spec ... How much does the specific tool really matter versus being serious about using it?

Gregory The interesting thing is I didn't really need to change the chapter much, aside from translating the source. Some sections were dropped and others will be added in, but for the most part, it's the same chapter and it follows the same general blueprint. This really underscores the fact that what matters are the ideas behind testing, not the technology. I'm hoping the reader will benefit from the simplicity of Test::Unit for my examples, but then take the knowledge and apply it wherever they want, whether it be to RSpec, Shoulda, or whatever it is the cool kids will be using when the book hits the shelf.

I think the specific tool matters, but only when it comes to comfort, not concepts. It's arguable that certain frameworks encourage you to embrace a concept more than others, but I don't think that's as big a factor as people might think.

How important is mocking as a Best Practice? What about Stubbing? Where do they fit in relation to each other?

Gregory Well, I think that mocking and stubbing are both pretty important when you need them, and completely worthless when you don't. I've seen systems in which every interaction with every other class was fully mocked out with all the behaviors specified. These systems are absolutely nightmarish to work with, because the tests become so brittle that you need to re-write your giant, complicated mocks every time you refactor. Tests should aid in refactoring, not get in the way, whenever possible. I've also seen (*cough* written *cough*) systems that stub out so much and produce canned results for everything which gives you wonderful passing tests but, well... don't actually test anything.

But of course, responsible use of mock objects to minimize your dependencies on expensive external resources can really help make your tests run faster and more clearly show what's going on. Stubbing out a method here or there to prevent you from testing things you don't care about can definitely be helpful. In general, I prefer to use whatever technique is the right combination of cheap, fast, and easy. That combination changes wildly from project to project so anyone who tells you that you should never make use of mocking / stubbing is crazy, and so are the people who want you to do it all the time.

As far as where all these things fit together, I think that's more a question for folks with a stronger grasp of theory than me. The best I can do is point you at Martin Fowler, then tell you that I don't really care about their distinctions at the high level. I only care about using the right approach for the job. Libraries like flexmock that intentionally blur the lines between mocks and stubs are great in the hands of responsible users, if you ask me. :)

While Ruby Best Practices is going to end up Free, O'Reilly has even more open in the writing of a couple of other books that are cropping up. How does this go 'round compare with your completely open work on the Ruport Book?

Gregory Well, the Ruport Book taught me a lot, both good and bad, about writing a community oriented book. The idea of having an internal review team is something we had on the Ruport Book as well, and I carried it on to RBP. It seems like because the topic is more general, this has worked out much better on this book than it did for the Ruport Book, simply because most of my internal review team knows a hell of a lot more about Ruby than I do!

But the Ruport Book and RBP are two very different books, so it's hard for me to compare them.

I'm having difficulty expressing my feelings on this, but basically, the way this book is formed in my head doesn't feel much like a textbook. It's more like a quasi-fictional narrative "based on a true story" with notable mentions of various Ruby hackers and their projects. It's sort of like I've stitched together a series of blog posts so that it bleeds into this textbook undercurrent. The book is meant to be read from cover to cover, or at least in whole chapters. This makes it tricky to make wide open in the early phases.

But once the work is done, I want it to be able to bend under the pressures of peer review. I want people to be able to freely use and remix what I've done, however they see fit. And of course, that's already planned to happen and so it will, it will just take some time.

I believe it can be a virtue to keep something a little quiet until you know for sure where it is going. It's sort of like waiting to do a first release of an open source project until you clean up the code a bit and make it useful and approachable to others. That's exactly what I'm doing with RBP now, and hopefully, that will benefit those who might be interested in contributing to the book down the line.

Lots of people coming into Ruby from other languages bring Best Practices (and sometimes Pessimal Practices) with them. What languages/communities do you think offer the best opportunity for finding good practices for Ruby?

Gregory That's a good question. I don't really know. I think we end up getting more bad patterns than good from other languages. This isn't to say anything bad about other languages, but it is to say that best practices aren't always transferable. Look how many patterns from Java aren't even remotely relevant in Ruby. Or how many cool functional programming techniques fall down and die when you try to import them. I think maybe the fact that we only got a few responses to our blog contest here was an indication of that, to some extent.

However, I think many communities within Ruby are a hotbed for best practices. RBP draws almost all of its key points via the influences of notable open source Ruby projects. Rails utterly changed the way people write Ruby, in many ways for better, in other ways for worse. Merb has really made me re-think issues like performance. Smaller libraries also pack a punch. FasterCSV is the source of a lot of inspiration for me, and in turn, I think FasterCSV has been influenced to some extent by Ruport. After-all, it has its roots there, anyway.

So if you pay attention to the conversations between well trodden Ruby projects, both in words, and in code, you'll see a whole lot of great strategies emerge. My hope is that this book will give people a snapshot of some of them so that they can pick up new skills in the way many of us hackers are doing: One new patch at a time.

I see that you've set up a twitter account for RBP. How do you think that will impact the book?

Gregory It'll motivate me a little to keep posting updates, give me a way to keep people informed about book related news (such as this interview), and give readers (or potential readers) a way to connect with me and share their thoughts. I'm not a big twitter addict, but I'll at least let people know when to expect new content and whenever something I think might be interesting comes along. Beyond that, I guess we'll see how it goes.

No comments: