217
Book Reviews Writing Efficient Programs, by Jon Louis Bentley, 1982; Prentice-Hall, New York, NY; 170 pages; $20.75; ISBN 13-970244-X Review by H a i m Kilov
The book is about the activity of 'writing efficient code which takes as input a high-level language program ... and produces as output a program in the same high-level language that is suitable for compilation into efficient machine code' which is ' t o o complex for most current and foreseeable compilers'. Programmers 'out there in the trenches' are dealing with these activities quite regularly, but this domain was almost never considered respectable enough. Proliferation of hackers was one of the results of such an approach, though, as the author stresses right from the beginning, 'writing efficient code need not remain the domain of hackers' because a set of principles (engineering techniques) could and should be formulated for a programmer working in this area. The book succeeds in describing precisely and explicitly this set of principles together with a wealth of examples and references. This book is definitely not for beginners; its audience should consist of 'readers who have worked on at least one large program' ('large' means containing more than 1000 lines of code). Naturally, some of the material may be appreciated and one of the main issues is when to use the techniques presented. As all of us (should) know, there are two main concerns in good program writing: the correctness concern and the efficiency [E.W. Dijkstra, A Discipline oJ Programming; Prentice-Hall, 1976]. These concerns should be separated. Indeed, time and again J.L. Bentley reminds the reader that 'the efficiency of a program is secondary when compared to the program's correctness' and that the
North-Holland Computers & Standards 3 (1984) 217-220
methodology to be used consists of 'correctnesspreserving transformations at the source program level'. Moreover, 'when we apply a rule, we should make sure that the application preserves the correctness of the program; this is usually done by applying the spirit, if not the actual formulas, of program verification' (p. 108). Such advice is indispensable for the 'average professional programmer' who too often thinks that program proofs are 'toys for the academics' and definitely not for him. This thought is wrong, and J.L. Bentley, who isolates carefully the efficiency concern, nevertheless does not forget about the correctness one and doesn't permit the reader to forget it. (The interested reader may be referred to J.L. Bentley's column, 'Programming Pearls' in Communications of the ACM, especially in the December 1983 issue.) In particular, loop invariants and other assertions (invariant conditions) are often explicitly used in the English prose accompanying the program texts (though, unfortunately, not in the program texts themselves). The author clearly outlines two main aspects of improving the efficiency of correct, but possibly inefficient, programs; when to worry (since, "premature optimization is the root of all evil') and what to do. Both of these aspects are discussed at length, and sound underlying principles are presented. Instead of a 'set of recipes', the author presents a methodology of building efficient programs. Moreover, he presents quite a few very interesting and non-trivial examples (and case studies from real-life situations). (As a result of efficiency transformations, the efficiency of programs was increased by factors that vary from a few percent to a few orders of magnitude.) References are always provided for the reader who wishes to know more (many of these references are not too well-known). Of course, for a truly professional programmer the methodology and rules presented by J.L. Bentley may be well-known, nevertheless, some of the rules are definitely more weltknown than others so it pays off even for an expert to read this book. All the rules are presented in proper perspective (taking into account that simplicity is the keyword in good program development) and lessons learned from the examples are also described quite explicitly, so that the
0167-8051/84/$3.00 ,~ 1984, Elsevier Science Publishers B.V. (North-Holland)
218
Book Reviews
book is most definitely not a cookbook! The underlying language is PASCAL but, for a professional programmer without knowledge of PASCAL, Appendix D provides a description of the PASCAL dialect used. Thus the professional programmer reader will not encounter any difficulties in studying the examples. (Of special merit is the neat presentation of the program fragments: they always fit into one page and never start on one page to finish on another. This is also a very good example of an efficiency solution - the reader's intellectual effort is saved at the expense of some extra white space.) I have remarks concerning the program fragments: (i) In presenting the insertion sort, the (third) Fragment 13 is cleaner, easier to understand and prove correct (and better conforms to the specification of the insertion sort!) than the (first) Fragment 11; (ii) In presenting the quicksort program, the idea of partitioning the sequence into three sub-sequences is indeed mentioned, but never used in the program fragments, though the three sub-sequences partitioning (see ' T h e Problem of the Dutch National Flag' in the Dijkstra book already mentioned) is simpler and more beautiful than the traditional two sub-sequences solution. All in all, this highly recommended book is taking a serious step into the right direction of ' m a k i n g professional programmers out of terminal jockeys'. Further, the reader is advised to follow one of J.L. Bentley's suggestions: ' O n e of the most important tools ... too often neglected by programmers is the literature search'.
Software Portability and Standards, by Ingemar Dahlstrand, 1984; Ellis Horwood Limited, West Sussex, England; 150 pages; UK £15.00; Index: ISBN 0-85312-642-9. This quiet book begins with a discussion of Portability and moves in five chapters 'towards better programming languages'. With precious little bombast, the author considers such important issues as: -
The purpose of standards; Data representation; Normal forms; FORTRAN;
- ANSI and ISO; - C o m m a n d languages; - C o m m o n programming language. Yet the author never raises his voice or becomes strident. The pleasant conversational form of the writing leads the reader into accepting his concepts easily. His concepts grow from long years of experience; some of that time learning good lessons, some, bad. He shares it with the reader in several specific proposals, specific enough for committees to pick up if they choose. US readers will find a lot of European history which indicates that while the US made the most noise, invention was general throughout Europe, too. ' . . . there is just one thing worse than a post-implementation standard, and that is a pre-implementation one . . . . (If the Ada people succeed at it, it will be a historical first.)' Now that quote presents a challenge. Let me complement this thought with my experience: most of the good ideas from pre-implementation standards are readily absorbed into implementations under other syntax and different names. The 'survival of the fittest' concept works here and is driven by user-demands. Note the alacrity that DBMS vendors accept ideas that sold their competitor's product. As all DBMS products increasingly share all accepted functions, the standard emerges as a post-implementation standard. Perhaps the relational DBMS concept is the most successful pre-implementation standard but it assuredly is being modified for 'real world' users. The author prefaces his statement that FORT R A N is his language of choice by listing major problems with F O R T R A N . Pausing to define the word 'undefined' which appears in many standards and plagues portability everywhere, the author discusses many potential solutions and proposes his preference. His chapter on data representation standards is short, he says, because most of the problems have been worked out. I find that opinion uncomfortable to support in view of the DBMS standards lack of progress. I view it as essential to find a Data Description Language independent of the procedures used to manipulate them but such work usually reverts to considering a new ' p r o g r a m m i n g language'. F O R T R A N began with primitive I / O and continues to struggle with it. The author reviews proposals which, when com-