Book Review: Think Like a Programmer by V. Anton Spraul
Programming is a complicated endeavor: from figure out a mental approach (algorithm, pattern, etc.) or strategy for a solution and translate it into code, to understand / modify existing code, debug / troubleshoot and find / implement the best way to test the code.
This book's description reminded me of G. Polya's renowned classic mathematics problem solving book "How to solve it" (http://en.wikipedia.org/wiki/How_to_Solve_It) that some are using it in the software development (http://www.softpanorama.org/Bookshelf/Classic/polya_htsi.shtml).
Author's goal was to boost programmer's creativity through the gained experience in writing new programs (following his strategies) rather than by reading and modifying existing code. For more details on this you can watch author's O'Reilly Webcast: Problem Solving The Missing Ingredient for New Programmers (http://www.youtube.com/watch?v=ahVgp69xj7I).
This book presents valuable problem solving programming strategies exemplified by solving simple legacy C++ beginner tasks. For reasons why C++ code before C++11 version is legacy code see Herb Sutter's 2012 talk "(Not Your Father's) C++".
The author draws lessons from solving classic puzzles (Sudoku, Sliding, "The Fox, the Goose, and the Corn", etc.) and applies them systematically throughout the book.
While ambitious and general in its title, this book will benefit the most and fastest the beginner legacy C++ or C-like languages programmer (C++ 11 and up versions are not covered / mentioned).
Intermediate or advanced C-like languages programmers may find value in the creative problem solving approach, some programming idioms or engage with author's ideas like learning creative problem solving, value of C++, managed languages, C++ object-orientation or the component definition / use.
General considerations about problem solving programming issues and original approach to gradually introduce new topics may justify an interest of programmers / teachers in / of other procedural / object-oriented / functional languages, willing to deal with C++ syntax and idioms.
My intent was to take a stand from a beginner's point of view and keep an eye on what value an experienced developer could get from the book.
The introduction chapter makes the plea towards the need for teaching programmers the creative problem solving techniques by emphasizing the lack of guidance in this regard in the programming education. Distinction is made between the two types of programming activities: left brain analytical tasks (code reading, learning language syntax or different APIs) and right brain problem solving by creative use of what was learned. The paragraph on why C++ was chosen is debatable considering the relationship between language vs. thinking and the well-known fact that each programming language has its own idioms and strengths in mapping mental concepts into code (justifying the multitude of "Thinking in ..." languages books). Debatable will be though any attempt to claim language independence approach to explain problem solving programming concepts considering the daunting task of such an endeavor.
The first chapter on "Strategies For Problem Solving" draws lessons by solving few classic puzzles mentioned above. Here are some of the problem solving lessons shared in the book:
- try methodically and backtrack to previous steps
- plan / use a systematic approach and avoid frustrations
- experiment with a reduced (in size) version of the problem
- use intuition to select the right solving tip for specific problems
- enumerate allowed operations and test them in search for a solution
- recognize analogies with other solved problems by studying the problem
- consider all of the problem's constraints instead of avoiding some, just to solve it
- think about the problem by restating / generalizing it eventually to gain insight for a solution
- divide and conquer (breaking down the problem into easier sub-problems, helps solving it (if successful) or gives insights for a solution, if it fails)
The next chapter (Pure Puzzles) exercises some of above problem solving techniques by dealing with elementary C++ tasks like: printing different output patterns, processing input in the Luhn checksum validation problem and tracking state in a message decoding problem. The problem solving techniques used are: divide and conquer, systematic use of problem scope reduction, experimentation, start from what you know, analogy with solved problems, following a plan, avoiding frustration, understand the problem and generalization.
Chapter 3 deals with solving problems using different types of arrays: fixed / dynamically sized, scalar / non-scalar and multidimensional. Besides ways to approach these problems there are presented and analysed implementation reasons and when array use is appropriate. The topics of refactoring and space / time performance of programs are introduced alongside.
The delicate topic of solving problems with pointers and dynamic memory, specific to legacy C++, is discussed in the next chapter. I disagree with the author statement that learning pointers use is essential to truly think like a programmer. As such I don't think that generally pointer less C-like languages (Java, C#, etc.) programmers will get much value from this chapter (excepting the challenge of following the C++ specific problem solving approach). Topics covered: when to use pointers, stack and heap memory, variable's lifetime, memory leak, variable length strings, solving by sample case, checking for special cases, code robustness and linked list specific problems like building, node adding and traversal.
Chapter 5 is about object-orientation and solving problems with classes. A beginner might have hard time understanding the chapter's first part that reviews class fundamentals and the goals of class use due to general nature of exposure used (areas sometimes covered by entire books). In contrast, the next part of the chapter shows through an example how to build a simple class and solve object-orientation implementation issues. This is followed by a more advanced example of a class implementing linked list operations. Readers not willing to become familiar with pointer concept will not benefit from this. While author's decision to use this example might be justified as a follow up of previous chapter linked list coverage I believe that the spirit of exposing object-oriented problem solving technique might have been better served by an example outside of C++ specific pointer concept.
The challenging new way of recursive thinking is originally covered in the next chapter. Author's goal is to make recursion simple by following a systematic approach. Two detailed explained original examples illustrate the head and tail recursion preparing the ground for introduction of the Big Recursive Idea. A very simple example of array summation is used to explain the Big Recursive Idea of transforming an iterative solution into a recursive one. Common mistakes of using too many parameters or global variables are clearly explained and exemplified. Next, the recursion use with linked lists and binary trees are exposed via two simple C++ pointers based examples. The need for public wrapper functions when class implementations use recursion is exemplified by solving a binary tree C++ problem. The chapter ends by discussing and exemplifying the pros and cons of recursion use.
Chapter 7 details an interesting approach towards solving problems through code reuse. Some might argue on the author's definition of reusable component, that includes both low-level artifacts (code block, abstract data type and library) and high-level ones like algorithms and patterns, but it serves well his purpose. Building component knowledge strategies (exploratory vs. as-needed) are exemplified with specific coding problems. While the example of use of analogy during the "as-needed" component use strategy is instructive I find its application quite unrealistic since a priori effort of learning component's capabilities is required. The tradeoffs made while choosing a component type are exemplified by two alternative implementations of a sorting problem. A modified insertion-sort algorithm component implementation is compared and analysed against a qsort C++ library component call.
Last chapter guides the reader to develop his custom problem solving plan and continuous learning strategy that will allow her / him to tackle any problem. This involves identifying of coding (design) weaknesses / strengths and build a master plan by planning against / for them, respectively. Next, the process of building a sample master plan is detailed. How to put the master plan to work is detailed exemplified through solving a non-trivial problem.
The author's extensive teaching experience is revealed in the chosen increasing complex topics and well documented presentation (question / answer and diagrammatic) style that sometimes is too elementary / verbose, justifiable though considering book`s broad scope. This style is sometimes contrasted with advanced programming statements, like the use of Standard Template Library or general statements that might challenge content understanding by a beginner.
Few caveats: 1. Luhn checksum validation problem is incomplete specified but is clarified later by examples and diagrams; 2. use of qsort and C++ Standard Template Library's vector in chapter 3 makes understanding harder (in spite of explanations) since it requires knowledge of C++ pointers respectively object notation explained later; 3. the advantages of object-orientation (object composition and interfaces use) are not enough explored / exemplified, justifiable though by the scope of the book.
It is laudable author's attempt to decipher the cause of challenges students have in grasping problem solving programming areas and provide valuable guidance throughout the book. In this regard I believe the author met his goal to explain systematic problem solving techniques in order to unlock reader's creativity by practicing them.
This book contributes towards the goal to fill the gap in the programming literature with such kind of books.
Note: this review is based on the ebook version provided via O'Reilly Reader Review Program.