Friday Yak Blogging

  • Posted By Stuart Halloway on April 26, 2008

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 By Stuart Halloway on April 23, 2008

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 By Stuart Halloway on April 23, 2008

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 By Justin Gehtland on April 21, 2008

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 By Justin Gehtland on April 20, 2008

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 By Stuart Halloway on April 18, 2008

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 By Stuart Halloway on April 08, 2008

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 By Stuart Halloway on April 07, 2008

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?

Intro to Ruby on Rails coming in May

  • Posted By Stuart Halloway on April 07, 2008

I (Stu) will be heading to Washington, D.C. the week of May 5-9 to teach a public Introduction to Ruby on Rails course.

We'll start at the very beginning, exploring Ruby from the console shell irb. Then we'll dive into Rails 2.0. By the end of the course we will be talking about how best practice shops use Rails (hint: test and refactor!).

Rails is one important step on the path to a future without legacy code. Isn't it time to take that first step?

Upgrades for ActiveRecord

  • Posted By Justin Gehtland on April 03, 2008

Ryan has been writing about what’s new in ActiveRecord. I love these new additions to the framework. The ability to track modified properties out of the box has been necessary for a while, and though I’m a fan of acts_as_audited, these changes will essentially obviate it and replace it with a before_save hook (don’t forget your transactions!).

I’m excited to see the partial- (and no-) update support as well. This should save tons of unneccessary write operations on unmodified objects. I’ve never been too concerned about the need for eliminating unchanged columns from a write operation, as long as there were some modifications, as we tend not to create objects so big or tables so wide that the performance gain is obvious. The suppression of completely unnecessary writes, though, is huge. I’m glad to see the changes made to the framework, though, because these are real performance gains, essentially for free if you move up to edge.

An Infiltrator at the Smackdown

  • Posted By Justin Gehtland on April 02, 2008

I spent the last several days in Las Vegas at The Server Side Java Symposium, acting as track chair for the Presetation Tier. That, in and of itself, is a fascinating topic that I’m going to be thinking and writing about over the next couple of weeks. But right now, I want to tell the story of The Smackdown.

Matt Raible approached me to ask if I’d join in on his panel. It was titled “The Web Development Framework Smackdown”, and he wanted me involved as the representative of Rails. I wasn’t particularly interested when first approached; the format didn’t seem informative, and I’m getting bored with arguing about who’s abstractions are better. However, I really like Matt, and decided that at the very least, we would entertain some people, and that’s a high moral calling. So I agreed.

Let me describe the final group that assembled on the stage:

  • Ed Burns, JSF lead, Sun
  • Keith Donald, Spring MVC and Web Flow lead, Spring Source
  • Geert Bevin, RIFE creator, Terracota
  • David Geary, GWT champion
  • Don Brown, Struts evangelist
  • Justin Gehtland, Rails champion

To quote that most formative of childhood influences, Sesame Street, “Five of these things belong together, five of these things are quite the same. One of these things does not belong here…..”

Now, the natue of a smackdown is to be as inflammatory as possible in knocking around your co-panelists and their frameworks. Geert ended up winning, mostly by making jokes about how Europeans are more civilized than Americans. And the panelists were all good natured about it, though the comments could be biting. None of that is very interesting, or important. Nor was the information gleaned as we speakers tried to summarize value positions in twenty-second sound bites. Instead, what fascinated me where the subtexts and accidental discoveries made in the lulls in the shouting.

First, look back at the list and see what is lacking. There was no Grails representative on the panel, even though there were at least two Grails talks on the agenda. Matt has posted that he was unable to get either of the Grails speakers to talk due to time conflicts. But it left a gaping hole in the panel.

So, as I sat thinking about this, one of the panelists asked a question of the audience: what are you actually using? “Aha”, I thought, “now we’ll get the Grails folks up and shouting.” And when we asked about Grails, 2 hands went up. By comparison, when we asked how many folks were developing in Struts 1.0, I would say 50 hands went up. Struts 2.0 and Spring MVC combined for another 50 or so hands. I won’t say I was stunned, but at the least taken aback.

This lack of Grails representation left me as the sole representative of a web framework based on a language other than Java. Which is the second major revelation of the evening for me: with all the talk that “Rails has peaked”, there I was on stage at TSSJS, surrounded by JSF, Struts, etc. I could not have felt more conspicuous if I’d been painted red – and yet, there is a continued fascination within the Java community with Rails, and I mean specifically Rails, not other web frameworks based on anything other than Java. Think about it: not only was there no Django, or SeaSide, or Merb, or Camping seat on the panel, there also wasn’t a PHP or ColdFusion or ASP.NET seat, either. I’m now spending some time trying to decide why Rails and Java seem to occupy close orbits. I’m not convinced that a PHP conference would bother to have a Rails representative working the crowd.

Third, and perhaps most intriguing of all, were the actual slings and arrows sent my way during the panel. I will say that I kept my comments almost entirely to statements of fact about Rails or personal attacks on my fellow panelists (in a good way) and largely stayed out of the attacks on the frameworks. There seemed no point in arguing against any of them individually. I said my peace at the beginning, when I noted that they all shared one thing in common: Java-the-language. This is differentiator enough from Rails that I thought no further argument was necessary. ;-)

However, here, reprinted in their entirety, are the arguments used against Rails.

  • “But Rails doesn’t scale.”
  • “Ruby is slow. And JRuby is five times slower than Ruby.”
  • “My friend runs a web host and Rails is his favorite technology of all time, because his customers just keep asking for more and more servers.”
  • (When asked how to add third-party additions to the frameworks, and I rather too pithily said “script/plugin install”) “Oh, c’mon, Rails plugins are just little bits of logic.”
  • (When asked how the frameworks evolve over time, and how they incorporate new libraries) “Yeah, and in Rails, when you need something new, you have to write it yourself! HAHAHA

That’s it. Scaling FUD, speed FUD, scaling FUD, and two astonishing accidental admissions. Look first at point number four. “Rails plugins are just little bits of logic.” The implication is that Rails plugins are toys because they don’t conform to the complexities of the plugin architectures of JSF or Struts or what have you. Have you ever heard a more succinct admission that ceremony matters more than effectiveness?

Now look at point five. I think it was Geert who said it, and I understand his point. If I can be so bold as to restate it, he was implying that the Java world has an enormous supply of libraries laying around that can be harnessed to accomplish great things, and that the Rails community has a much smaller crop of libraries from which to harvest value. And that we are forced, therefore, to reinvent a lot of things already invented in Java.

This point absolutely has merit, as long as you overlook two things:

1) Rails runs on the JVM, via JRuby, right now. And if Java has a library I’m desperate for, I can go get it. 2) When I need to write something, I CAN. Take one example from our recent experience: we decided that Grails offered one important advantage over Rails, and that we could use that feature on a current project. Namely, an auto-injected service layer with automatic transaction demarcation. So, we added it to Rails. In about an hour. And, no, not every framework feature can be created and added to your project in an hour. This is an anecdote. But a powerful one.

At the end of the panel, we all shook hands and agreed that we’d had fun and we went about our ways. I don’t know what the audience will have gleaned from the session; perhaps they understand a little better the differences between how JSF and Spring MVC manage state, or how GWT is a Swing-in-a-browser, not MVC at all, or that action frameworks are ideally suited to be RESTful hosts. I know what I learned: Java Web Development frameworks can and do solve a lot of problems for people, but there wasn’t anything I learned about them that makes me want to look backwards.

JavaScript: Let's Emit

  • Posted By Justin Gehtland on April 02, 2008

During my three days at TSSJS talking about the issues of client-side web development, one theme was repeated several times. There was this undercurrent of the group trying to decide the appropriate role of JavaScript in a web application development environment. As the presenter of “Modern JavaScript Programming”, careful readers will already know what my position is.

There were three camps in the discussion:

  • those who write JavaScript by hand
  • those whose framework controls the JavaScript, but it is still stored and maintained as raw JavaScript prior to being shipped to the client
  • those whose framework creates JavaScript from another source

The first camp was made up of ahderents of one of the many Ajax libraries out there, or their own “craptacular framework” as one of my fellow panelists put it. The second camp could be called the JSF camp, though Tapestry and Wickets and others fit here as well. The last is made up of the GWT people.

I heard this one phrase several times: “since framework X let’s me not worry about all that JavaScript mess…” The discussion turned several times to how GWT let’s you write your code in a decent language (Java) and pretend that the JavaScript just isn’t there. The phrase “compiling to JavaScript” was thrown around a bit.

I’ll state up front: GWT has obviously been used to create some compelling applications. They aren’t especially pretty, but they are effective. But I have a big problem with this belief that if you just ignore JavaScript and let your server code handle it, all will be well in the world.

First of all, JavaScript can not and should not ever be thought of as the output of a compiler. When Java is compiled to bytecode, the results are merely a different representation of the same functionality. There is no difference between the capabilities of Java and of bytecode. JavaScript, however, is an entirely different language, with a different syntax, and a variety of dissimilar runtimes. It is not possible to “compile” from Java to JavaScript with anything like the validity of an actual compiler.

And, once so “compiled”, the debugging story is a nightmare. You have written Java, but run JavaScript. Errors in your Java code appear as JavaScript errors in a browser. JavaScript errors in the browser must be traced back to Java code on the server. The abstractions here are not just leaky; they are we’ve-hit-an-iceberg perforated.

Glenn Vanderburg said it best at one of the panels: we, as an industry, don’t understand the interplay here enough yet to hide it away behind abstractions like this. Perhaps that day is coming, but for now, the JavaScript in an Ajax application should be treated as a codebase in its own right; written, maintained and tested as JavaScript.

To be clear, I have no problem with the JSF/Tapestry approach. Even though these frameworks tend to control the JavaScript that ends up in your pages, that JavaScript is treated as JavaScript by the component authors and can be viewed, and debugged, in its native form. To borrow Neal Ford’s formulation: some frameworks emit JavaScript and others excrete it. As much as possible, try to stick to emissions—(insert your own joke about excretions here).

Relevance Raises 3.6 million from Spelvin Capital

  • Posted By Stuart Halloway on April 01, 2008

Chapel Hill – April 1, 2008 – Relevance Inc., a leading provider of enterprise Ruby application development, today announced the closing of a $3.6 million Series A investment from Spelvin Capital. The funds will be used to develop Relevance's customer service organization worldwide, and to enhance a set of new technologies that support Ruby in the Enterprise. Spelvin general partner David Agnew will join the company’s Board of Directors.

"Ruby on Rails has been very successful to date, but only for 'toy' applications," Mr. Agnew said. "Relevance's new Ruby To Enterprise Expander (R2EE) will provide the heft that Ruby needs to play at the highest levels in the Enterprise. For example, the following Ruby code would make any serious developer cringe:"

attr_accessor :name, :balance  

It is impossible to develop an Integrated Development Environment (IDE) for such code. In R2EE, the same code is automatically converted to be more scalable:

attribute :name
attribute :balance  
def name
  @name
end
def name=(value)
  @name = value
end
def balance
  @balance
end
def balance=(value)
  @balance = value
end

Relevance is also unveiling BoundTight, a new Dependency Injection framework for Ruby code. "Most Ruby developers think Dependency Injection is unnecessary, because Ruby's duck typing minimizes dependencies and their impacts across an application" said Justin Gehtland, Relevance founder and President. "That's true, up to a point. But enterprise software needs complex dependencies. BoundTight scans your codebase, creating complex dependencies if yours are too simple. Then we provide the tools you need to manage the complexity."

Relevance's new offerings also extend to management tools. Stuart Halloway, Relevance founder and CEO, recently described Bergeron, a new tool for development managers.

Writing software is like running an assembly line. If you care about quality, developers need to be interchangeable parts. Traditionally, the problem has been at both ends of the scale. The bottom 10% of developers are unable to perform their tasks. But the top 10% are even worse--they constantly develop new techniques, that, while powerful, are unusable by your average developer. With Bergeron, we use sophisticated statistical techniques to reliably identify both ends of the bell curve, so that you can remove them from your organization. With Bergeron, we guarantee consistent results.

Relevance is also working with industry leaders to make the Ruby language more consistent and reliable. Borrowing on their extensive experience in the Java world, Relevance developers have created a set of new options for the Ruby runtime:

  • -XXno-meta disables all metaprogramming features in the Ruby language.
  • -XXcomments requires that all methods be commented, and prevents RubyDoc from including source code.
  • -XXcompressed requires that all Ruby code be compiled down to a canonical compressed form. "This will encourage more IDE usage. IDEs written in serious languages will be able to parse the new compressed from, and we are optimistic that Emacs Lisp lacks the expressive power to translate it."
  • -XXdata-lint will identify any uses of YAML or JSON, flagging them for conversion to industry standard XML. With the :strict option, all XML must be namespaced.

"Enterprises want the same kind of quality they are used to, and we are going to give it to them," Halloway said.

Ending Legacy Code In Our Lifetime

  • Posted By Stuart Halloway on April 01, 2008

Most software developers don't have an exact definition of legacy code, but to paraphrase Potter Stewart, they "know it when they see it." Unfortunately, legacy code has something else in common with Stewart's famous subject--it is embarrassingly ubiquitous.

What is legacy code?

Legacy is the degree to which code

  • fails to capture essence
  • fails to communicate essence
  • captures irrelevant detail (ceremony)

The modern interpretations of legacy code are all implications or symptoms of the above. For example, consider the idea of legacy code as "written by someone else and impossible to maintain." This indicates a failure to capture and communicate essence, usually on multiple levels:

  • Code is unreadable. This is easy to test: Can you figure out what the code does without the original developer at your shoulder?
  • Often even the original developer can't read the code.
  • Code does not have unit or acceptance tests. Code without tests does not capture essence. It is automatically legacy code, even if it was written this morning.

The Next Big Thing

Organizations often jettison legacy code when they jump to the Next Big Thing. In the circles I run in, Java Web Development was the Last Big Thing. Ruby and Rails Web Development is the Current Big Thing. The Next Big Thing is ... well, a subject for a different post.

For an IT buyer, these Big Things are Sisyphean moments. They get to start over at the bottom of the hill, rolling the same damn rock again. This isn't all bad: Platform shifts provide a rare and brief opportunity to jettison a codebase that is legacy crap. Unfortunately, there is little reason to believe that the next codebase will be much better.

It doesn't have to be this way. As software developers, our goal should be to build this generation's code so that the Next Big Thing won't force a complete "do over." That's pretty ambitious, but if we try hard and miss, the consolation prize would still be pretty good: improved maintainability and reuse within this technology cycle.

To get there, we have to start by rejecting ceremony.

Essence vs. Ceremony

Good code is the opposite of legacy code: it captures and communicates essence, while omitting ceremony (irrelevant detail). Capturing and communicating essence is hard; most of the code I have ever read fails to do this at even a basic level. But some code does a pretty good job with essence. Surprisingly, this decent code still is not very reusable. It can be reused, but only in painfully narrow contexts, and certainly not across a platform switch.

The reason for this is ceremony: code that is unrelated to the task at hand. This code is immediate deadweight, and often vastly outweighs the code that is actually getting work done. Many forms of ceremony come from unnecessary special cases or limitations at the language level, e.g.

  • factory patterns (Java)
  • dependency injection (Java)
  • getters and setters (Java)
  • annotations (Java)
  • verbose exception handling (Java)
  • special syntax for class variables (Ruby)
  • special syntax for instance variables (Ruby)
  • special syntax for the first block argument (Ruby)

High-ceremony code damns you twice: it is harder to maintain, and it needs more maintenance. When you are writing high-ceremony code, you are forced to commit to implementation approaches too early in the process, e.g. "Should I call new, go through a factory, or use dependency injection here?" Since you committed early, you are likely to be wrong and have to change your approach later. This is harder than it needs to be, since your code is bloated, and on it goes.

Getting to Essence

I have found the following techniques helpful in writing low-ceremony code.

  • Identify and implement real needs in a tight feedback loop with the customer.
  • 100% test coverage. When you are testing your own code, you are temporarily in the role of the client. If you find your own code painful to use, others surely will. (The drive to coverage also flushes out the weak: It is difficult for weak developers, or weak languages, to get 100% code coverage. Of course this is only a proxy measure for quality, but it is a start.)
  • Relentless code review, both during pairing and after the fact.
  • Insisting on well-composed methods. And classes. And packages! This little-documented pattern is simple to learn, difficult to master, and more important than the entire rest of the design pattern movement.

What has worked for you?

Notes

  • This essay began as a keynote at Code Freeze 2008. The slides are available.
  • The techniques listed above are not silver bullets, they don't work in isolation, and they require strong developers. For examples, I have seen 100% test coverage on very bad code. You will need a synergy of all these techniques, plus probably some others that I have failed to identify.
  • I first encountered Compose Method in Smalltalk Best Practice Patterns. Recommended.