Note that this is a book aimed at relative novices and so it is important that the low-level code sets a good example. After an email discussion with the original reviewer he asked to withdraw his review.
When you read the following, in fairness to the author, remember that an experienced reviewer initially liked the book. However, like many experienced reviewers he had not actually worked through the whole book. Here is what I wrote to the original reviewer. - Francis Glassborow.I have now had a chance to do a complete inspection of this book. I can see what impressed you because the author does a number of sensible things (they are almost all issues raised at a meeting at Blackwell's Bookshop a couple of years ago). Unfortunately there are a number of what I consider to be unacceptable deficiencies. In accord with my standard policy I will, if you wish, publish your original review but I shall (also in accordance with standard editorial policy) have to publish a review raising these deficiencies.
Among the problems I have are:
The continual gratuitous use of global variables [note that in the past I have argued in their favour where they offer some real advantage such as representing conceptually unique objects (singletons in current parlance)].
Unhelpful comments. For example on page 200 as part of a structure definition for a mailing label:
char state; /* two-character abbreviation */
Why only two characters (no space for a null-terminator)? The comment says what is obvious but fails to explain a design decision. Actually replace the '2' by '3' and the comment might make some sense. Note that I opened the book completely at random and simply looked at the first piece of code. That is how easy it was to find a poor comment.
Poor naming conventions (to see some really bad ones look at chapter 22 where he names a number of functions with a prefix
in_to show they all relate to the same object and then uses
in_commentas a global state variable.
The misunderstanding of
constin C (where he assumes that it is the same as C++) He makes choices that no experienced C programmer would make for variable types e.g. page 244 where he has
const char DATA_FILE = "numbers.dat";
- why a const char, rather than a const char *or plain char?
- why a global?
- why hard code the file name?
He repeatedly makes assumptions (such as that
fgets()will terminate by reading a carriage return, when it could do so because it had filled the buffer).
I could (and if you wish will) go on about the multitude of other instances of bad examples however the piece de resistance is chapter 22 where a stupid (there is no other word for it) design results in really terrible code. This design and code is what I would expect from an average student who had not put his/her (incidentally he continually lapses into gratuitous use of male pronouns when there are easy alternatives) mind to a clean initial design. Note that this is the 3rd edition so he has had plenty of time to get this design an implementation up toacceptable levels.
By the way he assumes that the execution and source character sets will be coded in ASCII, I guess he either does not know or chose to ignore
isalpha, isdigit, isxdigitetc.
Please do not misconstrue the above. I shudder when I look at some of my earlier reviews when finding some sane aspects coloured my assessment of an author's work. It is sometimes such a relief to find a book that uses
fgets()and a few sane coding guidelines that the problems get over-looked.
Sadly, in this case, I think that the author's understanding of programming and C in particular is superficial. He reacts to criticism by correcting what he thinks are the errors but without understanding the issues.