A few days ago, terror_firma drew my attention to this technique for using defaults and special cases in CSS, and I've been thinking about it ever since.
Sure, CSS has enormous potential for DRY, but the drawback of that approach is that you lose flexibility on the level of individual items. For instance, suppose I'm working on some software for Mister Client Man, and I implement failure and confirmation messages as explained in the article. One day, Mister Client Man tries to use the software and gets a failure message, which he has to squint at. So he tells me, "Failure messages are too small and hard to read. Make them huge and blinking." (Okay, so he probably wouldn't suggest they be blinking, but bear with me for the sake of example.)
Because of the implementation, my first question would be, "Should confirmation messages be huge and blinking, too?" The response I'd typically get then is either "No, that would be bad," or "No, that's not necessary." (My DRY is screwed either way, but the latter is particularly maddening, because it's intended to save me work, but it's actually making things more difficult!)
I could explain to Mister Client Man that failure messages and confirmation messages are implemented from the same default, but really, I'm the only one who should have to think about the implementation details of what I'm doing; if other people have to care about that stuff, it's generally a sign that something's wrong, no? And moreover, if I were to explain that they were implemented from the same default, his response might well be, "Well, that's stupid. Failure messages and confirmation messages are the opposite of each other!" Which is not quite true, but it's certainly hard to argue with.
This kind of thing comes up all the time in my work. Every time I've ever written an beautiful DRY style sheet that takes full advantage of the cascade, I've ended up having to pay for it later.
So what can be done? Do shifting requirements preclude elegant code? I really don't want to believe that. Here's what I want to believe instead: Inelegant requirements preclude elegant code. I want to believe that someone familiar with the software -- not from an implementation standpoint, but from a user's standpoint -- would have noticed (in spite of themselves, maybe!) that confirmation messages and failure messages follow the same basic pattern, and would realize, perhaps subconsciously, that if we make one look different, we should make the other look different, too (and that if it doesn't make sense for the other to change, then maybe it didn't make sense for the first one, either).
For this to happen, of course, the people making the requirements have to be intimately familiar with the software from the standpoint of user experience -- familiar in a way that Mister Client Man isn't yet. After two weeks, once he's seen lots of error messages and lots of confirmation messages and knows forwards and backwards what it's like to use the software and which particular things about it drive him nuts, then I want to hear what he has to say. In the meantime, I want him to shut up and test.
As programmers, I don't think we would let anyone who isn't familiar with the code dictate changes to to the code. Why, then, as UI designers, would we let anyone who isn't familiar with the UI dictate changes to the UI? Is it possible that we're fetishizing the whole "sit down and have it work immediately" principle to the point that we scramble to do whatever it takes to make the user's first ten minutes slightly better, even if those changes make the user's next ten thousand minutes slightly worse?
Or am I just a lazy programmer who doesn't want to do anything that will result in more work for me?