Friday, November 28, 2008

Three Hours to Ruby

Hey, lazyweb, I need your help.

I'm just about done teaching a series of classes on Bash scripting for the systems admins where I work (mostly junior types). I present a one hour course every other week, focusing on the basics that they'll be able put to use right away.

Pretty soon, I'm going to start a series of similar courses about Ruby. Here's the rub though, I'm not sure where to start. If you had three or four one hour blocks to get a group of junior to mid-level sys admins going on Ruby, what would you focus on?

Thursday, November 27, 2008

Ruby Best Practices: mini-Interview 1

In case you hadn't heard, O'Reilly has recently released Ruby Best Practices, by Gregory Brown, as a rough cut. This is one of those book that the Ruby community has been waiting for, even if we didn't know we were waiting for it. Not only is Gregory a great person to write a book like this, he's the kind of person who's going to make sure it does the most good for the community as a whole (read below and you'll see what I mean). Right now, we have the opportunity to grab a rough cut and help make it better, it seems like the least that we can do.

This is the first in a series of short interviews I'll be doing with Gregory as the book progresses. Please feel free to drop a question or two in the comments, They might make it into the next interview.

Let's start by talking a bit about code and community. You've been a GSoC student and mentor, you were the Ruby Mendicant, and now you're writing Ruby Best Practices for O'Reilly. Tell us a bit about this journey and what you've learned along the way.

I can sum it up very briefly, I'm simply doing my part to pay it forward. I've had wonderful mentors and teachers along the path I took to get me where I am today. Each one of these folks has never asked me for anything in return, but I'd feel far too selfish if I just kept their knowledge for my own personal gain. So GSoC, Ruby Mendicant, and RBP are all ways for me to turn whatever good things I've gained from the people who have helped me over the years into something I can pass forward onto others to enjoy.

I've learned so much over the last few years that it's very difficult to summarize. If you want to know about technical details, I'd say: Writing reporting software is harder than I thought (GSoC), writing a PDF generator is harder than I thought (Mendicant), and writing a book is harder than I thought (RBP). So these things lead me to believe that a strong ability to underestimate complexity combined with an obsessive compulsion with tackling certain problems can turn into a virtue in the right circumstances.

One of the things that I really like about your plans for the book is that it will eventually become a Creative Commons resource to the Ruby community. Why did you decide to do this, and how did you caonvince O'Reilly to go along with it?

I don't see how anyone could write a book that claims to curate "Best Practices" without making it as accessible to the community as possible. Rather than writing this book with the intention of having people think "Hmm, Greg is pretty smart, I will trust what he says", I wanted to foster a healthy level of skepticism so that the work can grow beyond its original content. What might be considered a best practice now won't necessarily be that way a few years from now, and getting the book under a Creative Commons license will help facilitate the necessary changes and make it easier for people to openly question and improve the work.

Because we chose the by-nc-sa license variant, O'Reilly was pretty easy to convince. My editor (Mike Loukides) was more than happy to go down that road. It felt as if there would be some tension if I removed the non-commercial restriction, but this is where you get into the murky territory of whether that removes an incentive for the publisher to support the work, and that's a whole other can of worms.

I'm just happy that 9 months after the book is on the shelves, if you want to print a few copies of it to share among folks you work with, or if you want to translate the book and put it on the web so more people can read it, or if you want to quote a large section of it so that you can pick me apart on your blaag, you can. This will make the book better, and prevent it from losing value over time.

Of course, if during the Rough Cuts period or first 9 months of the book sales people really get behind it and buy copies, that'll make me happy. Not only will I benefit directly from purchases, it'll help encourage O'Reilly to do more of this in the future. But no matter how good or bad it sells, it will certainly have more value once it goes out of print than most books under traditional licensing schemes do.

As part of your own Ruby best practices, I'm sure that you've built a set of tools that you rely on. Can you name a handful of them and why you think they're so important?

Using the right tools for the job definitely makes a difference, but I tend to be a bit of a minimalist. I get by fine with extensive use of rake, irb, and a decent text editor (TextMate on OS X, vim elsewhere). Having nearly everything in revision control under either svn or git means that I've got a large library of my own code (often complete with tests/specs) to refer to which helps me remember how to solve particular problems without having to refer to books. Of course, having written a lot of mailing list posts, API documentation, O'Reilly OnLAMP articles, and the Ruport Book, I've got a lot of explanations in my own words reminding me how to do the things I need to as well, and I tend to use these resources extensively.

Also, when my tools come up short, I can always stand to learn more from some of the smartest folks in our community. Since I'm not bashful about asking for help, my two most valuable tools in software development are email and my IRC client.

This answer may be a little boring, because I'm not one to hunt down the next latest and greatest tool to fix a problem I never knew I had. A simple work flow that involves doing some custom scripting when necessary seems to work best for me.

I've been going back through Code Reading by Diomidis Spinellis recently. I'm really sold on the idea that reading great code can us write better code. What are some code bases you'd recommend readin and what can we learn from them?

I've not yet picked up that book, but I imagine I should. Reading code is a great way to learn, and this is exactly what folks will be doing when they read Ruby Best Practices. I'm picking from my favorite bits of real code, some of them are my own, but many are not. For the functional programming chapter I'm writing right now, I had a fun read through MenTaLguY's lazy.rb and picked up some really interesting ideas for writing transparent proxy objects. I've also been digging through JEG2's Higher Order Ruby blog series and learning a ton.

Because Prawn was written concurrently with my initial work on Ruby Best Practices, and will continue to be a source for examples and case studies throughout the book, I recommend folks to check it out. PDF is a low level domain and that means there is some necessary complexity, and because things are moving fast they get rough around the edges at times. However, many parts of Prawn represent my best effort at writing masterful Ruby code, and I think people might pick up some tricks by reading through its source.

But really, people don't need to be so picky about what they read. Look through the source of every gem you've got installed if you have the time to! Try to think about why people wrote their code the way they did, and pick up some of the stuff you think you can groove with and try it in your own code. Sometimes, the coolness is lost in translation, other times, it's exactly the sort of inspiration you need.

If you want to get stronger at Ruby, don't just read API documentation, read the source of the code you use. You'd be surprised how much cool stuff there is out there.

Wednesday, November 26, 2008

reek for Ruby rocks

I've been interested in developer tools for Ruby for a while now, and was pretty excited to find reek by Kevin Rutherford. After playing with reek a bit on a variety of code, I decided to ask Kevin a little more about it. Here's what we talked about.

What prompted you to write reek?

Kevin Lots of little nudges all occurred simultaneously and added up to one big push!

In January 2008 I had just finished a coding project for a client, so my hands were itching. I think I started on reek as soon as I discovered the ParseTree gem by Ryan Davis of seattle.rb. It struck me that Java has a rich set of code quality tools but — at the beginning of 2008 — Ruby had none.

I wrote the first draft of reek in early 2008, but only went public with it when I was confident that the book would complete too. I was also hunting around for medium-sized codebases to use for examples in the book, so starting on a tool development project seemed like it might provide some fodder in that direction. (It didn't, as things turned out.)

What response have you seen from the Ruby community?

Kevin Generally very positive (over 500 downloads of the gem at time of writing). I've had a few emails from people who were perplexed by the Feature Envy warnings, and that's probably because reek isn't (yet) doing enough of the right kinds of static analysis. I hope the tool's early excesses haven't soured its audience too much, because it is getting smarter (and hence more reasonable) all the time!

I noticed you've tried out flay. What other refactoring tools have you seen/used for Ruby?

Kevin I think I've tried everything in this space as of now — flay, flog, roodi, towelie (the set is growing so quickly that there may be even more by now). I like flay a lot, and I'm sure it will also continue to get better and better. For some reason, complexity metrics and suchlike leave me cold; so although I respect flog etc, I don't use them. (I think it's very healthy that Ruby now has a growing corpus of code quality tools, and it's a great tribute to the Seattle.rb folks that such tools have suddenly begun to appear now, since the easy availability of parse trees.)

I also use the Ruby refactoring support in NetBeans for my day-to-day Ruby development. It does some simple things well right now &mdash although I wish the scope of a "rename" were tied down a lot better! And it goes without saying (although we've devoted a whole chapter in the new book to this) that refactoring is only safe in the presence of a version control tool (I use git) and various different kinds of automated tests (I mostly use rspec).

In fact, that's another reason why there's a need for Ruby refactoring books. One of the practical tips in Fowler's original Refactoring book is to use the Java compiler: When you make a change to a method signature, for example, the compiler will provide you with a list of everything that now no longer compiles; you can use the compile errors as a to-do list as you work through the refactoring steps. But Ruby can't do that; you're completely reliant on test coverage to tell you what's broken. If something in Ruby isn't tested, you are in much more dangerous territory than you would be in Java. Which means that tools such as heckle and rcov are much more important in Ruby, and the discipline of test-driven development (and test-driven bug-fixing) is even more necessary.

In discussing reek, you wrote about looking for a code base to mine for examples. Did you end up finding anything interesting?

Kevin I run reek on all of the gems I use, so that I have a broad view of whether it is reporting reasonable things about the code. So the open source community is a rich source of test material, and as reek evolves and deepens that will continue to be the case.

But the Ruby Refactoring Workbook is intended to be a self-study guide, and so the exercises work best when they are short and focussed. Real code is usually too large and complex (and messy, it has to be said) to be helpful in that context. The book has a few chapters in which the reader gets to work on more "complete" applications, and I was hoping reek's own code might be useful as one of those; but in the end, we again fabricated them from scratch in order to focus on specific themes.

What's your typical workflow in applying code quality tools to a Ruby codebase?

Kevin I follow the same general patterns I use in Java, C# and C++ projects, although it's only in the last few months that Ruby has begun to offer some of the tools...

I use TDD from the outset, and these days that means rspec. So my code grows alongside a set of examples, and rcov always shows coverage in the high 90s. Once I have the "walking skeleton" working (usually within a couple of days), I will briefly experiment with quality tools to find out what settings work best for this particular codebase. Then I'll add tests so that any future code will fail the "quality gate" if it isn't up to scratch. So for example reek's test suite includes a run of reek over it's own source -- any warnings reported are treated as fatal errors and the tests fail. I'll be adding flay to that suite soon too.

When a defect or feature request comes in, my first response is to write a new test (or set of tests) to describe the correct desired behaviour; I'll set these to "pending" until I have time to implement a fix.

Early in reek's development I also took a snapshot of a few source files from gems that stretched reek into new places. I have a "golden" report stored for each of these, and reek's test suite includes a regression run to make sure any new version of reek still finds their smells. (There are also unit tests for each specific thing those gems taught me.)

As an agile coach, I have a fundamental rule that I apply to all software projects, regardless of tools or technology: If something bad bites the project more than a couple of times, I look to prevent it occurring again, either by adding tests to help the project identify the problem situation sooner, or by tooling to make it easier to do the "right thing". Tests for quality, and regression tests for bugs, both come into that category; so does using rake, hoe and newgem.

As I mentioned before, I don't tend to use complexity metrics. I tend to think that any code that's free from smells will have naturally low complexity; so I prefer to focus on refactoring.

What value would you see in using reek, flay, and friends on widely used Ruby libraries, or on emerging code like Rubinius?

Kevin Well-factored code offers a couple of general benefits. First, it is easier to read and understand. Which in turn means that more people might feel they can contribute. And that, in turn, can be made safer if each project uses these tools to establish quality standards via regression tests suites. (As a community we could promote this by evolving an easy way to set these up for new projects; perhaps newgem and rails could install standard spec files that run reek and flay over the project's source -- there's code in reek's repository that could be used as a starter here!)

And second, well-factored code is naturally comprised of smaller, more cohesive and less coupled pieces. These are likely to be easier to reuse, which in turn leads to increases in both speed and quality of development. So the whole community benefits more from well-factored code.

Thursday, November 20, 2008

Puppet and Ralsh

I wrote about puppet and how we're starting to look into it at work a couple of days ago. Yesterday, I learned about an awesome little tool that puppet provides — ralsh, the Ruby Abstraction Layer SHell. To understand just how cool ralsh is, you need to know a little bit more about how puppet works. puppet allows you to describe how a server should 'look' using a declarative language (this is a hurdle a lot of people have problems with, but it's too big to go into here). It then provides the plumbing to enact those declarations on different kinds of servers (OS X, Solaris, Linux, etc.) using its 'Ruby Abstraction Layer'. This allows you to define something like:

user { 'postfix':
    ensure => 'present',
    uid => '51',
    comment => 'Postfix Daemon',
    gid => '51',
    home => '/var/spool/postfix',
    shell => '/bin/false'
Which says that you should have a user called postfix, defined as listed. If that user doesn't exist on a system where this is defined, puppet will do the right thing to add them for that kind of box. ralsh provides commandline access to this abstraction layer so that you can query the current configuration of the system, or modify that configuration. When used to query a system ralsh dumps out the current configuration in puppet's declarative language. For example:

$ ralsh service apache2
service { 'apache2':
    ensure => 'running',
    enable => 'false'
If you think about this for a minute, you'll see that it's a lot cooler than it first appears. Let's say you've got 15 servers that have been 'built' piecemeal. You're really not sure what's installed on them, or what's running there. Now, let's make a bad situation even worse, you need to build out a duplicate set of servers, only you're going to migrate from SLES to debian. ralsh suddenly looks like a great way to audit those servers and to provide a basic puppet configuration to build out the new ones. Don't expect this process to be perfect — debian and SLES name their packages differently enough, for example, that you're going to have to sort some things out by hand. It's a great way to start though. puppet and ralsh look like great tools to help you get out the door before five.

Wednesday, November 19, 2008

Bad News From the Rubinius Team

Yesterday, Evan Phoenix broke the news that Engine Yard has scaled back their Rubinius team to two members. This means a number of formerly employed Rubinius hackers are now going to be looking for work. Developments like this are never good news. It's certainly not the end of the world though. I'm grateful for Engine Yard's support, but I think it's important that we not tie Rubinius to Engine Yard. In addition to their work, there have been huge contributions made by unpaid Rubinius volunteers, part-timers (including multiple GSoC projects), and other companies. Some of the most important work has been the cooperation of multiple projects on common goals like the test suite. Engine Yard has poured a good chunk of resources into Rubinius over the last year or so, and has that investment has paid off in a better, faster, more complete Rubinius (see Tom Mornini's blog post for some details). In fact, they hired more engineers to work on Rubinius than Sun did to work on JRuby. Thanks, Engine Yard, for the contribution to a thriving Ruby community. Good luck in navigating the difficult economic times we're all facing. And good luck to the great hackers who are now looking for a soft landing — if any of you have some Ruby work that you could send their way, I'm sure it would be appreciated. [Note, while Engine Yard sponsors my blog they were not involved in writing the entry.]

Monday, November 17, 2008

Manga and Statistics

I don't have a lot of formal math training, so I'm always looking out for books that can help me bolster what I consider to be a weaker subject for me. When I saw that No Starch Press had released The Manga Guide to Statistics, I was immediately drawn to the idea. As soon as I started reading it, I found myself much more interested than I ever thought I'd be in a math book. The manga setting of the books provides a good hook for picking up the math. I've got to say that the Lolita-ish relationship between the two main characters is a bit unsettling at times — I guess that's par for the course though. The format also allows easier graphical representation of topics, although this breaks down a bit in later chapters. I've already had a couple of instances where I've recommended the book to a co-worker or friend who was boggled by statistics. I'll probably continue to recommend it when I run into similar situations. If you've already got a solid handle on even basic statistics, this book probably isn't for you, but for the rest of us it's a winner.

Thursday, November 13, 2008

Ruby's Pulling Puppet's Strings (and leading people to Ruby)

I've been trying to introduce Ruby at work for a long time, and have had some success here. I've been able to show many of the developers the value of Ruby, and it's made it's way into the organization as a valuable tool. I've never been able to make many inroads into the systems administration team that I work with though, and this has bothered me because I see myself as much more of a sys admin that a programmer. Something's changed recently though. We're working on some new projects, and Puppet is a good model for us to understand how we can automate the configuration of the systems involved. I've been watching Puppet for a while, and even interviewed Luke Kanies (or see his blog, the maintainer of Puppet, and James Turnbull, the author of Pulling Strings with Puppet: Configuration Management Made Easy. Now that some of my co-workers are looking at Puppet, I think they're starting to see the beauty that drew me into Ruby many years ago. I'm looking forward to working with them as we start to build out tools for our new project ... in Ruby. Who knows, maybe I'll even get one or two of them to come to MountainWest RubyConf 2009 with me.

Tuesday, November 11, 2008

Now that RubyConf 2008 is over ...

Ok, RubyConf 2008 is over (and I missed all the fun). Besides reading (or writing) about all the awesome presentations and the incredible hallway session, what should we be doing? Let me pitch two simple ideas that will help spread the joy that RubyConf brings.
  1. Come back to your local Ruby Brigade and share the wealth. Tell people what you learned and why it's important. Even better, start building on what you learned and share that knowledge too. Record your meetings and post the audio/video, or write about them at your blog. This is a great chance to share and build on the vision that you caught while you were in Orlando.
  2. Put together a proposal for your local Regional Conference. There's too much intellectual value in the community to keep it all bottled up. Whether you're planning on going to GoRuCo, the Ruby Hoedown, Ruby Fringe, MWRC, or some other conference nearer and dearer to your hear, you can make it better by getting involved.
Neither of these is all that hard. Give one (or both) of them a try. You and your fellow rubyists will be glad that you did.

Friday, November 07, 2008

Agile Retrospectives: Book Review

As promised over on Twitter, I'm blogging about one of the books I'm reading right now — Agile Retrospectives: Making Good Teams Great. My scout troop has gotten really good at doing a simple evaluation called an SSC (Start, Stop, Continue) after each major activity, but we hadn't been doing much with the information. I've also been thinking that my team at work doesn't do a very good job of evaluating our previous activity to find way to improve. This book seemed like just the ticket to help with both problems. When I started reading, I knew I'd picked the right book. While it's oriented toward an agile development team, the concepts and activities all look like they'll work well with a group of system administrators or a Boy Scout troop. The text is engaging and includes lots of examples. It's clear that Esther Derby and Diana Larsen (the authors) have a lot of experience in leading retrospectives. The first part of the book lays out how (and to a degree why) to run retropsectives, but the remainder provides a number of activities to use in actually running them. This catalog of activities is the key to the books usefulness. I've already started to see ways to use and modify the activities both in formal retrospectives and in shorter, informal evaluations. I'm already having some of my scouts read portions of the book to help them in their leadership roles. If you want to start holding team retrospectives, or want to improve the retrospectives you're already holding, this is the book for you. I'm so impressed by it, that I'm thinking about picking up another book by Esther Derby, Behind Closed Doors: Secrets of Great Management (Pragmatic Programmers), because I want to see what she has to say about leadership and management.