A few notes on programming style

Apparent inconsistencies in the format of C code

One important goal for the code examples in the book was that they fit on the page, both horizontally and vertically. At the same time, I attempted to use clear and descriptive names for everything, which makes some of the names pretty long. In particular, the way that lines are divided when a function has a number of verbosely named arguments can seem pretty arbitrary. Though I attempted to be consistent, the longer shaders required some fiddling to fit on the page, and I thought that was more important than an unyielding adherence to a single set of rules. The goal of consistency is to increase legibility, which in the end means that legibility is more important than consistency.

Since legibility also includes keeping code units on a single page (as part of my policy in the book, at least), I have also used multiple declarations that contain initializers. For example, in shader depth_fade, the miScalar variables are declared like this:
miScalar near = *mi_eval_scalar(&params->near); 
miScalar far = *mi_eval_scalar(&params->far); 
miScalar zpos = state->point.z, factor;  
Here I’ve separated the variables that are initialized to parameter values to two separate lines, but put the zpos and factor variables on a line by themselves. It just didn’t seem worth spending another line on factor, though I realize that the combination of the initialization of zpos (created simply to simplify the logic of the following code) with the non-initialized value of factor could be confusing. Coding standards in a formal programming environment will often dictate how such declarations should be handled.

The use of the underscore character as a delimiter in identifiers

It is currently fashionable in some quarters to give your code an object-oriented patina by using interior capitalization to delimit the words in a multi-word name. This is a syntactic use of capitalization. But capitalization is also used semantically, for example, to represent acronyms. These two uses can come into conflict and clarity is the victim. Consider, for example, that you would like a variable for a string that represents a filename for RGBA data stored in the TIFF format. The name TIFFRGBAFilename is very hard to parse unless you know the context. And in a scripting language without variable declaration, will you be able to tell that TIFFFRGBAFilename has an extra “F” in it? Maybe TIFF_RGBA_filename doesn’t superficially appear to be object-oriented, but at least you can read it.

Luckily, C++ programmers can avoid the fray by reference to a higher authority — just follow Bjarne Stroustrup’s advice and “use underscores to separate words in an identifier.” (See The C++ Programming Language, 3rd edition, page 81.)

Syntax of the C “return” statement

Many current mental ray example shaders put the “argument” to the return statement in parentheses. This implies that return is a function, which it is not — it’s a statement, like continue or break. Since this book is designed to also be used by beginning programmers (or at least, not scare them away), I think it’s confusing to suggest that return is a function. Since a parenthesized expression is syntactically acceptable for return, the compiler doesn’t complain, but it is at the very least misleading.

Uncommented code — what gives?

You can download the book’s software for free — the book is its documentation (which I hope you are therefore motivated to acquire).
25 April 2008 01:03:59