Saturday 29 August 2009

My Two Greatest Programming Sins

My programming sins are too numerous to count, but there are two which keep coming back to haunt me over and over:
  • version control - while developing a program I create multiple versions. Development may split into multiple paths or be backtracked. Without proper version control, confusion is inevitable.
  • illegible code - I make frequent tweaks and changes, use irrelevant names for labels and functions and fail to comment code. It's unlikely I'll understand the program if I return to it a few weeks later.
Earlier this week I posted an example of ugly code. By examining the program, the magic numbers or output for sample input, three readers identified the code as an implementation of parallel bit counting. Here's how the bit counter ought to have been implemented:
: (COUNTBITS) ( u1 u2 u3 -- u4 )
( u1 = partial count )
( u2 = power )
( u3 = mask )
( u4 = new partial count )
ROT 2DUP AND >R ROT / AND R> +
;

: COUNTBITS ( u1 -- u2 ) ( parallel count )
( u2 = number of 1 bits in u1 )
2   %101010101010101 (COUNTBITS)
4   %011001100110011 (COUNTBITS)
16  %000011100000111 (COUNTBITS)
256 %000000000001111 (COUNTBITS)
;
To increase code legibility, the following changes have been made:
  • function name now represents the word's behaviour
  • word factored into two simpler words
  • documented the word's stack activity
  • represented the bit masks in binary
It's also worth considering what countbits will be used for (any suggestions?). Do we really need a fast bit twiddling algorithm? A simple iterated count or sparse ones algorithm will probably suffice:
: COUNTBITS ( u1 -- u2 )( iterated count )
( u2 = number of 1 bits in u1 )
0 SWAP
BEGIN
2 /MOD >R + R>
?DUP 0=
UNTIL
;

: COUNTBITS ( u1 -- u2 ) ( sparse ones )
( u2 = number of 1 bits in u1 )
0 SWAP
BEGIN
?DUP
WHILE
DUP 1- AND >R 1+ R>
REPEAT
;

Now I've identified a couple of faults with my coding technique, I'm hoping to correct my shortcomings while tackling my next programming project. What is your greatest coding sin and how do you plan to deal with it?

Tuesday 25 August 2009

Impenetrable Code

However elegant a programming language, some fool will always find a way to write ugly code.

Here's a word I recently implemented in Forth:
: C
>R
256 15 16 1799
4 13107 2 21845
R>
4 0 DO
TUCK OVER AND -ROT
INVERT AND ROT / +
LOOP
;
Although I didn't set out to intentionally create something hideous, I'm appalled by how difficult to understand the code is. How can I make the word easier to comprehend and can you remind me what it's supposed to do?