patrickwilsonwelsh.com

Agile coding, agile testing, agile coaching, the agile enterprise, and Network Weaving.

Client Validity, Client Validation, Code Smells, TDD & BDD

Or, BDUF & Fast OO Karmic Resolution

I’ve been chewing this one over for awhile, and it is finally ready for the world to attempt to digest it. Or something like that. (Ewww.)

Why do our most carefully conceived UML diagrams of object models of any size fall apart? Wait. More precisely, how and when do they fall apart? How can we tell whether a given class exhibits, say, the “Inappropriate Intimacycode smell, or the “Message Chains” smell, or the “Middle Man” smell?

More to my immediate point, in the context of Software Karma and Justice: If you create a class or collection of classes that inflicts such suffering on programmers who later must maintain and extend your code, then who should be the first one to suffer as a consequence? Well, trick question, of course.

You should, baby. The karmic resolution should be this fast: you create a class with bad separation of concerns or a cruddy API or rampant duplication, and you are the first person who is made to suffer as a consequence. What goes around comes immediately around and smacks you in the head, like a tetherball. Ah, would that justice flowed thus swiftly in all realms! (spoken in Robin Hood voice from “Men in Tights.”)

Test-Driving: Delivering Smells to Your Nose First

So how is this possible in object design? Only through TDD and BDD, which require that in fact you be the first person to invoke the API of your new class. The unit test you are writing is the first client of the new behavior you are creating. In fact, you have to try to invoke the production code before it exists. You can’t pay karmic debt any faster than that. Pay in advance, baby! You try to instantiate the class, set up some state for it involving some new behavior, and make some assertions on that state/behavior. And you suddenly realize: Eeeew. That’s a horrible API (or at least this seems to happen to me a lot).

Most likely, for me, the class already exists, and I need some new behavior (fast, baby, fast!). What’s the first tool I reach for? The old procedural one from my Old Coder DNA: adding a method. Doh. And what happens? I test drive that new method and realize: Eeeew. This class is getting more bloated than MS Word. And I have some nasty duplication going on.

Oh, Man. Not only does this new method not belong there, but the last two methods I added elsewhere are just as bad as this one. In fact, I am going to have to split this thing into a whole new little object tree, and I think I am going to need a Template Method. I’ll be pulling stuff up and pushing stuff down my new little tree for the next several minutes, as soon as I get this ugly test to pass.

Cause My Client Told Me So

So the tube through which this smell arises for me, I am calling “Client Validation.” My point is this: only from the perspective of the clients of a given class’s API can we really tell how bad they smell. (I’m trying not to mix two metaphors of human sense here, but dude, it’s hard.)

Only once my test shows a bit of “Primitive Obsession” or “Message Chains” do I realize, from the perspective of my client test, that other programmers will likely find this API as stinky as I do.

So, one test method at a time, one API call at a time, I find a particular class to be slightly (or horridly!) client-invalid. From the client’s perspective, that class or method or method signature stinks.

And one test method at a time, one production method at a time, one production class at a time, I repair my design, refactoring it into a state that feels, from a client-test-method’s perspective, to be valid. I end up with an API that smells valid to its client tests (and production clients).

This is what I can never smell in my UML diagrams. I can never feel (oh great! Now my metaphors include sight, smell, and touch!) whether each of these calls is “Client Valid.”

This may be old news to some brilliant old Smalltalk farts I could name, but not to me. It is a useful little heuristic for my on-going TDD journey. Maybe this will all be easier in Groovy. Hmmm.

Anyway, I am going forth now, nose held high, to sniff out Client Validity in my object models, one horrid little test method at a time. If comments are code-smell deodorant, then refactoring is code-smell Febreze. My cube will be the one that smells of Febreze. That stuff is great, you know. It can eliminate all of the cat-urine odor from an entire 6′x6′ Little Tikes play-structure (moved indoors one Winter) that apparently served as the olfactory bulletin board for every feline in Oak Park, Michigan. But that, of course, is another blog, for another time.

No comments yet. Be the first.

Leave a reply