views:

86

answers:

1

I would like to have your feedback regarding code examples.

One of the most frustrating experiences I sometimes have when learning a new technology is finding useless examples.

I think an example as the most precious thing that comes with a new library, language, or technology. It must be a starting point, a wise and unadulterated explanation on how to achieve a given result. A perfect example must have the following characteristics:

  • Self contained: it should be small enough to be compiled or executed as a single program, without dependencies or complex makefiles. An example is also a strong functional test if you correctly installed the new technology. The more issues could arise, the more likely is that something goes wrong, and the more difficult is to debug and solve the situation.
  • Pertinent: it should demonstrate one, and only one, specific feature of your software/library, involving the minimal additional behavior from external libraries.
  • Helpful: the code should bring you forward, step by step, using comments or self-documenting code.
  • Extensible: the example code should be a small “framework” or blueprint for additional tinkering. A learner can start by adding features to this blueprint.
  • Recyclable: it should be possible to extract parts of the example to use in your own code
  • Easy: An example code is not the place to show your code-fu skillz. Keep it easy.

helpful acronym: SPHERE.

Prototypical examples of violations of those rules are the following:

Violation of self-containedness: an example spanning multiple files without any real need for it. If your example is a python program, keep everything into a single module file. Don’t sub-modularize it. In Java, try to keep everything into a single class, unless you really must partition some entity into a meaningful object you need to pass around (and java mandates one class per file, if I remember correctly).

Violation of Pertinency: When showing how many different shapes you can draw, adding radio buttons and complex controls with all the possible choices for point shapes is a bad idea. You de-focalize your example code, introducing code for event handling, controls initialization etc., and this is not part the feature you want to demonstrate, they are unnecessary noise in the understanding of the crucial mechanisms providing the feature.

Violation of Helpfulness: code containing dubious naming, wrong comments, hacks, and functions longer than one page of code.

Violation of Extensibility: badly factored code that have everything into a single function, with potentially swappable entities embedded within the code. Example: if an example reads data from a file and displays it, create a method getData() returning a useful entity, instead of opening the file raw and plotting the stuff. This way, if the user of the library needs to read data from a HTTP server instead, he just has to modify the getData() module and use the example almost as-is. Another violation of Extensibility comes if the example code is not under a fully liberal (e.g. MIT or BSD) license.

Violation of Recyclability: when the code layout is so intermingled that is difficult to easily copy and paste parts of it and recycle them into another program. Again, licensing is also a factor.

Violation of Easiness: Yes, you are a functional-programming nerd and want to show how cool you are by doing everything on a single line of map, filter and so on, but that could not be helpful to someone else, who is already under pressure to understand your library, and now has to understand your code as well.

And in general, the final rule: if it takes more than 10 minutes to do the following: compile the code, run it, read the source, and understand it fully, it means that the example is not a good one.

Please let me know your opinion, either positive or negative, or experience on this regard.

+1  A: 

This is spot on! I have experienced so many instances where an example promises to explain just what I am looking for but is rendered useless because of some minor 'obvious' omission.

It's partly for that reason that I don't import namespaces. When having difficulty understanding a new concept of language, using methods in some obscure namespace that have been Imported, but where Imports statement is not provided in the example, makes it that much harder to work with. Also for reusability - explicit names just make life easier all round.

For my examples, including my examples on StackOverflow, I generally use fruit. Everyone understands fruit. Fruit does a lot of cool stuff - they can implement interfaces (iPeelable, iSeeded), they can be fresh (if PeelTime > 20 mins Then Return False), and all sorts of other stuff.

But best of all, there is NO effort required of the reader to try and understand the domain. This allows them to focus on the issue being discussed.

True, fruit can't be used as an example of how to draw a polygon with WPF, but for language concepts, object oriented concepts, patterns, etc. it works very well.

It does actually compile and run under 10 mins, It's easy. Ok, it can't be recycled into a useful program, but at least they will understand how do use the concepts to accomplish what they need.

Michael Rodrigues