Tuesday, August 31

Obfuscating the package structure for clients

So you've got yourself a nice clean package structure. You're slowly building up your application organically, adding features here and there, driven by customer demand. releasing early and often, covering all the hip methodologies of the day. Then along comes a client who wants to make changes so drastic that they warrant sub-classing. We'll call this fictional client Acme. Let's say one of the classes to be altered is:

net.rudiment.calories.Calculator

So you make Calculator abstract, or an interface, and you create two sub-classes:

net.rudiment.calories.calculators.Generic
net.rudiment.calories.calculators.Acme

Seems simple enough. Perhaps years from now you'll have quite the collection of client-specific calorie calculators:

net.rudiment.calories.calculators.Cyberdyne
net.rudiment.calories.calculators.Hudsucker
net.rudiment.calories.calculators.Kumatsu
net.rudiment.calories.calculators.Oscorp
net.rudiment.calories.calculators.Tyrell
net.rudiment.calories.calculators.UAC
net.rudiment.calories.calculators.Vandelay

But what if calorie calculators aren't the only part of the system that gets commonly personalized for clients? What if you've got a few dozen classes spread out amongst the enormous source tree that have been abstracted and sub-classed like this? That makes it a little tedious to do site-wide client-specific changes. For example, if you needed to work on all the Acme-specific classes, you'd have to search them all out. It might be a little more convenient if you'd started with a structure like this:

net.rudiment.clients.acme.calories.Calculator

This also makes it easier to clean-up the code tree if you ever lose Acme as a client. You simply delete the root of the Acme-specific classes and presto, all gone. However, it makes it tricky to alter the abstract super-classes when you need to review and test all the sub-classes to ensure nothing broke; you have to search them all out rather than have them all conveniently right there in a single sub-package.

My current project is nearly five years old and contains over three-thousand classes in over six-hundred packages. Over the years we've used both of the techniques described above. And, as I explained, both have their drawbacks.

I'm curious to hear your opinions on the issue.

1 comment:

Anonymous said...

My comment? If those are your client's you are *doomed*--your best bet is to build some really fatal flaws into UAC, back Cyberdine early, and hope for some good fall out when Oscorp goes down.

That'd be my plan.

Oh--there was an article?

-M.