Thursday, December 17, 2009

Loadtesting As Functional Testing

I'm a fan of automated testing that exercises code and checks its results.

But I don't believe in striving for 100 percent coverage. Should I really spend time writing unit tests that exercise our database interactions given that Hibernate, our ORM layer, is heavily tested and community-vetted? I create mock versions of the service layer we put on top of our ORM to allow testing of the service clients, but I don't (usually) write tests to exercise the services themselves.

This works out fine. Except when I need to do a big refactor in the service layer, as I did yesterday. I moved common functionality to a base class and used Java Generics [pdf] to define methods in the base class that would, in the context of the child class, compile as if they returned the type appropriate to that child class.

How could I ensure that I hadn't broken anything before checking in the code? I thought of our load testing scripts, which I've been diligent about maintaining. They do a full CRUD cycle on a variety of object types.

I didn't need to test load, but this would exercise virtually all the code I had changed. I brought them up, set the thread count to 1, pointed them at my machine, and pressed go. Sure enough, they uncovered a few bugs. I fixed them, re-ran the scripts, and they all passed.

Automated testing is good. No matter what form it's in.

Friday, December 11, 2009

Facebook's Puzzles

A co-worker of mine pointed me to Facebook's Puzzle Page, a suite of challenging puzzles. The puzzles exist to find skilled programmers that Facebook might like to hire by letting those programmers sift themselves out, rather than taxing Facebook employees' time with trying to find wheat in the chaff of job applicants who come through normal channels.

But even if you're not interested in working at Facebook, they're a nice set of programming challenges. Especially if you're learning a new language and want some meaty exercises.

Even as someone who has challenged interviewees with logic puzzles — a standard practice for software companies — I find these types of puzzles to be interesting but not necessarily useful in finding good hires. Yes, it helps you find the bright folks who can figure out clever algorithms.

But those aren't necessarily the people who make good software engineers. Software engineering is about delivering quality code on schedule and within the budget. It's about writing code that other people will be able to work with and maintain, even years later. It's about debugging, but it's also about exposing bugs as early as possible. It's about understanding trade-offs, risks, and benefits. I spend a very small percentage of my time sussing out clever algorithms: I spend a very large percentage figuring out how to deliver scalable, high-quality features in a cost-effective way.

Being a good puzzle solver doesn't preclude those skills, of course, but it doesn't point to them, either. Puzzles test that you're bright in one way; they don't tell your employer if you can actually do your job.

On the other hand, Facebook is no doubt swamped with would-be employees, so these puzzles offer a way for someone to prove that they can be internally motivated (the only effective form of motivation) and self-starting. And they do test for one sort of programming intelligence. And, finally, I haven't yet figured out a way to test for the kind of programmer I look for, other than interviewing people.

Wednesday, December 9, 2009

Learning Ruby

Recently, I decided to learn Ruby, the programming language du jour of Internet startups.

The main reason was an essay in The Thoughtworks Anthology, a collection of essays about software development from some of my field's luminaries. The essay argued for polyglot programming, especially since the Java Virtual Machine enjoys wide distribution; a mature, scalable implementation; and a number of languages that compile down to Java bytecode. It showed a typical "isBlank" method in Java and an implementation in Ruby (in particular, JRuby) that was one-third the length and much more readable. The end result: code that's easier to maintain overall.

There were a few other reasons. If I'm laid off, Ruby knowledge would be a good resume item. I'm also drawn to the language's "Behavior Driven Development" testing tools Cucumber and RSpec, which a co-worker showed me. But the Thoughtworks essay was the catalyst.

I bought the "pickaxe" book and dug in.

As I've said before, I have a standard programming project I assign myself when I'm learning a new language: a solver for various types of word puzzles that you'd find in the monthly publication of the National Puzzlers' League. By the end of writing it, I have a good sense of the language's syntax, I've dug into the established class library a bit, and I've even learned something about performance: The dictionary I use is 838,000 lines, which means that I often have to optimize the code that runs in the loop over those lines.

I got my program up and running pretty quickly, and it's easy to see why people like Ruby. Even complicated tasks come together in some form pretty quickly in a much less verbose form than they would in, say, Java. I like that the language includes mixins, a way to fake multiple inheritance, and I like that you can add behavior to an existing class (which you can also do in Objective-C via categories) without subclassing it. I added a method to the String class with no effort.

And, though I haven't tried this yet, Ruby can plug in to the Open Scripting Architecture (do they still call it that?) on Mac OS X so you can control your applications via a Ruby script. At this stage in my life, I'd prefer writing a Ruby script to writing something in AppleScript.

Next, I'll try and put up a simple Ruby on Rails app. I haven't fully embraced Ruby as the one true path, but it's definitely a worthwhile addition to your programming toolkit.