31 March 2009

DRY plus Proper Responsibilities

It is not sufficient to blindly apply the DRY principle.

Where the single representation ends up living is just as important as avoiding the duplication in the first place.

Having the single, unambiguous, authoritative representation of a piece of knowledge living in a place that it doesn't belong is only slightly better than having it duplicated, once in a place where it seems to belong, and once in a place it does not.

So included in the task of reducing (or avoiding) duplication is the consideration of where to put the common code, *including* the task of inventing a new place if it doesn't seem to fit anywhere, now that it's being used from multiple places.

Usually, a new place is waiting to be invented -- that is why there was duplication in the first place -- the place didn't exist, or else it would have been fairly obvious where to put the logic and how to reuse it in the first place.

Perhaps that is part of what "authoritative" means.

20 March 2009

MountainWest RubyConf 2009

MountainWest RubyConf 2009 really helped me reorient in a very good way.

The emergent theme seemed to be "modularity".

Six main talks that were really enlightening:
Rack totally changed how I thought about building a webapp. Decomposing things into pieces that have the minimum to do with each other is possible in a really clean way with rack. And treating each of those pieces as a separate app, even, with its own release schedule, etc. -- that was a very refreshing view.

When I heard Jon say that the Perl script he had up on the screen was a monolith -- he was absolutely right. And I thought that the system *I* was working on was a monolith.

I was going to give a lightning talk about fshelper.org's link feature, but I wanted to rewrite it in broken-up rack pieces. I tried my best to do that between talks, but I didn't quite get the app to function as middleware, so I just gave up and listened.

19 March 2009

Tracking work to be done

My team had the task of porting code off of an old API onto a new (hopefully-mostly-equivalent) API.

Diomidis Spinellis wrote an article in IEEE Software titled "Start with the Most Difficult Part" (on his blog here, official reference here). Now seemed like a good time to apply the advice.

So I wanted to measure: What was the most difficult part. I wanted to know how many usages of the old API were present and where I should focus my efforts first.

So I wrote macker rules to detect usages to port. And I wrote a ruby script that drove the ant macker target and pulled the usage counts into a list of counts. Then I published the current counts and started a graph so we could get the usages to zero.

Here is the chart we ended up with:


This drove us to two useful behaviors:
  1. Getting our tests converted first, the most complex one first (exposed a lot of issues early).
  2. Giving our work a metrics-driven feel -- all we have to focus on is getting this to zero.
There were also two things I missed:
  1. The hardest task to port was one in which the new API didn't have anything near what we needed, and the usage measurement didn't catch that. ==> A quick pass over the tasks looking for especially risky ones (where the port would be really hard) would have exposed that earlier.
  2. Another team was doing other work that intersected with ours, and we were unaware of the impact of their efforts on what we were doing. ==> Being able to get their changes quickly and easily may have helped expose the problem earlier.
Now that we've started using git, I'm going to suggest that we do two things:
  • Get an SVN task branch so we can integrate as a team during the sprint
  • Get an SVN task branch right before merging to release and re-apply all our git patches onto that task branch so the merge is really smooth
Or maybe if we can get done in time, we could volunteer to do that for the team that has the sprint-long task (getting them on everyone else's changes with a minimum of svnmerge.py headache).

Past Bylines

Here are past bylines of this blog (in reverse chronological order):
  • [Mar. 2009] Alma 34:38: Live in thanksgiving daily, for the many mercies and blessings which he doth bestow upon you.
  • [Feb. 2009] 1 Tim 4:15: Meditate upon these things; give thyself wholly to them; that thy profiting may appear to all. (KJV) -- too overreaching

09 March 2009

Test code structure

There are a lot of ways to build an unmaintainable test suite. Jay addresses this topic straight on. The most important idea I got out of it is this: "If It Hurts, You're Doing It Wrong."

Now how to get from painful to joyful ... that is the question. Probably by just applying common sense and proper code structure to tests, not just production code.

UPDATE

I've done my share of painful, stupid things:
  • the monolithic build system that had super-ant-tasks with laser vision
  • the event subsystem that was really just JMS
  • the custom deploy system that really should have been one of rsync or rpm
  • the object persistence layer that was supposed to be super-generic, but was really tied super-close to the domain objects
  • ... I'm sure I could go on
The main thing I've learned is to work with the door open. And stay wide open to how to do things better and to always strive to see the things I'm missing.