There’s one final aspect of programming style that I want to touch upon, and that’s “Literate Programming“. Literate programming got its start with Donald Knuth’s seminal book “Literate Programming“. The entire TeX project was written (or rather re-written) using literate programming. Literate programming is in many ways the antithesis of many of the things I’ve talked about here – with a more traditional programming style, the code is the documentation, in literate programming, the documentation is the code. The literate programming paradigm is a totally document-centric paradigm, in fact the code is almost irrelevant. In the literate programming paradigm, your source code is a document, and the actually resulting program is built up by stitching together fragments of code.
When I wrote my compiler back in my senior year in college, I wanted to explore the idea, so I wrote my compiler using literate programming. Here’s a simple example:
58. Determine if the fields of a record are legit, and return a pointer to the type field of the rightmost field on the list Variable^.LHSOperand.
<Check and return the type of a record field access 58> ==
with Variable^ do
TSTE := Type_of_Var(LHSOperand);
if LHSOperand^.NodeT in [Terminal, ProCall] then
RValue := Type_of_Record(IDList, TSTE)
SemError( ‘Huh? Record fields can only be identifiers or arrays’, Error);
This code is used in section 57.
Section 57 had:
if Variable^.NodeT == LValue then
< Check and return the type of a record field access 58>;
Literate programming isn’t a style for everyone (I’m sure that the literate programming people are going to be mad at that statement), going back over my compiler, in retrospect, it’s clear that I didn’t do a great job of living up to the paradigm, but it IS a viable form of programming style.
As I’ve pointed out, there are literally dozens and dozens of ways of writing a particular piece of code, and all of them are “correct”. The differences between those representations is what brings “style” to a piece of code.
And just like fashion, coding styles have had trends – various coding constructs come in and out of style – for instance, currently exception handling is in, and error codes are out. This may (and likely will) change as time goes on – time changes peoples perceptions of the value of various constructs (there was a time when structured error codes were the rage – that particular fad climaxed in x.500 error codes, which were highly structured entities that encapsulated not only the error, but the reason, recommended action, etc.
Over time, every developer comes up with their own particular style – it may be the style that their mentor (or team) used, it may be the style that was in a piece of code they admired, it may be in a construct that they ran across in a textbook, it might just be from hard experience.
Ultimately, the purpose of having a coding style is to result in more maintainable code. Even if your code will only ever be used by you, having a consistent style is STILL critical – you’re still going to have to maintain your code, and if your code is internally inconsistent, then you’re going to struggle when you go back to that old code.
I’ve got to say that I was reasonably pleased when I went back and looked at my old code for this series – there were some seriously cringe-worthy bits, and the quantity of comments was scarcer than it is today, but overall, it wasn’t that hideous.
If you’re working on a team, it’s even more important that you have a single coding style (or rather coding conventions). As I pointed in this article last week, if you don’t have a single coherent coding style, all you get is a mishmash, and mishmashes are rarely maintainable (and yeah, the spelling checker had mishmash in it).
Coding style brings together individual and team discipline, personal esthetics, and a little bit of magic to make a coherent whole.
Tomorrow, what does my personal coding style look like?