‘Think Like a Programmer’ is aimed at people in the early stages of their trip down the programming lane. It describes different approaches to solving problems using various constructs (if that sounds vague, don’t worry, it’ll make sense later).
I found the book helpful, it provided well-defined descriptions of approaches that I was using intuitively and some helpful advice on self-improvement (some of it familiar, some of it new to me). The language of the book is quite straightforward and understandable, but it’s worth noting that most of the examples are written in C++.
The author argues that C++ is a meeting point between functional and object oriented languages, that’s why using it for code examples is a good idea - you’re never forced to use one or the other, you make a conscious decision to go functional or OO. I would argue that, while that is true, some of the used C++ syntax seems too convoluted to pass as a simple example, if that’s what the author was really aiming for. But hey, I suppose it’s a matter of preference.
Two main pieces of advice in the book seem to be: before jumping into code - develop a strategy, lack of planning makes addressing the problem less systematic, more dependent on a lucky break, more chaotic and is more likely to take longer or produce a result that is sub-par; reduce the problem into small manageable isolated pieces and attack them one at a time. I suppose there’s also a third advice - don’t get frustrated. Good advice in theory, but I think it has more to do with how successfully you use advice #1 and advice #2.
The book is full of examples and exercises aimed at driving the point home and at some stage, I think, the author expresses that his main aim for this book is to turn coders into programmers. A noble aim indeed.
So in short: it’s a pretty good book. If that’s not enough information, keep reading.
Strategies for Problem Solving
In this chapter Spraul looks at non-code related puzzles, like the puzzle with getting a fox, a goose and a sack of corn across the river - you know the one; or sliding tile puzzles; or sudoku. He then analyses the problem and comes up with a strategy for solving it. After that he shows how some of these strategies can be re-used with different puzzles. The chapter is pretty straightforward and doesn’t require any programming skills.
Here the author starts going into code. The challenges in this chapter are more or less straightforward and have to do with outputting specific patterns or decoding encrypted messages. So, basically, input/output stuff. The main messages Spraul focuses on are: break the problem down before attacking it, store code for future reuse.
Solving Problems with Arrays
Spraul talks through what arrays are and how they work. As he is talking about deep and shallow copying and how to look for things in arrays - he conveniently brings up the problem of sorting them. The exercises that he goes through in this chapter, one way or another, have to do with implementing quick sort or insertion sort. He talks about which sort is better to use under which circumstances. There’s a mention of multidimensional arrays and an exercise that basically introduces the reader to maps (only by using two separate arrays - one for keys, other for values).
Solving Problems with Pointers and Dynamic Memory
I really enjoyed this chapter. Spraul spends a while explaining what pointers are and how memory works, covering stack and heap memory allocation as well as the lifetime of a variable. And I suppose this is where Spraul’s decision to use C++ really shines. The exercises have to do with appending to arrays, so they really build on what’s already been covered. Then the rest of the chapter focuses on linked lists.
Solving Problems with Classes
Understandably, the chapter starts by explaining what classes are, and what their benefits and disadvantages are. There is a brief note on constructors and destructors, and the difference between support/helper methods and retrieval and storage methods. Just like before, Spraul builds upon the previous chapters and the exercise he goes through has to do with creating a ‘StudentCollection’ class that utilizes a linked list.
Solving Problems with Recursion
I found this to be one of my favourite chapters in the book. I don’t play around with recursion enough, so it was interesting to read about different approaches to problem-solving with recursion, and which situations would suit head-recursion best, which are great for tail-recursion and which shouldn’t use recursion at all. The examples provided were quite simple and very ad hoc, but I think it’s a pretty good introduction into recursion with its potential pitfalls.
Solving Problems with Code Reuse
Here Spraul talks about good reuse and bad reuse, how to discern one from the other, as well as different types of code components: code blocks, algorithms, patterns, abstract data types and libraries. He talks about building component knowledge and different approaches to doing that: exploratory learning and as-needed learning. The names are self-explanatory, but just in case - exploratory learning is learning something when there is no explicit need to learn it (for fun, out of curiosity or for a number of other reasons); as-needed learning is learning something because it is directly related to the problem at hand. Spraul also talks about which components are best suited for which problems, taking into account the amount of work needed to make them do stuff and their flexibility (for example: a pattern can be extremely flexible, but its implementation requires a lot of work, a library, on the other hand, doesn’t require a lot of work, but isn’t particularly flexible).
Thinking Like a Programmer
And in the final chapter the author talks about creating one’s own Master Plan to solving problems. The suggested blueprint for it involves planning against design and coding weaknesses, taking into account your own strengths and weaknesses and just generally improving yourself (by learning new programming languages, by learning new aspects of an already familiar programming language, by studying well-written code and, most importantly, by ceaselessly writing code and experimenting).