Monday, March 24, 2008

Example Dilemma

Creating examples for blog entries, presentations, articles, and books is very, very hard. You need an example that is easy enough that hopefully all, but at least most can understand it quickly. However, any example that trivial almost always has to make several conscious omissions.

For example, rarely do examples take into account error handling, performance, security, etc. Almost no example will include code that addresses cross cutting concerns. Nor should they, in my opinion. When the topic is error handling, the examples should include error handling. But, when the topic is how to design a DSL, it's much better to concentrate on communicating only that.

Cross cutting concerns aren't the only things ignored in the name of concise examples. Proper domain modeling, encapsulation, and many other best practices are also often ignored. I believe this is because many of those choices depend so heavily on context it would be impossible to devise an example that fits all possible scenarios. Instead of building the proper context, it's better to create an example that focuses on the problem and simply admit that you'll need to mold the example to your domain.

Of course, I'm not the first to write about these things. The following excerpt is from Martin Fowler, in chapter 1 of Refactoring.
With an introductory example, however, I run into a big problem. If I pick a large program, describing it and how it is refactored is too complicated for any reader to work through. (I tried and even a slightly complicated example runs to more than a hundred pages.) However, if I pick a program that is small enough to be comprehensible, refactoring does not look like it is worthwhile.

Thus I'm in the classic bind of anyone who wants to describe techniques that are useful for real-world programs. Frankly it is not worth the effort to do the refactoring that I'm going to show you on a small program like the one I'm going to use. But if the code I'm showing you is part of a larger system, then the refactoring soon becomes important. So I have to ask you to look at this and imagine it in the context of a much larger system.
Michael Feathers also has a section in the Preface of Working Effectively with Legacy Code where he describes his approach to coming up with examples.
One thing that you will notice as you read this book is that it is not a book about pretty code. The examples that I use in the book are fabricated because I work under nondisclosure agreements with clients. But in many of the examples, I've tried to preserve the spirit of code that I've seen in the field. I won't say that the examples are always representative. There certainly are oases of great code out there, but, frankly, there are also pieces of code that are far worse than anything I can use as an example in this book. Aside from client confidentiality, I simply couldn't put code like that in this book without boring you to tears and burying important points in a morass of detail. As a result, many of the examples are relatively brief. If you look at one of them and think "No, he doesn't understand—my methods are much larger than that and much worse," please look at the advice that I am giving at face value and see if it applies, even if the example seems simpler.
I see this most often with blog entries. Of course, this is because example code for blog entires isn't (usually) reviewed before it's published. Generally, a blog entry is published and a few comments begin to appear with a "better" way to solve the problem. Of course, the "better" way doesn't address the topic of the blog entry, so they aren't very relevant. The author (or another comment) responds with the traditional "You missed the point" and neither side really gains anything.

I used to believe that it wasn't my problem if the reader missed the point. I was wrong. Martin and Michael's books are proof, this isn't a new problem. The entire reason I write is to provide ideas to my readers. I do believe it's my responsibility as an author to come up with the best possible example, which includes accounting for ways that someone might miss the point. If they miss the point, I've failed.

Of course, feedback comes in many forms. The last comment I got started with "I know this is off topic...". When a conversation is framed that way, the author is much less likely to become defensive of their example, and much more likely to happily address the off topic comment. I've often gotten similar comments related to examples that start with "I understand why the example addresses the problem you're writing about, but why not solve the problem using...". The people who leave comments this way seem to understand the Example Dilemma, and always seem to get better responses from authors.

Most people are curious and excited when they have what they believe to be a superior solution. This explains the constant flow of "better" examples and off topic questions. I think this is a good thing, otherwise I would turn comments off on my blog. But, I think understanding the Example Dilemma can turn an adversarial exchange into a beneficial one.

I don't believe the Example Dilemma is going anywhere, but I do believe we can all benefit from being more conscious of it.
Post a Comment