Ethan Dicks wrote:
On 8/14/06, Don <THX1138 at dakotacom.net>
wrote:
I don't blame languages. I blame the folks
who either
don't fully understand the characteristics/consequences of
certain language features *or* the folks who don't
understand (nor appreciate) how to *test* things.
Agreed. I ran into a Perl debugging situation at one company where
the code to hit the database and aggregate thousands of e-mail
addresses was written by a web developer and then handed off to a
database developer when the first guy left. Essentially, the problem
was that on a particular day, the code, which had been working, got
swamped because it was (legitimately) being asked to handle 20 times
the normal amount of recipients. At the bottom of everything, there
was a loop with '$x .= $r[$n]' sort of a construct in it to build a
list of names, and there was so much string copying going on in the
loop that the Perl interpreter eventually barfed (after chewing on the
list for 8 hours). My solution was to replace the inner loop with a
'$x = $r[$a..$b]' construct - the modified program ran to completion
in 20 minutes.
The "everything should be in assembler" (paraphrased) comment has
some merit -- you get to see what the machine is *really* doing
at your behest.
Of course, doing *everything* that way quickly becomes
counterproductive (and, doesn't eliminate the need for
"quality programmers")
The "real" problem was that the first
guy didn't really understand the
impact of his original construction on the underlying system, and "it
worked" for a few thousand names. Didn't scale worth beans, though.
Exactly. Like:
for (x=0; x<XMAX; x++)
for (y=0; y<YMAX; y++)
foo[x][y] = ...;
vs.
for (y=0; y<YMAX; y++)
for (x=0; x<XMAX; x++)
foo[x][y] = ...;
They *look* the same but *aren't*.
And, in languages like C++, all of the machinery going
on "behind the scenes" (automatic type conversion,
constructor invocations, etc.) is so far out of the
typical "programmer's" mind/scope of knowledge that
it's a wonder *anything* works! :-(
I found one piece of code that was literally counting bytes
to determine the size of a file instead of stat(2)-ing it
(no, it wasn't a sparse file, special device, etc. ... just
a regular "box of bytes")
That's exactly the kind of stuff I have to deal with on a
regular basis. We have a large database manipulation application
full of classes with accessor methods that return instances of
string classes. Copy constructors executing all over the place.
Memory being uselessly copied from place to place accounts for
over 30 percent of the app's CPU usage. Programmer's response
to the suggestion that maybe some of the accessors return
(const char *) insead?
"That's just wrong." "My classes are bullet proof."
"Someone
could recast the pointer and sabotage my classes." "Modern
computers have plenty of CPU capacity."
This code does not go out of our shop... We all regularly
review each other's code but he spouts all of the "patterns"
nonsense.