Practicing What I Preach

As I mentioned in an earlier post, I believe in continually honing my programming skills through practice. My problem of choice is a database layer, code that allows for easy persistence of domain objects. I’ve built one of these several times, and each time it comes out quite a bit differently. It’s a good exercise in maturing a design through TDD.

Over the next umpteen blogs I’ll deliver on rebuilding this layer one more time. I don’t have a real application in mind, yet, so I’ll start with some simple presumptions. In lieu of an application, I’ll build specific persistence for a “user” object (a name and a password). Then I’ll add some complexity and repetitious application needs in order to flesh out a generalized solution.

First things first, I need a User class. Building that is simple enough. I usually drive crummy data classes through a quick creation test:

import junit.framework.*;

public class UserTest extends TestCase {
   private static final String name = "a";
   private static final String password = "b";
   private User user;
   
   protected void setUp() {
      user = new User(name, password);
   }
   
   public void testCreate() {
      assertEquals(name, user.getName());
      assertEquals(password, user.getPassword());
   }
}

The implementation for that is easy enough. In trying to keep this and future blog posts short, I’ll always make the entire codebase available (once I get the project set up in CVS). The post will capture only key points and just enough code to make those points.

The next step is to design in the interface that drives persistence. Here’s a simple start:

   public void testPersist() {
      user.save();
      User retrievedUser = User.find(name);
      assertEquals(name, retrievedUser.getName());
      assertEquals(password, retrievedUser.getPassword());
   }

This brings up one of those age-old questions: do the save and find methods belong in the User class or elsewhere? Please drop your comments; I’m not going to worry about the answer until I have a second class that requires persistence services.

I can get this test to work by storing a saved user in a static-side User collection. Or, obnoxiously, since I only have one User, I can use the Monostate pattern (all state variables are static), and derive the retrieved user from the static fields. Either one is perfectly acceptable, and in the spirit of the “you ain’t gonna need it” mantra that XP diehards babble.

But I’m not going to do that. Or rather, I ain’t gonna do that. I have a specific business need, namely, real persistence. The story is, “data is not lost when the server restarts.” Good enough for me. I need persistence, and I can imagine there’s a story about reliability that suggests an RDBMS is the best place to start.

This is where I break from the XP purists: inevitable architectural decisions don’t always need to be test-driven. Yes, there’s some value to finding out where the tests and associated zealot refactoring will lead you. And sometimes, you’ll end up in a different spot, not even needing an RDBMS. But on rare occasions, you just know.

Enough for today, I’ve got to get the CVS project set up. Next I’ll work on getting my persistence test to pass.

Generalizations

One thing I’ve done over the years is to mentally characterize the groups I work with and for. From my experiences with dozens and dozens of teams, I’ve come to some unsupported conclusions. Here are a few thoughts:

  • Out of 20 people, two are excellent. Three are good or have the right attitude, five are worthless or worse, and the rest will do the work but are largely there to collect a paycheck.
  • You can’t instill the desire to learn in an adult.
  • It’s very hard to teach an old dog new tricks. Forty is old.
  • Teams predominantly composed of 30-year-olds usually have their collective head on straight. Teams predominantly composed of 20-year-olds already know everything.
  • One counter-productive person on a team is enough to sabotage a project.
  • Hiring for attitude, not technical skill, results in a much more productive team. But you still will need experts. Don’t attempt to figure out on your own what expertise will get you more cheaply.
  • Forcing experienced developers to do things never takes. The team has to decide themself what they want to do.

These of course are obscene generalizations. Your mileage may vary.

Practicing Programming

I was able to entice Ron Jeffries to speak at the Colorado Springs Agile Users Group (cosAgile) a few months ago. As usual, the talk was very entertaining. Ron, deck of 3×5 cards in hand, went through a number of topics, talking about “why software development is easy.” Or not.

One of the central messages was about practicing the craft of programming. Musicians do scales, professional sports teams have scrimmages, and firemen run drills. But most programmers I know don’t seem to practice much.

Or maybe they do, but I just don’t hear about it. There are gobs of open source projects out there, and geeks who just sit at home working on pet projects. Do these count as “practice?”

Ron is one of those guys who practices the bowling game, over and over, to see how his solution improves each time. I’ve done the same thing, working on building a database interface layer. It comes out a little differently and a little better each time. The last place I was at, we used this database interface layer as the basis for a weekly lesson in TDD.

CosAgile meets weekly to work on a password manager application, PeakPassMan. While the result will be a functional, usable product, that’s not the primary goal. The goal is for programmers to get together, share ideas, and work on a common source base while trying to learn more about things like test-driven development. CosAgile is certainly not the first group to promote the idea of getting together weekly to practice building code, but it sets a good, shining public example.

Practice makes perfect! Well, there is no “perfect” in programming, but honing your skills by practicing a problem is a great idea.

Atom