What You Can Learn From ido.el

Posted on May 14, 2008 by stu

I have put together a 25-minute screencast on What You Can Learn From ido.el. At first glance, the screencast appears to be about TextMate and Emacs, but it's really about this.

Getting JRuby on Rails working with DB2

Posted on May 13, 2008 by stu

Aaron and I are trying to get Jruby on Rails on DB2 to actually work. So far, we have been wrestling with the following issues:

We are driving our effort by porting existing projects that work with other databases, and seeing what breaks. We are not DB2 experts, so a lot of this is conjecture+test. We would love to join forces with anyone interested in getting the DB2 driver to first-class status. Give us a shout.

Scalable Social Networking Reaches JavaOne

Posted on May 10, 2008 by stu

Folks in the Java community know a ton about scalability. So when they needed to connect at JavaOne last week, they turned to a scalable social networking platform.

Keynoting RubyNation

Posted on May 08, 2008 by stu

I will be the closing keynote speaker at RubyNation. I'll be beating my current favorite drum: Ending Legacy Code In Our Lifetime. (And yes, the Ruby community has legacy code. If we don't change our ways soon, we will end up with a lot more of it.)

Speaking at Refresh the Triangle on May 22

Posted on May 08, 2008 by stu

I will be speaking at Refresh the Triangle on May 22. The topic: Ending Legacy Code In Our Lifetime. Hope to see you there.

Defeating DRM...

Posted on May 06, 2008 by stu

... is more confusing than ever. Thanks Apple, I think.

Rich Consistency

Posted on May 01, 2008 by stu

Alan Keefer has written on the benefits of clean, expressive syntax. He picks four main reasons that syntax matters: (fewer) lines of code, readability, memorability, and discoverability.

It is an excellent list, and I would like to add a fifth: rich consistency. By rich consistency, I mean two things: a sufficiently rich set of first-class objects, and the whole language there all the time.

Rich, Consistent Platforms

In a rich consistent platform, you have all the basic tools you need, and you can combine them any way you see fit, at any time. As an example, consider the following basic toolset. (This is not a "rich" set of tools, but it is plenty large enough to demonstrate the issue.)

  1. Encapsulation of verbs (functions)
  2. Encapsulation of nouns (objects)
  3. Polymorphism
  4. Control structures/loops
  5. Namespaces
  6. Dynamic loading of code

Starting with our basic tools, we can mix and match. A simple example would be to write a method that loops over a collection invoking some operation. Our method is a function (1) attached to a noun (2) that contains a control structure (4) invoking a polymorphic method (3).

That's easy enough, and most modern languages can handle it. The problems start when you consider all the other possible combinations. Ask yourself if your primary programming platform can do the following. (Don't feel too bad if it can't: many platforms can't handle any of these.)

  1. Define a new verb (1) that acts as a control structure (4), usable in the exact same ways that the built-in control structures are used.
  2. Invoke a verb (1) polymorphically (3) based on more than one noun (1).
  3. Create new verbs (1) or new (kinds of) nouns (2) from inside a control structure (4).
  4. Switch or alias namespaces (5) inside a control structure (4) inside a verb (1).
  5. Change how polymorphic lookup (3) is resolved based on dynamically loaded code (6).

You may not be able to think of a real-world use case for all of these combinations. If the ones that seem realistic to you are exactly the same ones that your favorite platform supports, you should be very worried.

Impoverished, Inconsistent Platforms

What happens when your platform is not richly consistent?

  1. You see a proliferation of special cases. E.g.: Your language has control structures (duh!), but you are not allowed to use them in certain places. Instead, your platform provides a localized, ad hoc solution. Maybe you cannot write a loop to deal with aliases ("imports" if Java is your first langauge). Instead your language provides a wildcarding mechanism to help deal with namespaces. This mechanism only only works when dealing with namespaces, and nowhere else in the language. (This may seem minor, but multiply it by a few hundred and it creates a huge cognitive load.)
  2. Your platform is difficult to learn and remember, because of the special cases. Once you have learned the special cases, you become blind to these costs. Ruby's class <<self; self; end comes to mind.
  3. Instead of composing solutions using your basic tools, you create repetitive, redundant solutions via cut and paste. If your platform community is small, this is embarrassing, and goes by the name "spaghetti code". If your platform community is large, this is a point of pride, and is called "design patterns."
  4. Your community develops platform extensions to automate and conceal the most visible platform embarrassments. Often these extensions take the form of IDE automation for cut-and-paste tasks.
  5. Code is difficult and expensive to test. Test harnesses need to isolate code in ways not generally needed in production. Trying to write a thorough test suite will uncover some (but not all) of the ways that your platform is not richly consistent.
  6. Your platform loves code generators and aspect weavers to automate common idioms. Since consistency is not valued, these generators probably have their own syntax and rules, different from the core language.

Duct Tape, Anyone?

There is some good news. If your platform is large enough, then the open source community will rise to the challenge, and build a superstructure that deals with platform inconsistencies. The Spring Framework Mission Statement is a great example. It begins with:

We believe that:

  • J2EE should be easier to use
  • It is best to program to interfaces, rather than classes. Spring reduces the complexity cost of using interfaces to zero
  • JavaBeans offer a great way of configuring applications
  • OO design is more important than any implementation technology, such as J2EE
  • Checked exceptions are overused in Java. A framework shouldn't force you to catch exceptions you're unlikely to be able to recover from
  • Testability is essential, and a framework such as Spring should help make your code easier to test

The paean to OO design is mom-and-apple-pie, but the other five items can be summarized as "Is your poor, inconsistent platform failing for large, complex problems? Fear not. We have felt the same pain, and have packaged a set of workarounds."

The Spring team has done a good thing. I wish them well, and would bet money on their continued success. But "good abstraction over complexity" is not the same as simplicity.

We're Getting There

Programmers are moving to richer, more consistent platforms. But this movement could be much more direct. In general, we don't value consistency, or even notice its absence. But we do value killer apps, and they (slowly) drive platform choices in the right direction.

The next generation of software will be written on platforms that are more richly consistent. As a nice bonus, such platforms interoperate easily, so we might even hope that the days of platform monoculture are coming to an end.

Friday Yak Blogging

Posted on April 26, 2008 by stu

If you are working under a tight deadline, then yak shaving is a mortal enemy. Nevertheless, yak shaving is a useful skill for a programmer to have. Multitasking and tangential thinking are often the only way to avoid local minima, in progrmaming and in life.

Are you a yak barber? See if this story sounds all too familiar:

2:00 pm. Reading an interview with Paul Jansen (the TIOBE guy). The part about coding standards and tests really rubs me the wrong way, and I think I will blog about it.

2:10 pm. This blog will be much better with some pictures...

2:13 pm. My Grab application saves files as TIFFs by default. Not very web-friendly. Any way to change this? Hmm, not in the preferences.

2:14 pm. Jason sends me instructions for taking screen shots, which include instructions for using defaults write com.apple.screencapture.

2:15 pm. Wait a second. The built-in key commands for screen grabs are easier to use than the Grab application, I'll just use them.

2:19 pm. The built-in key commands save files to the Desktop. I promised myself that the next time I touched the desktop for any reason, I would clean up the 200+ files of cruft there.

2:21 pm. Decrufting of desktop proceeding well, except that opening text files in the default editor is surprisingly slow. How do I change the default application for a file type?

2:22 pm. Jason again: "Bring up the info panel for a single file. Choose the 'Open With:', and then 'Change All...' of that type."

2:24 pm. Awesome. Now several file types open in Emacs by default. But I bet there is an easier way to change a bunch of types all at once, by editing a plist file somewhere.

2:26 pm. Judging by file modify times, I probably should be looking at com.apple.finder.plist.

2:27 pm. The Property List Editor does not have very powerful search and replace capabilities, so I open the file in a text editor instead.

2:27 pm. Surprise! The file isn't XML. Aren't plist files XML?

2:30 pm. Aaron: "I have the command line fu you need to convert a plist to XML, and back again after you are done." No thanks! I usually open files from Quicksilver anyway, and having spent nine minutes on Finder is enough. (What do you think I am--some kind of yak barber?)

2:31 pm. I should bookmark those screenshot instructions in del.icio.us. I click on the Firefox toolbar item, and del.icio.us prompts me to login--but in a popup window that doesn't have the 1Password button. So I open 1Password directly to copy the password.

2:32 pm. Why do I have a super-secure password on del.icio.us anyway? I am likely to use it from a random browser where I don't have 1Password, so I will go ahead and change my password while I am here.

2:33 pm. Jason mentioned at lunch that Quicksilver can actually manage your social bookmarks, so I should go and install that plugin.

2:36 pm. Victory is mine. Plugin installed, original mission accomplished. I think. What was I doing again?

Refactoring from Ceremony to Essence

Posted on April 23, 2008 by stu

The Essence vs. Ceremony issue plays out at both strategic and tactical levels, but the tactical examples are the easiest to follow and understand in a small example. I used to give a conference talk demo of refactoring from ceremony to essence, but I never set the example in prose. Chad Fowler is teaching today, and wanted to show the example, so here it is:

Step 0. Initial Code

public ActionForward edit(ActionMapping mapping, 
                          ActionForm form,
                          HttpServletRequest request,
                          HttpServletResponse response)
    throws Exception {
  PersonForm personForm = (PersonForm) form;
  if (personForm.getId() != null) {
    PersonManager mgr = 
      (PersonManager) getBean("personManager");
    Person person = mgr.getPerson(personForm.getId());
    personForm = (PersonForm) convert(person);
    updateFormBean(mapping, request, personForm);
  }
  return mapping.findForward("edit");
}

Step 1. Duck Typing

edit(mapping, form, request, response)
    throws Exception {
  personForm = form;
  if (personForm.getId() != null) {
     mgr = getBean("personManager");
    person = mgr.getPerson(personForm.getId());
    personForm = convert(person);
    updateFormBean(mapping, request, personForm);
  }
  return mapping.findForward("edit");
}

Step 2. Once you are duck typing, the local variable personForm is not needed.

edit(mapping, form, request, response)
    throws Exception {
  if (form.getId() != null) {
    mgr = getBean("personManager");
    person = mgr.getPerson(form.getId());
    form = convert(person);
    updateFormBean(mapping, request, form);
  }
  return mapping.findForward("edit");
}

Step 3. Return can be implicit (everything should return a value), and things can always go wrong (so there is no need to declare that an Exception can be thrown).

edit(mapping, form, request, response) {
  if (form.getId() != null) {
    mgr = getBean("personManager");
    person = mgr.getPerson(form.getId());
    form = convert(person);
    updateFormBean(mapping, request, form);
  }
  mapping.findForward("edit");
}

Step 4. Don't add a manager layer to MVC (yet). YAGNI.

edit(mapping, form, request, response) {
  if (form.getId() != null) {
    person = Person.find(form.getId());
    form = convert(person);
    updateFormBean(mapping, request, form);
  }
  mapping.findForward("edit");
}

Step 5. Conditionals make code expensive to test; so ceremonial conditionals are a particular nuisance. Let framework error handling deal with missing data on the form.

edit(mapping, form, request, response) {
  person = Person.find(form.getId());
  form = convert(person);
  updateFormBean(mapping, request, form);
  mapping.findForward("edit");
}

Step 6. All action methods have the same four arguments. Stop repeating yourself. Make them instance variables/methods on the controller instead.

edit() {
  person = Person.find(form.getId());
  form = convert(person);
  updateFormBean(mapping, request, form);
  mapping.findForward("edit");
}

Step 7. Let the model do double duty: backing the form and representing the database object. Adding a separate layer here is YAGNI until proven otherwise.

edit() {
  person = Person.find(form.getId());
  mapping.findForward("edit");
}

Step 8. Standard routing will already find the right view template, so don't be explicit.

edit() {
  person = Person.find(form.getId());
}

Step 9. Rubyize the syntax.

def edit
  @person = Person.find(params[:id])
end

Code reviewing git commits

Posted on April 23, 2008 by stu

On a weekly basis, I am code reviewing hundreds of commits on a dozen separate projects managed by git. So far I have bounced between the following tools:

  • TextMate plus the TextMate git bundle
  • Emacs (git mode ships with git itself)
  • gitk

This week I am going to try GitNub.

The needs of a code reviewer are different from the needs of a developer. What I think I want is:

  • beautiful Mac interface
  • keyboard access to everything
  • quick ability to move from viewing a point in time (one commit) to a point in space (one file), and back again
  • easy navigation into an editor of choice

What works for you?

Relevance Welcomes Erik Yowell

Posted on April 21, 2008 by jgehtland

Relevance is pleased to announce that Erik Yowell has joined the team. Erik brings 10 years of experience in application design and development, ranging from small-business to enterprise clientele. He also brings passion for the artistic aesthetic of design and the interactive user experience. Currently, he is deeply involved in the agility of the creative and design process, while maintaining a high level of visual appeal for both users and customers.

We’re thrilled to have Erik aboard, and can’t wait to start showing off his work!

Wide Left -- by, like, fifty feet

Posted on April 20, 2008 by jgehtland

Applebee’s. A corporation desperate for renovated image has crafted perhaps the most uninformed ad campaign ever. If you haven’t seen it, John Corbett voices the standard “look at our Tyler Florence-influenced menu with burgers and fries” montages, but with two very, very noticeable differences.

First: the new “Applebee’s Trio” is referred to as a “killer app”, and second, the logo is visibly morphed from the age old Apple and thick font to a newer one that has undergone clear w2206n. It has an apple that looks like it was designed by 37signals and the font has switched to a cleaner, less “drawn” and more “typed” look with a clean, solid sheen green that was picked from the web pallet.

Which, on the surface, you think: “Well, they are just changing with the times. After all, they changed the slogan too, to ‘Its a whole new neighborhood.’” But that’s just not true. What is true is they have been misled into believing that is what they are doing, but instead, they are throwing money down a big, empty hole.

Here are the three possible audiences for this advertisement:

1—regular Americans who already patronize Applebee’s and wouldn’t know the phrase “killer app” from “killer bee”. In which case, the ad is just another montage of vaguely appetizing mini-burgers and beer.

2—people who consciously recognize what is going on. This is people like you and me, who hear the phrase “killer app” applied to sliders and fries and think “WTF??? Really? Who came up with that crap?” Then we see the logo change, and are just perplexed. It is such a mis-application of the concepts that we are turned away from the product, instead of toward it.

3—people who subconsciously recognize the phrase and the logo change. This is the kids, maybe 20 and under, who have been inundated in tech culture all their lives, who recognize memes and technical phrases as part of their lexicon, but who may or may not recognize their specific manifestations. Now, Applebee’s has always marketed itself as your “neighborhood” bar, even when you are in a suburb of Dallas a thousand miles from home in San Diego and you need a place to feel at home, a place to connect to your community. However, for this demographic, the idea of “community” is so far removed from what Applebee’s has to offer that the idea that they might be attracted to it because the logo is hipper is beyond laughable. This demographic is connected via broadband through MyFaceTwitterDiggBook to a hundred people they know by first/last, and a thousand more called LOLHamburger and Kitty546, and not one of them is likely to ever suggest getting a plate of onion rings at Applebee’s to hang out. Hell, for them, suggesting a quick run down to Bloodmyst Isle for some grinding might be a bit passé.

In all, I’m fascinated that somewhere in the Applebee’s corporate hierarchy, somebody decided that in order to increase their market, they needed to target the tech culture. I’m more fascinated that nobody else in that hierarchy was able to talk them down from it.

*NOTE: edited to fix my numerological mishap. Thanks, Glenn!

Long methods cause cancer?

Posted on April 18, 2008 by stu

My friend Scott Davis suggests that long methods are like cancer. Right on! But let's be a little more specific:

  • > 30 lines ~ pancreatic cancer
  • 30 lines ~ brain cancer
  • 15 lines ~ prostate cancer
  • 8 lines ~ no cancer (yet--keep trying)

If you are fortunate enough to know nothing about cancer mortality rates, go back and follow the cancer link. Delightful surprise to my googling on the topic.

We're looking for a web designer

Posted on April 08, 2008 by stu

Relevance, Inc. is seeking an interactive web designer in the Durham/Chapel Hill, NC area. The ideal candidate would have boundless creativity, an engaging portfolio of web design, experience with several of the following items, and a passion to learn the rest:

  • HTML, XHTML, CSS, Javascript
  • Photoshop, Illustrator, Flash
  • Cross-browser Testing
  • Accessibility, Standards Compliance, Microformats
  • Iterative Design, User Interface Prototyping
  • Digital Illustration, Typography, Iconography
  • Ruby on Rails
  • Mac OS X

Relevance is a leading developer of enterprise web applications, using agile methods and user-centered design. Relevance's creative designs move quickly from concept to real-world use.

Do you want to work with a small, talented team, and develop your skills and creativity? Please send a resume and a portfolio link to jobs@thinkrelevance.com.

Open Source and Job Interviews

Posted on April 07, 2008 by stu

Open source projects always need extra minds. Does your hiring process contribute to open source? It could, and it's easy to do.

Part of our hiring process is a day-long visit that includes a lot of pair programming. To make the day valuable for all involved, we want to work on interesting problems. Open source is made to order:

  • There are no NDA or confidentiality issues
  • If you want, it is easy to agree on (and study) projects in advance

We also do whiteboard sessions, where interviewees and Relevance folk work together to solve design problems. In the past, I haven't made a specific effort to find open source projects for these sessions. This morning I was reading about a Guice/Wicket integration issue, and it occurred to me that open source issue trackers are a goldmine of interview opportunities.

The next time you encounter a complex issue in an open source project, file it away for your next job interview. If you make interesting progress, contribute it back. It doesn't have to be code! Good analysis and documentation can be a huge help to the next developer on a project.

Oh, and if you are interviewing at Relevance in the next few months, be ready for this interview question:

There is an interesting Wicket/Guice integration pitfall documented on the Wicket wiki and as issue WICKET-1130. If you were free to change anything (e.g. Wicket, Guice, Java, the value of Pi) how would you solve this problem? How would your answer differ if you could change only Wicket?

energizing development:

nobody does it better.