Kuro5hin.org: technology and culture, from the trenches
create account | help/FAQ | contact | links | search | IRC | site news
[ Everything | Diaries | Technology | Science | Culture | Politics | Media | News | Internet | Op-Ed | Fiction | Meta | MLP ]
We need your support: buy an ad | premium membership

[P]
Review: Writing Solid Code

By Inoshiro in Technology
Tue Jun 05, 2001 at 11:08:15 PM EST
Tags: Books (all tags)
Books

Writing code is not hard. Writing good code, code which works well, is hard. But why? Bugs don't exist because malicious gnomes came along and insert them into the code; bugs come from the programmers. So why can't programmers write better code? The simple answer is because they have not read and understood this book (although it's more likely a lack of experience and/or an accident).


What This Book Means to Me

I'd seen this book originally on mozillazine.org as a JWZ reccomendation. Having read design docs by him before, I was inclined to trust his praise of the book. And what a read it was! If you're like me, or hurstdog, you'll breeze through the book in no time. Easy to follow examples and end of chapter exercises, combined with MS development anecdotes, make for an engaging read.

Outline of the Book

Table of Contents

1 A Hypothetical Compiler

How to use compiler warnings to avoid embryonic bugs (warnings about using uninitialized variable use). This chapter also examines what the software won't do in terms of bug catching (like = instead of == with the lvalue being a variable).

2 Assert Yourself

Proper useage of assertations and error conditions. If you've never taken an advanced class on programming (most DIY OpenSource people), you're probably misusing assertation calls. This chapter also outlines extra sanity checks you can add to the debug version to spot algorithm issues before they become data shredders.

3 Fortify Your Subsystems

More aggressive than assertations alone, strict checking of your functions' arguments can help stop other programmers from misusing your functions to get results. The example code in this chapter includes a memory allocation subsystem.

4 Step Through Your Code

By quickly examining the data flow through any new code or algorihtms, you can spot bugs as you introduce them. It also mentions how stepping through code doesn't take very long, especially compared to hours finding hard to reproduce bugs.

5 Candy-Machine Interfaces

How to remove the bugs (rather than treat the symptoms of them) by having a properly designed API. The real-world results are best illustrated by the OpenBSD project's API of strlcpy and strlcat, which are consistent and easy to use (hard to misuse).

6 Risky Business

Where and when to trade risky, crash prone algorithms for safer, more reliable ones. How best to avoid language idioms in the quest for more performance.

7 Treacheries of the Trade

A deeper look at dangerous habits programmers have, and how to address them.

8 The Rest is Attitude

The most important chapter of the book -- the one addressing the atitude at programmers. Things to think about, goal wise, while writing code which will reduce your bug count.

Why This Book Is Important

When I go to write something for Gnome, and I'm forced to grep through megabytes of source to get examples of how to use an API, I know that the people who wrote that API could use this book. The lack of proper programmer documentation, subsystem checks, and easy to misuse APIs of many big name projects (such as the Linux Kernel, Gnome, and others), would be fewer in number if this book was more widely read. It would reduce the release of code which is not fit for others to work on.

I once spent a week tracking down obscure memory leaks in a program I wrote which displays RSS news in the Gnome panel. I used memprof, a great debugging tool which let me track where memory was being allocated and not freed from. Every single one of the 3 leaks I found was because I had misused an API. Other bugs I've had to deal with were because of a lack of documentation (gdxpixbuf dereferencing is not explained well, for example). When the docs fail me, I go read code wich has the API used in it. But these examples are also often flawed. Then there are programs which have large problems (like the Gnome Tasklist applet, which leaks ~250kb memory each time I switch virtual desktops) that should have been dealt with long ago.

After reading this book, and thinking about the discussions on the Linux Kernel mailing list, I understood why a lot of professional programmers sneer at the kernel. I'm surprised it works as well as it does (or maybe I'm not, considering 2.4.5 is still not ready for production use, despite 4 months of useage/hacking). I see a lot of OpenSource which can benefit from the information this book teaches. Just ignore the bits about Hungarian notation :)

You'll probably just want to borrow this from a friend if you don't program in C, since most of the specific examples and same of the advice does not apply to higher languages (like Perl or Python)

How To Get This Book

I found my copy at the MIT co-op bookstore. It seems pretty hard to find in "traditional" book stores which only stock "For complete computer illiterate retards" ™ books, but it can be had easily online thanks to Fatbrain. Their price for the book is for 19.96$.

Title: Writing Solid Code: Microsoft's Techniques for Developing Bug-Free C Programs
Author: Steve Maguire
Publisher: Microsoft Press
ISBN: 1-55615-551-4
Price: $24.95 USD || $32.95 CDN
Pages: 288
Date: May, 1993

Sponsors

Voxel dot net
o Managed Hosting
o VoxCAST Content Delivery
o Raw Infrastructure

Login

Related Links
o mozillazin e.org
o design docs
o memprof
o Linux Kernel mailing list
o Perl
o Python
o price for the book
o Also by Inoshiro


Display: Sort:
Review: Writing Solid Code | 129 comments (123 topical, 6 editorial, 0 hidden)
Great Book! (3.00 / 5) (#1)
by ucblockhead on Tue Jun 05, 2001 at 07:56:42 PM EST

That's one of the best books on my "how to be a good programmer" shelf. Damn good book. Not enough people know the stuff it has to say.
-----------------------
This is k5. We're all tools - duxup
Recomendation seconded (none / 0) (#42)
by codemonkey_uk on Wed Jun 06, 2001 at 04:14:41 AM EST

The book is a little bit out of date, but its still valid. It focuses on C but much is applicable to C++ and other languages as well.
---
Thad
"The most savage controversies are those about matters as to which there is no good evidence either way." - Bertrand Russell
[ Parent ]
This book's credibility is greatly damaged... (2.60 / 15) (#2)
by marlowe on Tue Jun 05, 2001 at 08:02:33 PM EST

by the fact that it comes from Microsoft. If they know so much about writing solid code, why is their code such utter crap?

And incidentally, I worked with Microsoft APIs for many years before getting fed up. Their documentation was at least as full of errors and omissions as anything else. And then there's the implementation behind the APIs. And without recourse to source code, there was no good way to figure it our yourself, let alone fix it.

And Windows CE 2.0 became infamous for leaking memory like a sieve.

Microsoft loves to get up on the grandstand and preach, but their actual practise is something else.

-- The Americans are the Jews of the 21st century. Only we won't go as quietly to the gas chambers. --
I'm still handing out l33t hax0r stickers.... (3.62 / 8) (#3)
by regeya on Tue Jun 05, 2001 at 08:13:47 PM EST

...'cause people keep coming up with real zingers.

This book is published by Microsoft Press. Microsoft's a big frickin' company. Calm down. I have a nice intro-to-UNIX book on my bookshelf from years ago, published by Microsoft Press. Yeah, they were already planning their efforts to run INX into the ground then, but hell, they diversified.

Please, Microsoft loves to get up and preach? Until Microsoft is a single person, please don't make statements like that. They just make you look like a moron, and we don't want that; really, we don't.

[ yokelpunk | kuro5hin diary ]
[ Parent ]

whoops, typo (3.33 / 3) (#4)
by regeya on Tue Jun 05, 2001 at 08:15:02 PM EST

s/INX/UNIX/

[ yokelpunk | kuro5hin diary ]
[ Parent ]

I think you're underestimating (4.00 / 4) (#14)
by slaytanic killer on Tue Jun 05, 2001 at 09:29:23 PM EST

If Writing Solid Code is the book I recall reading from MS Press, it talked about lessons Microsoft learned, including Simonyi's little experiments (the successful ones, of course). This is defintely a Microsoft book, and might be considered representative of MS' "best coding practices" at one point in their evolution.

Microsoft is the McDonald's of software. That might be a good thing, but one must always accept the fact that you'll eventually get a pretty fucked-up hamburger because it's all about pumping them out for money.

[ Parent ]
Your credibility is greatly damaged... (3.14 / 14) (#5)
by Inoshiro on Tue Jun 05, 2001 at 08:26:41 PM EST

by the fact you have not read the book. If you know so much about it, why would yau say it is bad?

And incidentally, I worked with Microsoft APIs for a few years before doing Linux full time. Their documentation existed, and detailed what each function did in a standardized manner. Although I didn't have access to the code behind the APIs, with MSDN I was able to get plenty of skeleton example code which I could use in my apps. Without worrying about fixing bad examples.

And Gnome became infamous for leaking memory like a sieve.

marlowe loves to get up on the grandstand and preach, but his actual experience with this book non-existant.



--
[ イノシロ ]
[ Parent ]
Yeah (4.14 / 7) (#6)
by trhurler on Tue Jun 05, 2001 at 08:52:51 PM EST

Well, the book might be golden; I don't know or pretend to know, and from what you said, it sounds like I already know most of what it contains anyway, if not all. However, he's dead on right about Microsoft; if you didn't run into API problems and other stupidities in their code all the time, then you weren't doing real work. Their stuff sucks. Among its mistakes are inconsistency(these are all subclasses of that, and that is what the other interface manipulates, but it can only handle that if it is one of some strict subset of the subclasses, handles that work differently from one place to the next, etc,) incompleteness(we support these interfaces for all these things, but not those things - WHY?!,) and so on. It is, by far, the worst API of any size I have ever seen released by "professionals."

--
'God dammit, your posts make me hard.' --LilDebbie

[ Parent ]
Points to consider. (4.50 / 2) (#11)
by Inoshiro on Tue Jun 05, 2001 at 09:10:01 PM EST

First off, I never said their API was good, I just said it was documented in a consistent way. That's better than forcing you to grep through source trees because the docs do not exist.

Second off, this book should be nothing new to you. It should serve to remind you of what programming for good, solid code is about. "If you're very good at what you do, you will make it to the end of this book thinking, "well of course, all of that was obvious." But then you will think, "wow, I really wish my coworkers had read this book, that would have made my life much easier." This book is about defensive programming -- it's about how to write your code for maintainability and debugability."



--
[ イノシロ ]
[ Parent ]
If it's nothing new, then it's redundant. (3.00 / 3) (#30)
by hjones on Tue Jun 05, 2001 at 11:52:15 PM EST

Therefore, if it should be nothing new, then it should be redundant. So which it? Is this a book we don't need, or a book we shouldn't need?
"Nietzsche is dead, but given the way of men, there may still be caves for thousands of years in which his shadow will be shown. And we -- we small-minded weaklings, we still have to vanquish his shadow too." - The Antinietzsche
[ Parent ]
But it is needed (4.50 / 2) (#34)
by andrewm on Wed Jun 06, 2001 at 12:39:37 AM EST

Therefore, if it should be nothing new, then it should be redundant. So which it? Is this a book we don't need, or a book we shouldn't need?

It shouldn't be anything new, but to far too many people it contains large amounts of new ideas, or old ideas that aren't actually used - resulting in time "saved" which is then used fixing problems. And even if you know everything in it, chances are you know someone who doesn't, and they need to know it.

ie: It's one we shouldn't need, but most people need at least some of it. :) And even if you know everything, you probably also know some people who you wish would write better code, and it needs to be available for them :)



[ Parent ]
No. (4.33 / 3) (#35)
by Inoshiro on Wed Jun 06, 2001 at 12:40:16 AM EST

It's a book you should read everyonce in a while. It's good to read and review the same way that mathematicians (physicists, etc) read and review all the time. If you don't practice and USE a skill, you will LOSE the skill.

If you think practice is redundant, then you are one of those people I don't want on my projects because I will end up spending more time cleaning up after you than getting work done.



--
[ イノシロ ]
[ Parent ]
You're changing the subject. (none / 0) (#59)
by marlowe on Wed Jun 06, 2001 at 12:00:47 PM EST

It's not about practise. It's about a source of information. Let's all stick to the subject, please. Thankew.

-- The Americans are the Jews of the 21st century. Only we won't go as quietly to the gas chambers. --
[ Parent ]
Hi! (4.00 / 1) (#76)
by Inoshiro on Wed Jun 06, 2001 at 05:39:19 PM EST

I'm a programmer. And I don't have a stick up my ass about the source of good information. Just because you have some jihad against everything MS doesn't mean I have to care. I read and enjoyed the book, and learned some good ideas from it.

Unlike you, I can learn from my enemy. I can apply what I learned to OpenSource. You are too busy debating with your own demons to understand this, though.



--
[ イノシロ ]
[ Parent ]
Not redundant at all (3.50 / 2) (#57)
by keyeto on Wed Jun 06, 2001 at 11:42:06 AM EST

This book, and books like it, will not be redundant until every programmer actually conforms to the good coding practices they describe. And note well that the practice is different from merely reading such a book.


--
"This is the Space Age, and we are Here To Go"
William S. Burroughs
[ Parent ]
Missing the point here. (3.00 / 2) (#62)
by marlowe on Wed Jun 06, 2001 at 12:17:13 PM EST

So long as we have books like it, we don't need this book.

-- The Americans are the Jews of the 21st century. Only we won't go as quietly to the gas chambers. --
[ Parent ]
I disagree (3.00 / 1) (#91)
by keyeto on Thu Jun 07, 2001 at 06:37:51 AM EST

As long as there is a need for such books, then there is a need for lots of different ones, including this one. Different readers respond differently to different writing styles. It takes a book that a particular reader likes in order for them to take on the good practices.

I should have made this clear in my original post, though.


--
"This is the Space Age, and we are Here To Go"
William S. Burroughs
[ Parent ]
About that redundancy. (4.00 / 3) (#61)
by marlowe on Wed Jun 06, 2001 at 12:16:15 PM EST

I think it would be much more to the point to talk about books which have this sort of information, but come from credible sources. Or at least sources to whom we can extend the benefit of the doubt.

Gang of four, anyone? How about Fred Brooks? P.J. Plauger? Come on, we have alternatives. Let's discuss them.

-- The Americans are the Jews of the 21st century. Only we won't go as quietly to the gas chambers. --
[ Parent ]
And while we're at it (none / 0) (#70)
by hotcurry on Wed Jun 06, 2001 at 01:43:31 PM EST

Let's talk about the importance of code and design reviews, and the consideration of alternatives. I think Eric Raymond has a lot of useful insights on that score.

[ Parent ]
On Eric Raymond (none / 0) (#87)
by stuartf on Wed Jun 06, 2001 at 11:55:08 PM EST

I think Eric Raymond is a perfect example of a good coder with ideas above his station. He is not a philosopher, and his Cathedral/Bazaar ideas are basically wrong. He's obviously a good project manager as well, but seems to be a little misguided about his own contribtion

Eric's argument is something like: The cathedral way of doing things is to have a master architect, with lots of other little weeds underneath him doing all the work. The bazaar way of doing things is for anyone to be able to do anything. He uses his own software (Fetchmail) as an example. However, reading through his example of Fetchmail, it's quite clear to me that Fetchmail has a master architect (ESR), making the final decisions about what goes into that cathedral. Every successful open source architect has a good master architect (or set of architects) at the top - Linux is the perfect example. While anyone is free to offer a suggestion, Linus has the final say.

[ Parent ]

Who else should read the book (4.80 / 5) (#12)
by Robin Lionheart on Tue Jun 05, 2001 at 09:11:08 PM EST

> Your credibility is greatly damaged by the fact you have not read the book.

"Microsoft's Techniques for Developing Bug-Free C Programs"? Maybe Microsoft should read the book, too.

[ Parent ]
Cute. (none / 0) (#111)
by Sax Maniac on Thu Jun 07, 2001 at 10:38:14 PM EST

Pithy saying, but I'll step up to defend them a bit. Those guys at MS do generally know how to program.

That being said, it doesn't always make business sense to write bug-free code. You heard me right. They're not selling air-trafiic control software. They're selling what amounts to inconsequential, if not popular, trinkets.

It may not be in their financial interest to fix all the bugs in a $100 piece of software. The amount gained in fixing them isn't necessarily worth the money spent fixing them. MS knows the average user's tolerance for bugs and knows right where the price point is. Don't be fooled.

I've used Quicken for years, and know what? There are bugs that have been in there for about 8 years now that they well know about, but don't bother fixing. Why, when I paid $25 dollars for it? Do you really think it's worth their while?

So, my bet is that the MS hackers know exactly where the bugs are and want to fix them, but the suits are saying "don't fix it- it's not worth it". Sad to say, that's a valid business decision.


Stop screwing around with printf and gdb and get a debugger that doesn't suck.
[ Parent ]

I should think the source matters most of all. (4.00 / 7) (#28)
by hjones on Tue Jun 05, 2001 at 11:39:59 PM EST

A stopped clock tells the right time twice a day. Is that to the clock's credit? The issue is not whether it happens to be correct on any given point. The issue is whether the fact that the bok says something is a meaningful signifier. If not, then the book serves no useful purpose. Marlowe has raised a valid point and you have dismissed it in a petty and irresponsible fashion. I've read Code Complete and it's full of good stuff that I also read in books from more credible sources, plus lots of obvious stuff that I'd already figured out for myself. Is this to that book's credit? Why do I need the book if evrything good in it can be had elsewhere, and with more certainty?
"Nietzsche is dead, but given the way of men, there may still be caves for thousands of years in which his shadow will be shown. And we -- we small-minded weaklings, we still have to vanquish his shadow too." - The Antinietzsche
[ Parent ]
Which book? (3.00 / 1) (#49)
by Macrobat on Wed Jun 06, 2001 at 09:07:30 AM EST

I've read Code Complete and it's full of good stuff

I agree, but we're talking about Writing Solid Code here, not Code Complete. (I thought we were talking about CC when I first read the story, too, until I got to the chapter outlines.)

"Hardly used" will not fetch a better price for your brain.
[ Parent ]

Missing my point. (none / 0) (#73)
by hjones on Wed Jun 06, 2001 at 04:30:05 PM EST

I was using Code Complete as an illustration of the principle.
"Nietzsche is dead, but given the way of men, there may still be caves for thousands of years in which his shadow will be shown. And we -- we small-minded weaklings, we still have to vanquish his shadow too." - The Antinietzsche
[ Parent ]
Gnome vs Windows CE (3.66 / 3) (#46)
by jmullman on Wed Jun 06, 2001 at 08:28:39 AM EST

And Gnome became famous for leaking memory like a sieve
Well, at least we can not use GNOME, and just switch to another Desktop Enviroment(that is, if you want to use one at all). Where as with the Windows CE situation... well, we all know where that sentence is going.

[ Parent ]
Not quite. (none / 0) (#77)
by Inoshiro on Wed Jun 06, 2001 at 05:40:56 PM EST

I like Gnome and use it as my desktop environment. I'm improving it using what I know so that I can not have to suffer through memory leaks and other random bugs :)



--
[ イノシロ ]
[ Parent ]
Oh, knock it off. (4.00 / 1) (#63)
by marlowe on Wed Jun 06, 2001 at 12:23:06 PM EST

I raised a valid point about the usefulness of an information source, and you respond with sarcasm and misdirection. Now I don't mind sarcasm per se, but the misdirection is shameful. And the sarcasm is tainted by being used in its service.

-- The Americans are the Jews of the 21st century. Only we won't go as quietly to the gas chambers. --
[ Parent ]
Tsk. (none / 0) (#78)
by Inoshiro on Wed Jun 06, 2001 at 05:46:52 PM EST

All I did was take your template Anti-MS troll anh turn it into an Anti-OpenSource troll as an example of how hollow your argument is. Because, as your sig says, -- For those who refuse to understand, no explanation will ever suffice.

I reviewedd a book, you started a jihad.



--
[ イノシロ ]
[ Parent ]
Nice spin, but the fact remains... (none / 0) (#80)
by marlowe on Wed Jun 06, 2001 at 07:18:42 PM EST

you haven't even addressed the point, let alone found a fault in it. All you've done to date is turn this into a personal attack on me. Where the hell does that come from? I didn't start this spitting contest. I might just start the next one, since it's gotten harder to give you the benefit of the doubt now, but I didn't start this one.

Would it kill you to address the point of the credibility of the source? Already, others have pointed out significant flaws in the book's code. Doesn't that embarrassing fact suggest you that maybe the source of information does matter?

Come on, quit personalizing this and address the issue. I promise it won't kill you.


-- The Americans are the Jews of the 21st century. Only we won't go as quietly to the gas chambers. --
[ Parent ]

Nice spin, but the fact remains... (none / 0) (#81)
by Inoshiro on Wed Jun 06, 2001 at 08:21:35 PM EST

Had this just been another book by RandomPress, you would not have gone jihad on me. Your only reason for posting seems to have been to defame the book. Read the book like the people you brokenly link to, then come and post about what you found bad with the book.

Or you could, as I have done, focus on the positive aspects of the book, learned from the general guidelines for good code which it has, etc. I don't see why the publisher makes the information bad. If Hitler wrote a great book an Quantum mechanics, would the information it presents be any less useful because he's Hitler?

No. You can learn from everything if you choose to.



--
[ イノシロ ]
[ Parent ]
If Hitler wrote a book on quantum mechanics... (none / 0) (#84)
by marlowe on Wed Jun 06, 2001 at 10:09:48 PM EST

it would be far from my first choice on the subject. Even if he went and did some careful research and got a lot of things right. Why not? Because there are other books on quantum mechanics, and they come from people who've actually got some credibility on the subject.

And yes, that is the point. Why dick around with someone who may or may not know, when you've got someone who you're reasonably sure does know? It's hardly an effective use of time.

And I'm not some kind of loon just because I have the gumption to actually point this out. There was no need for a discussion of this book and/or its background to turn into a discussion of you and me. But it seems I hit a nerve in you. How was I to know this was a hot button issue for you? And by the way, just why is it a hot button issue for you?

-- The Americans are the Jews of the 21st century. Only we won't go as quietly to the gas chambers. --
[ Parent ]
Discussion now over (none / 0) (#92)
by jonathan_ingram on Thu Jun 07, 2001 at 06:50:52 AM EST

Congratulations - you have now lost the argument. Godwin's law invoked. Next time try to find more interesting bogey men to compare Microsoft to.
-- Jon
[ Parent ]
Is Heisenberg more your style? (none / 0) (#104)
by slaytanic killer on Thu Jun 07, 2001 at 08:16:46 PM EST

Would you read a book by Heisenberg, the alleged "father" of quantum physics? I believe he was a Nazi, which makes the example ironic.

[ Parent ]
The sad thing (4.57 / 7) (#18)
by ucblockhead on Tue Jun 05, 2001 at 10:19:31 PM EST

The sad thing is that most of the code Microsoft has released to the public (Like ATL, MFC and many sample apps) looks like it was written by people utterly ignorant of this book.
-----------------------
This is k5. We're all tools - duxup
[ Parent ]
borland warnings (slightly off-topic) (3.00 / 4) (#7)
by Delirium on Tue Jun 05, 2001 at 08:54:05 PM EST

This chapter also examines what the software won't do in terms of bug catching (like = instead of == with the lvalue being a variable).

On somewhat of a tangent, Borland C/C++, at least the old versions, would give intelligent warnings on this. If you did something like if(blah = 5) it would warn you, since people rarely mean to write code like that, but if you do something like if((fp=fopen("blah","rb")) == NULL) it won't warn you.

Neat! (3.33 / 3) (#8)
by Inoshiro on Tue Jun 05, 2001 at 09:02:34 PM EST

Steve says that you should encourage your C compiler vendor to add warnings for all risky code idioms. like this one. I have yet to see it appear in an OpenSource compiler, though :-/



--
[ イノシロ ]
[ Parent ]
warnings (2.66 / 3) (#15)
by Delirium on Tue Jun 05, 2001 at 09:45:41 PM EST

Yeah, I like warnings. The more the better. =] Even better are warnings that, if you really did mean to do what they're warning about, you can override so they don't pop up anymore, like explicitly (casting) data types; that way there's a nice balance between missing errors that could've been caught and warning about so many nitpicky things that you just end up ignoring all the warnings.

[ Parent ]
Idn't it (4.00 / 3) (#16)
by meersan on Tue Jun 05, 2001 at 09:47:18 PM EST

I have yet to see it appear in an OpenSource compiler, though

What, gcc doesn't count?

if (prof = 2)
return (prof);

gcc -Wall prof.c
prof.c:16:warning: suggest parentheses around assignment used as truth value

I suppose most people don't bother using -Wall, though. Compiler warnings are your friends! :)



[ Parent ]
Heh. (3.00 / 2) (#26)
by Inoshiro on Tue Jun 05, 2001 at 11:21:22 PM EST

I do use -Wall, but I've yet to see an error like that because I read my code over (and over) a few times before I compile it :)



--
[ イノシロ ]
[ Parent ]
My warning switches... (none / 0) (#66)
by beergut on Wed Jun 06, 2001 at 01:07:23 PM EST

I generally tend to use these when compiling with gcc:

-W -Wall -ansi -pedantic

You'd be amazed at how easy it is to write clean code, though, if you put your mind to it.

The only problem I have with it, then, is doing stupid crap like:

int
fun (int a, int b, int c)
{
/* I only use a here, so shut up gcc */
b = b; c = c;

printf("%d\n", a);

return a;
}
This wouldn't be a problem, except in writing code which uses function pointers to handle various situations (an adjust_insert() routine for a binary tree library, for instance, which is called by a generic insert() routine, but which acts differently for different tree algorithms.)

In these situations, I document the reason I do what I do.

i don't see any nanorobots or jet engines or laser holography or orbiting death satellites.
i just see some orangutan throwing code-feces at a computer screen.

-- indubitable
[ Parent ]

Proper fix (none / 0) (#102)
by fluffy grue on Thu Jun 07, 2001 at 08:02:07 PM EST

Make b and c anonymous:

int fun(int a, int, int)
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

That's C++, not C (none / 0) (#110)
by Sax Maniac on Thu Jun 07, 2001 at 10:23:02 PM EST

Wrong, that's C++ and is not legal C. I wouldn't recommend doing that if you ever want to have some semblance of portability.

void foo(int)
{
}

% cc warn.c
cc: Error: warn.c, line 1: In the definition of the function foo, a parameter has no name. (unnameparm)
void foo(int)
---------^

Even gcc has the decency to bitch about it, even with no extra warnings turned on:

% gcc warn.c
warn.c: In function `foo':
warn.c:1: parameter name omitted

Stop screwing around with printf and gdb and get a debugger that doesn't suck.
[ Parent ]

Oh, whoops (none / 0) (#113)
by fluffy grue on Thu Jun 07, 2001 at 11:50:56 PM EST

I thought that anonymous parameters were valid C as well (since anonymous structs are). My bad.
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

Uh.. (none / 0) (#115)
by Inoshiro on Fri Jun 08, 2001 at 03:34:55 AM EST

Why would you pass args that are not used?



--
[ イノシロ ]
[ Parent ]
Off the Top of my Head... (none / 0) (#116)
by Matrix on Fri Jun 08, 2001 at 08:20:37 AM EST

Maybe a function that you're going to register (using function pointers) as a callback for a standard library of some sort (say, an X widget library) has a parameter or two that gets passed to it that you don't care about for what you do in that function, but which are still needed to avoid compiler errors?


Matrix
"...Pulling together is the aim of despotism and tyranny. Free men pull in all kinds of directions. It's the only way to make progress."
- Lord Vetinari, pg 312 of the Truth, a Discworld novel by Terry Pratchett
[ Parent ]

But if you're using function pointers.. (none / 0) (#118)
by Inoshiro on Fri Jun 08, 2001 at 05:27:20 PM EST

There is no way for the compiler to check it, since pointers don't lend themselves to prototype checking. So there's no reason to do the b = b; c = c; crap.



--
[ イノシロ ]
[ Parent ]
The reason... an illustration... (none / 0) (#125)
by beergut on Thu Jun 14, 2001 at 07:33:21 PM EST

The reason I use function pointers in some of the code I write is so that I can set up a typed vtable that will cause the compiler to shit bricks if I make a booboo.

/* forward declare */ struct bstree;
/* forward declare */ struct bstree_node;

struct vtable {

    void (*adjust_insert)(struct bstree*, struct bstree_node*, int);
};

void
_bstree_adjust_insert (/* struct bstree* bst, */ struct bstree_node* nod, int dir)
{
    /* use 'dir' to adjust the initial node */
    if (dir < 0)
    {
      ++nod->lindex;
    }

    for ( ; nod->parent; nod = nod->parent)
    {
      if (nod == nod->parent->lchild)
      {
        ++nod->parent->lindex;
      }

      /* there is no need to use 'bst', as there
       * are no changes to the tree's structure,
       * only adjustments to indexing tags on the
       * nodes from the insertion to the root.
       */
    }

    return;
}

void
_rbtree_adjust_insert (struct bstree* bst, struct bstree_node* nod, int dir) {
    /* use 'dir' to adjust the initial node */
    if (dir < 0)
    {
      ++nod->lindex;
    }

    for ( ; nod->parent; nod = nod->parent)
    {
      if (nod == nod->parent->lchild)
      {
        ++nod->parent->lindex;
      }

      /* Here, if a path imbalance is detected,
       * I may have to rotate subtrees to restore
       * balance. 'bst' may be dereferenced here
       * so that the root pointer may be changed.
       */
    }

    return;
}

struct vtable foo = {
    _bstree_adjust_insert
};

struct vtable bar = {
    _rbtree_adjust_insert
};

When compiled, an incompatible type error shows up for foo, but not for bar. (This, of course, is delta the compilation failure due to incomplete types because I am too lazy to define my bstree_node structs.)

Since I wish to use these types polymorphically, and I want the code to pass super-anal syntax checks (as much as gcc can give me, anyway ... TenDRA tends to have better lint capabilities), I accept a meaningless first arg in _bstree_adjust_insert (i.e., I uncomment struct bstree* bst,) but do not use it (but I do make a note, and set up what is essentially a NOP).

i don't see any nanorobots or jet engines or laser holography or orbiting death satellites.
i just see some orangutan throwing code-feces at a computer screen.

-- indubitable
[ Parent ]

Microsoft (3.33 / 3) (#19)
by ucblockhead on Tue Jun 05, 2001 at 10:31:44 PM EST

Unfortunately Microsoft's own headers generate so many warnings at warning level four that the feature is unusable.


-----------------------
This is k5. We're all tools - duxup
[ Parent ]

Useful warnings to switch on in MSVC6 (4.00 / 1) (#43)
by AndrewH on Wed Jun 06, 2001 at 06:09:23 AM EST

#pragma warning(3:4019 4057 4061 4121 4125 4128 4130 4132 4134 4152 4189 4206)
#pragma warning(3:4207 4208 4209 4210 4211 4212 4213 4220 4221 4222 4232 4234)
#pragma warning(3:4235 4236 4239 4268 4504 4505 4507 4515 4516 4611 4665 4670)
#pragma warning(3:4671 4672 4673 4674 4699 4705 4706 4709 4727)

John Wilkes Booth, Lee Harvey Oswald, John Hinckley Jr — where are you now that we need you?
[ Parent ]
My Solution (none / 0) (#119)
by tnt on Sat Jun 09, 2001 at 01:56:52 PM EST

My solution to this is to write stuff like:

     if (5 == blah)

So if I do accidently write something like:

     if (5 = blah)

I get an error.



--
     Charles Iliya Krempeaux, B.Sc.
__________________________________________________
  Kuro5hin user #279

[ Parent ]
That's mentioned in the book. (none / 0) (#121)
by Inoshiro on Sat Jun 09, 2001 at 04:53:10 PM EST

But as the books says, the proper solution would be for the compiler to warn when someone assigns a variable a new value within a logic test.



--
[ イノシロ ]
[ Parent ]
Spell Checking (none / 0) (#122)
by tnt on Sun Jun 10, 2001 at 01:35:15 AM EST

It would be nice if compilers did some simple spell checking too. Especially when the spelling error is that of letter case -- lower case or upper case.

I remember writing a Modula 3 program (a long time ago), and spelled one of the method names in one my class incorrectly. I had a lower case letter, where it should have been upper case. And I got some cryptic error message. It took me quite a while to figure out that I just misspelled it. Surely a compiler could easily check for that kind of spelling mistake. It would produce a much better error message. Maybe something suggesting that there is another method (that is spelled very similarly) that I might have meant to have used.

--
     Charles Iliya Krempeaux, B.Sc.
__________________________________________________
  Kuro5hin user #279

[ Parent ]

Not so easy. (none / 0) (#123)
by Inoshiro on Sun Jun 10, 2001 at 07:17:52 AM EST

Since K&R defines a rather loose interpretation of lymbol definition, and so many subpar programmers fail to properly prototype/check their code, this'd probably be too hard to spot consistently.

You could try, but it's easier to just not mix case and be careful.



--
[ イノシロ ]
[ Parent ]
Assertions (3.00 / 3) (#9)
by enterfornone on Tue Jun 05, 2001 at 09:05:18 PM EST

Assertions was the majority of my first year programming class (using eiffel). They are hardly advanced material. People don't use assertions because they get lazy and it's too easy to forget about them and hope for the best.

--
efn 26/m/syd
Will sponsor new accounts for porn.
Not in my experience. (3.50 / 2) (#13)
by Inoshiro on Tue Jun 05, 2001 at 09:15:31 PM EST

I hadn't heard a formal explanation of why to use an assertation (vs. if) before reading this book. To the majority of self-taught programmers, in they learned C from a book when they were teenaged, and never took a programming course higher than high school -- it is an advanced debugging idea.

My local university does not touch Eiffel until third year. Java and Javascript are all the rage in first year, and they are taught like my first basic course I took in grade 9.



--
[ イノシロ ]
[ Parent ]
First-Year CS (4.00 / 1) (#45)
by Matrix on Wed Jun 06, 2001 at 08:15:09 AM EST

My local university does not touch Eiffel until third year. Java and Javascript are all the rage in first year, and they are taught like my first basic course I took in grade 9.

I wish the university I'm attending had started with Eiffel or something in first year. They started with Java, and not only did they focus on the wrong things (Applets and flashy uses of trivial code instead of basics of coding well, good code style, basic data structures, and object oriented coding concepts) by they taught them the wrong way. "Use this collection of code when you want this effect" instead of "this code structure does, in general, things like this".

I'm not sure if that makes sense, but its the way I think of it. Focusing on teaching code snippits that do specific things instead of teaching something more generalized. From the things I've heard from friends, that's not limited to just this one school or the prof I had.

Maybe if CS departments started off on good coding practice, debugging techniques, and things like that earlier on, this wouldn't be as much of a problem? (And it is, even among CS graduates or near-graduates. I've seen enough mailing list posts by them to know that.)

(Went a bit off-topic there... But I can never resist that particular rant.)


Matrix
"...Pulling together is the aim of despotism and tyranny. Free men pull in all kinds of directions. It's the only way to make progress."
- Lord Vetinari, pg 312 of the Truth, a Discworld novel by Terry Pratchett
[ Parent ]

A very non-trivial teaching problem (none / 0) (#51)
by slaytanic killer on Wed Jun 06, 2001 at 09:58:43 AM EST

There seems to be the big Chicken-and-Egg problem -- should students code interesting colorful apps first, or do they start by learning good coding practice? Before a quick answer is given, consider that this is a much larger educational debate -- start children out with the technical parts of English first, or start them off by reading interesting things?

[ Parent ]
reading interesting things (4.00 / 1) (#65)
by Kellnerin on Wed Jun 06, 2001 at 12:41:15 PM EST

This is not so chicken-or-egg; nothing says you have to do one, then the other. You start children off by reading interesting (yet simple) things, before you get into the subjunctive mood, and the difference between a direct and indirect object. Expose them to language (not just in school, but in all of life) and they'll pick it up, and all will go swimmingly until they start saying things like "mouses" and then you'll have to explain irregular plurals to them, and eventually subject them to the torture of diagramming sentences. They'll forget everything about diagramming, of course, but the idea is to remember the part about nouns, verbs, adjectives and so on. Not that they stop reading at this point and start doing "grammar." They'll still read, and hopefully learn how to write well too.

By contrast, though, if you learned a foreign (human) language later in life, you probably got a mixture of reading/speaking (starting with "Hello, my name is X. How are you? What's your name?" and moving on) and grammar at the same time. You learned proper usage along with trivial examples of that aspect of the language in action building on the things you already knew, because you can't learn the rules in a vacuum. It's not very exciting learning a language when for the first year or so you can't even talk about what you did over the weekend because you don't know proper past tense yet, but it all falls into place. Only very few times was I told "just say this in that kind of situation, don't worry about why it's that way," and in those cases it was usually idiomatic.

Anyway, there is no good reason you shouldn't learn good coding practices up front, or at least mixed in with the more fun examples. Most people are not going to pick up which data structure to use when, or what a while{} loop is good for, by mere osmosis. My French teacher never let us use the past tense until we learned the various constructions, so why should you just mindlessly type in examples (you're learning to code, not how to use a keyboard) without understanding what you're doing? Why is it that no one would say they speak Spanish if all they can say is "My pencil is yellow" but they do know Java if they can make a "Hello World" applet that prints a message in 16 different colors?

--Stop it, evil hand, stop it!--
[ Parent ]

2nd year (none / 0) (#127)
by fatjim on Mon Jun 18, 2001 at 04:47:47 PM EST

Actually, It starts in 2nd year at that particular university ;)

[ Parent ]
Assertions misused (5.00 / 1) (#23)
by fluffy grue on Tue Jun 05, 2001 at 11:08:34 PM EST

The very few times I see assertions used in opensource projects, they're used in all the wrong ways. SoundTracker, for example, is a perfect example of this. The code performs assert() on sanity checks for external data - which means that if you try to, say, load a corrupted .wav file, the entire program exits with no potential way of saving!

This seems obvious, but assert() is only to be used for internal sanity checks. External sanity checks should be handled by error handlers.
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

actually (4.00 / 1) (#38)
by enterfornone on Wed Jun 06, 2001 at 01:43:39 AM EST

I was always taught that asserts should be used for all sanity checks and then error handlers should be used in addition - ie the assert is there to make sure the error handler is working properly.

--
efn 26/m/syd
Will sponsor new accounts for porn.
[ Parent ]
Sorta (4.00 / 1) (#39)
by fluffy grue on Wed Jun 06, 2001 at 03:08:17 AM EST

Asserts as sanity checks on the error handler make sense. Asserts as error handlers are what I was bemoaning. Imagine if Netscape did an assert() on the result of gethostbyname() rather than handling the error properly - it'd exit completely every time an unresolved hostname were used! That's the same sort of thing which is happening in SoundTracker - it's performing an assert() on arbitrary data such as .wav files, rather than simply checking to make sure the data's valid. assert is for checking internal consistency, not external data.
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

No. (4.00 / 1) (#41)
by Inoshiro on Wed Jun 06, 2001 at 04:09:12 AM EST

Assertations are there to validate assumptions. Like a LET statement in a math proof. For a function which is called in many places, it lets you assert that wha you are passing to it in each place is correct. That data is valid, and the function is not being misused. Asserts should only ever exist in the debug/developer version of a program. For general use, an if statement should handle the error conditions the program encounters.

So you see, assertations ensure proper structure and validate design for the developers, and error handlers ensure the end user does not lose data (which is VERY, VERY BAD).



--
[ イノシロ ]
[ Parent ]
On the other hand (none / 0) (#90)
by sigwinch on Thu Jun 07, 2001 at 01:37:59 AM EST

The code performs assert() on sanity checks for external data - which means that if you try to, say, load a corrupted .wav file, the entire program exits with no potential way of saving!
OTOH, it's a great technique when you're too lazy to write a proper error handler. Be thankful -- they could've just ignored it. Better to blow up now than to silently corrupt later.

--
I don't want the world, I just want your half.
[ Parent ]

Huh? (none / 0) (#96)
by fluffy grue on Thu Jun 07, 2001 at 12:28:43 PM EST

What's so hard about just returning NULL?
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

Re: Huh? (none / 0) (#97)
by sigwinch on Thu Jun 07, 2001 at 12:57:41 PM EST

With multiple possibly bogus inputs, returning NULL hides the cause of the problem; you can't find the cause without either using a debugger and binary with debugging symbols, or putting printf()s in the source and recompiling. If an assert blows up on line 1243 of brain_damage.c, you can untar the source, look at line 1234, and know what not to do. It's may not be proper input validation, but it's better than either segfaulting or having an opaque failure. Think of it as constructive laziness.

--
I don't want the world, I just want your half.
[ Parent ]

Um, no (none / 0) (#98)
by fluffy grue on Thu Jun 07, 2001 at 01:41:42 PM EST

I mean, if a function can't return valid data, then return NULL instead. That's how most error handling works. Then the application checks to see if the function returned NULL instead of a handle to data, and if so, says, "Hey, I couldn't [do whatever]. Sorry it didn't work out." If you want to get really fancy you can do proper exception or errno-style handlers, but simply returning NULL instead of raising an assertion is much, much better.
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

value parameters and returning "int"... (5.00 / 1) (#126)
by beergut on Thu Jun 14, 2001 at 08:12:15 PM EST

I tend to return int from most of my functions, as it makes error handling easy and reasonable.

int
get_some (struct some_struct** p)
{

    struct some_struct* tmp;

    tmp = (struct some_struct*) malloc(sizeof(struct some_struct));
    if (tmp == NULL)
    {
      return MY_ERROR_NOMEM;
    }

    *p = tmp;

    return 0;
}

Then, you get the benefit of having your cake and eating it, too. You get the memory, if it's available, or you don't get the memory, and an error code.

i don't see any nanorobots or jet engines or laser holography or orbiting death satellites.
i just see some orangutan throwing code-feces at a computer screen.

-- indubitable
[ Parent ]

Put another way... (5.00 / 1) (#99)
by slaytanic killer on Thu Jun 07, 2001 at 02:41:04 PM EST

Asserts are only there for "impossible" values. When a sound program loads a .wav file, it is perfectly possible for the file to be corrupted. Proper design holds that this case be taken care of through standard operation. But asserts are used for cases which SHOULD NEVER occur, except through some defect in implementation.

People tend to disable the asserts in code released to customers. That is because you want the user to at least have a chance to save while the program crumbles around her. If you leaned on asserts, you would have absolutely no errorhandling since it was stripped in released code.

[ Parent ]
fat chicks in party hats (3.92 / 13) (#10)
by shoeboy on Tue Jun 05, 2001 at 09:08:21 PM EST

Bugs don't exist because malicious gnomes came along and insert them into the code; bugs come from the programmers.

I dunno, I tend to classify bugs in the compiler as being evil gnome bugs. Sure they were introduced by the programmers who wrote the compiler, but since they mess up my code without actually being *in* my code, they might as well be introduced by evil gnomes.

Before you ask, I did run across 2 separate bugs in Microsoft Visual C++ when I was trying to learn C++. (Documented bugs too, found them in KB.)

That's one of the problems with being a sucky programmer, you'll find bugs in compilers and libraries that writers of idiomatically correct code will never encounter. And since your code looks like ass, no one will believe the bugs aren't your fault. Especially since 99.99% of the bugs are your fault.

Anyway, I've long since given up C++. If I can't solve the problem with perl, I just claim it's NP complete.

--Shoeboy
No more trolls!
If you can't solve a problem with perl... (none / 0) (#20)
by kovacsp on Tue Jun 05, 2001 at 10:34:23 PM EST

then it probably is NP complete. Perl is a turing complete language afterall. Well, not necessarily NP complete, but potentially anyway.

[ Parent ]
NP-complete != unsolvable (none / 0) (#37)
by plastik55 on Wed Jun 06, 2001 at 12:52:29 AM EST

*nt*
w00t!
[ Parent ]
Microsoft Visual C++ (3.00 / 1) (#47)
by codemonkey_uk on Wed Jun 06, 2001 at 08:39:13 AM EST

Is chock full of bugs. I've seen it malform:
//...
a = array[b++];
//...
In debug mode it worked fine, but in release mode it, I know not why, generated code equivilant to:
//...
a = array[++b];
//...
Causing the loop to read off the end of the array, and generate garbage results. Which was fun to debug. Coding with MSVC++ makes every day like walking in a metaphorical mine field.
---
Thad
"The most savage controversies are those about matters as to which there is no good evidence either way." - Bertrand Russell
[ Parent ]
re-use (4.00 / 4) (#22)
by jesterzog on Tue Jun 05, 2001 at 10:54:42 PM EST

I haven't read the book so I'm not sure if it's covered, but this wasn't mentioned in your review so it seems worth mentioning.

One of the very useful things I've found about making code solid is to abstract things and re-use the same code as much as possible. For me, this helps a lot with maintenance during the coding, and later on. Mostly because there's a lot less code to maintain.

Where I'm working at the moment the libraries have been written without much abstraction or re-use in mind. I'm slowly trying to convert people, but in general the libraries we're using encourage coders to write the same code over and over in lots of different places for relatively similar tasks.

It's also mostly in VB, which (IMHO) is a dreadful language for encouraging good coding techniques. It doesn't help that I'm the only coder who isn't mostly trained on VB.

This, of course, means that whenever there's even a small policy change with how things are done, we have to go through 50 to 100 different bits of code and change them all. The obvious problems with this are inconsistencies and bugs everywhere.


jesterzog Fight the light


Re-use where it makes sense. (4.00 / 3) (#27)
by Inoshiro on Tue Jun 05, 2001 at 11:28:10 PM EST

A lot of books pimp agressive re-use. Too aggresive, in fact. This book makes a point of ensuring that people understand that re-use is important where it makes sense, not just everywhere.

Example: realloc. Realloc is a dangerous function because it can (with the proper arguments) allocate ram, shrink memory buffers, grow memory buffers, and free memorf buffer. If you accidently pass it a size of zero (inited to 0 var which was not checked), and you free memory you meant to be growing..you know what I mean :)

My rule of thumb is to have a good reason for having a function beyond ~20 lines or so. This encourages me to keep the functions small and easy to prove correct, and allaws me to split off functionality to other areas. While a split off function might not be shared with any other ones, it increases the readability of the program. I have litterally been able to came back to the project after ignoring it for hasf a year, and re-read the entire thing in one sitting :)



--
[ イノシロ ]
[ Parent ]
And another thing (none / 0) (#29)
by jacob on Tue Jun 05, 2001 at 11:41:01 PM EST

I find that if I want my code to be readable, I have to do two things: split up any function that's larger than about half a screen wide, which is about 10-15 lines, and logically order and group all of my functions.

I have one source file for one logical program unit, and it starts with the functions that the rest of the world ought to see from the unit. After that are the helper functions that those functions call directly (in the order they were called in the first program's source code), and then the ones that those functions call, et cetera. It's not at all natural for me to program that way when I'm in the middle of a program, but I don't feel like it's done until it's ordered like that.

Funny you should mention it, I was just taking a break from splitting up some huge monolithic functions when I read your comment.


--
"it's not rocket science" right right insofar as rocket science is boring

--Iced_Up

[ Parent ]
An exception (none / 0) (#58)
by keyeto on Wed Jun 06, 2001 at 11:53:45 AM EST

Decomposing functions into their relevant parts is important, but there is at least one exception to the "no method/function/subroutine should be longer than N lines" rule. It's when you're writing a state machine, using a humungous switch statement inside a looping construct.


--
"This is the Space Age, and we are Here To Go"
William S. Burroughs
[ Parent ]
Read my comment. (none / 0) (#75)
by Inoshiro on Wed Jun 06, 2001 at 05:32:13 PM EST

"My rule of thumb is to have a good reason for having a function beyond ~20 lines or so."

And as I've written in my own apps in the comments:

/* Function called when our timer expires.
mouse_cb controls the timer_config.mouse_lock variable, letting us not harras
the user unintentionally.
Note: this function is long since it's essentially a big finite state machine
with some recursion :)
*/



--
[ イノシロ ]
[ Parent ]
Bad languages for CS people (3.50 / 2) (#32)
by jacob on Wed Jun 06, 2001 at 12:00:20 AM EST

I know that a lot of people really like VB, but I really don't understand the appeal. I haven't used it nearly as much as it sounds like you have, but I also noticed that it really doesn't make it easy for you to program well -- it's fine for making a basic GUI (or rather, the VB IDE is), but other than that I don't know of anything to recommend it at all. I find its notion of file i/o particularly strange.

If you think VB is bad for abstraction, though, you ought to try ColdFusion. There's a language whose appeal I absolutely cannot fathom. It absolutely lacks abstraction support in-language- it's like the language designers didn't think it was important. For example, if it's possible to declare a function in ColdFusion, I never figured out how. You can do "custom tags," which are like BASIC's GOSUB only more cumbersome (you have to have a separate file for each one).

And when I say "never figured out," I don't mean I couldn't do it after fiddling around for half a day. I mean I actually read through the entire programmer's manual, read through newsgroup and website postings, looked at large amounts of sample ColdFusion code, and basically did everything I could for a course of a couple months while I was developing a website in CF for my work (at the time, I was the "web guy" at my office because I had a passing familiarity with WWW-related stuff and could actually write HTML. When it came time to do an interactive web site the bosses chose CF and then told me to program it :]).

I know there are tons of people that swear by ColdFusion, but to the best of my recollection I've never done any swearing related to ColdFusion that wasn't at it ... =)



--
"it's not rocket science" right right insofar as rocket science is boring

--Iced_Up

[ Parent ]
Ranting more about bad languages (none / 0) (#44)
by jesterzog on Wed Jun 06, 2001 at 08:11:49 AM EST

Sorry I should have said VBScript, which is more correct about what I've been using. I've been working there for a little over six months now and we use VBScript as the ASP language for a web interface for the product thing we're building.

Having come off a diet at university of java, C, C++, assorted unix scripting languages and a couple of functional languages, I hate it. The repetition and lack of reuse is one of the worst parts of it, because apart from the bug problems I've already mentioned, it also takes the thrill out of designing cool and rewarding ways to do things conveniently. Instead it's just rewriting almost-the-same-thing over and over again.

Even ignoring the bad documentation in MSDN, it's so completely obvious that the whole thing's hacked together. It's okay for doing very basic things, but language-wise there are inconsistencies around every corner. It's quite unpredictible what's possible and what's not, because things that imply they should act the same act completely differently under different contexts without any real explanation.

I doubt the company's going to switch away from Microsoft given it's a small company and other people there have the relevant qualifications. But concerns about Sun-Microsoft competition aside, I almost can't wait for Microsoft to hurry up and start embedding C# (or whatever they call it now) into everything. If I get a chance to move some code to that, it'll be such a relief.

I'm lucky that I'm still studying for a postgrad degree part time, which keeps me sane. I'm not sure where I'd be without the relatively "do-it-right" attitude of academia.


jesterzog Fight the light


[ Parent ]
I agree VB is hack (none / 0) (#52)
by nobbystyles on Wed Jun 06, 2001 at 10:04:15 AM EST

I am developing database apps with VB at the moment. I spend most of my time trying to work around bugs in the components that MS provides such as ADO and various controls. Crap documentation and inconsistent behaviour don't help either.

You still have to use Win 32 APIs to do anything useful as well.

[ Parent ]
VB and external API's (none / 0) (#54)
by jacob on Wed Jun 06, 2001 at 11:07:06 AM EST

Don't you think it's funny how people defend VB and other languages by saying, "it's really easy to use, and if you need extra power you can link to COM objects or external modules when you need it!" Wow! What could be better? ... Except a language that's easy to use and powerful enough that you don't need to use COM objects every time you want to do anything useful! =)

Ooh, he's really askin' for it now!



--
"it's not rocket science" right right insofar as rocket science is boring

--Iced_Up

[ Parent ]
JScript (none / 0) (#72)
by guinsu on Wed Jun 06, 2001 at 03:54:38 PM EST

I've found that Microsoft's JScript (basically Javascript) is the way to go when doing ASP sites. Its got its problems and I would rather do a combo of Java and Javascript (JAva for classes, error control and database access and a light layer of Javascript on my HTML pages for interface).

[ Parent ]
There is no way to declare a function in CF (none / 0) (#50)
by farmgeek on Wed Jun 06, 2001 at 09:21:25 AM EST

I've run into the same problem as you, and I've decided that there is no way to declare a function in ColdFusion (currently). I think it may have something to do with the mindset employed by the designers when they were implementing a "tag based" scripting language. The resemblence to HTML may have muddied their thinking. But as far as it's appeal, well it generally works, is easy to learn, is pretty fast as far as a server side scripting language goes, and is ridiculously easy to tie to a database.

But you're right about the custom tags bit. It's much more trouble than it is generally worth IMHO. And the programmers manual and the documentation in general are not up to par with what they should be, especially once you get into some of the deeper application/security based issues.

[ Parent ]
Cold Fusion functions, and its documentation (none / 0) (#71)
by ajf on Wed Jun 06, 2001 at 03:22:09 PM EST

True, Cold Fusion does have a few annoying quirks. It's a pain not being able to write functions, especially for simple string manipulation. And it seems odd that you can write things like "blah blah #variable# #SomeFunction(foo,bar)#" (which replaces the stuff between the hashes with the value of variable and the result of the function call), but you can't do "#1+1#". It didn't take me long to get used to dealing with custom tags, and I'd probably rather work with Cold Fusion than PHP (and I'd certainly choose it over VBScript, which I've fortunately avoided dealing with too much).

And, as farmgeek said, the documentation can be pretty inadequate. My favourite example is About CFScript - there's a <CFSCRIPT> tag which allows you to do some non-tag-based coding when it's appropriate, but the entire documentation of CFScript seems to be "Umm, well, it's sort of like Javascript, really".



"I have no idea if it is true or not, but given what you read on the Web, it seems to be a valid concern." -jjayson
[ Parent ]
Why the preference? (none / 0) (#88)
by jacob on Thu Jun 07, 2001 at 12:33:02 AM EST

... I'd probably rather work with Cold Fusion than PHP ...

How come? I'm curious: what does ColdFusion have to recommend it that PHP doesn't? I've used PHP and I found it to be adequate if not spectacular -- sort of a sanitized Perl with lots of built-in web library stuff. I absolutely loathed ColdFusion, though, and I'd never pick it over PHP given any choice. I have, in fact, actually argued a boss into letting me use PHP for a web site rather than ColdFusion.

So, what's the alternate view?



--
"it's not rocket science" right right insofar as rocket science is boring

--Iced_Up

[ Parent ]
Readability (none / 0) (#124)
by ajf on Tue Jun 12, 2001 at 07:55:30 AM EST

I just find that because it's a tag-based language, the code "feels" like a web page, rather than the jumpy code-HTML-Code-HTML-CodeWithHTMLInPrintStatements-HTML-Code mess PHP seems to end up in.

In my previous job I set up Sourceforge's code to use its bug tracking system, which involved a lot of hacking out pages and code that were only useful to sourceforge.net itself, and the code was much harder to work with than, the company's entire web-site, developed in Cold Fusion using Spectra (Allaire's content management system), even though the web site's live started in a mad rush in two weeks, followed by six or so months of building on that codebase without getting a chance to go back and clean up things that had to be done quickly rather than cleanly.



"I have no idea if it is true or not, but given what you read on the Web, it seems to be a valid concern." -jjayson
[ Parent ]
have you read Refactoring? (none / 0) (#56)
by Kellnerin on Wed Jun 06, 2001 at 11:40:06 AM EST

Perhaps you have, or don't really need to anyway, since you're already convinced of the advantages of reuse, but it's a nice guide to cleaning up code so it's more readable and maintainable. It's written with Java in mind, so it might not help you in VBS, but in the vein of "You may not need this, but you may know someone else who does!":

Refactoring: Improving the Design of Existing Code
Martin Fowler, et al.
Addison-Wesley
0-201-48567-2

--Stop it, evil hand, stop it!--
[ Parent ]

Thanks for the tip (none / 0) (#83)
by jesterzog on Wed Jun 06, 2001 at 09:29:29 PM EST

I haven't read it, but thanks for the tip. I'll see if I can track it down.


jesterzog Fight the light


[ Parent ]
comment from a former Microsoft programmer (4.54 / 11) (#25)
by adamba on Tue Jun 05, 2001 at 11:20:01 PM EST

I fully agree that more Microsoft people should read this book. For example, I worked there for ten years, most recently on the Windows 2000/XP kernel, and I never read the book, although I did skim through it at the company store.

I would like to point out that there is *no* standard for programming at Microsoft. There are no company-wide classes on how to program (or how to anything except do interviews). So, for example, this book has a foreword by Dave Moore, whose title was "Director of Development, Microsoft." So you might think, this is a guy who all the thousands of developers work for, right? Or at least, he's a guy who commands great respect among all the developers and they all listen carefully to what he says, right?

Of course, that's not true. Microsoft at some point decided they needed some people to think about the "right" way to develop, test, etc. So they had Moore as director of dev with a small (very small) team under him thinking about this, and they had a directory of test with a very small team, etc. And more-or-less nobody paid much attention to them. There was one attempt to have a company-wide "developer day" back in 1996, which was very interesting, but mostly did not have any effect on the developers.

I'll also mention that there is definitely a different mindset, or what have you, between the apps and systems developers. The apps guys mostly do use Hungarian, probably pay more attention to Dave Moore (who came out of apps I believe), etc. The systems guys tend to do their own thing. For example, NT/2000/XP/etc follows the coding guidelines that Dave Cutler brought from DEC with him (Cutler has been the main technical force behind NT since 1988). Hungarian notation is most definitely not used, variable/function names all spelled out (names like CopyBitsToScreenAndOverlay()), and so on. And then there are the arguments over how to format C code...Having worked in NT for most of my 10 years I think it is more natural, but other disagree. I do think that Cutler has forgotten more about software development than Dave Moore ever knew, but that is just my opinion.

My main point is you can take what Dave Moore says with a grain of salt. And the suggestions in "Writing Solid Code" may be very valid. But don't for a minute think that they are the "one true Microsoft way", because there ain't no such thing. At most this is a distillation of some common practices in the apps groups.

- adam

P.S. ObSelfPromo: if you thought that was interesting...

David Moore? (3.66 / 3) (#40)
by Inoshiro on Wed Jun 06, 2001 at 04:04:25 AM EST

This book was written by Steve Maguire, an intelligent sounding guy. The foreward was just a few pages I don't remember anymore :p



--
[ イノシロ ]
[ Parent ]
Hungarian notation (none / 0) (#101)
by fluffy grue on Thu Jun 07, 2001 at 07:13:02 PM EST

I hope that comment of yours wasn't intended to promote hungarian notation. HN is evil - it's the prototype which is supposed to say what the function prototype is, not the name. There are many long, well-thought-out treatises on why Hungarian Notation is nothing but bad, and I'm not going to repeat them here; I'm sure it's been gone over on K5 many times in the past, as well.

The only valid use of functionname-specified typing that I've ever seen is in doing function overloading in languages which don't support it (C, for example). The way that OpenGL handles these things, for example, is very nice; they refer to a function as, for example, glColor*(), and then there are various specializations of it which go into the * (for example, 3f, 4f, fv to specify three floats, four floats, or a float array).

All that hungarian notation does is to get in the way and make it much more difficult to modify the API or remember function names. The only sort of prefixing I personally use is m_ to specify that something is a member variable (rather than a variable declared within a method or passed as a parameter). I differentiate between variables and types via capitalization (for example, class Bobo { ... } vs. Bobo larry). It effectively namespaces things automagically, while keeping things nice and abstract without having to worry about type clashes.

If you really need to know the types of your parameters and return value, then you should be prototyping your functions and generating compile errors. :) Hungarian notation only "helps" when you're a sloppy programmer who can't follow basic modular coding practices...
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

oh yes, Hungarian is bad IMHO (none / 0) (#106)
by adamba on Thu Jun 07, 2001 at 08:33:22 PM EST

My point was supposed to be, 1) apps used Hungarian and NT didn't, 2) I worked in NT, 3) NT roolz, 4) Hungarian is bad.

I especially hate variable names like lpschX, where "X" is the name and the other gobbledygook is supposed to help you tell what kind of variable it is. I mean literally just a single capital X. How useless is that? Even lpschOverflowBuffer or something is no more useful than OverflowBuffer. Then you get cases where the same function has locals lpBuffer and plpBuffer and wBuffer etc.

Really it always struck me, in my systems-ish way, that if Hungarian actually helped, then you weren't doing anything very complicated.

I agree about m_. Also in NT, which used intercapped names, some people used initial lower-case for locals and initial caps for params. So NumberOfTiles (params) vs. numberOfTiles (local).

- adam

[ Parent ]

case vs. prefix (none / 0) (#108)
by fluffy grue on Thu Jun 07, 2001 at 09:51:17 PM EST

IMO, if your function is so long that you can't remember whether a variable is local or parameter, it's time to split your function up. :)

BTW, one thing which I've seen a lot of which is bad, bad, bad is when people use or declare stuff starting in underscores or two underscores. I believe that _foo is only to be used for library-specific internal stuff and __foo is to be used only for compiler internal stuff. Declaring or using things which begin in a _ may cause undefined results, and is seldom portable.

The only exception to this rule, of course, is if you're using #ifdefs to determine which compiler/OS you're using. i.e. #ifdef _WIN32 etc.

BTW, I really love how older versions of glibc (libc5/glibc1) actually exported some global variables for no good reason. For example, it exported a 'float y1,' which was supposed to be used in some math function. Of course, when writing throwaway hack code which needed a global variable called y1, this caused problems...
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

Why one language is better than another (none / 0) (#117)
by slaytanic killer on Fri Jun 08, 2001 at 08:53:52 AM EST

That's the one reason I'd rather program in Java than C/C++. Using _ as a prefix is so much more beautiful than using m_.

[ Parent ]
Yeah. (none / 0) (#109)
by Sax Maniac on Thu Jun 07, 2001 at 10:06:17 PM EST

I actually think a small dash of HN isn't so bad. An occasional "pfoo" instead of "foo" can help, when it adds clarity, but that's about as far I can go without feeling soiled. Using it blindly like the Windows code gives me the willies with all the lpsz crud all over the place. Shiver.

I can buy using HN in assembler, but man, not in anything with a type system.

It's funny you mention OpenGL. I got really pissed at it one day for all the strange symbols all over the place, so I wrote a C++ wrapper that used overloading to filter them all out. But, for some reason, OpenGL's use of the funny symbols isn't that bad. That's because they were smart and put the funny letters at the end. (Imagine gl3fSetColor, yech.) (Of course, my argument is silly because I didn't complain about the 'gl' prefix and that's in the front, but at least it's the same everywhere.)

Instead of m_foo, I use "myFoo" or "my_foo" (ourFoo/our_foo for statics). It's a bit cutesy, but it reads very nicely.


Stop screwing around with printf and gdb and get a debugger that doesn't suck.
[ Parent ]

Overloads (none / 0) (#112)
by fluffy grue on Thu Jun 07, 2001 at 11:33:11 PM EST

Well, the OpenGL style is just C-style function overloading. :) The gl* prefix is pretty much necessary, since it namespaces it to OpenGL. Imagine if the glColor function were just called 'Color.' That'd suck, especially if you wanted Color to be a structured type. IMO, there's absolutely nothing wrong with OpenGL's naming convention.

I agree about HN in assembler. There it makes sense.

myFoo is cute, but in a kind of distrcting way. I prefer m_foo. That's just personal preference, though, and myFoo definitely gets the point across just as well, if not better. The ourFoo for statics is definitely a nice idea - hadn't thought of that. Then again, I've always avoided using static members. :) There's only a few circumstances where they're necessary, and I've never seen them used for any of those...
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]
[ Parent ]

Ways to identify (none / 0) (#120)
by tnt on Sat Jun 09, 2001 at 02:17:43 PM EST

You said:

The only sort of prefixing I personally use is m_ to specify that something is a member variable (rather than a variable declared within a method or passed as a parameter).

Personally, I use the this-> pointer to show that I am dealing with a member variable. That way I can avoid mangaling the variable's name... and the this-> pointer is part of the language after all (and shows it just the same).



--
     Charles Iliya Krempeaux, B.Sc.
__________________________________________________
  Kuro5hin user #279

[ Parent ]
Big assumptions (3.00 / 2) (#48)
by miggsectomorph on Wed Jun 06, 2001 at 08:49:04 AM EST

What is a bug? I would like to point out that most people seem to assume that this question has already been settled. It may seem childish to question it, but here goes: logical error. This means that you intended the processor/memory state to change in some way, and it didn't do exactly that. As with most definitions, to be accurate they must be extremely broad. Thus people find it very disturbing to have to start from scratch, but I think we'll all be better off in the long run if we actually agreed upon definitions. I for one don't much care what some programmer at Microsoft thinks is the best way to check for ranges of input values. It's all just logic. I'd have to talk directly to him about very specific errors in his code to make a guaranteed worthwhile decision. But I suppose I'm just 'like that'. Ectomorph

_Writing Solid Code_ is full of bad C (4.60 / 10) (#53)
by pfaffben on Wed Jun 06, 2001 at 10:17:44 AM EST

Steve Maguire may know about programming in Microsoft Visual C++ on x86 platforms, but he doesn't know much about writing portable C code. The following are some of the problems I found in just the first 100 pages of Writing Solid Code last year when I was reading it. These are excerpted from a USENET article that I wrote; the complete thread is available on deja.

  1. Every time he assigns a void pointer to any other type of pointer, or vice versa, he uses an explicit cast. This is hardly conducive to "Writing Solid Code".
  2. On page 22, chapter 2, and later in the book too, he shamelessly declares a function strdup() without mentioning why you shouldn't do that.
  3. He assumes that pointer arithmetic works outside of allocated arrays without ever mentioning that assumption. Seen often, first on page 20.
  4. He gratuitously ignores standard prototypes of standard functions and redeclares them according to his whim (type "byte" instead of "int", leaving off "const" specifiers, and so on). He has some sort of "defense" to this in the first chapter, but not one that I understand. (Leaving off const is particularly unforgivable: const is valuable when trying to write reliable code.)
  5. He assumes that void ** is a generic pointer-to-pointer. It's not. Seen first on page 47, chapter 3.
  6. In his pointer validator, he assumes that everything is allocated in dynamic memory. Am I the only one who also uses pointers to automatic and static variables? I doubt it.
  7. On page 94, he states that realloc() will return the same pointer it is passed if the block is to be shrunk. This is false: the C standard makes no such guarantee.

These are just those that I found by quickly paging through the book up to this point. Basically, I believe that Steve Maguire is a good programmer on the systems he's familiar with, but he doesn't understand the C standard and so doesn't know how to write portable code. Some of the problems above would be okay (i.e., #3, which applies only to his debug code, where it could be useful on systems where it works and disabled somehow on systems where it doesn't) if he'd just *mention* them instead of being blissfully unaware of them.

I can't recommend this book for anyone who isn't planning to be a Windows programmer for ever. It just doesn't promote good, portable code.



Three comments on your comments: (3.00 / 1) (#55)
by adamba on Wed Jun 06, 2001 at 11:36:46 AM EST

Every time he assigns a void pointer to any other type of pointer, or vice versa, he uses an explicit cast. This is hardly conducive to "Writing Solid Code".

What is wrong with this? I do this just to remind myself what type it is (also do the same when comparing/assigning to NULL). The alternative, not casting at all, is not any more or less valid or portable.

He assumes that pointer arithmetic works outside of allocated arrays without ever mentioning that assumption. Seen often, first on page 20.

Either this is wrong or I don't understand what you said. Pointer arithmetic works with any pointer.

On page 94, he states that realloc() will return the same pointer it is passed if the block is to be shrunk. This is false: the C standard makes no such guarantee.

He should have said, "don't use realloc, it's bogus."

The rest I agree with.

- adam

[ Parent ]

Responses to these comments on my comments (3.50 / 2) (#60)
by pfaffben on Wed Jun 06, 2001 at 12:02:42 PM EST

  1. Inserting a cast when it is not needed is not a good idea. Casts are a way to step around C's type system. If you don't need to do this, then you shouldn't. Inserting a cast to the wrong type accidentally can cause bizarre failures (I've seen this often in the hands of novice programmers who don't understand what they're doing; not that the book is targeted at novices).
  2. The ISO C standard says that comparing or subtracting pointers that don't point within the same array is undefined behavior. You can't, for instance, use the < operator to compare two pointers returned by malloc(). Most modern computers will let you do this anyhow, but it would be nice if he would at least mention that it isn't strictly allowed by ISO C.


[ Parent ]
maybe I misunderstood (none / 0) (#67)
by adamba on Wed Jun 06, 2001 at 01:19:00 PM EST

Inserting a cast when it is not needed is not a good idea. Casts are a way to step around C's type system. If you don't need to do this, then you shouldn't. Inserting a cast to the wrong type accidentally can cause bizarre failures (I've seen this often in the hands of novice programmers who don't understand what they're doing; not that the book is targeted at novices).

Right but you were talking about void pointers.

Now maybe I misunderstood what was being cast. Did you mean that he does things like (assuming some struct is typedef'ed as FOOBAR):

if (somevoidpointer == (VOID *)foobarpointer)

I don't like that. What I do is something like

if ((FOOBAR *)somevoidpointer == foobarpointer)

Actually that is a bit of a contrived example. What I do are

if (foobarpointer == (FOOBAR *)NULL)

and also

foobarpointer = (FOOBAR *)malloc(xyzzy)

The ISO C standard says that comparing or subtracting pointers that don't point within the same array is undefined behavior. You can't, for instance, use the < operator to compare two pointers returned by malloc(). Most modern computers will let you do this anyhow, but it would be nice if he would at least mention that it isn't strictly allowed by ISO C.

Oh. Sure. Well why would you do that. When you said it only works on allocated pointers, I thought you meant it didn't work, say, to step through a static piece of memory.

- adam

[ Parent ]

void pointers and casts (none / 0) (#68)
by pfaffben on Wed Jun 06, 2001 at 01:34:13 PM EST

What I meant was this. Suppose that you have a function that returns a pointer to void. IIRC (I don't have the book on hand) he would write something like this:

int *p = (int *) func();

when it's safer and simpler to write it without the cast:

int *p = func();


[ Parent ]
hmmm, it *is* safer without the cast (none / 0) (#79)
by adamba on Wed Jun 06, 2001 at 06:11:03 PM EST

since if the thing doesn't really return void *, you are hiding a bug. Still I always did this. Thinking about it, I'm not sure there are too many functions besides a memory allocator that should return a void *.

- adam

[ Parent ]

Yup, it's a common error, though. (none / 0) (#100)
by Sax Maniac on Thu Jun 07, 2001 at 05:53:17 PM EST

Good, you've got the point. Unnecessary casting to/from void* is a pre ANSI C-ism that simply is useless today. Unfortunately, so many books hold on to this K&R C relic that it persists.

C has valid implicit conversions, some conversions require a cast. For example, you don't think anything about writing 2 + 2.3, do you? That's because the 2 gets an implicit conversion to double. Implicit conversions are perfectly valid.

Using an unnecessary cast is the "Big Fuckin' Hammer" approach that hides more problems than it solves. It's like using a chainsaw to cut your sandwich: sure, it's more powerful, but you're likely to take out the table and a few fingers with it, and, it's silly to take that risk if you've got a butter knife handy.

Hey, Ben, nice to see another old clc pedant such as myself on K5. (Now when's Dann gonna show?)


Stop screwing around with printf and gdb and get a debugger that doesn't suck.
[ Parent ]

wait, I thought "void *" was new in ANSI (none / 0) (#105)
by adamba on Thu Jun 07, 2001 at 08:24:32 PM EST

OK I may be about to say something completely stupid. But I thought void * was introduced in ANSI C, basically to solve the problem, "what should malloc return"? Didn't malloc return char * in original C?

Don't have either the new or old K&R around to check this statement, so I'll just throw it out here for the K5 coding crew to take a swat at.

- adam

[ Parent ]

Right. (none / 0) (#107)
by Sax Maniac on Thu Jun 07, 2001 at 09:48:13 PM EST

Not stupid at all. You are correct. I muddled that sentence a bit. I should have said "casting to/from generic pointers".

K&R C used char* as a generic pointer, however, it had no implicit conversion. So, when you got a pointer from malloc(), or sent a pointer to free(), you had to cast it to/from char*.

ANSI C added void* to be used as a generic pointer, and gave it an implicit conversion to and from any other pointer type so casting was not necessary.

C++ takes a (yet another) different approach where the conversion to void* requires no cast, but converting from it does.

BTW, the book looks interesting. I liked Moody's "I Sing..." and am curious to see it from a developer's view.
Stop screwing around with printf and gdb and get a debugger that doesn't suck.
[ Parent ]

Casting void * (none / 0) (#89)
by sigwinch on Thu Jun 07, 2001 at 01:31:34 AM EST

Inserting a cast when it is not needed is not a good idea. Casts are a way to step around C's type system. If you don't need to do this, then you shouldn't. Inserting a cast to the wrong type accidentally can cause bizarre failures...
A cast to the wrong type should cause a compiler warning; if it doesn't, delete the compiler immediately.

And there are places where void * casts can be useful. Consider this code:

struct some_struct {
    char x;
};

struct some_other_struct {
    char x;
    int y;
};

int main( int argc, char **argv ) {
    struct some_struct *a;

    a = (struct some_struct *)malloc( sizeof(struct some_struct) );

    do something with a
}
Suppose after writing a bunch of code that you discover that a more general struct should have been used. So you change the declaration like this:
struct some_other_struct *a;
When you try to compile after this change, the typecast will cause the assignment of the malloc() return value to complain. So this technique can be beneficial.

Although this is really pointing towards the fact that you should never, ever use malloc directly (nor anything else that returns a void pointer to arbitrarily allocated storage). The proper fix for this problem is:

#define ALLOC(x) ((x) = malloc( sizeof(*(x)) ))
#define NALLOC(x,N) ((x) = malloc( sizeof(*(x)) * N ))

--
I don't want the world, I just want your half.
[ Parent ]

Comments on your comments on his comments. (4.00 / 1) (#64)
by beergut on Wed Jun 06, 2001 at 12:41:05 PM EST

    Every time he assigns a void pointer to any other type of pointer, or vice versa, he uses an explicit cast. This is hardly conducive to "Writing Solid Code".
What is wrong with this? I do this just to remind myself what type it is (also do the same when comparing/assigning to NULL). The alternative, not casting at all, is not any more or less valid or portable.

I generally do the same, for the same reasons, and it is portable, but not great style. The only times I use it is when working with opaque structs, in the guts of library code wherein I know exactly what is where.

    He assumes that pointer arithmetic works outside of allocated arrays without ever mentioning that assumption. Seen often, first on page 20.
Either this is wrong or I don't understand what you said. Pointer arithmetic works with any pointer.

While it may work if you cast to char*, and use the integer value of each pointer, it is not portable.

Consider the case where you are reading binary data from a file (yes, this is nonportable anyway). Your code for reading the file may have been written on a system (and for a compiler) wherein you could assume things about the layout of the data. For instance, you may assume that the data in the structure is laid out back-to-back, packed. Compile that same source code on a different system, or with a different compiler, and whammo - instant bugs.

    On page 94, he states that realloc() will return the same pointer it is passed if the block is to be shrunk. This is false: the C standard makes no such guarantee.
He should have said, "don't use realloc, it's bogus."

Sorry, can't agree with you there. realloc() is God. It is pure foolishness and wastefulness to allocate an entirely new piece of memory from the heap, then copy all the contents from one piece to the other, and then free the first piece, if there is sufficient room after the first piece to meet the request.

i don't see any nanorobots or jet engines or laser holography or orbiting death satellites.
i just see some orangutan throwing code-feces at a computer screen.

-- indubitable
[ Parent ]

realloc can be dangerous. (none / 0) (#74)
by Inoshiro on Wed Jun 06, 2001 at 05:22:54 PM EST

If your code is buggy and passes garbage to realloc, it can do many different things which are considered valid.



--
[ イノシロ ]
[ Parent ]
Care is needed, anyway... (3.00 / 1) (#82)
by beergut on Wed Jun 06, 2001 at 08:51:56 PM EST

If your code is buggy and passes garbage to realloc, it can do many different things which are considered valid.

Indeed. realloc() assumes you are not a moron. :-)

i don't see any nanorobots or jet engines or laser holography or orbiting death satellites.
i just see some orangutan throwing code-feces at a computer screen.

-- indubitable
[ Parent ]

Of course it's not portable. Vested interest. (5.00 / 1) (#69)
by hotcurry on Wed Jun 06, 2001 at 01:35:25 PM EST

Microsoft Press has no intention of teaching us how to write portable code. Quite the opposite. And Microsoft tools aren't all that portable either. Want portable C code? Use gnu. It runs on virtually any platform out there. You'll need some #ifdefs on Microsoft and Apple OS's, but it's doable.

[ Parent ]
I'm not getting enough abuse here. So... (3.33 / 3) (#85)
by marlowe on Wed Jun 06, 2001 at 10:39:57 PM EST

I'm going to go out on a limb and suggest something I myself and only half convinced of. Bring on the flames!

Do we really need books on programming? We've got code to look at! Open source code! Lots of it. Plus sample code from closed source vendors, some which isn't half bad. Plus the closed source code we actually have to look at at work, but the less said the better. Books are a lot of talk. It may be true talk. It may be false talk. But code is the real thing. You can actually fire it up under a debugger and watch it run. Or not run. Code can't lie to you and get away with it for very long.

The surest way to know how something done involves watching it done. Commentary and explanations may be necessary, but watching it done is practically always necessary. So why not cut to the chase and actually study some good code? have a look at it and see what makes it good.

The thing about really good code is it explains itself. I've seen open source code that had hardly any comments, and yet I was able to follow it without any trouble. Why? Because all the symbol names were well chosen. They actually described the things they represented. And no, they weren't long and wordy like in parts of the Java class library. They used abbreviations, but they were obvious abbreviations, and they were used consistently. Such a thing is possible. I've seen it. Look at the code for xmms. And no, my point isn't that you needn't bother with comments. My point is there things you can do other than comments that are extremely helpful in and of themselves.

And then there's a thing called literate programming, whereby the documentation is contained as comments in the code, in a form that an automated tool can pull them out and create documents as needed. Javadoc is sort of along these lines.

Want to know how to write an OS kernel? Look at the source code for Linux. No really. Look at it.

Of course there are counterexamples. The openSSL code isn't very pretty. (It works, though, so it can't be all bad.) But they're all fairly obvious. It's not hard to filter them out. Just apply the simple rule: if it gives you a headache, it's probably a bad example of coding practices.

When you've seen enough code, both good and bad, and written a fair amount yourself, you get a feel for what makes quality. And this is better than any book, for the simple reason that you know this understanding to be true. If you just trust a book, you may save a lot of time, but there's no quality control. You may get stuck with the author's silly prejudices all mixed up with the good stuff.

If you must have a book, read it only after you've studied a wide variety of code. Then you'll be better able to filter out the nonsense from the insights. And make it someone like Brooks or Plauger. They've got no corporate agendas. The GoF has an ideology/methodology to push, but you can keep all that in perspective so long as you've worked with code.

Remember: code is reality. Code is the territory. Books are at best maps, and even that's being generous.

-- The Americans are the Jews of the 21st century. Only we won't go as quietly to the gas chambers. --
on the other hand (none / 0) (#93)
by speek on Thu Jun 07, 2001 at 07:19:44 AM EST

If you find good code to study, I'm betting you could learn a lot from it, but you could probably learn a whole bunch more from the author of that code. After all, that author probably went through a lot of thought processes and trial-and-errors that are not evident just from looking at the code.

So, if you can find good code, plus an author of that code with an ability to communicate, then you've got a potential book that really can teach you something. For me, such a book is Refactoring, by Martin Fowler.

--
al queda is kicking themsleves for not knowing about the levees
[ Parent ]

Definitely do not agree (none / 0) (#95)
by slaytanic killer on Thu Jun 07, 2001 at 07:56:27 AM EST

Read something by Knuth, like the METAFONT book. Or read Digital Typography. Code is not all; it is just a small subsection of thought. In fact, programming for me has little to do with computers, at least at first. When I think of programming, I think of a pen and paper. (I know, it should be pencil, but I like the feel of pens more.)

Code does not exist in a vaccuum; otherwise it would just be masturbation. (Which of course has its uses; pure fun is not a bad thing.)

[ Parent ]
Bugs and Unit Tests (none / 0) (#86)
by genman on Wed Jun 06, 2001 at 10:55:01 PM EST

I have mostly suggestions for C++ and Java folks, so this is kind of off-topic.

Extreme programming suggests that (among other things), you provide a suite of unit-test code that demonstrates (and excercises) all possible conditions of each code module you write. These tests should be automated and essentially prove that new bugs have not been introduced when refactoring. Unit-tests also provide these sorts of results:

1. You (tend to) write code that can be tested. Code is written in manageable sections.

2. Tests provide documentation on what sort of behaviors (errors and success cases) your API really provides. Since documentation is always out of date and often inexact, you can always be sure the behavior shown in the unit tests will be (probably) the same in actual production code.

3. Unit tests can be run against memory leak detectors, ease debugging tasks, and allow for performance improvements without having to run the entire application.

4. You should be able to demonstrate all the boundry conditions and error conditions. These can often take a lot of time to set-up properly, but it is often the case that people never do test all their code, and only when something rare and unexpected (that was supposed to be caught) shows up and bites them in the ass.

I haven't read that book (since the ideas aren't too new to me) but I have these opinions regarding the summary:

1. Asserts aren't so helpful in Java, since upon failure a stack trace is provided. For C++, it is not too hard to write foolproof APIs that don't allow for garbage data to be passed in. Method calls can be done entirely with objects (passed by reference so you don't run into memory problems), and the objects themselves can be (nearly) failure-proof, in how they restrict their construction and usage. The goal ultimately is to minimize the number of possible failure points, and this will cause the usage of assert to be quite minimal.

For C, you still have structs. It is still not too hard to write at least functions that will "sanity" check these, employing them in your unit tests.

2. Actually, C++ can be written entirely without "new" and "delete." Automatics, reference-counted objects, etc., allow for pointerless code. (I've done without a "new" successfully for a few weeks at work.) The STL provides container classes and string classes that do away with typical array usage anyway, and provide bounds checking.

3. I know the book is really about "C" -- for C the best you can do is (again) unit test things, which can show of course you have actually ran all the code you wrote.

If you write about 1:1 test to actual code, then you probably have enough test code. If you do have test code, then it is often not too necessary to be careful in the actual program, since you know what the behaviors are. (You can leave out those asserts and sanity checks sometimes. You can write fancy stuff, leave out some comments since your tests can explain things better than you can in English.)


Minor differences (none / 0) (#94)
by slaytanic killer on Thu Jun 07, 2001 at 07:50:04 AM EST

Asserts aren't so helpful in Java, since upon failure a stack trace is provided.
Probably quite true, however assert()'s are in jdk 1.4. The beta is out now. The point of assert() is to say, "The data in this class satisfies a set of conditions when you enter a function, and when you leave it." It is about object integrity. A stacktrace only says something went wrong, which could easily have come from earlier steps of object corruption.

But if the design is good enough and there aren't too many threads hanging around, then the stacktrace is definitely good enough for finding defects.
Extreme programming suggests that (among other things), you provide a suite of unit-test code that demonstrates (and excercises) all possible conditions of each code module you write.
While there is overlap between unit tests and asserts, I think the difference is that unit tests are just that -- they test units. Reading on the JUnit forums, it seems to me that they don't necessarily test data integrity, instead they test if the white box gives good answers. True, the tests are phrased as assert()'s, but it's not a matter of testing preconditions and postconditions. Real asserts are placed inside the object, while unit tests are external to an object.

That said, it is important to refactor your classes to be easily tested. Just like if you had a complex mechanical part, you'd play with the design so you can plug in your test machine. But I think there's still a place for internal tests, at least during development.

I don't think I'm at all disagreeing with you, just have minor differences in degree. However, I think 1:1 test to actual code may be a broad rule of thumb. Part of the point of unit tests is that they are more trustworthy than your normal code. If they're not smaller, then they should be much less complex. (Of course, I have not been using them very much, so you might be right. Like that awful rule about comments being 1:1 to actual code -- it often ends up being that way without you knowing it.)

And I definitely agree on unit testing's ability to serve as documentation, just like using design patterns. Definitely a statement of intent.

[ Parent ]
No fair (none / 0) (#103)
by fluffy grue on Thu Jun 07, 2001 at 08:16:35 PM EST

Inoshiro's allowed to use <H> tags and we're not! :(
--
"Is not a quine" is not a quine.
I have a master's degree in science!

[ Hug Your Trikuare ]

Now don't cry. (none / 0) (#114)
by Inoshiro on Fri Jun 08, 2001 at 03:25:20 AM EST

Bounce your submission off an admin. Chances are they'll post it for you with the tags. Some tags are just a little too bad to the formatting for unsupervised posting.



--
[ イノシロ ]
[ Parent ]
a much better book by the same author... (4.00 / 2) (#128)
by frogg on Sun Jun 24, 2001 at 10:12:16 PM EST

I've got 'Writing Solid Code' and read it cover-to-cover. But to be honest, I don't go back to it very often.

My main reason for this is that I also own a copy of 'Code Complete' by the same author (and also another Microsoft Press book).

In my opinion, 'Code Complete' will be a more useful book for any real-world programmer in the long run - no matter what language they program in.

If 'Writing Solid Code' sounds good to you, I'd recommend checking out 'Code Complete' - it's an order of magnitude more useful.

(FWIW, I have (all?) the other books by this author, and 'Code Complete' is by far the best of the lot!)

HTH,
frogg

Why buggy code gets written (5.00 / 1) (#129)
by Orion Blastar on Tue Jul 03, 2001 at 05:20:58 PM EST

The PHBs in charge of most IT departments want everything done as quickly as possible. This is the "Fast Food" Syndrome. Treating IT like it was "Fast Food" instead of IT. Write those program changes in less than 15 or 30 minutes and then ship it out to the users. Have the Help Desk and Technicians take a hit, and then pass it back to the developers so that the support takes more time than the development. People like me that spend more time on writing the code, than supporting it, get told that we take too long and to seek employment elsewhere. It doesn't matter that our programs run stable, and hardly have any bugs at all, if we don't produce code as fast as the other developers, we are out the door!
*** Anonymized by intolerant editors at K5 and also IWETHEY who are biased against the mentally ill ***
Review: Writing Solid Code | 129 comments (123 topical, 6 editorial, 0 hidden)
Display: Sort:

kuro5hin.org

[XML]
All trademarks and copyrights on this page are owned by their respective companies. The Rest 2000 - Present Kuro5hin.org Inc.
See our legalese page for copyright policies. Please also read our Privacy Policy.
Kuro5hin.org is powered by Free Software, including Apache, Perl, and Linux, The Scoop Engine that runs this site is freely available, under the terms of the GPL.
Need some help? Email help@kuro5hin.org.
My heart's the long stairs.

Powered by Scoop create account | help/FAQ | mission | links | search | IRC | YOU choose the stories!