Please create an account to participate in the Slashdot moderation system

 



Forgot your password?
typodupeerror
×
News Books Media Book Reviews

Review:The Practice of Programming 168

SEGV has returned with a review of Kernighan and Pike's latest effort, The Practice of Programming This book has both practical and method aspects, including exercises. If you're serious about your programming, read below to get the skinny on the book.
The Practice of Programming
author Brian Kernighan and Rob Pike
pages
publisher Addison-Wesley
rating 9
reviewer SEGV
ISBN 0-201-61586-X
summary Practical and enjoyable, this book captures its authors' considerable wisdom and experience on the practice of programming.

This book is written by some heavyweights in the industry: Brian Kernighan and Rob Pike. I have not read previous efforts such as The UNIX Programming Environment or The C Programming Language, but I understand that they are excellent works. I was hoping that this book would live up to that pedigree.

I was not disappointed. The Practice of Programming is a great resource. I found the book to be a good mix of Steve McConnell's Code Complete, Steve Macguire's Writing Solid Code, and Jon Bentley's Programming Pearls: all excellent works in my experience.

Structure

The book offers nine solid chapters devoted to the practice of programming: the tasks that we perform every day to develop software. They range from the beginning of the process (eg, interface design) to the end (eg, testing); from higher-level considerations (eg, portability) to lower-level (eg, naming).

The authors provide examples culled from their real-world experience. I particularly enjoyed their debugging anecdotes, especially their hubris in discussing their own bugs. The authors also provide illustrative exercises, annotated supplementary reading, and an appendix of collected rules. The quality of these is high.

Style

Kernighan and Pike write with facility, clarity, and authority. It is easy to tell that their advice comes from wisdom and experience. I found the text to be readable and enjoyable, and the examples to be relevant and understandable.

The authors' presentation really makes this book valuable. It is neither dry nor difficult to read. In fact, even when they cover difficult material, they are careful to present it in an accessible manner. A college-level programmer should be able to absorb chapter 9, even though the authors build a toy VM with JIT compiler -- not a trivial undertaking.

Examples

The examples in this book really stand out. There are many, almost one per page. The bad examples are appropriately marked with '?' characters, the good examples are nicely commented, and each is concise and typically adapted from real code.

The authors employ many programming languages to illustrate their points. Although they have a distinct bias towards C and Awk, they also present C++, Java, and Perl code, and are careful to use idioms particular to each language.

Often, they will present several versions of the same program. When they do so, they discuss code length, clarity, and related issues, and compare performance, scrupulously noting the environments used.

For example, in chapter 3 they design a single program and implement it in C, Java, C++, Awk, and Perl. In chapter 6, they apply their testing tips to those programs. I appreciate this kind of continuity in a book.

Nitpickings

I have a few nitpicky comments regarding this book. I really don't like the authors' predilection for short local names, which seem clear in a book's example but aren't so sensible when being maintained in real-world code. The world would have been a better place with a compare_strings function instead of strcmp.

Scott Meyers counsels us (More Effective C++ Item 6) to prefer preincrement to postincrement, yet the authors continue to use the latter in loop control statements. The authors also eschew Java's boolean/false/true in favour of int/0/1; for what reason, I am not sure.

Still, these are nitpickings. Those issues are relatively minor, somewhat religious, and do not detract from the value of the book.

Summary

I think this is a good book, and I definitely recommend this sort of reading for colleagues of mine. If you've read the books I listed in the overview, then you can get by without this one. However, I feel that it doesn't hurt to be exposed to slightly different presentations of the same material, if only to reinforce the lessons learned.

While I read this book, I was engaged in a coding standards effort in my previous employment. I did find this book, in conjunction with others, to be a useful resource. In particular, I believe it is the most directly applicable book of its sort to development shops that have a lot of C code. That includes the Linux community.

The Practice of Programming is most suited to an intermediate level programmer, although beginning and advanced programmers will also find knowledge in its pages appropriate to their level.

The book's official site contains source code and other resources.

To purchase this book, head over to Amazon and help Slashdot out.

TABLE OF CONTENTS

Preface
Chapter 1: Style
Chapter 2: Algorithms and Data Structures
Chapter 3: Design and Implementation
Chapter 4: Interfaces
Chapter 5: Debugging
Chapter 6: Testing
Chapter 7: Performance
Chapter 8: Portability
Chapter 9: Notation
Epilogue
Appendix: Collected Rules
Index

This discussion has been archived. No new comments can be posted.

Review:The Practice of Programming

Comments Filter:
  • by Anonymous Coward
    Apparently there are a lot of programmers here.
    So I just wonder what what you think about using evolutionary algorithms(I know, really heuristics)
    to generate code. Danny Hillis said in his book
    that this is what he was working on (at least in part).
  • by Anonymous Coward
    #1 - Steve McConnell is NOT an employee of MS. He is a consultant that they have used (occasionally to bring their products back on track when they start slipping).

    Quite often he also uses his experience from MS as examples of something NOT to do.

    Just because he wasn't involved in the development of Unix Or C doesn't mean he isn't a highly capable programmer.

    To find out more about him, chekc out his
    home page [construx.com] (http://www.construx.com/stevemcc/)
  • strcmp() et al. come from an older time when external symbols had to be kept unique within the first 6 characters and not case-dependent so the GECOS, 370, etc. UNIX ports could use them.
  • Look at the bottom of the article. There are usually big fights in the comments after book reviews between people who don't like Amazon.com and people who do, but for some reason those have slacked off recently.
  • Kernighan also is (or at least was) executive editor for the Addison Wesley Professional Computing Series, which gave us among other things, the wrintings of W.R.Stevens and several other well known personalities.
  • strcmp(x,y) == 0 definitely means that the two strings are identical in content and length.
    strcmp("abc", "abcde") will return a negative number.
    --
  • I'm no master of obscure C code (I use a reference when I need it, and I much prefer using a small subset of the language), but there is a response at RTFM [mit.edu]* to some of the Comp.Lang.C. FAQ's that cites Schildt in C: The Complete Reference as a support, and nothing else.

    Thus my guess would be, if Schildt's books pit him against Comp.Lang.C's FAQ maintainers and contributors, that, well... he needs help.

    (*) The filename is Re:_comp.lang.c_Answers_(Abridged)_to_Frequently_A sked_Questions_(FAQ) -- but entering in the ASCII codes for parentheses, I still get errors. So go to the directory and get the file :)
  • Except that in the cases where they are equal, it would be horrendously inefficient ...
  • If you want an int return type, use an int. The problem with this multi-purpose return type thing is it's just begging for misinterpretation of the return value.

    You would get far fewer errors, I think, with an AreStringsEqual or even a strequ function, rather than using strcmp when all you care about is equivalence.
  • The 6-character limit was actually in force this decade. SGI's GL libraries (before X took over the world) had full-length names for C, and 6-character abbrs. for fortran. I assume this was due to language or compiler constraints, not just linker inability...
  • ...but a neat little trick that I saw (and now use) is to rearrange the evaluation order to:

    int iRet = strcmp(x,y);
    if (0 == iRet) // instead of (iRet == 0)
    blah();

    That way, if you happen to accidently type 1 = instead of 2 (==), you die at compile time rather than runtime.

    Of course, this is not applicable to the given example (since the function doesn't evaluate to a valid LHS of an =), but I figured Id throw it out there in case someone hadn't seen it before.
  • Of course, there are many reasonable compilers that don't flag it at any warning level.

    I dissagree about readability too. Its a "free" practice adjustment. *shrug* Follow your heart AC.
  • Assuming that we are dealing with fixed-width characters (which is probably a bad assumption these days), finding the length of a string is O(n), and doing a string compare of 2 strings is O(min(n,m)).


    Err... finding the length of a string is trivial, it's simply the number of characters in it. Finding the length of that string's representation on the screen is a somewhat different problem.
  • Heh. I'm hoping he actually meant Apache...
  • Obviously, You missed the point of the chapter on style.
    In the book they very clearly point out, its not which style you choose(ie variable naming, etc)
    but the fact that you choose one and stick with it.

    I would suggest you stop pretending to be an "experienced" programmer and go back and read the book. Everyone, *Everyone* has something to learn from this book. For the "experienced" programmers its a good refresher, because everyone strays from the path.

  • You still don't get it. Too bad.

    On a side note:
    Why do I care who you are or what you wrote?
    I use lots of software everyday, some I wrote, some others have written, and maybe even some you wrote. Just because I may use your code, does make you experienced.
    But then again when I think of experienced programmers I think of people who can write "good" code.

    BTW: Does benefit mean pisses me off once everyday?? Then I guess I do benefit from your code.
  • I beg to differ. I think if you take a major application, such as the GIMP (which I've never read the source code), you will find it to be complex.

    There's the OS (a complex beast in itself). X above it. Toolkits: gdk, GTK+, etc. Probably some GIMP utility modules. Modules for the graphics. Modules for the UI. Modules for the plugins.

    All together, it is complex. Probably it is understandable because it is well designed, by two people. You are correct though that when you are working on a larger project with several teams of 8-10 programmers each, where the architecture has been poorly documented and subverted in cases, that complexity becomes overwhelmingly obvious.

    In summary, strcmp is a simple function. It needn't be complex, and shouldn't be. But many software systems in general are quite complex.
  • I don't see how hard physical constraints would invalidate an otherwise good general guideline. That is, of course there will be special exceptions to the rule and perhaps this is one.

    Also, I realize that strcmp is more of a global than a local name. I didn't intend for it to be an example strengthing that specific point I made, only an example of the more general point of naming.

    Just today I was helping a colleague at my former employment, where he had gone through my prototype code (excusably imperfect) and changed some (local) variable names to be better named: clearer, longer, more expressive. I have to admit the code was more understandable to myself, who wrote it. That's to say nothing of those who will have to finish implementing it.
  • I've long suspected that I control the computer book industry, either through my purchases or through my reviews. :-)

    Say hi to K. for me.
  • You are correct, Scott Meyers actually advises on knowing the differences and issues involved. They apply both to writing and to using the operators.

    I see several compelling reasons to always prefer pre:

    1) it isn't slower
    2) it can be faster
    3) STL iterators work that way
    4) consistency
    5) can be argued that it is more semantically correct

    In the end, those were just my personal nitpickings and are to be taken with a grain of salt. Others will have different nitpickings.

    Actually the K&R style bracing really annoys me and I can't believe I didn't mention that as well...
  • After writing this review and reflecting on the quality of the book, I went to Chapters and purchased The UNIX Programming Environment, The C Programming Language 2nd ed., and The Awk Programming Language.

    I record titles and authors in my Palm Pilot, so I can keep track of what's in stock in Chapters and what the online reviews say. They should have net access in the store.
  • Exactly, use the idiom to suit the language.

    K&P use int in Java code where boolean should be used. That was my beef.
  • You are correct. For builtin types, which pretty much means all C types, pre and post increment are the same. Although, I have heard it argued that post increment still requires a temporary somewhere, and so still is slightly slower.

    But for user defined types, there is a performance hit. Therefore, in the interest of standardizing on one, I prefer that. Also, I find it more semantically appropriate in most cases.

    Finally, I believe STL iterators promise the availability of preincrement but not necessarily postincrement. Therefore, consistency with STL iteration would also dictate preincrement.
  • Well, I am a professional software developer, a rather good one, and I benefited from reading that book. Even after reading Code Complete and Writing Solid Code and other such books. I still benefited somewhat. Imagine if I hadn't read those other books!
  • Well, YMMV. I don't obey everything in WSC and CC but still found them to be good sources of information.

    I actually went out and bought the other K&R and K&P books after dwelling on them. I don't need them to program (I programmed UNIX professionally for 2 years, though likely not at a "hacker" level) but felt they were gospel.
  • I must agree. Part of the reason I get books like these is so I can share them with others. I didn't mention that in my review, but I photocopied a select section or two for junior developers I was working with. In general I try to convince them to purchase and read the entire book. It only helps me later. :-)
  • Functional programming?

    Maybe I should read and review Coplien's Multi-Paradigm Design for C++ next. I understand it is a good book, but have yet to read my copy.
  • A boolean that was a byte would be smaller than a short int which was two bytes.

    The oft-overlooked point is that in structures and classes, the compiler may pad and align members to that it takes 2/4/8 bytes anyways, defeating your efforts. :-)
  • I wouldn't be so quick to absolve older, more experienced programmers. Myself and my younger colleagues have fixed too many of their bugs and design flaws to have that much faith in them, even if they are otherwise quite capable and smart.
  • Once again, str* as a specific example is in C. But the general principle remains as I have stated it. And in my review, I said only that the world would have been better with compare_string, not strcmp, which is true, in general, not accounting for specific issues such as the linker's limit on characters.
  • It is published by Microsoft Press, but not written by Microsoft. McConnell is not an employee. Probably Microsoft doesn't follow his advice wholly.

    But it is an excellent book. It covers more than Writing Solid Code. It backs up its statements with references to studies and further reading. It is long enough to cover the topic of software construction rather fully.

    I've read each of Writing Solid Code, Code Complete, and The Practice of Programming and each is worth reading.
  • Well, I (personally) review them as I read them. Sometimes I read recent books, and sometimes I read slightly older books. It's not my full-time job (I am a professional programmer) so you get what I read. :-)
  • I'm curious, how does Pike advocate dealing with the complexity of modern software without layers of abstraction, design patterns, etc.? I may be misinterpreting, can you elaborate on his views?
  • I understand that reasoning.

    But cos is universal in math as cosine. If I went to a non-computer-type and wrote "strcmp" they would be puzzled.

    In C++/Java we use namespaces/packages to partition the global namespace, and not naming conventions.
  • by SEGV ( 1677 )
    Yes I meant humility. The internal dictionary must have failed me.
  • The habit of using "!" to not the return of a function will also blow up on you at the oddest times.

    Look at the return of the system() call.

    C people avoid TRUE/FALSE definitions because it isn't built in. You never know when some goof ball is is going to stomp on your TRUE/FALSE definitions and some people use T/F or TR/FL or other bad things(tm).
    --
  • GLIB takes a good approach here:

    #define FALSE 0 #define TRUE !FALSE

    It's still a good idea to not compare to TRUE and FALSE, though, and it's never necessary.

  • I liked this book. In fact, I was planning to sit down and review it myself next week, I liked it so much.

    'The Practice of Programming' has found itself a spot next to my computer, right next to K&R's 'The C Programming Language, Second Edition'. I think this is one of the best books a programmer could read, especially someone with limited experience.

    Ideally, it should be read by all college seniors who are working towards a computer science degree. It is intended for 'younger' programmers, meaning people with fewer than 2-3 years of experience. If you have more than 3 years of programming experience, most of what is covered in this book will likely already be familiar to you. It also does assume a pretty good knowledge of programming over all, so I wouldn't recommend reading this until you've gotten at least a few heavy programming classes under your belt.

    Regardless of you skill level though, you don't want to miss this book. The topics it covers include a number of things that are not often well covered, or sometimes not covered at all, in college programming classes. The book picks up where the classes leave off, and gives you a good dose of real world information.

    It's kind of like having a mentor at your side, ready to pass on some of his wealth of experience and knowledge. A lot of what is in this book is the type of thing that seems so obvious once you are told, but that you often don't actually pick up for years.

    To sum it all up, anyone with less than 3 years of programming experience would benefit greatly from this book. Anyone with more might still want to check it out, as a refresher or even just an interesting read. And personally, I'd like to see it made mandatory reading for seniors in college working towards CS degrees. ;-)
  • by kraut ( 2788 )
    strcmp is also a standard C function... compare_string is not.

    Knowing the language doesn't stop at the syntax - you should also make use of the standard libraries, rather than rewriting the same tools all the time.
  • Using int to represent boolean values is bogus. Yes, it can be used to represent true, false, and error, but that's only valid for languages which don't have a good way of representing errors. The modern languages use exceptions. True or false represents valid return values and an exception is raised for when an error is reached.

    This is significantly more sensible than the 0 for false, 1 for true, -1 for error. The code also looks much nicer.
  • A pity that your mindset is so limited. Code Complete is an excellent book. The fact that it is published by Microsoft is irrelevant.
  • Hey, you make the world you live in. My comment was in regards to your opinion which was based on speculation and no authoritative experience. I have read Code Complete. You have not. Why not pull back your foreskin of ignorance and apply the wire brush of enlightenment?

    What makes the book so great? It's a good collection of techniques that are platform and language independent. It empowers any programmer not so much in terms of completely original material, but as a handy collection of useful tips, tricks, technqiues, methodologies, and so on.

  • Hmm. I'm not positive, but wasn't "Elements of Programming Style" written before there was C? The RATFOR preprocessor made FORTRAN look more like a dialect of Pascal (1969).

    I'm reading TPoP right now and I like it, especially the examples. But I agree with you that they are concentrating on low-level programming, without that much consideration for building larger systems.

    ...richie

  • I've got one Schildt book that is damn useful. It's his book on the STL. It's brand new and it covers the ISO standard STL. It's the only readable introduction to the STL that does not start with an assumption that you care deeply about the implementation differences between different sorts of iterators. (yes I care, but not in the middle of a tutorial)

    "Thinking in C++" (Bruce Eckel) just confused the heck out of us -- we spent more time disentangeling the code samples than we spent talking about what was actually going on.

    But yeah, the Schildt C++ bibles and whatnot are good doorstops.
  • IIRC, the first book I read by Brian Kernighan contained a lot of programming examples written in RATFOR (Rational FORTRAN). A lot of those concepts later appeared in C.
  • I recently bought and read this book on the recommendation of a colleague. I quite enjoyed it, and would advise any serious programmer to read it. This book is in the category with other books like Writing Solid Code which are not about languages or algorithms, but about how programming works at a much more abstract level. Even though each chapter in this work covers a specific programming task, the issues that are tackled are lofty things like debugging, automatic code generation, clarity and maintainability. I do have some issues with the cover art. What's with the wiener-dog? As usually, anything by K or R gets props: 10/10.
  • Ugh, that is such a bad idea. When I write C++ I prefer to see:
    if (strcmp(x,y) == 0) ...

    Why do you prefer that? What is the difference between all of the following:

    if (!strcmp(x,y))
    if (strcmp(x,y) == 0)
    if ((strcmp(x,y) == 0) == 1)
    if (((strcmp(x,y) == 0) == 1) == 1)

    I don't do C++, so maybe I am missing something. But I don't think I am. The first one is the idiomatic form.

  • Short names for "intrinsic" functions are good. It's not just the matter of preferring cos() to math_trig_cosine_angle(). Having all the string functions in the form strXXX() or strXXXX() lets you claim a portion of the namespace for the standard library (I think current C forbids application programs to use externally-scoped names of the form strXXX; perhaps you're allowed to have str_foo, but strfoo is definitely out).

    Having compare_strings() would mean you're all over the namespace, and (as others have noted) string_compare() would fail due to the unique first 6 chars rule.

    And, of course, common functions should have short names.

  • During the first half of last year, while he was working on the book, Pike gave a semester course in Software Engineering at Sydney University. I was lucky enough to be able to attend most of it. It looks like the course was a test-bed for the book - we implemented shaney and wrote a virtual machine with a just-in-time compiler - both examples from the book, many other code snippets come straight from the lecture notes for the course - indeed much of the lecture notes look
    like preliminary copies of chapters from the book.

    Something that can, perhaps, not be geaned from the book is the "Pike-course-experience". He started the first lecture by holding the previous year's Software Engineering textbook aloft, and loudly proclaiming that it was less than worthless, and that we shouldn't pollute our minds with it. This caused the academics in the audience (which probably included the previous year's lecturer) to gasp, faint and haemorrage. Much of the CompSci faculty attended the lectures - the sight of two rows of Professors, Assistant Professors, Lecturers, Assistant Lecturers, and Tutors nodding sagely at his every word, showing that they, at least, were in complete agreement with Pike, and in fact came to the same conclusions quite independently, is something that will haunt me for the rest of my days. The fact that Pike is perhaps one of the most opinionated men I've met in my life (regardig programming, at least), didn't make the Faculty's life any easier. At one point one of them questioned a Pike-ism with "But Dijkstra said...", and Pike shot him down with "Dijkstra was a brilliant man, but he never compiled a single line of code he wrote...". He had similar biting things to say about C++, the Sparc architecture, Apple computers, EMACS, X-Windows, Java, and others too numerous to mention...

    What I carried away from the course was a subtle shift in my conception of programming. Pike is vehemently opposed to all the layers of abstraction and obfuscation we impose on ourselves in software. He had many, many elegant solutions to everyday programming problems, including gems on header files, byte-order in network programs and user interfaces. He has a keen eye for what can and should be done away with, and his coding style and ethos is a pleasure to behold. If I didn't do the course, I'd probably buy the book...
  • In the case of iterators, though, you usually want to prefer prefix, since it's faster (it doesn't need to make a copy of the iterator, which you then just throw away).
  • Clearly the reasoning is that users should be able to use either with preference.

    DOH! That should read "...without preference."

    --JT
  • Scott Meyers counsels us (More Effective C++ Item 6) to prefer preincrement to postincrement...

    Not exactly. What Scott counsels us about postfix and prefix operators is to know the difference, especially that they return different values (including const vs non-const). The only sense in which he counsels a preference is when he says that the postfix operator should be defined in terms of the prefix operator, because these operators are supposed to be exactly the same except for their return values. A fine example of the rock-solid common sense underlying his terrific C++ books.

    Besides, he was talking about the writing of operators, as would be required if creating an Abstract Data Type. Nowhere did he say that in using these operators should you prefer one to the other. Quite the opposite, in fact: his advice that postfix should be defined in terms of prefix would ensure that users of the ADTs could use either safely. Clearly the reasoning is that users should be able to use either with preference.

    --JT
  • BTW, I believe that 'Code Complete' is not just published by M$, but that its author is a M$ employee.

    I don't have my copy handy, but I believe that it's published by Microsoft Press.

    My problem with Code Complete was not with its being a Microsoft product, but that it completely ignored Object-Oriented programming issues. On the other hand, having seen some of the MFC C++ source code, it's probably just as well.

    --JT
  • ...on Herb Schildt. I don't find your comments on him inflammatory at all. His books make great doorstops and table levelers, but nothing more.

    There are also entire publishing lines not worth ther weight in scrap cellulose... if Sams went out of business tomorrow, I think I'd dance in the street. I've had to deal with too many newbie coders who I've had to help, only to discover they had a Sams book that represented the center of their programming universe.
  • Just ask yourself that question... would you go to work everyday on the 80th floor of an 'evolved skyscraper'?

    Any given sizable base of code is as complex if not moreso. I'll believe that 'evolving' code is a good idea when I see an evolved system perform as well or better than a system written by good designers and programmers.
  • ...that you can't just make a comment on my opinion rather than trolling through the gutter of personal attacks. Why not tell me about what makes 'Code Complete' so special?

    And 'it doesn't matter that it's published by M$'?? Using that logic, I shouldn't look askance at a book called 'Love and Compassion for Your Fellow Man' if I noticed it was written by Adolf Hitler.

    BTW, I believe that 'Code Complete' is not just published by M$, but that its author is a M$ employee. Therefore, since I haven't knowingly used any of his code, the only measuring stick I have is the M$ code I've seen (uniformly bad to mediocre) or the middling M$ apps I've used. Which is NOT a good basis for a 'coding best practices' rep...

  • I had a book of his when I was learning C, but I threw it away because so few of the examples would compile. The book was specifically written for the compiler I had, but that shouldn't matter much anyway with most code. I mean, you know, ANSI and all that. I'm reminded of O. S. Card's comments about his generally horrifying experiences editing programming books.

    OTOH, I know some sensible people who've liked other Schildt books a lot.


    -j

  • for some reason those have slacked off recently.

    Maybe they all realized it's a dumb thing to argue about.


    -j

  • One of the common initial implementation goals of new general purpose programming languages is to bootstrap the language in itself.

    Not if it's interpreted. You sure could write a java compiler in java (in fact it's probably been done) but I don't think you'd want a JVM written in java. I mean, it's turtles all the way down, you know?

    Your point is valid, though, as a general observation. It's a good acid test of a language. If you can't write its compiler in it (or if the developers just don't *want* to :), then it's probably not as good for writing compilers as C is. Then again, not every language needs to be good for that. On the third hand, if a language is called "better than C", then it's being compared to C, right? So, you get either A or B:

    A) It's comparable in intent to C. In that case, the comparison is fair, and it damn well better be good for writing compilers. Ada is probably an example if this, right? I tend to think that Pascal is also, but I really don't have any feel for what the original intent of Pascal was. The dialects I've used (all Borland) smelled a lot like C, but with clunky keywords and assignments inexplicably refusing to return values the way any red-blooded expression ought to. Then again, maybe it grew that way in an attempt to compete with C. Um, I guess nobody actually cares one way or the other :)

    B) It's not at all comparable in intent to C. In that case, it's probably excused from the compiler implementation requirement, but it's also meaningless to say it's "better" than C. Perl is an example of this second category. Saying Perl is "better" or "worse" than C is like saying cats are "better" or "worse" than dogs -- not only is it meaningless, but nobody with half a brain gives a rat's ass either way. I mean, what are you going to do about it? Pass laws? Run for congress on the C platform?


    -j

  • obviously you are special, and only other people have problems.

    Erm . . . I really sounded like a jackass there, didn't I? Sorry. I do think that not enough people are willing to bear in mind that a pointer is a sharp pointy thing that you shouldn't carry when you're running. C is a language that will merrily bite you if you don't keep a close eye on it. (Actually, that was exactly the point that I was replying to, wasn't it?) IMHO people who get hurt with it are probably not looking at it the right way. A different language isn't just a different syntax; it's a different mentality. At any rate, running off the end of an array in basic or whatever is a bug, too.

    Obviously, as you point out, people a lot smarter and more experienced than I make these mistakes. It may be that I'm in denial, or merely that I was drunk when I wrote that post :)


    See the Fuzz Revisited paper. The most common programming errors in the standard unix utilities which they tested were pointer errors and array access errors.

    I didn't read that, but I remember reading about it, and IIRC GNU utilities came out looking a lot better than most. This was gratifying, because GNU has these coding guidelines somewhere, which (among other things, like their barbaric indenting style :) encourage a really paranoid mentality about pointers: Never allocate without checking the pointer you get, never use a buffer of fixed size unless you can guarantee the size of what goes in it, etc. ad infinitum. I mean, I'll willingly grant that I'm probably not up to their standards, but it appears that people who are, can write very solid code in C.


    The more I think about it, the more I think I'm just defending C because I like it so much on an emotional level. So, as in all things, YMMV and use what works best for what you use it for.


    -j

  • You mean you know of a skyscraper that was completely evolved from scratch? One where wild animals were let loose on a set of raw materials at close to their lowest form, and through almost completely random action, along with natural selection and survival of the fittest, produced a completed building?

    Just one? Hell, right across the river in Boston there's a slew of 'em :)


    If you have, I suggest you alert the media.

    I think they know already.


    -j

  • You would get far fewer errors, I think, with an AreStringsEqual or even a strequ function, rather than using strcmp when all you care about is equivalence.

    If that's what yer into, IMHO use C++, which is a cool language for a whole lot of reasons, not just that kinda stuff.

    I don't agree with the "far fewer errors" thing, though I certainly never do !strcmp( ). The problem with that isn't that people forget what strcmp( ) does, but rather that it's easy not to notice the !. I think anybody who's been writing C code for more than a month has come to terms with what strcmp( ) does. Some people always put whitespace around ! (except in !=, obviously), and I respect that a lot. In this particular case, though, strcmp( ) == 0 is far harder to miss, and IMHO it expresses the intent better. Since strcmp() does not return a boolean value, IMHO there's no good reason to use a "boolean value" idiom to deal with it. Once you get past the boolean thing, the whole issue melts into air.

    Of course, that's just strcmp( ), which we all know and love from infancy onward. Some random function foo( ) that my pothead coworker dreams up is another matter. Still, I have, after all, seen things like that before, and there should certainly be an explanatory comment in the header file.

    You can certainly define a macro

    #define streq(a,b) (strcmp((a),(b))==0)

    . . . but IMHO that kind of syntactic sugar misses the point of c. Next thing you know, you'll be defining even worse things . . .

    #define begin {
    #define end }
    #define then /* pfft! */

    . . . or, worst of all . . .

    #define LPSTR char *

    aaaarrrrgggghhhh! :)


    -j

  • Seriously, don't knock evolution. Given ten million years of hard knocks, "all bugs are shallow".


    -j

  • On the positive side:
    It is more productive than writing in assembler.
    It is relatively easy to write a compiler for.
    It is nearly universal.


    You forgot one: From the user's standpoint, it's an enormously elegant, graceful, pleasant, powerful language. People like it. It's clear and simple, minimal and (for the most part) sufficient. It's a beautiful piece of software.


    It is not typesafe.

    You mean casts? Hmmm. Yeah, I'll go along with you there. They're good to have, but they're unsafe.


    It doesn't check array access.
    It doesn't have automatic memory management.


    True -- you get to do those jobs :) But when you need the cycles, you can blow 'em off. This can be (and frequently is) seen as a feature.


    It has pointers, a source of constant errors.

    I've never understood why people say that. You just have to know what you're doing, which is a requirement anyway. Anybody who gets "constant errors" with pointers, would probably get constant errors with references or psychic data levelling or anything else.


    It doesn't support functional programming.

    Well, that's probably true, but since I have NFI what functional programming is, I haven't often felt the absence as a loss :)


    It doesn't support object-oriented programming.

    True. There are people who say that you can do OOP in C, but IMHHHO they don't grok OOP. For one example, much of what is implied by inheritance just doesn't translate into C in any way that I can imagine. I don't see a need for OOP in C, though, because we already have OOP in C, a.k.a. C++, which out of the two is my preferred language most days. For some (relatively trivial) uses, I really think C++ is overkill, and for others it's not efficient enough (kernels etc.) -- but day in and day out it's a really damn nice language to program computers with. I like the fact that C has thrived (thriven?) separately from C++. It's cool to have both.


    -j
  • I don't mean to rain on SEGV's parade or dismiss his talents as a reviewer, but:
    1. Having not read K&R and the UPE, is a major drawback for any reviewer of the newest book: those are classics that are definitely mandatory for any (wannabe) UN*X hacker.
    2. To compare a book by the Elders(TM) to books published by Micros~1 Press is sacrilege! And to boot, "Writing Solid Code" is crap distilled. Its tips are either common sense or useless garbage (e.g. Hungarian notation) and it's pretty obvious they don't practice what they preach. Yes, I *have* read it.

    This is not meant to be a flame, BTW.
  • Then again, you're assuming that it takes the average human lifespan to do a test of the program. That would be a useless program anyway.

    Instead, consider that an "evolved" program can go through many generations very quickly...it doesn't necessarily need 5 million years or anything silly like that.

    -Doviende

  • I'll take that with a salt block, thank you.

    Code Complete is an excellent book. While it didn't have many great revelations for me (I had been programming professionally for years before reading it), I found it to be full of good wisdom. (Feel free to translate that as 'it agreed with what I had already decided was good programming practice.') It contains lots of good advice on the craft of programming that is not taught in college, and I've handed it to recent grads at work whose code I'm going to have to maintain.

    Of course, you are probably right that Microsoft itself doesn't heed its own author's advice ... but that's no reason anyone should deprive themself of this useful reference.


  • >Everyone has an opinion on variable names, but once you've made

    >up your mind, do you really care how someone else deals with
    >them? Would any advice make you change?

    Actually, I've been exposed to just such advice not too long ago. (Well, maybe a year?)

    It came in two parts: an anecdote and then the Perl Style Guide. First, I was in a talk with my (now ex-; non-pointy-haired) boss about programming practices. He mentioned an obfuscated piece he'd done one time, using the same variable name on practically every level of execution (global, subroutine, plus various levels of what Perl calls blocks, though he was writing in C). The whole thing worked because he was insanely careful with scope declarations.

    It occurred to me then that I should be more careful about scope in my own stuff, though I still see no reason to take it to extremes. :)

    About a month after that, I happened to run into the Perl Style Guide, where it advises using variable_names instead of VariableNames, partly because you can then use case to determine the difference between CONSTANT_VARIABLES, Global_Variables and local_variables.

    That one really gave me food for thought, and I eventually decided to adopt it. (Which causes its own problems: not only did I have to learn some new variable-naming habits, but now that I've learned them, it starts to flip me out when I see my old code!)

    I'll agree that it's rare for someone to change hir mind on aesthetic issues like that, but it does happen.

  • Here's a little ditty I like to define in various places when I'm coding. It's short, sweet, and to the point, and fits well in the C idiom.

    #define strequ(x,y) (strcmp((x),(y)) == 0)

    --Corey
  • I particularly enjoyed their debugging anecdotes, especially their hubris in discussing their own bugs.

    That's a rather eccentric use of the word "hubris". I suspect the reviewer might have meant to use "humility." (Hint: they are opposites.)
  • >there is no such thing as a "perfect" programming language. Even when using the right
    >tool for the job. Imperfect C is. But its diamonds must far outweigh its stones.

    Complaints about C should be laid at dmr's door, not Kernighan or Pike. Or did he mean AWK, which I think is a Kernighan production?

    I'll definitely be checking out this book. Despite comments above, I learned C from K&R (King James ed) and think it the best programming language tutorial I've come across - as distinct from a 'how to program' book, which it isn't.

    While we're slagging off programming tutorials, can I put a bad word in for Deitel & Deitel? Only the on the basis of their Java book (which succeeded brilliantly in frightening a relation off programming for life), you understand. But a shocking squandering of previous environmental resources, firmly in the 'sold by weight' category of computer publications.

    A depth of though and the clarity that comes from a true mastery of the subject has been the hallmark of the Kernighan, Richie and Pike works I have read in the past. Yeah, after (mmph) years in before the keyboard I expect it won't all be a total surprise, but I will be taken heavily aback if they don't make me think about some things in a radically different way in future. And that's the mark of a really good book.
  • And no, I won't tell you what it is or who I am, but if you use a web browser you'll catch the hint.

    You wouldn't be referring to Netscape, would you? I seem to have heard a thing or two about crufty code in that piece of programming.

    Not a flame, just a good-natured jab
  • FWIW, the posting by Peter Seebach regarding Schildt's book was made on April 1. Also note that Peter Seebach is a well informed authority on C. He posts many informative messages to comp.lang.c and comp.lang.c.moderated. He is also listed in the credits of the C FAQ.

    Draw your own conclusions... :)
  • DOH!! it's not needed, but would be potentially faster if the
    strings are indeed not equal. Can't even read my own code most of the time....
  • but strcmp() does not mean strequ(). strequ() needs to be..

    #define strequ(x,y) ((strlen(x) == strlen(y)) && (strcmp(x,y) == 0))
  • Where'd you hear that? The fastest type would be whatever type matches the register size of your computer, which is usually int.

    Boolean is good because its only 1 bit of information so with a 32 bit int you can store 32 bits of information, as far as speed, if you are polling this information at one point in a program it would certainly be faster than retrieving 32 seperate integers.


    A couple problems with this comment. First, short int require virtually an identical amount of time as 'int'. Also, it will insure that it is using the smallest word size for the computer.

    Now, about using boolean to save space... You OBVIOUSLY don't know what you're talking about. When the computer allocates a variable, it has to use at /least/ the smallest word size, which I believe is 1 byte. Which is what a short int is. So, when it allocates a boolean type variable, it allocates 8 bits, but only uses 1 bit for actually storing the information, so it saves /no/ space, and is less likely to be compatible in different compilers.
    --
    Matthew Walker
    My DNA is Y2K compliant
  • I haven't actually used this book, but it sounds like a good thing. I know that despite the fact that I am fairly set in my ways on a lot of things, I still like to see how other people do their programming, so that I can possibly improve my programming style. I'll definately look into getting a copy of this book, so that I can give it a good look.

    As far as short identifiers go, I hate them as well. I like the name to give me a clear idea of what it was intended to do. And it should (preferably) be easy to remember. I can't tell you how many times I've had to go look up those 6 letter function names, so that I could remember which was which.

    Someone mentioned something about Boolean in one of their comments. I find that I rarely use a type boolean... If I need one, I usually just declare a short int instead, and use it. It's just as fast, uses the same amount of memory, unless I'm confused about the way allocation works, and doesn't require that your compiler know type 'bool'.
    --
    Matthew Walker
    My DNA is Y2K compliant
  • Again, in case anyone is interested, there are two excellent critiques of Schildt here. First seebs':

    http://www.plethora.net/~seebs/c/c_tcr.html

    and (on Schildt's Annotated ANSI C Standard - even worse):

    http://www.lysator.liu.se/c/schildt.html

    I.
  • This book uses C and Java and AWK to illustrate many good ideas about programming.
    It is NOT a book about C or Java or AWK.
    It is about showing how two very experienced programmers think about how they work.

    The themes of the book are: Simplicity, Clarity, Generality, Evolution, Interfaces, Automation, and Notation.
    You're ready to dismiss some very important thinking about how to write programs that work (and keep on working) because of some religious idea about notations.

    If functional programming is so much better than standard languages (which it is, in many ways), then it is all the more impressive to be able to show how to use abstraction and mental flexibility with the less-helpful languages K & P have chosen. I'm sure they would agree with you that FP and scheme are very powerful tools. They also have enough experience to know that there is no one language that is good for all uses. The last chapter is devoted to the implications of that fact, with sections like "Programmable Tools", and "Programs that Write Programs".

    If you don't read this book, you won't learn anything. Your loss.
    Anyone that takes the time to read it and think about what it says, will learn.

    --
  • Time in evolution is not measured in years, but in generations. An evolutionary software process can go through millions of generations in a day, compared to humans, which take roughly 20 years for each generation.
  • by bluGill ( 862 )

    Linkers are only required to maintain 6 charicters for external references. Just because nearly all modern linkers maintain more does not mean they all do, nor that your code will not be called to run on an old hp (which is the only machine I'm aware of that accually only maintained 6 charicters) I'm always careful that my external references are 6 charicters. Note that this does not mean they are six charicters long, only that the first six charicters are always significant enough.

    Maybe this should be in the jargon artical that follows this one...

  • He unleashed on the world a language with a great number of design flaws.

    Any programming language that wasn't designed by God will have flaws; it's inevitable. Besides, most of the languages that are usually considered "better" than C (Scheme, Java, etc.) use run-time interpreters that are usually implemented in C.

    TedC

  • I tend to think that Pascal is also, but I really don't have any feel for what the original intent of Pascal was.

    The original intent of Pascal was to teach programming to undergraduate CSci students.

    Borland tweaked it quite a bit and turned it into a pretty good C-like systems language.

    It's regretable that no one is working that much on new systems languages these days. Most of the interest seems to be with higher level application programming and scripting languages. I think part of the problem is that C is "good enough" -- there isn't any one thing that could be done to make it a really great language, but there are 30 or 40 minor tweaks that that would make it really good (and incompatible with existing code, unfortunately).

    TedC

  • One of the common initial implementation goals of new general purpose programming languages is to bootstrap the language in itself.

    "Pipe dreams" might be a better phrase than "goals".

    TedC

  • How do you define 'systems languages'?

    A language that can be used to write an operating system or language compiler without dropping down to assembly language too much. A certain amount of asm is probably unavoidable for performance reasons, although good optimizing compilers are getting harder to beat unless you're really an expert asm programmer.

    I'll have to look into the five alternatives that you mentioned. I've heard of Eiffel and Dylan, but I thought they were higher level OO languages intended more for application programming that systems programming.

    TedC

  • Everyone has an opinion on variable names, but once you've made up your mind, do you really care how someone else deals with them?

    I do, because I'm resisting the temptation to make up my mind about anything when it comes to programming. I figure that day I do that is the day I start impeding my own progress. Besides, there's nothing worse than working with a progammer who has made up their mind, and I don't want to be hard to work with. :-)

    TedC

  • I would assume they don't use boolean because it is not part of C which is where they are coming from. The worst thing you can do in C is declare a boolean type, or possibly worse:
    #define TRUE 1

    Ugh, that is such a bad idea. When I write C++ I prefer to see:
    if (strcmp(x,y) == 0) ...

    But when I write C, I prefer:
    if (!strcmp(x,y)) ...

    Different idioms for different languages. (Of course, in C++ I would use a string class, but that was tangential to my point.)
  • I'm not saying it is illegal in C++. I knew I should have found a better example. C++ can obfuscate your code in too many ways to add more of them.
  • That may be the most readable code, but it's also wrong.

    strcmp returns a value greater, equal to, or less than zero. It does not return 1, 0, and -1. That means you shouldn't compare the return of strcmp with your STRCMPGREATER or STRCMPLESS.

    This allows strcmp to be implemented in a very simple and efficient way.
  • I have always enjoyed Kernighans style (and Ritchies to obviously) I have the elements of programming style on my desktop, and reckon its really useful even if I have to translate the points made from PL/1 and fortran (I can't remember which they use) to C(++) and Perl.

    I have to point out that using an int as a Flag or True/False allows you to do 2 extra things -

    1 it can be used as a simple semaphore which is always handy and still preserves the true/false testing by having a 0 or not 0 state

    2 it can be used as True/False/ErrorCode(n)/ErrorCode(n+1)
    and again preserve the testing by having a 1 or not 1 state

    The flag could also be used to return an int value as a result and maintain state in the same way as a semaphore.

    Using a true/false bool type limits it really badly.

    Aaron
  • I had NO idea I was addressing a bodhisattva of coding wisdom... perhaps I should ditch my job, give away my belongs and follow you barefoot for the next decade...

    On the other hand, your attitude indicates that while you may (again, MAY) be 'enlightened', maybe you're such a pain in the a$$ to work with that you have little opportunity to share your knowledge with others.

    Before knocking the 'world' others live in, why not check out your own? Yours seems to be full of road signs that indicate that only *you* know the right way... or better still, join the real world that the rest of us poor stiffs have to live in... you might find it refreshing.
  • I haven't read 'Code Complete' before, so take this with a grain of salt. If I were going to buy a 'coding best practices' book it would be most likely this one, simply because Kernighan and Pike are the authors. These are two guys who have been writing solid (and in many cases, revolutionary) code for DECADES now.

    On the other hand, I never heard of the guy who wrote 'Code Complete' before the book came out. And (warning: anti-Mickeysludge diatribe follows) from the several unpleasant times I've actually seen M$ code before there may not be a SINGLE PRODUCT from M$ written with any of the techniques 'Code Complete' advocates.
  • *Programmer to Customer* 'Yep, Mr. Smith, using our nifty new evolutionary software engineering process, we can produce a program that works FABULOUSLY... and we can deliver it in a mere 1.5 million years...'

    If you're going ot be dealing with normal, human timeframes, evolutionary programming is unlikely to deliver the goods. This is the reason why bridges and buildings are designed and built by people, rather than letting a few packs of chimps loose in a forest full of hardwoods and saying 'we'll be back for our structure in a few eons...'.
  • You mean you know of a skyscraper that was completely evolved from scratch? One where wild animals were let loose on a set of raw materials at close to their lowest form, and through almost completely random action, along with natural selection and survival of the fittest, produced a completed building?

    If you have, I suggest you alert the media. Otherwise, I think what you mean is that the designers and builders tweaked things as it went along. that's completely different from what people mean by 'evolutionary' programming.
  • "The programming languages they use in the book are the standard ones..."

    Choose a language because it efficiently maps onto the problem set. C has proven that it maps well onto a wide range of problem sets.

    Soustrup designed C++ because the language he was using didn't map well. That's a good reason to switch languages.

    You should never pick a language because it is "new" or even because it is "interesting", but because it does a good job with the problem at hand.

  • I imagine that was a very illuminating and entertaining course. I've only seen Pike in person a couple of times at a Usenix sometime in the previous decade. Among other things, he delivered a paper wearing harem pants (him, not the paper).
  • This doesn't fix the problem, it just confuses the notation even more. TRUE equals !0 (which equals 1), which is still a single value.

    If you try something like: if (a == TRUE)

    it maps to: if (a == !0)

    which means if (a == 1) NOT if (a != 0)

    so non-1 values of a will still fail this test.

    Bottom Line: Don't test against TRUE/FALSE no matter how they are defined

  • by Mr Z ( 6791 ) on Thursday April 08, 1999 @11:15AM (#1943248) Homepage Journal

    From reading the other comments here, it seems that several readers agree that this book isn't truly necessary if you've already "been around the block", so to speak. That may be true.

    However, I am still seriously considering getting this book so that when people ask me "what's a good book on programming", I can reach over to my shelf and grab a good book before they accidentally pick up the latest boat-anchor by some dubious author such as Herbert Schildt* or the like. All too often, people buy books based on size or weight, and not on the solidity of the content. (Even K&R2's latest reprinting is twice as thick as the one I bought, but with the same number of pages.)

    If you're a good, professional coder in any reasonable organization, you will eventually be asked to mentor, tutor, or otherwise assist less-experienced programmers. Make sure you can make the best of the opportunity by having appropriate resources ready.

    (*Note: I realize that my comments regarding Schildt might be slightly inflammatory to some, but they're not without some forethought. See the comp.lang.c FAQ for more information. And no, I don't let the FAQs think for me -- I've actually seen Schildt's work and found it atrocious. I reference the FAQ since it points out most of the same things I would and more.)

    --Joe

    --
  • by Cassius ( 9481 ) on Thursday April 08, 1999 @10:09AM (#1943249)
    I found this book to be useful, but if you're a halfway experienced programmer, I think you will have dealt with all of these issues and settled on solutions that you are satisfied with.

    Everyone has an opinion on variable names, but once you've made up your mind, do you really care how someone else deals with them? Would any advice make you change? This is the sort of thing I am talking about.

    This is a good book for someone to look at after completing a few undergrad courses (when they only know enough to be dangerous, and could use the "realignment").

    For more experienced programmers, I don't see too much of use.
  • by Cassius ( 9481 ) on Thursday April 08, 1999 @12:20PM (#1943250)
    Just when I'm having fun reading constructive discussion in here, I come across crap like

    I would suggest you stop pretending to be an "experienced" programmer and go back and read the book.

    Oh Chad, you don't know how many times (a day, perhaps) you benefit from my programming. How droll. And no, I won't tell you what it is or who I am, but if you use a web browser you'll catch the hint.

"Life sucks, but death doesn't put out at all...." -- Thomas J. Kopp

Working...