Sunday, April 25, 2010

Peter Watts - about birthdays....

I'm one of those people that just has a knack for seeing the world a bit 'differently" than most people. What some people see as absolutely normal social behavior, I often see as utterly absurd.

This is not usually an advantage, if you were wondering.

But I've got nothing on Peter Watts, the now famous Sci-Fi author, border-guard crushing bad-ass, and sadly... convicted felon. His writing is filled with this kind of totally brain breaking logic.

Like birthdays...

Below is an excerpt from his excellent novel "Blindsight" that exemplifies exactly the kind of thinking that breaks most people's brains. The novel is available online for free under a Creative Commons license (CC), or you can buy it in paper or audio if you prefer.

In prelude, know that the character Sascha has multiple personalities (the Gang of four as they are known  in the book).

"Yeah? Name one."

"Birthdays," I said, and immediately wished I hadn't.

Sascha stopped chewing. Something behind her eyes flickered, almost strobed, as if her other selves were pricking up their ears.

"Go on," she said, and I could feel the whole Gang listening in.

"It's nothing, really. Just an example."

"So. Tell us." Sascha cocked James' head at me.

I shrugged. No point making a big thing out of it. "Well, according to game theory, you should never tell anyone when your birthday is."

"I don't follow."

"It's a lose-lose proposition. There's no winning strategy."

"What do you mean, strategy? It's a birthday."

Chelsea had said exactly the same thing when I'd tried to explain it to her. Look, I'd said, say you tell everyone when it is and nothing happens. It's kind of a slap in the face.

Or suppose they throw you a party, Chelsea had replied.

Then you don't know whether they're doing it sincerely, or if your earlier interaction just guilted them into observing an occasion they'd rather have ignored. But if you don't tell anyone, and nobody commemorates the event, there's no reason to feel badly because after all, nobody knew. And if someone does buy you a drink then you know it's sincere because nobody would go to all the trouble of finding out when your birthday is — and then celebrating it — if they didn't honestly like you.

Of course, the Gang was more up to speed on such things. I didn't have to explain it verbally: I could just grab a piece of ConSensus and plot out the payoff matrix, Tell/Don't Tell along the columns, Celebrated/Not Celebrated along the rows, the unassailable black-and-white logic of cost and benefit in the squares themselves. The math was irrefutable: the one winning strategy was concealment. Only fools revealed their birthdays.

Sascha looked at me. "You ever show this to anyone else?"

"Sure. My girlfriend."

Her eyebrows lifted. "You had a girlfriend? A real one?"

I nodded. "Once."

Thursday, April 22, 2010

Don't let unit testing push you around!

Test Driven Development (TDD) and the ever increasing trend towards Unit Testing as a religion among developers is probably a good thing for software quality in general. I've just  spent a couple of weeks trying to employ the recommended unit testing techniques with Entity Framework 4, and this has reinforced my misgivings about the wisdom of some of the  basic concepts behind how unit testing is supposed to be done.

I've always been somewhat lukewarm towards unit testing. I certainly don't do as much testing as I probably should, but I do agree that some unit testing is essential to developing a quality application. So, I always do some unit testing, but only to the degree that I feel the testing is appropriate or necessary.

But unit testing has grown in popularity over the last 10 years, to a point where it appears that common sense is not a part of the process anymore.

The source of my misgivings about this blind commitment to unit testing deals with one of the fundamentals; that a unit test should only test logic within the specific block of code that is under test.

I don't disagree with this principal, but the sticking point is that you have to fake your code's dependencies, especially the external ones like real databases and external services. In most modern applications, external dependencies are pervasive and sometimes very hard to avoid.

To support testing without hitting external dependencies, you generally design your code in a way that allows for dependency injection. There are several ways to do dependency injection, but the different techniques can range in complexity a lot. On the simpler side you can just use overloaded constructors or write methods so they take their dependencies as parameters. On the other end, there are horribly complex programming acrobatics such as the Inversion of Control (IoC) design pattern.

No matter which techniques you use, the overall point is that your unit tests are able to supply their own versions of any dependencies instead of using real ones. These mock (fake) dependencies will mimic the behavior external systems or other complex code routines.

I'm not opposed to making some concessions in my code in the name of enhanced testability. Indeed, many of the simpler dependency injection techniques lead to better code in general. But there are cases where simple techniques just don't work. This is where I start to have serious misgivings about the wisdom of unit testing.

I've always had the opinion that the use of fancy OOP tricks, complex inheritances in particular, should only be used if there are direct benefits to the application. Likewise, employing advanced design patterns is only worth the effort if the patterns solve issues within your application's actual problem domain.

To some degree, facilitating better unit testing can be considered a good reason to employ some of these more advanced techniques. Indeed, the TDD guys will usually tell you that unit testing is a part of the application's problem domain, and that a full suite of unit tests must be part of the delivered product. I do see their point, but I do believe that there are cases where it is misguided --and unwise.

In my opinion, you should never compromise your application's primary requirements just for the sake of unit testing. Testing is at best a secondary concern; an optional requirement when it doesn't interfere with other priorities.

But that doesn't stop developer after developer from doing insanely stupid shit to their code for the sheer sake of testability. I've seen so many otherwise simple applications become bloated and convoluted beyond reason, and often to the detriment to both developers and the application's functionality.

The most recent case of this that I've run into was with the next version of TicketDesk. I have a class library to encompass the application's core domain logic. Here I had planned to auto-generate my entity model from my database, add some data annotations and custom logic of my own, then just create a simple service API to expose the model to my web application; and in the future potentially other clients such as Silverlight.

All-in-all this is a pretty standard design. My entire reason for choosing the Entity Framework was to leverage the more advanced features, both within the library as well as within the client code consuming it.

After spending a solid two weeks exploring how to make Entity Framework 4 testable the correct way, I'd ended up with an insanely complicated hand-hacked variation of a standard generated EF model. But to support the necessary dependency injections, especially with the problematic EF ObjectContext, I had produced gobs of abstract interfaces and classes. Return types at the service API had become so abstract that the consuming clients had lost access to all of the special functionality of EF models; the very features that had made EF an appealing choice in the first place.

I got far enough into this to prove that achieving a useful level of testability could be done, even with the dreaded ObjectContext. But well before I reached that point, it was apparent that doing so would make my code into a complex and time consuming maintenance nightmare.

I still needed to be able to unit tests my custom logic and service layer though, but I was done with doing it "the right way". Instead, for my tests I pointed the ObjectContext at a real database server, used the built-in CreateDatabase method to generate a temporary fake database schema from the EF model, and wrote my tests against it.

My tests are able to add any fake data needed directly to the temporary database via the strongly typed and auto-generated ObjectContext. With this approach, I can still test the relevant code blocks, but without jumping through hoops to dodge a dependency on a database server.

Sure, it isn't technically the correct way to do unit testing... and yes, many of my tests do spend a bit of time talking to the external database, or managing the test data within it; but all of the extra complexity is encapsulated directly within the unit tests or helpers classes within the test project; not junking up my actual application.

I'm sure the more fanatical unit testing advocates, especially the TDD guys, would foam at the mouth at this approach, but I have nearly 100% code coverage in my tests (excluding generated code). And for me, the biggest advantage is that my application code is simple, elegant, effective, and highly maintainable...

Isn't that the whole point of unit testing?