In this post I’m going to talk about how we use C3D Toolkit to generate 'live' sample code snippets for our CGM documentation.
One of the things we’ve done with the CGM documentation from the start is to focus on what we call “HowTos”. These are standalone sample functions in our DocWiki that illustrate how to use CGM functions to accomplish some task – the idea is that customers can paste the function into a *.cpp file in their application and modify it to suite their particular needs. This initiative has been very successful – our customers really like the HowTos. It is also not rocket science – sample usage code as part of the documentation of an API is standard stuff. The interesting part comes from the word 'live' that I used above.
What do I mean by live sample code? I mean sample code that is used in a real application and so is called by end users every day, as opposed to sample code that is motivated by a documentation requirement “every interface method must have sample code which calls it”. How many times have you looked at the sample code for a method and seen some silly little program that is obviously contrived to just set up a bunch of inputs and call the method? If we think of a testing analogy, live samples are analogous to contract checks, in that they are an integral part of the application code, while contrived samples are analogous to unit tests, in that they are isolated executables that set up data structures for the express purpose of calling a particular method.
One of our goals in developing C3D Toolkit was to give ourselves a platform with which to develop live samples. The way we’ve done this is to turn the implementation of the C3D Toolkit extensions (commands) into HowTos which are placed in our DocWiki; the goal is that every modeling extension has a corresponding HowTo. For example, we have a “Fillet” extension in C3D that fillets (rounds) sharp edges. The C++ code underneath this extension eventually (after extracting argument lists etc.) calls a standalone function “HowToFillet”, which contains the code that a customer would use in his application to implement a fillet feature. Voila – we’ve got a live code snippet for the fillet operator.
As you’ve probably figured out, I think that live sample code is vastly superior to contrived samples. By making our samples part of our C3D Toolkit application, we gain the following advantages:
- Our sample code is built every night. If an interface changes that breaks the sample our nightly build process will catch it.
- Our sample code is tested every night. We have tests that do fillets in C3D Toolkit – these tests ensure that our sample code doesn’t regress (against the tests).
- We have a good chance of detecting subtle mistakes in our sample code. Our sample code is being used every day in C3D Toolkit. If there are subtle, 1-in-a-1000 bugs in the sample code, we have a good chance of someone stumbling across them while using C3D Toolkit. If, in contrast, the samples were simply contrived executables built and run in isolation, there would be no opportunity for discovering such nasty bugs. We just benefitted from this a couple of months ago; we had written a sample without realizing that the operator being called might return multiple bodies. As part of fixing the C3D Toolkit bug, we automatically fixed the bug in our sample and the improved sample was automatically included in our documentation. This is the core advantage of live over contrived samples, in the same way that contract checks are superior to unit tests. By integrating the samples in an end-user application, the selection pressure of lots of users using the application is applied to continually improving the samples.
Finally, live samples directly support rapid prototyping for customers. Let’s say a customer wants to prototype a new workflow that he will include in his application. We recommend the following steps:
- Prototype the workflow as a C3D Toolkit script (i.e. get it working in C3D Toolkit).
- For each extension called in the script, look up the corresponding HowTo.
- Write a (C++) workflow function in the application that calls these HowTo functions in the appropriate order.
As easily as that, the customer has a working C++ prototype for the workflow that they’re coding up. In practice the customer might need to do some clean-up to get the C++ function working, but this process brings him very close to where he needs to be.
As you can see, I really like the idea of live samples; I hope I’ve convinced you that they’re an important documentation tool as well.