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.
- “Look for all fancy wordings and get rid of them.”—Jacques Barzun, Simple & Direct, A Rhetoric for Writers (Harper and Row, 1975), page 27. Read this book. Barzun is an acknowledged genius.
Dale Emery, Understanding Coupling and Cohesion, YouTube video.
“You and Your Research” given by Richard Hamming given on March 7, 1986.
Those who cannot remember the past are condemned to repeat it.—George Santayana, (1905) Reason in Common Sense, p. 284, volume 1 of the Life of Reason.