Monday, February 16, 2009

Recommended Reading: Flex on Rails (Addison-Wesley)

Disclaimer: Addison-Wesley sent me (unsolicited) a review copy of this book at no charge, with the tacit assumption being that I would read it and review it publicly. There are no conditions, however, on the content of said review. What you are about to read is my unbiased, unvarnished take on this book, written to inform you, not to curry favor with the publisher or the authors. Also, I do not have any business relationship with any of the parties involved in the publication of this book; I will not gain in any way if you choose to buy it. But, as it happens with this book, I believe you will gain if you choose to buy it. Here's why:

The Good

Flex on Rails, by Tony Hillerson and Daniel Wanja, does many important things right, tech-book-wise, which I find astonishing; more so given that it's the first book by both authors. The material strikes an effective balance between easy-to-absorb and useful-in-real-life, without spending too much time at either extreme, and -- mercifully -- no time at all in "Hello World".

Aside to would-be (and a lot of already-are) tech book authors: Read Chapter 1 of this book -- all seven pages of it -- to see how it's done. Notice how much (read: "how little") time and print is expended on rehashing yet again the minute details of installing Ruby, RubyGems, Rails, and other requirements. This is not one of those books that has chosen to pad its page count by wallowing in the comfort zone of a twenty-page "Getting Started" tutorial.

Chapter 1 sets the tone. Subsequent material flows naturally, and never overwhelms. Chapters 2 and 3 combine effectively to introduce the concepts of Flex and Rails' use of XML and REST to communicate betwixt themselves, but without the seemingly-obligatory over-exposition of the history and motivation of either XML or REST.

The authors introduce testing early on (Chapter 4); not quite TDD, but not bad either, for a tech book. A brief detour into RubyAMF (Chapter 5) follows, and then we get another key topic, Debugging (Chapter 6), early enough to be useful but not so early as to be overwhelming.

Throughout this first part of the book, the authors assume a fair amount of Rails knowledge/experience. For example, Chapter 2 ("Passing Data with XML") jumps right in with a sample Rails app, complete with (minimal) scaffolding and a simple database migration. Rather than bog the reader down with minutiae, as far too many other tech books do, this material is presented with an unforced, matter-of-fact tone that assumes reader familiarity, but doesn't condescend. Now I concede that I'm an experienced Rails developer, so I take this stuff for granted. But I believe that someone new to Rails would not be overwhelmed. And -- key point here -- there are other, better resources for learning about Rails' scaffolding and migrations. An ill-timed dissertation here would just turn off seasoned developers entirely and distract any new kids in the audience. Good for Tony and Daniel (and whatever wise editors they worked with) for avoiding this all-too-familiar trap.

The second half of the book demonstrates another key concept that too many tech books don't bother with, and one that I think this team just nailed: Flex on Rails is not an introductory tutorial, and it's not an advanced recipe book: it's both! Each of Chapters 10 through 22 presents a solution to a problem that is very likely to crop up in any real-world usage of this technology. To name a few:

  • Source Control (Chapter 10), including Subversion and Git

  • Deployment (Chapter 12), largely with Capistrano

  • Authenticating (Chapter 15)

  • Communicating between Flex and JavaScript (Chapter 21)

  • File Upload (Chapter 22)


I've saved mentioning my favorite chapter for last, and I think it is just way too cool that it's in the book, because it reflects a personal mantra of mine -- Chapter 13: "Read the Source!" I am constantly preaching this, whether it's Rails, or Capistrano, or JRuby, or even Ruby. Open source software is a treasure trove of HOWTO: Write Code in all its glory. It is a cornucopia, constantly replenished by the experience and learnings and mistakes and refactorings and holy wars of a horde of extremely bright and capable programmers. Is it sometimes flawed? Sure. But it's there. And it's the best source of education in computer programming -- both how to and how not to -- that you have available to you. Use it.

The Bad

Not a lot to write here. I've long since ceased to be as outraged as I used to be about the computer publishing industry's contempt for (okay -- let's be charitable and call it "indifference towards") the English language. Let's just say I won't be letting my son use this or any tech book as a primer in either spelling or grammar. This book is not as bad as some, but it still has its share of sloppy copy editing -- typos here, unfortunate typesetting choices there (primarily inconsistent/inadequate use of fixed-width fonts or otherwise visually highlighting stuff that's best viewed as code and not prose).

The Meh

For a book that seems to have been designed deliberately to respect its target audience's intelligence and skill level, Chapter 8 ("Flex MVC Frameworks") takes a bit of a detour into Probably Should Be Obvious Land in its coverage of the Model-View-Controller paradigm. Yes, it's in the context of describing how Cairngorm and PureMVC specifically do MVC, but come on -- it's MVC. Even here, though, the authors rise above the average tech book experience, by implementing the same app using both frameworks, so you can compare and contrast and maybe get a sense for which framework fits your needs better.

Gratuitous Name-Dropping Reference

Tony Hillerson and I worked on a Rails project (my first) together a few years ago, and even then he was valiantly (but alas, in vain) trying to convince his partners to let us use Flex for the UI. I'm glad to see him realizing that dream and in fact thriving on it. I've met Daniel briefly, at the Pragmatic Studio's Cocoa Programming class in Denver, but I don't think he knows who I am. Other than that, I have no business relationship with either, and I do not stand to benefit in any way from the sales of their book. But, as I said in my disclaimer above, I believe that you will benefit from buying it. Let me know if you do. And let me know how it goes.

Saturday, January 10, 2009

A Gem Is Born: Announcing Gemviz

Final (potentially) update: Now appearing on github:
git://github.com/davidrupp/gemviz.git

Update to first update: I realized that I did not specify a gem dependency on ruby-graphviz in my hoe-generated Rakefile. This is in place as of version 0.1.2.

To quote Groundskeeper Willie in The Simpsons - Treehouse of Horror V: "Och, I'm bad at this!"

We now return you to the first update.

Update: Peter Cooper correctly points out in his comment that Gemviz has a hard dependency on Graphviz, which isn't installed by default on Macs. I tend to take it for granted because it's one of the first things on my checklist to install when breaking in a new Mac. I use The Mac OS X Edition of Graphviz, as referenced on the Graphviz home page.

We now return you to the regularly scheduled original post.

Original Post: I can't really call myself a hotshot Ruby programmer until I release a RubyGem, now can I? Well, I still won't call myself a hotshot Ruby programmer yet...but, as of today -- and the release of versions 0.1.0 and 0.1.1 (for documentation purposes) of my new gem gemviz to rubyforge.org -- at least I'm one step closer!

Check it out, yo:
[sudo] gem install gemviz
Now you can do e.g.,
gemviz rails
(assuming you have Rails installed as a gem which, if you don't by now: huh?), which produces this graph on my system:


In fairness, I should disclose that Gemviz is only about 30 lines of code, and makes heavy use of other people's work to do its magic. Here's how it works:

* it scrapes the output of the system command gem dep gem_name --pipe.
* for each dependency thus listed, it adds that dependency to the list of dependent gems.
* it does the same recursively for each dependent gem until it finds that the current gem has no dependencies, or that some (recursively) dependent gem is not installed on the system.
* it builds a Graphviz graph from the graph so built.
* it runs the awesome tred utility on the resulting Graphviz graph, which translates the original messy graph into one that properly represents all of the transitive dependencies.

If you're not sure what that last bit is about, don't feel bad: I didn't either at first. So here's the picture that's worth a thousand words (give or take):

The difference is subtle, but telling. The second graph shows that the rails gem has dependencies on activesupport and actionpack. Which is true, as far as it goes, and is reflected in the output of the gem dep command thusly:
gem dep rails
Gem rails-2.2.2
rake (>= 0.8.3, runtime)
activesupport (= 2.2.2, runtime)
activerecord (= 2.2.2, runtime)
actionpack (= 2.2.2, runtime)
actionmailer (= 2.2.2, runtime)
activeresource (= 2.2.2, runtime)

But it turns out that gem dep doesn't tell the whole story. rails does depend on those other gems, but only through its dependencies on activerecord, actionmailer, and activeresource, as shown in the first graph. That's what the tred utility (part of the Graphviz package) does: reduce the second graph to its minimal equivalent representation in the first graph.

Here's another more fun example, for merb, prior to transitive reduction:


And post tred:

This implementation owes much to the existing DepGraph, especially its use of Graphviz and tred. I basically just extracted the simple use case of graphing a gem at a time, and neglected to implement a bunch of DepGraph's options. For instance, the output of gemviz is always a single .png file per requested gem, named after the gem and placed in the current directory.

Keep in mind that this is a very simple initial release. Please let me know if you find it useful, and especially what improvements you can think of.

Tuesday, December 30, 2008

QOTD: Hans Küng

From The Catholic Church: A Short History:
Those who deliberately step in all the puddles should not complain too loudly about how bad the road is.

Monday, December 22, 2008

Bad RSpec! BAD RSPEC!!

My first gig as a consultant for ThoughtWorks has been a whirlwind of security lines, flights to Texas, and Ruby on Rails. I'm very pleased that they were able to make me billable so quickly; to be getting paid to work on Rails again after two years in the Java mines is an extra added bonus.

My pair and I spent today upgrading one of our apps to Rails 2.2, as a sort of trial run for eventually upgrading all our apps. This involved the usual amount of concomitant upgrades to plugins, with no shortage of "great, this is broken...now something else is broken...not that too!" hijinks. The best part of the day, though, was the RSpec tests that kept failing no matter what we tried to throw at them.

Long story short, we have a controller that uses a rescue_from handler to redirect in the event of a connection error. Works like a charm when we're clicking through the app. But after upgrading RSpec and RSpec-Rails it simply refused to pass the specs that verified the redirect behavior.

It turns out that the latest version of RSpec has some secret sauce that defeats rescue_from, instead going directly to raising the exception that needed rescuing from in the first place. I guess I wouldn't mind so much if we didn't have several behavior-driven tests that, you know, tested behavior.

Not too cool, Rudy.

There is, of course, a workaround. Simply add controller.use_rails_error_handling! to your test and you can defeat RSpec's defeating of rescue_from. But, just as double negatives fail to not clutter English prose (see what I did there?), having to demand that RSpec get out of the way of Rails' standard and -- in this case -- reasonable behavior just uglies up my code. I would much rather the maintainers of RSpec had elected to make the ability to bypass the rescue handler and skip straight to the underlying exception an "opt-in" behavior.

Monday, December 01, 2008

One of These Things is Not Like the Others...

I (heart) Amazon's recommendations service, but...


...I'm not entirely sure what the message is here. For me or any other fans of programming languages and/or algorithms.

Friday, October 17, 2008

QOTD: Donald Knuth

Ripped directly from this interview:
...I trust my family jewels only to Linux.
I'm a Mac guy myself, but...respect, brother. Respect.

Friday, August 15, 2008

Regarding Ruby, instance_of?, kind_of?, and ===

So I was reading through some Ruby source code tonight -- primarily because I haven't in a while, thanks to a busy stretch of Java work -- and I ran across an idiom that I found a little confusing at first. The Ruby source code belongs to Why the Lucky Stiff's Shoes project, "a very informal graphics and windowing toolkit" (according to the official website).

One of the first files I looked at, lib/shoes.rb, opens right up with this interesting bit of interestingness:
class Range 
def rand
conv = (Integer === self.end && Integer === self.begin
? :to_i
: :to_f)
((Kernel.rand * (self.end - self.begin))
+ self.begin).send(conv)
end
end
Okay. So we're defining a rand() method on the built-in Ruby class Range, which will return a random value from within the begin and end values of the Range. Neato. And apparently the use of conv is meant to produce a result of a float or an integer, depending on the nature of the endpoints of the Range. Again: neato. But I hadn't seen the use of the === operator in this context before.

The docs and the Pickaxe book are a little obtuse on this, so I did some irb spelunking:
>> r = (1..27)
=> 1..27
>> r.class
=> Range
>> r.begin
=> 1
>> r.begin.instance_of? Integer
=> false
>> r.begin.class
=> Fixnum
>> r.begin.kind_of? Fixnum
=> true
>> r.begin.kind_of? Integer
=> true
Hmm. So instance_of() doesn't mean quite the same in Ruby as, say, the instanceof operator in Java does. (That, or Fixnum doesn't truly inherit from Integer in Ruby.)

Also, as it turns out:
>> Fixnum === r.begin
=> true
>> Integer === r.begin
=> true
So it would seem that the [class] === [value] syntax is syntactic sugar for [value].kind_of? [class]

It's the bit about:
>> r.begin.instance_of? Integer
=> false
that surprised me most, being the pathetic Java programmer that I am. And being that (according to the documentation for Integer on ruby-doc.org):
Integer is the basis for the two concrete classes that hold 
whole numbers, Bignum and Fixnum.
Apparently "is the basis for" != "is a superclass of".

Or is that "!==="...?