Notes on Dijkstra's Book, Chapter 1
I spent a few hours today wrangling with the Flask “microframework” to add authentication to a web app. The framework seems okay, but I felt that at the end of the day, it might have been easier to just roll it myself with CGI (primarily because Flask doesn’t provide much). I also had to install some middleware for the server to translate requests between Flask and itself, which felt suboptimal. Since I have just begun exploring it, I am hestitant to write it off yet.
Separately, I started reading Dijkstra’s “Selected Writings on Computing: A Personal Perspective”. The preface talks a bit about Dijkstra’s day to day errands, and how he wanted to capture a slice of his life in the book. The first chapter deals with Dijkstra describing his methodology for program development. He discusses two problems: finding the first 1000 prime numbers, and instruction processing for the “Flexowriter” typewriter.
There are a few interesting observations. First, he uses the same methodology to solve both problems: start off with a very high level outline of how the program should work, then write functions that implement that logic; these functions can use high level logic as well, requiring additional functions, etc. This methodology reminds me of Mcconnell’s advice in “Code Complete 2” – write all the comments first describing the logic, then implement. Second, he is not afraid to introduce new terminology that would be considered confusing on first glance, as long as it is well defined. E.g., he defines a number to be “throdd” if it neither divisible by 2 or 3, and uses the word in his program. This style contrasts my company’s, which eschew abbreviations and non-standard terms. Third, I cannot tell how much optimization he believes programs should have. For the prime generator, he skips all numbers divisible by 2 or 3, since he believes it will speed up the program; however, he also states that, “There is no indication that any gain will result from taking the next prime (i.e. 5) out of the cycle as well, and we shall not try it.” (page 6) There is obviously gain (multiples of 5 will not be tested), so I feel there is something else going on. Does he believe that the incrementor he uses for skipping numbers (if N has been tested, the next two numbers to test are N+2 and N+4) will be made significantly more complicated? Does he think that the percentage speed increase is small enough to be considered negligible and not worth doing (for 1000 primes, I would think the number of values checked would be reduced by ~20%)? I do not know. Also, it is very interesting that at one point he writes a while loop instead of an if statement, even though they are equivalent and the if statement is faster (the while loop only iterates once, so it does an extra check at termination). He stats, regarding the replacement of the while with the if, “… to my taste the marginal gain in efficiency is not worth the intellectual effort to prove its validity. A programmer should learn to be lazy at the right moment and let the principle, “Safety First” prevail!” This is a very interesting statement – he is stating that the while loop’s correctness is much easier to understand, and since the speed up is negligible, it is not even worth pursuing. I have mixed feelings about this statement – on the one hand, I agree (otherwise we’ll spend all of our time optimizing parts of programs that have no discernible effect on the outcome), but on the other, I am concerned about a death-by-a-thousand-cuts where a program becomes slow and bloated. Maybe a better way of putting it is – the program loses a sense of beauty by not being optimal.