Technology As If People Mattered

Wednesday Sep 24, 2008

Speaking At The Voices That Matter Conference


Well it‘s official: I‘m going to be teaching a half day seminar at the Voices That Matter: Professional Ruby conference in Boston. The conference runs from Nov 17 – 20 and I will be teaching the first day, Monday, Nov 17.

The topic of my talk is “Fluent In Ruby: Getting Beyond The Basics“ Here‘s the blurb:

One of the best things about learning Ruby is that it is such a familiar looking language. Solve some straightforward problem in Ruby and your code will probably be a bit more compact, but recognizably similar to what you would have written in Java or C#. Don‘t let this familiar facade fool you. Underneath Ruby‘s very mundane surface lurks a wickedly powerful and flexible language that lets you cope with hard problems in some very unexpected ways.
In this seminar, Russ Olsen will look at the parts of the Ruby language that enable you to wage unconventional warfare on your coding challenges. In Ruby you can change classes on the fly, but why would you want to? Ruby has this method_missing thing but where and why would you use it? And what is the Ruby object model and what does it have to do with metaprogramming?
If you are familiar with Ruby but still wondering what all the shouting is about, come find out.

If you decide to sign up, make sure you enter the priority code PRDPKRL for the special “I saw it on Russ Olsen‘s blog” discount.


Russ

Thursday Sep 11, 2008

Ruby Nubie Night at the Northern Virginia Ruby Users' Group

If you are going to be anywhere near Northern Virginia this coming Wed and you are interested in learning the basics of Ruby, have I got a deal for you. We are starting a new thing at the NoVa Ruby Users‘ Group, a friendly intro to Ruby, done in rapid fire style by four local Rubyists, including, well, me.

Take a look at the Northern Virgina Ruby Users' Group NOVARUG site for all the details.

Hope to see you there.

Russ Olsen

PS

Free piza

Tuesday Sep 09, 2008

Rocket Science and Software Engineering

Here‘s a book for your late summer beach reading: Achieving the Vision for Space Exploration on Time and Within Budget. Well technically it's not really a book, it's more of a book sized report. Achieving the Vision is written by a group of rocket scientists who think that NASA‘s efforts to build the next generation of manned (or more accurately crewed) space vehicles has gone seriously off the rails.

The story behind Achieving the Vision centers around NASA‘s efforts to come up with a replacement for the space shuttle. The plan is to create a couple of new, specialized, rockets: The first will be a smaller people-moving booster and capsule combination similar to the old Apollo setup. The second, larger and unmanned rocket would be used for lofting the heavy bits of hardware, the kind of gear that you might need to go to the Moon and Mars. Both of these new rockets will be largely based on shuttle technology: For example, the people mover will use a stretch version of the shuttle solid rocket booster for a first stage, while the second stage of the cargo booster is pretty clearly derived from the shuttle external fuel tank. The hope is that this new pair of rockets will loft the people and stuff without killing the former and incinerating the latter with disturbing regularity.

What hasn‘t gotten a whole lot of play in the news is the fact that there is a vocal minority of rocket scientists who think that the current NASA plan is going seriously wrong. Achieving the Vision is the work of these dissenters who contend that two new rockets is one too many; they want a single design with variations for different missions. The folks behind Achieving the Vision also argue that while the current NASA designs are based on the shuttle, they are not based on it enough. The dissenters think that the next generation of NASA rockets should be directly derived from the shuttle: Let's not build a rocket that uses shuttle technology, let's build a rocket that uses shuttle parts.

This aerospace disagreement echos with a familiar ring to my software engineering ear. In the one corner we have the folks who want to build the new system with bits and pieces of the old, but who don‘t want to be restrained by decisions made ages ago. In the other corner we have the folks who want to hold on to more of the old design, to bring forward the working bits of the old into the new, more or less unchanged. In short, the second group wants to maintain binary compatibility while the first doesn‘t.

So, the obvious question is: Who‘s right? NASA or the Achieving the Vision authors? I haven't a clue. This is rocket science after all, a technical topic of daunting scope and complexity. Certainly the Achieving the Vision argument seems plausible to me. But so does the NASA response. Here perhaps is another lesson we can take away from this snapshot of someone else‘s technical dispute: I‘ve been interested in space flight my whole life and know more about it than the average guy on the street. I also studied mechanical engineering, again a leg up in understanding this kind of issue. But I have to admit that I‘m glad I don‘t have to make this call: The quick and easy, seat of the pants reaction to complex technical questions like this are only correct about half the time. The trouble is that no one knows which half.

Aside from the parallels to software engineering, Achieving the Vision is a fascinating look at what it takes to put people in space. It's the rockets that get all of the attention, but a real space program needs boring launch pads for the rockets to sit on, ground vehicles to move the rockets to the launch pad, workshops to assemble the rockets, test fixtures to ... well you get the picture. Achieving the Vision manages to lay this all out for the reader without becoming too mind numbing. For the type of document that it is (a technical position paper) Achieving the Vision is actually very well written and interesting.

Achieving the Vision for Space Exploration on Time and Within Budget. was written by Stephen L Metschan, Cyril A Longton, Ross B Tierney, Antnio H F Maia, and Philip J Metschan and is put out by the American Institute of Aeronautics and Astronautics.

Russ Olsen

Thursday Sep 04, 2008

Exploring The Ruby Interpreter

Ever wonder how some Ruby class or method is implemented only to discover that the thing is actually part of the built in classes that come with your Ruby environment? Well don’t let that stop you! It turns out that it is actually pretty easy to dig into the source code of the ruby interpreter.

Exploring MRI

If you do decide to go spelunking in the Ruby interpreter, the first question you need to ask is, “Which Ruby interpreter?” Chances are, if you are using plain old Ruby you are actually using the original interpreter written by Matz himself. This Ruby interpreter, known as the Matz Ruby Interpreter or MRI is written in C. You can download the MRI source from here , unpack it and start exploring.

Just to get started, imagine that we want to find out how array indexing works. Looking around in the top level source directory of the MRI distribution we come across a file called array.c: Seems like the obvious place to start. If you look at the bottom of array.c you will find a C function called Init_Array which sets up the Array class. Somewhere in that method is the following call:
 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
This method defines a new instance method on the Array class, a method called “[]”. The punchline is that when [] is called in the Ruby code, it is actually the C function rb_ary_aref that gets fired. If you look at the rb_ary_aref function, you will see that it looks like this:
VALUE
rb_ary_aref(argc, argv, ary)
    int argc;
    VALUE *argv;
    VALUE ary;
{
    VALUE arg;
    long beg, len;

    if (argc == 2) {
        if (SYMBOL_P(argv[0])) {
            rb_raise(rb_eTypeError, "Symbol as array index");
        }
        beg = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        if (beg < 0) {
            beg += RARRAY(ary)->len;
        }
        return rb_ary_subseq(ary, beg, len);
    }
    if (argc != 1) {
        rb_scan_args(argc, argv, "11", 0, 0);
    }
    arg = argv[0];
    /* special case - speeding up */
    if (FIXNUM_P(arg)) {
        return rb_ary_entry(ary, FIX2LONG(arg));
    }
    if (SYMBOL_P(arg)) {
        rb_raise(rb_eTypeError, "Symbol as array index");
    }
    /* check if idx is Range */
    switch (rb_range_beg_len(arg, &beg, &len, RARRAY(ary)->len, 0)) {
      case Qfalse:
        break;
      case Qnil:
        return Qnil;
      default:
        return rb_ary_subseq(ary, beg, len);
   }
    return rb_ary_entry(ary, NUM2LONG(arg));
}

The interface is very much like the arguments passed to a main program in C or Java: You have an argument count, followed by an array of arguments, except that in this case everything is a Ruby object (a VALUE). There is an extra parameter, ary, which is the instance (i.e. the array) that the method is operating on.

Looking at the details of rb_ary_aref shows that it actually handles a fairly wide range of arguments: along with the usual one number (i.e. array[4]), it can handle two numeric arguments (i.e. array[1,4]) as well as a range. Look closely and you will find that passing a symbol as an index to an array is a bad idea.

And For The Java Enabled…

If C code frightens you, there is always JRuby, which you can download from here. The key source directory is right where a Java programmer would expect it: src/org/jruby. Look around in that directory and you will find everything you ever wanted to know about arrays in JRuby in RubyArray.java. JRuby has no rb_define_method call to guide you, but finding the right method is really pretty easy. In this case just search the file for “[]” (with the quotes):

    /** rb_ary_aref
     */
    @JRubyMethod(name = {"[]", "slice"}, required = 1, optional = 1)
   public IRubyObject aref(IRubyObject[] args) {
        long beg, len;
        if(args.length == 1) {
            if (args[0] instanceof RubyFixnum) return entry(((RubyFixnum)args[0]).getLongValue());
            if (args[0] instanceof RubySymbol) throw getRuntime().newTypeError("Symbol as array index");

            long[] beglen;
            if (!(args[0] instanceof RubyRange)) {
            } else if ((beglen = ((RubyRange) args[0]).begLen(realLength, 0)) == null) {
                return getRuntime().getNil();
            } else {
                beg = beglen[0];
                len = beglen[1];
                return subseq(beg, len);
            }

            return entry(RubyNumeric.num2long(args[0]));
        }

        if (args.length == 2) {
            if (args[0] instanceof RubySymbol) {
                throw getRuntime().newTypeError("Symbol as array index");
            }
            beg = RubyNumeric.num2long(args[0]);
            len = RubyNumeric.num2long(args[1]);

            if (beg < 0) beg += realLength;

            return subseq(beg, len);
        }

        Arity.checkArgumentCount(getRuntime(), args, 1, 2);
        return null;
        }

Note that they even give us a back reference to the original C code method name in MRI! If you compare the MRI C with the JRuby Java you will see that JRuby logic is a bit rearranged and rewritten, but recognizably similar to the original.

Well You Do Do Ruby, Right?

Finally, if you don’t do C and you don’t do Java, perhaps you do do, um, Ruby? For that, you can look at Rubinius, which is Ruby implemented (mostly) in Ruby. Get the code at http://rubini.us/download. I’m not nearly as familiar with the Rubinius source as I am with the other two, but a quick look turns up ./kernel/core/array.rb:

  def [](one, two = nil)
    Ruby.primitive :array_aref

    # Normalise the argument variants
    start, finish, count, simple, is_range = nil, nil, nil, false, false

    if one.kind_of? Range
      is_range = true
      start, finish = one.begin, one.end
    elsif two
      start, count = one, Type.coerce_to(two, Fixnum, :to_int)
      return nil if count < 0       # No need to go further
    else
      start, finish, simple = one, one, true
    end

    # Convert negative indices
    start = Type.coerce_to start, Fixnum, :to_int
    start += @total if start < 0

    if simple
      return nil if start < 0 or start >= @total
      return @tuple.at(@start + start)

    # ONE past end only, MRI compat
    elsif start == @total
      return self.class.new

    elsif start < 0 or start >= @total
      return nil
    end

    finish = Type.coerce_to finish, Fixnum, :to_int if finish
    finish = (start + count - 1) if count    # For non-ranges

    finish += @total if finish < 0

    finish -= 1 if is_range and one.exclude_end?

    # Going past the end is ignored (sort of)
    finish = (@total - 1) if finish >= @total

    if finish < 0
      return self.class.new if is_range
      return nil
    end

    out = self.class.new

    return out if finish < start or count == 0

    start.upto(finish) { |i| out << at(i) }
    out
  end

I have to admit that even as a reformed C hacker who did Java for years, I prefer reading the Ruby version of this code.

It’s Mine! All Mine!

Remember, with open source, you don’t have to take my word for it, you don’t have to read a book or ask the experts. With open source you can always pull down the source and find out for yourself.


Russ Olsen

Tuesday Aug 26, 2008

To IDE Or Not To IDE

Since I live near Washington DC and this is a presidential election year, I am painfully aware that people sometimes do not agree on things: at the moment I am thoroughly sick of Democratic vs Republican. But it is not like the technology world is immune from these kinds of unending disputes, disagreements that are waged with religious ferocity without any foreseeable conclusion. In fact, the civilian world can‘t really compete with us techies: Windows vs. Mac. GIF vs JPEG vs PNG. We even make fun of ourselves about it: Big Endian vs Little. And then there is the old favorite: to IDE or not to IDE. In case you are somehow unfamiliar with this argument, it revolves about the question of how much reliance a good software engineer should place on the Ginsu Knife of program development, the Integrated Development Environment or IDE.

Primitive Rampage

In the one corner we have the folks whom I will call the Primitives No, the Primitives don't develop software in a loincloth by the light of a camp fire (though I have to admit that picture is strangely attractive). Instead the Primitives are deeply suspicious of 'automagic' tools like the IDE. Remember, my primitive friends say, the Devil is in the details and you should be very skeptical of any tool that claims to hide those details from you. If you are a Java programmer, then in some sense your job is to make JAR or WAR files. If you don't know how a JAR file is made in more detail than "I just click the Build menu button." then you are not really a Java programmer. Besides, while we typically look at IDEs as labor saving devices, sometimes all of that pointing and clicking is the labor and you would be much better off just being able to run some commands in a script.

The IDEers Strike Back

“Nonsense”, say the folks in the other corner, a post-modernest bunch that I will call the IDEers IDEers take the very reasonable position that the Integrated Development Environment, is just the latest in the same evolutionary line that has brought us assemblers and linkers and compilers and editors with syntax highlighting. Software is hard enough, the IDEers say, we can't go ignoring any sort of tool that will make it a bit easier. Why stop at the IDE, this group asks: why not go back to coding in binary by throwing switches on the front panel? Why remember a bunch of command line nonsense when you can just click on the nice Build menu item and it is all done for you? Save your brain power for more vital things like object models and database schemas and where you are going for lunch.

Besides, by providing a one stop shopping for all your software development needs, including project templates, wizards and those wonderful popup menus that know that the method is called write not save IDEs are invaluable tools for getting beginners off of square one and producing code quickly.

The Most Dangerous Place In A Duel Is Between The Parties

There is an old bit of wisdom to the effect that there is a special place in Hell for people who can‘t choose a side in an argument. If so, save me a seat next to the brimstone. My reaction to the whole Primitive vs. IDEer dispute is to come down firmly in both camps. The IDEers are right: why turn down a tool that makes you more productive? In my days of being a manager for a very large corporation I was subjected to a lot a management training. Most of it passed through me without disturbing a single neuron, but one bit of wisdom has stuck with me: The best way to find out what will make some worker more productive, is… wait for it … ask ‘em. “Gee Fred, what can we do to make things go easier for you?”

When it comes to their job, people tend to know what works and what doesn‘t. If Fred is a software engineer and Fred says that an IDE will make his life easier (and incidentally make the development go faster) go get Fred an IDE. You might also want to pick up a second copy of that IDE for George, the very junior guy who is still trying to figure out where they keep the office supplies. Having gone through the painful process of bringing a beginning coder up to speed many times, let me vote for the path with the fewest landmines, which has got to be the IDE.

But this is not the whole story, because there are some serious drawbacks to relying on your IDE too much. The primitives are right about those “hidden” details that sometimes come roaring out of the dark to bite you in a sensitive place. To take a concrete example, a couple of years ago, during one of those insane ‘fix all the bugs before the release‘ periods I ended up working on a problem with a particular JSP page. Now I‘m not much of a web presentation kind of guy, but duty called and I somewhat reluctantly answered.

The problem centered around a bit of JSP that looked something like this:
<% boolean loggedIn = false; %>

...

<% if (loggedIn)%>
<p>Don't forget to log out when you are finished.</p>

Simple enough: If the user is logged in, put out some text reminding him to log out. The trouble was, as I‘m sure my JSP savvy readers already know, the message was alway being displayed, no matter if the user is logged in or not.

I probably stared at this problem for the better part of the afternoon before I got the bright idea of changing levels: exactly what Java code was my little JSP gem creating? Here‘s what I found when I tweeked the options on my JSP compiler and had it spew out the Java:

if (loggedIn)
out.write("\r\n");
out.write("      <p>Don't forget to log out when you are finished.</p>\r\n");
out.write("\r\n");

Ah Ha! Obviously the JSP compiler was generating more Java than I (and the person who had written the thing in the first place) was expecting. The only thing that my if was doing was deciding if there should be a bit more or less white space in the HTML.

Having seen the Java code, the fix was very simple:

<% if (loggedIn) {%>
<p>Don't forget to log out when you are finished.</p>
<%} %>

Note the braces around the if statement. My JSP problem was an example of what Joel Spolsky calls a leaky abstraction.Some of the details from the lower, Java level had managed to work themselves up into my naive JSP world. I figured the problem out because I was able to change levels, mentally pull myself out of the JSP worldview and see the Java code.

Sometimes even the dedicated IDE user will need to pull him or herself up out of the IDE world view and look at things in terms of compilers and class and JAR files. Mostly IDEs work just fine most of the time. But occasionally an IDE will stumble over an unexpected file permission, or a directory that accidentally got deleted or renamed. And suddenly your nice IDE abstraction has sprung a leak that could sink the Titanic. And if all you know is your IDE and the Build then you are stuck. But if you understand the next level down, if you understand what is really going on, then you can usually work the problem out.

Turtles All the Way Down?

One problem with this argument is knowing when to stop: If it is good to understand how your IDE works, wouldn‘t it be even better to know the details of how your compiler works? And once you have grasped all of that, why not dive down into the VM and then the assembly language… Looks like we had better let the project manager know that this little web app is going to be a bit late…

Well, no. The nice thing about leaky abstractions is that in any decent system they are going to be relatively rare. And they tend to get rarer as you go down the stack: As a rule IDEs tend to be buggier than compilers, which tend to be buggier than VMs and so on. So when that IDE abstraction starts leaking all over your desk, chances are pretty good that the was caused by the IDE and not something further down.

What this means is that, practically speaking, you only need to dive one level down: To really master a tool, you need to understand the tool and something about the next level down. Think about my JSP problem: I dropped one level down into Java and all was revealed. So if you want to get a real handle on Ruby then go exploring the Ruby interpreter. And if you want to really master that Java IDE, then get to know the Java SDK.

Russ Olsen

PS Thanks to Dave Bock for pointing out the Joel Spolsky article.

Tuesday Aug 19, 2008

Some Important Numbers For Developers

Software engineering is one of those semi-mathematical technical professions that is just chock full of numbers. Our machines run at so many gigahertz and produce some exact number of mega-flops. We have deal in the hard physical reality of memory in kilobytes and the more ethereal idea of so many big O‘s for each sub N. But I‘ve been thinking that there are some numbers that we have been neglecting. For example:

Three

The optimum number of software engineers that can collaborate on a single project. As Fred Brooks pointed out long ago, people are simultaneously the power source and one of the main impediments to writing code. Add some more people to your project and they might make things spin faster, but more people can also slow progress down, since more people means more meetings, more memos and more misunderstandings. I know that there are lots of projects out there that require more than three people, but I do think that three is an optimal point on the curve.

Zero

The number of uniquely correct solutions to any given software problem. The key word here is ‘uniquely‘:Just about all real word problems have many fine solutions, not just one. The belief that my solution is the one true way is almost certainly wrong and is quite likely to drive down another important figure – the number of working solutions that we actually manage to produce.

Infinity

The number of incorrect solutions to any given software problem. Just because I think that are many good solutions doesn‘t mean that yours happens to be one of them.

500,000

An estimate of the number of ways that any given programming problem might be solved, at least within the borders of the United States. As it happens, there are also about half a million coders working in the US at the moment. This estimate might be high, since not every coder will have an opinion on every problem. On the other hand it might be low: I tend to change my mind six times before lunch. On a good day.

625

Six hundred and twenty five is approximately the number of programming languages found on wikipedia‘s list of programming languages. Lately I have been playing with Erlang which is a functional programming language designed for concurrency. It is such a weird language that I‘ve nearly given up three or four times, but I have each time I come back to it with that “Oh, I see!” feeling. At this point the jury in my head (it‘s amazing we can all fit in there) is still out, but I am sure of one thing: learning about Erlang has changed the way that I think about programs and computing, changed it in some subtle ways.

But Erlang is just one of 625 and each of those languages represents a unique view of the computing terrain as well as a vehicle for crossing that terrain. Most of those 625 languages are destined to live out their lives in well deserved obscurity, but taken as a group they sum up much of the thinking that we have done in the past half century on how to build programs. Have you learned a new language lately?

Three

The number of programmers who will write most of the code in a system developed by a team of 24 engineers, two project managers, three group leaders, a quality lead and an office manager.

Russ Olsen

Tuesday Aug 12, 2008

Book Review: Why Size Matters

No, it‘s not what you think: This is a book about how going for a swim is different for a bacteria than a whale, how a deep breath is cleansing for a person but unknown to a mite and why all of those giant spiders/crabs/manti so beloved by the writers of bad sci-fi are less likely than you think.

Why Size Matters was written by John Tyler Bonner who is a professor of ecology and evolutionary biology at Princeton. Based on the contents of this book, I bet the good professor‘s classes are standing room only. Bonner has managed to write a book which is simultaneously informative, fun and (most importantly) short. Divided into seven delightful chapters, Bonner‘s slim volume explores why being twice as big means needing much thicker legs while being ten times as big means needing a whole lot more than really thick legs. The book starts with the familiar: Why that giant crab is not going to be attacking any Japanese cities this week (though I have to say that if I lived in the Tokyo of the 1950s science fiction movies, I would move). The familiar is just a warm-up for, shall we say, bigger things: Bonner quickly moves on to chapters about size and evolution as well as how bigger frequently means a greater division of labor in everything from protozoa to aircraft carriers.

The subject is heavy but the style is light – and did I mention fun? The fun goes all the way through with this book: even the physical layout of it is a bit of an inside joke: What else would you call a book with this title that is all of 5 inches wide by 7 inches tall (12 by 17 cm). Given how much I enjoyed this book, size truly does not matter.

The full title of the book is Why Size Matters/ From Bacteria To Blue Whales and it was published by Princeton University Press in 2006. If you like you science with a pinch of levity, go get this book.

Monday Aug 04, 2008

New Ruby Book Discussion Group

Well it has been a while since I’ve written here, mostly because I was spending a fair bit of my time helping to organize (and speaking at) the RubyNationconference. The conference went as well as we could possibly hope with Neal Ford leading off and Stu Halloway bringing down the house at the end.

So what am I going to do with all of this free time? Well, along with blogging a bit more (i.e. some), I’m also participating in a new Ruby book discussion group. This was started by fellow Addison Wesley author Aurelius Prochazka. By chance, the first book they are doing is my own Design Patterns in Ruby – I had nothing to do with it, I swear. Stop by and check it out!

Russ Olsen

Saturday Jan 26, 2008

Let's Just Chill

At least from my point of view, 2008 has gotten off to a somewhat rocky start. As a developer with one foot in the Java camp (proven, reliable, fast) and another in the Ruby camp (expressive, elegant, fun) I sometimes feel like I'm playing the role of the small country stuck between two great feuding powers. That's why we need more folks like my buddy Matt, who has started writing some light hearted stuff over at his One Flew Over the Server Rack blog.

Let's hear it for more laughter and less shouting.

Russ

Monday Jan 14, 2008

Book Review: Business Process Management With JBoss jBPM

A couple of interesting things happened to me recently. I have been designing a system with a workflow side to it and the thinking was that the JBoss jBPM workflow engine might be a good fit. So I was wading into the documentation to see if I could make some sense of the thing. Like a lot of large software products, jBPM comes complete a circus full of acrobat files, documentation that is detailed, in depth and kind of, well, incomprehensible. At least for the beginner. I’m sure once I get out of this initial spin up phase, I’ll soon have all of my business processes humming along, but I have to admit that so far it has been rough going.

Which brings us to the second interesting event: out of the blue I got an email from the PackIt publishing company asking if I would like to review one of their books, Business Process Management With JBoss jBPM by Matt Cumberlidge. They would even send me a free copy. It is dangerous to ignore luck like that and so here we are.

Cumberlidge’s book opens with an outline of what can only be described as the business process management philosophy: understand your business process, automate it (or a part of it) with a workflow engine and then iterate to improve. The book then launches into its single case study, the heart wrenching adventures of Bland Records in its quest to turn musical talent into profit. Thank goodness - if I have to sit through one more online pet store implementation I was going to get violent. After taking us through an analysis of the Bland workflow (aren’t they all bland?) Mr. Cumberlidge, talks briefly about the architecture of jPBM and then jumps right into is main topic: the details of getting jPBM set up and flowing that work.

And I do mean the details – this book starts by explaining how to install Java and moves on to using the jPBM Eclipse plugin to build the workflow definition. From there we segway into creating jBPM based user interfaces and deploying the whole thing (in JBoss, naturally). We finish up by discussing such real world issues as monitoring your workflow, sending email alerts when your process starts to smell a bit fishy, and deciding if the whole effort was worthwhile.

There is a lot of detail in this book – many, many screenshots, lots of handholding through menus and dialogs. Perhaps a little too much for me, but I’ll make allowances since Cumberlidge’s focus is so squarely on helping the reader become productive with jBPM rapidly. The details are all very Windows oriented, but this Linux/Mac user had no trouble translating them into my OS as needed.

Aside from the technical content, there are a couple of things I really like about the book. The text is clearly written (if just a tiny bit wordy). Best of all, Mr. Cumberlidge writes in an easy, informal style. There is none of the “consider this” and “therefore it may be concluded that” nonsense that makes so many technical books read like 700 pages of stereo instructions. Be aware that this is a very focused book: it is less like “jPBM The Missing Manual” and more like “jPBM The Missing Quickstart Guide”. Still, Business Process Management With JBoss jBPM is a competent book that fills a real gap.

Russ Olsen

Friday Jan 11, 2008

An Interview over at On Ruby

New interview with yours truly over at the On Ruby blog

Friday Dec 07, 2007

... And An Italian Version...

The very gratifying international career of Ruby Spin-up: Where Did That Method Come From? continues with an Italian translation.

Thanks to Valerio Schiavoni!


Russ Olsen

PS

One of my less technical friends suggested that perhaps someone should translate the article into English!

Thursday Dec 06, 2007

Chinese Version Of the first Ruby Spin-up article

This is getting to be a regular thing: Here is a Chinese version of the first Ruby Spin-up article.

Thanks to Charles Zhou.


Russ Olsen

Portuguese Version Of the first Ruby Spin-up article

Lucas Húngaro was kind enough to translate my article Ruby Spin-up: Where Did That Method Come From? into Brazilian Portuguese. You can find the results over at Aquecimento Ruby: “De onde veio esse método?”

Thanks Lucas!


Russ Olsen

Monday Dec 03, 2007

Ruby Spin-up 2: Missing, Mobile and Manufactured Methods

Last time, we talked about how reading real code is a great way to learn a new programming language. This applies to just about any language, including Ruby, but Ruby does present some challenges to the learner because there are so many ways in Ruby to connect some code with a method name.

In the last article we looked at the more pedestrian ways that you might define a method on a Ruby object: you could just do the traditional thing and put the method in the object’s class or super-class or its super-duper class. You might also define the method in a module that gets included (‘mixed in’ as we say) into the object’s class (or any of its super classes). Finally we saw that you might define a singleton method on an individual object, a method that exists only on that object.

This time around we are going to look at three somewhat more exotic ways to hook my_object.this_method up to some code.

Method_missing: The Method With A Thousand Faces

Imagine that you are trying to follow some code that calls my_car.drive_to_washington, but you can’t find the drive_to_washington method anywhere. You have searched your classes and modules. You have kept an eye out for those pesky singleton methods. You have searched and grep’ed and grep’ed and searched and that stinking drive_to_washington method is just not there. Relax, you may have just come across a case of method_missing (cue scary music).

We have seen that when you call a method on an object, Ruby goes through this exhaustive search – it looks in the object’s singleton class and its modules, then in the regular class and its modules, and then in the super-class and so on. But what if there is no method to be found? You just get an exception right?

Not exactly: when Ruby fails to find a method on the first pass, it doesn’t just give up. Instead Ruby begins the method hunt all over again, starting with the singleton class and working its way up the tree, this time looking for a method called method_missing. Essentially, Ruby tries to inform your object that someone called a method on it and that that method was, well, missing. It does this by calling the method_missing method. What happens from there is really up to you. Do nothing and the method_missing from the Object class will eventually throw the exception that you expect. But you can also define your own method_missing method and catch those unexpected calls and do whatever you want with them.

To see how this works in practice, let’s define a method_missing to implement that mysterious my_car.drive_to_washington call:


class Car
  def method_missing(method_name, *arguments)
    if /^drive_to_/ =~ method_name.to_s
      place = method_name.to_s.sub(/^drive_to_/, '')
      puts "I'm driving to #{place}" 
    else
      super
    end
  end
end

There really is not a lot going on here. The method_missing method gets called with the name of the absent method along with all of the arguments that it was called with. What the Car class does is to look at the name of the method: If the method name begins with the string “drive_to_” then the code will clip off the last part of the method name and announce that that is where it going. Notice that if the method name does not look right, method_missing calls super which will eventually call method_missing from Object and we will experience an exception.

With our new version of car we can drive where ever we want:

c = Car.new
c.drive_to_washington
c.drive_to_ny

The key thing to notice about the way we implemented the drive_to_washington and drive_to_ny methods is that the strings “drive_to_washington” and ‘drive_to_ny’ never actually appear in the source code. That is something that you need to keep in mind as you are scouring some application for an enigmatic method: it may be hiding, nascent, in method_missing.

Methods Here And Methods There

Sometimes the explanation for those hard to find methods is a lot simpler than method_missing. For example, you might be looking for a method and you have looked at the class definition, you have looked at the modules and you have searched diligently for any method_missing’s and you still can’t find that method. What gives?

Wait… Did you say the class definition? You see, in Ruby there is no such thing as the class definition. Oh a lot of classes are just defined in one place, like this:

class Convertible < Car
  def color
    "Sizzling red" 
  end

  def top_down
    puts "Putting the top down" 
  end

  def top_up
    puts "Putting the top up" 
  end
end

But it is also perfectly possible to define a class in several chunks. You might, for example, find the first part of your convertible in one file:

class Convertible < Car
  def color
    "Sizzling red" 
  end
end

And then come across more of it in a second file:

class Convertible
  def top_down
    puts "Putting the top down" 
  end

  def top_up
    puts "Putting the top up" 
  end
end

Note that that second bit of code doesn’t create a new Convertible class; instead it reopens the existing Convertible class and adds a couple of methods to it.

The thing to keep in mind about Ruby is that when you define a class, you are not doing something all that special. What you are doing is creating a new object – an instance of Class. The object that you create, Convertible in our example, is special in some ways (you can create new instances with it, for example) but in the end it is just an object. In Ruby you can modify existing classes as easily as you can create new ones. So if it is convenient to define one part of a class over here and another other there, people will. You just gotta keep your eye open for it.

Manufacturing Methods With Metaprogramming

The final twist in method making that we will look at is creating methods with metaprogramming. Metaprogramming is one of those very powerful techniques that can make writing an application so much easier but which can also make the code completely incomprehensible if you don’t get it. But read on, because get it you shall…

The idea of metaprogramming is that your program modifies itself as it goes. This is relevant for us, because a very popular way to modify a class via metaprogramming is to add a method to it. One way to do this is to simply evaluate the code to add the method:

class Car
  def self.add_destination(dest)
    code = %Q{
      def drive_to_#{dest}
        puts "Good bye!" 
        puts "I'm driving to #{dest}" 
      end
    }
    eval(code)
  end
end

The example above defines a class method called add_destination. The first thing that the add_destination method does is to conjure up a string (the %Q{...} syntax is just a convenient Ruby way of making a multi-line string) containing the Ruby code for the new method. It then evaluates that string as Ruby code. Instant method.

So if you call Car.add_destination('washington'), the string ends up being:

      def drive_to_washington
        puts "Good bye!" 
        puts "I'm driving to washington" 
      end

Evaluate this and you end up with a new method in the Car class called drive_to_washington.

You can also define methods a little more directly by using the (what else?) define_method method:

  class Car
    def self.add_destination(dest)
      define_method "drive_to_#{dest}" do
        puts "Good bye!" 
        puts "I'm driving to #{dest}" 
      end
    end
  end

There are some practical differences between the eval technique and define_method, mostly having to do with the visibility of variables, but at the very gross level they are the same: in both cases you end up with a new method without an explicit definition of that method in the source code.

Wrapping up

So there you have it, a whole bunch of ways to connect that method call with some Ruby code. Back in part 1 we saw that you that can do the traditional put all of your methods in the class or its superclasses thing, or you can define methods in a module and include the module in your class. Not only that, but you can also hang methods on individual objects. This time around, we saw how you can catch calls to non-existent methods with method_missing or spread your method definitions in different files. Finally we took a quick look at metaprogramming, a way to cook up brand new methods on the fly.

If you are new to Ruby you may be thinking that the only possible reason that Ruby would support all of this variety is to drive the beginner nuts. I know that is how I felt at first. But every one of the more exotic Ruby method definition techniques has a purpose; Each one eases the burden of building programs in its own way. Want to know how? I think the best way to learn that is to pick up your favorite Ruby program and start reading.

Russ Olsen

Buy the book!

Calendar

Search

Translations

Feeds

Navigation