Feineigle.com - Good Habits for Great Coding Improving Programming Skills with Examples in Python

Home · Book Reports · 2018 · Good Habits for Great Coding Improving Programming Skills With Examples in Python

Published: July 28, 2018 (5 years 8 months ago.)
Tags:  Programming · Python



The book in...
One sentence:
Some style, some algorithms, some problems solving; too little of too much written in a hard-nosed, holier than thou, style.

Five sentences:
It starts off fairly strong with a focus on readability and style, though much of this is subjective and/or determined by your shop style, which boils down to consistency more than anything else. He talks about not being clever or using tricks since they are often hard to read, but then goes on to mix his message while breaking his own advice by being clever multiple times. There are several mentions of problem solving, devoid of any actual advice aside from the suggestion to read Polya. More haphazard advice litters the remainder of the book; advice on comments, tests, and loads of other stuff that isn't necessarily bad, but the tips are all over the place. Lastly there is a few chapters on algorithms and dynamic programming that don't feel like they fit at all.

designates my notes. / designates important.


Thoughts

My first impression is that I don’t like the author’s style. He seems extra stern, even hard-nosed. His way is the best, maybe…

I was expecting more of a book on style, best practices, patterns and such, but it feels more like an intro to algorithms. There is a fair amount of good advice, but it feels like it is coming at the problem from too many different angles. Would not recommend.

It begins with a hardcore story about how being average is a sin and will lead to, poverty, divorce, and losing everything you love. WAY over the top. Not everyone can be great, if they were, that would be the new average.

Next it introduces a few tricks, mostly for optimizing a Fibonacci number generating program. One ’trick’ is to save certain computations and reuse them. This seems completely reasonable and he shows the speed increase for doing it. Then decorators and memoization are introduced, which give a lot more horsepower to the Fibonacci program, but after introducing them the author says they won’t be used in the rest of the book.

At this point I was already put off; chapter one seemed very off topic, or maybe I took the title the wrong way?

Ah, chapter three focus on style, readability, and python idioms. This is what I expected. Actually it is more of an argument for these concepts; how (high school) student programmers don’t see the need for such things since the programs they write are short and are only read by the teacher.

Back to Fibonacci, but with a focus towards which of the previous examples is best? What is best? Fastest? Most readable? Easiest to use? Of course, it depends on the context.

Building on this we see age old advice: functions should be short and sweet; they should do one thing. This is presented with a discussion on coupling, several functions hooked together, versus cohesion, on large function.

He then goes on to point out examples where he prefers the latter. Quite the mixed message.

A lot of his advice is contrary to what you might be taught. Loosely coupled code is something worth working toward I’d say, and putting too much in a function is never a good idea. His point is that there are no hard and fast rules. He explicitly deviates (and states so) from the Zen of python, “your problem is not special enough to break the rules”, or however it goes.

Still on point we see more advice on style. He fusses over some minor things, like vertical alignment, that are personal/shop preferences. Being a mathematician, he labors how you should write equations. I agree with his preference of 2*(a + b) over 2 * (a + b) or 2*(a+b). The first ‘feels’ more traditional since multiplication is written close (without parenthesis) with a little more space to the other operators.

On piece of advice I really like is the idea to name functions returning boolean values with a leading ‘is’. For example: ‘isAnimal’ versus ‘animal’.

Following along with style, he discusses design styles: top-down versus bottom-up. Top-down, having an outline for what the program will do and then iterating over the development, adding detail at each step, is more professional, takes more time, but in the long run, produces more reliable results. Alternatively, bottom-up, or seat of you pants, programming is what most students use; try something until it works, peck away here and there with only a vague idea of an end goal. Clearly the former is preferred for large programs, but simple scripts and high school level assignments probably don’t need such detail.

A short chapter on comments that includes nothing of interest comes next, which introduces self-documenting code through proper layout and variable/function names is better than a slew of comments that only get in the way.

There is a quick mention of comment driven design; this is the first time I’d ever heard this term. It seems like nothing more than a basic outline.

Some great advice follows: if you don’t understand what you’re writing: stop. It may be time to start over. This doesn’t necessarily mean you failed; you can look at it as the lines you’re tossing were required to get you to an elegant solution.

A comparison is made here. Either do it right, with heavy up front planning, or follow the ‘worse is better’ philosophy and do only what you need, keep it simple, and add features as needed. The thought being, if you keep additions simple you’ll eventually get a clean result. Both are reasonable approaches.

There is a chapter on testing, which seems to not fit with the theme again, but maybe you can shoe-horn it in saying it is part of the design process, ala test driven design.

The advice is pretty basic. Write tests as you to or write the tests first, ala TDD. Is there another way? I guess you could not write tests…

A short chapter on error traps follows the test chapter. This feels more style oriented than the test chapter. When and how to use error checking, etc.

A second piece of advice I like is to use (row, col) instead of (y, x) when indexing a matrix since it is so easy to make the mistake and type (x, y) by accident. I’d say this is the most useful stylistic advice in the whole book, and he admits the idea came from a Youtube commenter!

The book takes another turn here. In fact the rest of the book feels almost like a random hodge podge of advice. Not that it is bad advice, it is just a lot of different topics in a lightning round of advice.

On the topic of refactoring he fails to follow his on previous advice of not being clever, with, by his own admission, clever solutions. The refactoring aspect, going back over your code; making it cleaner; easier to understand; commenting what needs commenting; etc, seems to be lacking. He suggests stringing ands, ors, and nots, together, which in some cases feels harder to read. One thing I did like, and had never really considered, was trying to always use inequalities where the smaller number is on the left. That is, always use less than (<) since, reading from left to right as on a number line, it is more intuitive.

Now we move back to tests, or, what he calls smoke tests. Supposedly this comes from hardware testing: turn it on, if it smokes turn it off, test complete. These are nothing more than basic tests that you might use early in development to reduce inputting test data. That is, if you aren’t following test driven design. This seems blatantly obvious to me; of course you don’t want to type the input over and over again, and, since you’re at least know how to do things programmatically… again, obvious.

Some of the examples he gives are misleading. He says this code is better, because it is shorter, but all he really did was collapse a series of if: doSomething() statements onto single lines.

He also uses three if statements in a row, pointing out that using elif would be 33% faster but, in some strange way, harder to read. He mentioned this preference to multiple ifs without elif or else several times. He called them bleeding ifs and backstabbing elses. I completely disagree on this one.

The randomness continues with a chapter full of quotes from experts. The quotes themselves are generally agreeable.

Moving again to a completely different angle, he takes a look at design procedures. You should start small, get a little piece working, design and run simple tests, and then add features. Basically, follow an iterative approach.

Next he criticizes OOP, which I totally agree with. The chapter begins with this:

“My opinion is that OOP is one of the great frauds perpetrated on the community. The truth of the matter is that the single most important aspect of OOP is an approach devised decades ago: encapsulation of subroutines and data. All the rest is frosting. I used to say that encapsulation is 70% of what object programming provides, but I think I’m changing that to 90%.” -Thomas Kurtz

Back to iterative design; this time with an example. The chapter follows the development of a tic-tac-toe insert X/O function.

After covering so many algorithms, and making a point to say every program should report its running time, (not to mention the 33% slower function he said was easier to read), he proceeds to tell us that inefficient algorithms are perfectly acceptable, in some contexts. They could be easier to write, debug, maintain, and of course, read. I can’t disagree with any of that. Use the simplest tool you can get away with.

Now we move to computer simulations. Did I mention this book is all over the place? There are some interesting problems in this chapter and he makes it known that computer simulations are one of the main ways science is advanced. Counter to this he has a half page digression about how he hates metaphysics. Why is this here? Who knows.

The second to last chapter provides general problem solving advice and suggests Polya as further reading. Could not agree more. Skip this book and read How to Solve it. He and Polya agree that the only way to get better at problem solving is to struggle with difficult problems. If you look at the answer and think ‘oh yeah, I get it’, you probably are setting yourself up to fail.

The last chapter covers dynamic programming. It is by far the most involved chapter and, again, doesn’t feel like it fits in this book. The difficulty isn’t a problem, as the previous chapter correctly pointed out, you need to work on hard problems to get better, but this feels like it should be in an algorithms or dynamic programming (what a thought!) book.

To reiterate, this isn’t a bad book. I agree with most of what it offers, but it is all over the place. You’d do better reading PEP8 and some algorithm, data structures, dynamic programming, or design books. It will be more work, but you’ll learn a whole lot more. I wouldn’t even recommend this as an introductory book to those topics.

Further Reading


“Someone suggested that all Boolean functions should begin with is. Thus, allVowels should be isAllVowels. Initially, I didn’t think much of this advice, but then I noticed that it actually made some of my code read like English sentences. So now I follow this suggestion.

“One YouTube commentator suggested never using x and y for matrix coordinates, but rather use row and col. Why? Because it is too easy to write (x,y) for what should be (y,x), whereas (row, col) are unlikely to be interchanged.

“Some experts prefer to use ‘<‘over’>’ in if tests, because this is consistent with the number line, which keeps the smaller numbers to the left.

“My opinion is that OOP is one of the great frauds perpetrated on the community. The truth of the matter is that the single most important aspect of OOP is an approach devised decades ago: encapsulation of subroutines and data. All the rest is frosting. I used to say that encapsulation is 70% of what object programming provides, but I think I’m changing that to 90%.—Thomas Kurtz, Found in Masterminds of Programming (O’Reilly, 2009), pages 91 and 93. [Dartmouth professors Thomas Kurtz and John Kemeny co-developed the BASIC language in 1963–64. Kemeny won the IEEE Computer Pioneer award in 1986, and, for the same work, Kurtz won it in 1991. At the time of this interview, the 80-year-old Kurtz had been retired for 15 years and no longer wrote code.]

“Note on Proof by Computer (Simulation and Verification): How important is computer simulation? As far as I can tell, there are only five ways to make progress in the sciences: 1) abstract modeling (with mathematical proof ), 2) field observation, 3) experimentation, 4) mathematical calculation of measurements, and 5) computer simulation. In some cases some people will prefer simulation to a mathematical proof, especially if they cannot understand the mathematical proof. But even the most rigorous proof has some philosophical objections.5


Table of Contents


· Introduction

Part 1: Not Learned in School

· 01: A Coding Fantasy

page 12:

· 02: Coding Tricks

page 25:

· 03: Style

· 04: More Coding Tricks

Part 2: Coding Advice

· 05: Function Design

page 61:
page 66:

· 06: Self-Documenting Code

page 68:

page 73:
page 76:
page 90:

· 07: Step-Wise Refinement

· 08: Comments

· 09: Stop Coding

· 10: Testing

· 11: Defensive Programming

page 126:

· 12: Refactoring

page 131:
page 136:

page 137:
# Here is the useful subscripted list trick:
def doIt(x):
  return['-',2,3,4][x]

· 13: Write the Tests First (Sometimes)

· 14: Expert Advice

Part 3: Perspective

· 15: A Lesson in Design

· 16: Beware of OOP

page 197:

page 198:

· 17: The Evolution of a Function

· 18: Do Not Snub Inefficient Algorithms

page 214:

Part 4: Walk the Walk

· 19: Problems Worth Solving

page 224:
page 227:

· 20: Problem Solving

· 21: Dynamic Programming

page 267:
page 269:
page 271: