Old-School Coding Techniques You May Not Miss 731
CWmike writes "Despite its complexity, the software development process has gotten better over the years. 'Mature' programmers remember manual intervention and hand-tuning. Today's dev tools automatically perform complex functions that once had to be written explicitly. And most developers are glad of it. Yet, young whippersnappers may not even be aware that we old fogies had to do these things manually. Esther Schindler asked several longtime developers for their top old-school programming headaches and added many of her own to boot. Working with punch cards? Hungarian notation?"
Some, not all... (Score:5, Insightful)
Some of those are obnoxious and good to see them gone. Others, not so much. For instance, sorting/searching algorithms, data structures, etc. Don't they still make you code these things in school? Isn't it good to know how they work and why?
On the other hand, yeah... fuck punch cards.
Re: (Score:3, Insightful)
Its absolutely essential to know how those work and why. If not you'll use the wrong one and send your performance right down the crapper. While you shouldn't have to code one from scratch anymore, any programmer who can't do a list, hash table, bubble sort, or btree at the drop of a hat ought to be kicked out of the industry.
Re:Some, not all... (Score:5, Insightful)
any programmer who can't do a list, hash table, bubble sort, or btree at the drop of a hat ought to be kicked out of the industry.
Why?
Lists, hash tables, and sorting is already built in to many languages, including my language of choice. The rest, I can easily find in a library.
When performance starts to matter, and my profiling tool indicates that the sorting algorithm is to blame, then I'll consider using an alternate algorithm. But even then, there's a fair chance I'll leave it alone and buy more hardware -- see, the built-in sorting algorithm is in C. Therefore, to beat it, it has to be really inappropriate, or I have to also write that algorithm in C.
It's far more important that I know the performance quirks of my language of choice -- for instance, string interpolation is faster than any sort of string concatenator, which is faster than straight-up string concatenation ('foo' + 'bar').
And it's far more important that I know when to optimize.
Now, any programmer who couldn't do these at all should be kicked out of the industry. I could very likely code one quickly from the Wikipedia article on the subject. But by and large, the article is right -- there's a vast majority of places where these just don't matter anymore.
Not that there's nowhere they matter at all -- there are still places where asm is required. They're just a tiny minority these days.
Re:Some, not all... (Score:5, Insightful)
Because if these well known tasks are difficult for them their job title is really typist, not programmer. The challenge is not to write bubble sort day in and day out, but being several levels above that so it is as easy as computing six times seven or reading road signs.
True story (Score:5, Interesting)
Let me tell you a true story to illustrate why I think people should still learn that stuff.
ACT I
So at one point I'm in a room with what looks like two particularly unproductive Wallys. Though it's probably unfair to call both Wally, since at least one looks like the hard working kind... he just makes as much progress as a courier on a treadmill.
So Wally 1 keeps clicking and staring at the screen all week and spewing things like "Unbelievable!" every 5 minutes. My curiosity gets the better of me and I ask what's happening.
"Look at this," goes Wally 1, and I indeed move over to see him toiling in the debugger through a Hashtable with String keys. He's looking at its bucket array, to be precise. "Java is broken! I added a new value with the same hash value for the key, and it just replaced my old one! Look, my old value was here, and now it's the new one!"
"Oh yes, we had that bug too at the former company I worked for," chimes in Wally 2. "We had to set the capacity manually to avoid it."
I clench my teeth to stop myself from screaming.
"Hmm," I play along, "expand that 'next' node, please."
"No, you don't understand, my value was here and now there's this other key there."
"Yes, but I want to see what's in that 'next' node, please."
So he clicks on it and goes, "Oh... There it is..."
Turns out that neither of them had the faintest fucking clue what a hash table is, or for that matter what a linked list is. They looked at its hash bucket and expected nothing deeper than that. And, I'm told, at least one of them had been in a project where they actually coded workarounds (that can't possibly do any difference, too!) for its normal operation.
ACT II
So I'm consulting at another project and essentially they use a HashMap with string keys too. Except they created their own key objects, nothing more than wrappers around a String, and with their own convoluted and IMHO suboptimal hash value calculation too. Hmm, they must have had a good reason, but I ask someone.
"Oh," he goes, "we ran into a Java bug. You can see it in the debugger. You'd add a new value whose key has the same hash value and it replaces yours in the array. So Ted came up with an own hash value, so it doesn't happen any more."
Ted was their architect, btw. There were easily over 20 of them merry retards in that project, including an architect, and neither of them understood:
A) that that's the way a hash table works, and more importantly
B) that it still worked that way even with Ted's idiotic workaround. It's mathematically impossible to code a hash there which doesn't cause the same collisions anyway, and sure enough Ted's produced them too.
ACT III
I'm talking to yet another project's architect, this time a framework, and, sure enough...
"Oh yeah, that's the workaround for a bug they found in project XYZ. See, Java's HashMap has a bug. It replaces your old value when you have a hash collision in the key."
AAARGH!
So I'm guessing it would still be useful if more people understood these things. We're not just talking abstract complaints about cargo-cult programming without understanding it. We're talking people and sometimes whole teams who ended up debugging into it when they had some completely unrelated bug, and spent time on it. And then spent more time coding "workarounds" which can't possibly even make any difference. And then spent more time fixing the actual bug they had in the first place.
Re:True story (Score:5, Insightful)
Of course, this doesn't hold true 100% of the time, especially when you're pushing the limits of new versions of large 3rd party libraries, but when one is just starting to program (and hence using very well known, well tested libraries and code) it's true 99.99% of the time.
(Oh, btw, I love your sig. Makes me laugh every time.
Re:True story (Score:5, Insightful)
>>If you think you've found a bug in a compiler, or an operating system, or a programming language, or a well-known commonly used library... you're wrong.
You apparently never tried doing template coding in C++ ten years ago. =)
Re:True story (Score:4, Informative)
It's all too-often that people get the wrong view of a program using the debugger, either because it's not showing what's really there, or they're not interpreting it right. If you think something's wrong based on what you see in the debugger, write a test program first. More often than not, the test program will pass. After all, the compiler's job is to output code which meets the language specification regarding side-effects, not to make things look right in the debugger. In this case, the developer should have written a simple test which inserted two different values that had the same hash code, and verified that he really could only access one of them in the container. He would have found that they were both still there.
Re:True story (Score:4, Funny)
So Wally 1 keeps clicking and staring at the screen all week and spewing things like "Unbelievable!" every 5 minutes. My curiosity gets the better of me and I ask what's happening.
Is it just me who would be_much_ more tempted to say, "You keep using that word. I don't think it means what you think it means."
(Yes, I know it's a slight misquote, but it's close enough to be really tempting...)
Re:True story (Score:5, Interesting)
Though it's probably unfair to call both Wally, since at least one looks like the hard working kind... he just makes as much progress as a courier on a treadmill.
The hard working kind is the worst, because a manager can't really see why such a team member isn't working out.
I used to work with one of those. This Wally was very smart, a genius in fact; extremely articulate and fluent in several world languages, a PhD, a decade of experience as an architect and developer for various high profile customers. A fantastic work ethic: worked 10 hours a day, meticulously tested everything they checked in so that the countless bugs this person checked in never showed up in normal user testing. Race conditions, memory leaks, thread safety, thousands upon thousands of lines of unreachable code, countless more lines of workarounds for supposed bugs in 3rd party tools that were actually the proper results to their improper input.
Re:True story (Score:5, Insightful)
Re: (Score:3, Insightful)
Even more puzzling to me is how someone could decide to use a data structure without understanding its behavior (and without at least checking the Java APIs or simply Googling).
Easy. They learned that they should use *insert class here* in Intro to Programming 1 or 2 and never thought about it again since then. Horrendous overuse of StringBuilders is probably the most common example of this, but it can apply to just about anything.
Re:True story (Score:5, Insightful)
Well, obviously all 3 above knew how to use a Hashtable or HashMap, but neither knew what they really do and all ended up trying to fix what's not broken.
But the real answer I'm tempted to give is more along the lines of the old wisecrack: In theory there's no difference between theory and practice. In practice there is.
In theory, people shouldn't know more than what collection to use, and they'll be perfectly productive without more than a Java For Dummies course. In practice I find that the people who understand the underlying machine produce better code. Basically that you don't need to actually program anything in ASM nowadays, but if you did once, you'll produce better code ever after. You don't need to chase your own pointers in Java any more, but you _can_ tell the difference between people who once understood them in C++ and those who still struggle with when "x=y" is a copy and when it holds only a reference to the actual object. You theoretically don't need to really know the code that javac generates for string concatenation, but in practice you can tell the difference in the code of those who know that "string1=string2+string3" spawns a StringBuffer too and those who think that spawning their own a StringBuffer is some magical optimization. Etc.
And then there are those who are living proof that just a little knowledge is a dangerous thing. I see people all the time who still run into something that was true in Java 1.0 times, but they don't understand why or why that isn't so any more.
As a simple example, I run into people who think that to rewrite:
as
... is some clever optimization, and it speeds things up because Java doesn't have to check the extra bounds on i any more.
In reality it's dumb and actually slower, instead of being an optimization. Any modern JIT (meaning since at least Java 1.2) will see that the bound was already checked, and optimize out the checking in the array indexing. So you have exactly one bounds check per iteration, not two. But in the "optimized" version, it doesn't detect an existing check, so it leaves in the one at the array indexing. So you _still_ have one bounds check per iteration. It didn't actually save anything. But this time the exit is done via an exception, which is a much more expensive thing.
For bonus points, it introduces the potential for another bug: what if at some point in the future the doSomething() method throws its own ArrayIndexOutOfBoundsException? Well, they'll get a clean exit out of the loop without processing all values, and without any indication that an exception has occured.
Such stuff happens precisely to people who don't understand the underlying machine, virtual or not.
Re:True story (Score:4, Insightful)
LOL, I used to believe that, but I can now reliably make SunPRO, GCC and MSVC miscompile things. SunPRO has a bug where it always considers children of friends to be friends. SunPRO occasionally constructs locals when an exception should have caused flow control to leave the block earlier. GCC insists on copying temporaries passed by const reference. SunPRO outright crashes when you try templating on a member function pointer type. MSVC incorrectly mangles names of symbols in anonymous namespaces contained within other namespaces. GCC won't find global operators inside a namespace that contains operators, even for completely unrelated types. Giving GCC the same specific register constraint for an input and output of an inline assembly block will cause miscompilation - you need to use numeric constraints. People say that I only find this stuff because I'm digging around in the dark corners of the language where no-one else goes. It still sucks to be tearing my hair out over it, though.
And more cargo-cultism (Score:5, Funny)
And a few more examples of cargo-cultism, from people who were untrained to understand what they're doing, but someone thought it was ok because the Java standard library does it for them anyway.
1. The same Wally 1 from the previous story had written basically this method:
Then he called it like this, to try to get around an immutable field in an object. Let's say we have an object called Name, which has an immutable String. So you create it with that string and can't change it afterwards. You have a getName() but not a setName() on it. So he tried to do essentially:
I understand that he worked a week on trying to debug into why it doesn't work, until he asked for help.
2. From Ted's aforementioned project:
So they used the wrapper classes like Integer or Character all over the place instead of int or char. This was back in Java 1.3 times too, so there was no automatic boxing and unboxing. The whole code was a mess of getting the values boxed as parameters, unboxing them, doing some maths, boxing the result. Lather, rinse, repeat.
I ask what that's all about.
"Oh, that's a clever optimization Ted came up with. See, if you have the normal int as a parameter, Java copies the whole integer on the stack. But if you use Integer it only copies a pointer to it."
AAARGH!
Premature optimizations (Score:5, Informative)
"The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet." - Michael A. Jackson
That being said, when I hit the experts only situation I can usually get 2 orders of magnitude improvement in speed. I just then have to spend the time to document the hell out of it so that the next poor bastard who maintains the code can understand what on earth I've done. Especially given that all too often I am this poor bastard.
Re:Some, not all... (Score:4, Interesting)
This reminds me of a very educational example [perlmonks.org]. On Perl forums sometimes the question arises: which is faster - single quotes or double quotes, the difference being that the latter interpolates variables.
People in the know pointed it out multiple times that the single vs. double quote issue is a benchmarking mistake. See, Perl is a VM based language, with compile time optimizations. The code that people write as single or double quotes gets compiled down to the same thing. This is the kind of knowledge that is useful, knowing a bit of the theory and design of the underlying language, instead of having benchmark results, but not knowing how to interpret the results...
Re:Some, not all... (Score:4, Insightful)
When performance starts to matter, and my profiling tool indicates that the sorting algorithm is to blame, then I'll consider using an alternate algorithm.
Sure, that profiler might say that you are taking n% of your time in it, but how are you going to objectively know that that n% can be reduced significantly? Is your profiler an artificial inteligence?
..and finally.. being ignorant is not something to be proud of. Seriously. Your answer to discovering that the canned solution isnt acceptable is to "buy more hardware." Developers don't get to make that decision. Customers do... and thats assuming the hardware exists. If I was your boss I would fire you immediately for being a willfully ignorant bad programmer.
That, my friend, is the problem with canned solutions. You never really know if the implementation is decent, and in some cases you don't even know what the algorithm used is. Still further, if you are a clueless canned solution leverager, you probably don't know the pitfalls associated with a given algorithm.
Do you know what triggers quicksorts worst case behavior?
Do you know why a boyer-moore string search performs fairly badly when either string is short?
Do you know the worst case behavior of that hash table implementation? Do you know what the alternatives are? What is its memory overhead?
Are any of the canned solutions you use cache oblivious?
Now lets get into something serious. Algorithmic performance deficiencies are often used in Denial of Service attacks, and any time you use a canned solution you are setting yourself up as an easy target. Your profiler will never tell you why your customer is experiencing major problems, because the attack isn't on your development machine(s.)
Re: (Score:3, Insightful)
Lemme just review your *ahem* "arguments":
Because they're dead simple
Your first key point is that programmers must understand them because they're simple??? Um...
and if you don't know how they work you won't write good code.
Now you're asserting that it's impossible to write good code unless you understand these things. So all of good programming hinges on this? That's incredible! </sarcasm>
If you aren't, you're not qualified to program. Period.
Heehee!
Try this one: thinking logically is critical to being qualified to program.
Re:Some, not all... (Score:4, Insightful)
I'm thinking perfectly logically. If you don't understand and can't replicate the concepts that underpine your craft, you aren't qualified to practice it. It's like a physicist who can't understand force, or a mathematician who doesn't understand the first fundamental theory of calculus. They aren't capable of doing their job. Apparently this includes you.
Re:Some, not all... (Score:5, Insightful)
I'll agree with you for most of what you said, but I disagree that programmers should learn to implement sorting algorithms. Unless they're doing serious research on the subject it's doubtful that Joe Programmer is going to be whipping up a sorting algorithm that's better than the one provided.
What you're suggesting here isn't like a mathematician not understanding calculus. It's more like a mathematician only having pi memorized to the 8th decimal. I see zero value in learning to parrot quicksort, especially since the information is easily obtained and the implementation you use is almost certainly as fast as is possible (assuming you aren't Abrash).
Re:Some, not all... (Score:5, Insightful)
but I disagree that programmers should learn to implement sorting algorithms.
Dead wrong. Every programmer worthy of the name must be able to implement the basic data structures and algorithms, understand Big-O notation, and be able to do fault isolation (this last one is tricky). This is the lowest bar.
Re:Some, not all... (Score:4, Insightful)
I don't think you read my post very thoroughly, because I'm pretty sure I didn't say what you clearly think I said.
My argument is that learning to implement a sorting algorithm will not impart special knowledge beyond the experience that can be attained by completing virtually any other task. Like I said above, I see absolutely zero value in the ability to recite a particular solution from memory.
By restating my argument from memory I have successfully completed a similar task to the one you are challenging your contemporaries with. Literally anybody could read the Wikipedia article about the Bubble Sort and write their own implementation based on it. In a similar vein, I am reiterating my previous point. Both the aforementioned hypothetical programmer and I could have accomplished the same task by copying and pasting earlier efforts.
Re:Some, not all... (Score:5, Insightful)
the problem is that you're conflating two different things. the "ability to recite a particular solution from memory" is largely, i'd agree, useless in most cases. but that's not really what this is about. the process of learning imparts special knowledge beyond what is learned. you begin to understand the "whys" of things in ways that you simply cannot if you've never learned the thing.
in most ways, statements of the form "you must know X" are really proxies for statements of the form "you must have learned X" (even current retention is less important), mostly because they're so much easier to verify.
Re:Some, not all... (Score:5, Insightful)
Number of times I've had to implement sorting algorithms in my 10 year career: 0
They make good teaching exercises, but any programmer in my team who wasted time building their own sorting algorithms rather than using a library function, would get a few sharp words about efficiency.
Re:Some, not all... (Score:4, Insightful)
As an aside, you could also argue that programmers should have a good grasp on design patterns, requirements, planning, etc... Which seems to fall under the title of software engineer now. My CS department to date has required me to take a single SE course since I've been here and it'll be the only one I'll take.
'Programmer' is too vague a description, as it is just one who programs, regardless of how they learned, why they are programming, what they are programming, etc... It could be someone writing Lisp for their Masters/PhD research, some web designer writing javascript for their new website, or a CE/EE writing assembler for a new driver/BIOS for hardware.
Re:Some, not all... (Score:4, Interesting)
I suppose it depends on what the programmer is doing. A programmer that does little more than code web scripts that interface with previously coded databases.... yeah, they can probably manage to have a career doing that and not ever need to code a sorting algorithm, or do anything equally complicated. However, if you're tasked with writing a game, or a OCR scanner, or a natural language parser, fundamental concepts of "obsolete" functions such as sorting suddenly will become extremely important. Not so much because you're going to need to suddenly learn how to program a computer to sort a bunch of integers, but you might be faced with a multidimensional structure with millions of elements and need to come up with an efficient way to organize and access it... and previously coded "sort" algorithms aren't probably going to be of much help. You're going to want to have some idea of where to start.
-Restil
Re:Some, not all... (Score:4, Insightful)
I'll agree with you for most of what you said, but I disagree that programmers should learn to implement sorting algorithms. Unless they're doing serious research on the subject it's doubtful that Joe Programmer is going to be whipping up a sorting algorithm that's better than the one provided.
That is completely missing the point. Nobody is expecting the average programmer out there to write a superior sorting library.
Your example of a sorting algorithm being related to decimals in pi is completely bonkers. You're really comparing learning and comprehending an ALGORITHM to memorizing digits? If you (and I don't mean you specifically) don't understand how sort algorithms work, if you don't understand linked lists, etc--and furthermore, think learning them is unnecessary rote memorization--I'd bet a years pay that you're producing shit code and probably not even realizing it.
Re:Some, not all... (Score:5, Insightful)
*different* AC
Why, why, why do people get SO offended when you tell them they have to learn computers to be good at computers?
People expect to learn engineering to be a mechanic. To study biology if they want to be a surgeon. Hell, to read a cookbook just to learn how to cook.
But answer "How do I program?" with "Well, there's this manual, see..." and you get "Elitist! Elitist! Hey everybody, come see the arrogant condescending elitist who's persecuting me! Come and see the violence inherent in the sys-teeeem!"
Fine then, let's start telling everybody it's magic. Get some chicken bones and some goat's blood and some black candles...
Because most people do it in an insulting way (Score:4, Insightful)
Why, why, why do people get SO offended when you tell them they have to learn computers to be good at computers?
Because you're essentially attacking them.
What if I responded to you by saying: "I'm sorry, but if you don't understand how flatly attacking people's qualifications for their job is insulting and threatening, you shouldn't be having this discussion. You simply don't have the interpersonal skills to articulate this kind of thing in a manner that would be productive, let alone persuasive."
Get your dander up at all?
And please don't hide behind the "I was just stating a fact, if the shoe fits, wear it." There are lots of good ways to say what you're trying to get at that are probably even closer to the truth.
Which is that really don't have to learn *everything* about computers in order to be good at computers. It is certainly an underlying truth that the more you know, the better you are as a developer. But it's entirely possible to be a reasonably productive developer without knowing everything... as long as your abilities are matched to what you need to accomplish. And there's more or less a curve of task difficulty to go along with a curve of developer abilities.
I don't know very much about building compilers. Some people would say that makes me a mere dilettante of a software developer. That's a rash overstatement. It's absolutely true I would be a *better* developer if I knew more about these things, and certain problem domains would be more open to me, but there's a huge problem space that really doesn't require this knowledge. This works the other way, too: I probably know more about Linear Algebra and Discrete Mathematics than many developers and even some CS majors (studied Math in school) and I'm familiar with the Logic Programming paradigm (written full programs in Prolog). These things make me a better developer, particularly for some problem domains, but it certainly doesn't mean anyone who doesn't know these things is a simple hack.
I think implementing hashes and other primitives that are now part of libraries/languages falls in this category. Being able to implement them is certainly a *demonstration* that you've mastered certain skills. The contrapositive doesn't necessarily follow. Not ever having implemented them -- in particular because you've never had to -- doesn't necessarily imply that you lack the ability to solve that class of problem.
And in fact, it might demonstrate a certain stripe of wisdom: there's a limited amount of time and a pretty much infinite supply of problems. What do you spend time learning how to do?
Re:Some, not all... (Score:5, Insightful)
If you don't understand and can't replicate the concepts that underpin your craft, you aren't qualified to practice it.
Well put. Saying that sorting algorithms are readily available in libraries for virtually all platforms, and thus that modern programmers need not learn them, is just wrong. It's like saying that an engineer need not know about moments of inertia when designing a beam, because he can click a button on his design software to tell him the rigidity. Or like a mechanic not knowing how to use a spanner because he has an air gun available.
I probably couldn't code a particularly efficient quicksort, for example, off the top of my head - but I certainly understand how it works. Contrary to what Unoriginal_Nickname says below, it's not like a mathematician not memorising Pi past 8dp, it's more like a mathematician not ever learning what Pi is because he has a computer program that he can use to calculate the circumference of a circle.
Re:Some, not all... (Score:4, Insightful)
In almost all cases, all I need to know about sorting is how to use the built-in function, and a general idea of how efficient it is. In the other cases, I can consult Knuth or Wikipedia.
I don't happen to remember right now how Quicksort works in detail enough to write, and I don't even know what algorithm the C++ STL sort I use uses. Last time I needed to know something like that, it was heapsort, and that was years ago. I have understood quicksort in the past, and wouldn't require more than a few minutes to brush up on it, but as long as I know what it does and what its performance is like I don't need to know the details.
Similarly, I've forgotten a lot of my parsing theory, and don't remember offhand what separates LALR(1) from a more general LR(1) parser, but I seem to be able to use compilers and come up with a usable YACC grammar.
It's certainly worth learning this stuff at some point, and you do need to understand the implications of what you're doing, but I find that what I've forgotten about algorithms that are built into every programming language I use has never been a problem.
Re:Quicksort (Score:5, Insightful)
1) Don't optimise.
2) (Experts only:) Optimise later.
Or as I once read it eloquently expressed:
1) Make it work.
2) Make it work right.
3) Make it work fast.
Re:Some, not all... (Score:5, Insightful)
Maybe you guys are frozen in time - or maybe you're some kind of elitist-coder types.
From where I stand, the most relevant optimizations have to do optimizing the data flows between systems - the most typical of which are appServer-database and GUI-appServer and between storage and memory. We're talking about shaving hundreds of miliseconds, maybe even seconds per-operation: not nanoseconds.
Even if you work in standalone, small size applications, were knowing the basic principles of algorithms can be more important, hand-coding your own is not only useless (there are plenty of libraries out there with good implementations) it's actually counter productive (it introduces a complex piece of code which is often not properly tested and might be even slower than the library ones)
Understanding the basic principles = important.
Being able to code your own = only important for those who never evolved beyond just-a-coder.
Re:Some, not all... (Score:4, Interesting)
You mustn't do any real-time processing with any serious volumes of data. I do market data systems for my day job. All the microseconds I can save add up. Yesterday, I knocked several seconds off the time required to do an initial load by getting rid of some redundant copying that was going on. Today I improved the response latency for certain market events by changing the data type used for a key in a map. You might not need to understand when you're doing typical desktop applications, but you'll have to be content being a hack. The real software engineers will always have to understand.
Re:Some, not all... (Score:4, Insightful)
I'm a mathematician who works as a programmer. My apologies for not fitting into your simplistic argument.
(My job requires plenty of mathematical knowledge, and a maths background was more appropriate for my job than computer science, despite being a programmer.)
Perhaps we should take it further - surely by your reasoning, only a Bubble Sortist needs to know how to hand code a Bubble Sort under exam conditions, but other kind of programmers don't? After all, it's surely not possible that different fields may cross over, and that different people have different experiences.
What I would value far more is not someone who can regurtitate his college days where he memorised line by line an algorithm that you shouldn't be using anyway, rather, someone who can hand code any given algorithm as and when he needs to, when he hasn't previously memorised it - that could be a bubble sort if he hasn't previously learnt it, but it's even better to test that with other things.
Furthermore, for standard algorithms I would value someone who reads up about the algorithm, and preferably uses a standard version, to ensure optimised usage, no bugs, and to know about it's flaws (as is obviously the case with bubble sort), or whether they should be using it at all. Far better than that then someone who only shows off his skills by hacking together a quick version from memory without doing any checks.
Re:Some, not all... (Score:5, Insightful)
while we are being pedantic...
From TFA: "most text editors instantly tell you the variable type"
a *text editor* should do no such thing.
Re: (Score:3, Insightful)
Another example: The computer can do exponentiation for you too, but actually understanding it will occasionally let you vastly improve the quality of your code.
Re:Some, not all... (Score:5, Insightful)
One problem I've seen with some programmers, is they use the built in libraries to solve all problems. I've seen C++ maps (ie, red-black trees) be used to implement something a trivial array could do (ie, they keys were an 8 value enumeration). They've got a hammer, and all problems look like nails.
It's not difficult to whip up data structures or algorithms that can beat the one-size-fits-all versions in language libraries. Of course, some people say "don't reinvent the wheel", but then there are applications where size and performance really do matter. Or maybe limited memory and limited CPU systems are considered too old school for some.
Re: (Score:3, Insightful)
I've seen C++ maps (ie, red-black trees) be used to implement something a trivial array could do (ie, they keys were an 8 value enumeration). They've got a hammer, and all problems look like nails.
Sure, it's excessive, but unless it's performance critical, I'd do the same thing - simpler and clearer usually trump faster these days.
Ya I would compare it to long division (Score:5, Insightful)
You don't need long division in normal life. Regardless of if you are in a math heavy career or not, you aren't going to waste your time doing it by hand, you'll use a calculator which is faster and more accurate. However, you need to learn it. You need to understand how division works, how it's done. Once you learn it, you can leave it behind and automate it, but it is still important to learn. An understand of higher level math will likely be flawed if basic concepts aren't learned properly.
Re:Ya I would compare it to long division (Score:4, Insightful)
Re:Ya I would compare it to long division (Score:5, Funny)
Re:Some, not all... (Score:5, Informative)
or that a for loop should be processed with >= 0 where possible (or split into a while loop) to reduce computation time.
This is an obfuscating micro-optimization with pitfalls (e.g. unsigned is always >= 0) and should not be a general rule. In many cases the compiler will do any optimization here automatically, and in other cases you need to profile first to make sure this is the bottleneck before obfuscating the code.
Re:Some, not all... (Score:5, Interesting)
I did a ton of work in THINK C 5 on Mac OS 7. Programming in C on a computer with no memory protection is something I never want to experience again. Misplace a single character, and it's reboot time-- for the 13th time today.
What's *really* weird is that at the time I didn't think that was particularly strange or difficult. It was just the way things were.
Re:Some, not all... (Score:5, Insightful)
Recently, I had a colleague ask me what sorting algorithm he should use in the inner loop of some algorithm he was implementing. Most CS majors I've talked to just blurt out "QUICKSORT!" without thought. Ok, that's got an average runtime of nlg(n). After about an hour of discussion and analysis, we came up with an algorithm that ran in sub-linear time. Now's the time for the CS kids to blurt, "ZOMG, but you can't sort in less than O(nlg(n)!" Ah, but you can, if you know what your input is going to look like.
When a function gets executed billions or trillions of times, it's worth optimizing. Often times, doubling the speed of a deep internal function does nothing -- other times, it can cut the runtime of your program in half. I come from a mathematical background, and I do lots of computation. Often times, it can take a year or more to solve a problem with a quick implementation. Spend a few weeks optimizing it, and you might be able to solve the problem in a few hours.
There is no substitute for analyzing your code. And I do mean, sitting down with a writing implement and a blank surface, and tracing through the algorithm. Then, profiling the code and hammering down hotspots. And then, take a page out of Knuth's book -- throw the code away, and write it again.
Punched cards - there was a machine for that (Score:3, Insightful)
I was an early adopter of the "let the machine do as much work as possible" school of thought.
Re:Punched cards - there was a machine for that (Score:5, Interesting)
Jeez. You must have taken the same course that I did. (Probably not actually.) In my case it was a programming class emphasizing statistics taught by someone in the business school who actually wanted card decks turned in. (This was probably no later than, maybe, '80/'81.) I did the same thing you did. I wrote all the software at a terminal (one of those venerable bluish-green ADM 3As) and when it was working I left the code in my virtual card punch. When I sent a message to the operator asking to have the contents sent off to a physical card punch, his message back was "Seriously?
Begone, common file format loaders! (Score:4, Interesting)
Get down to the metal (Score:4, Interesting)
Yeah, some of these are pretty old. I do remember working on a machine where the compiler wasn't smart enough to make the code really fast so I would get the .s file out and hand edit the assembly code. This resulted in some pretty spectacular speedups (8x for instance). Mind you, more recently I was forced to do something similar when working with some SSE code written for the Intel chips which was strangely slower on AMD. Turned out it was because the Intel chips (PIII and P4) were running on a 32 bit bus and memory access in bytes was pretty cheap. The Athlons were on the 64 bit EV6 bus and so struggled more so were slower. Once I added some code to lift the data from memory in 64 bit chunks and then do the reordering it needed using SSE the AMD chips were faster than the Intel ones.
Sometimes I think we have lost more than we have gained though with our reliance on compilers being smarter. It was great fun getting in there with lists of instruction latencies and manually overlapping memory loads and calculations. Also when it comes to squeezing the most out of machines with few resources, I remember being amazed when someone managed to code a reasonably competent Chess game into 1K on the Sinclair ZX81. Remember too that the ZX81 had to store the program, variables, and display all in that 1K. For this reason, the chess board was up at the left top of the screen. It was the funniest thing to be writing code on a 1K ZX81 and as the memory got full you could see less and less of your program until the memory was completely full and you could only see one character on screen....
Universal timeless programmer problem (Score:5, Funny)
What a retard! (Score:5, Insightful)
First of all, most actual practices mentioned are well alive today -- it's just most programmers don't have to care about them because someone else already did it. And some (systems and libraries developers) actually specialize on doing just those things. Just recently I had a project that almost entirely consisted of x86 assembly (though at least 80% of it was in assembly because it was based on very old code -- similar projects started now would be mostly in C).
Second, things like spaghetti code and Hungarian notation are not "old", they were just as stupid 20 years ago as they are now. There never was a shortage of stupidity, and I don't expect it any soon.
Dirty old Fortran (Score:4, Interesting)
Hollerith constants
Equivalences
Computed Gotos
Arithmetic Ifs
Common blocks
There were worse things, horrible things... dirty tricks you could play to get the most out of limited memory, or to bypass Fortran's historical lack of pointers and data structures. Fortran-90 and its successors have done away with most of that cruft while also significantly modernizing the language.
They used to say that real men programmed in Fortran (or should I say FORTRAN). That was really before my time, but I've seen the handiwork of real men: impressive, awe-inspiring, crazy, scary. Stuff that worked, somehow, while appearing to be complete gibberish -- beautiful, compact, and disgustingly ingenious gibberish.
Long live Fortran! ('cause you know it's never going to go away)
Re:Dirty old Fortran (Score:4, Funny)
Years ago I programmed with a true genius. His language of choice was PL/1, but sometimes he had to use FORTRAN to fit in with what other people were doing. Any fool could write FORTRAN code in any language they wanted, but he was the only man I ever saw write PL/1 in FORTRAN.
Re: (Score:3, Interesting)
Hollerith constants Equivalences Computed Gotos Arithmetic Ifs Common blocks
There were worse things, horrible things... dirty tricks you could play to get the most out of limited memory, or to bypass Fortran's historical lack of pointers and data structures.
Long live Fortran! ('cause you know it's never going to go away)
Didn't most of the tricks just boil down to "Define one big integer array in a common block and then pack all your data, whatever its type, into that"? All my PhD research was done with code like that. It was mostly written by my supervisor years and years before even that and I never actually learned how it worked.
Fortran implicit integers (Score:5, Informative)
For some reason the article says that only variables beginning with I,J,and K were implicitly integers in Fortran. Actually, it was I-N.
Re: (Score:3, Informative)
Re:Fortran implicit integers (Score:5, Informative)
Nonsense, it's simply because i - n commonly is used to denote integer variables (sum x_i from 1 to n) i mathematical notation. This is a practice dating back at least to Gauss.
Duff's Device (Score:5, Interesting)
Some of those are just wrong (Score:5, Informative)
First off, most of the things on the list haven't gone away, they've just moved to libraries. It's not that we don't need to understand them, it's just that not everyone needs to implement them (especially the data structures one- having a pre-written one i good, but if you don't understand them thoroughly you're going to have really bad code)..
On top of that, some of their items
*Memory management- still needs to be considered about in C and C++, which are still top 5 languages. You can't even totally ignore it in Java- you get far better results from the garbage collector if you null out your references properly, which does matter if your app needs to scale.
I'd even go so far as to say ignoring memory management is not a good thing. When you think about memory management, you end up with better designs. If you see that memory ownership isn't clearcut, it's usually the first sign that your architecture isn't correct. And it really doesn't cause that many errors with decent programmers(if any- memory errors are pretty damn rare even in C code). As for those coders who just don't get it- I really don't want them on my project even if the language doesn't need it. If you can't understand the request/use/release paradigm you aren't fit to program.
*C style strings
While I won't argue that it would be a good choice for a language today (heck even in C if it wasn't for compatibility I'd use a library with a separate pointer and length), its used in hundreds o thousands of existing C and C++ library and programs. The need to understand it isn't going to go away anytime soon. And anyone doing file parsing or network IO needs to understand the idea of terminated data fields.
Re:Some of those are just wrong (Score:4, Insightful)
you get far better results from the garbage collector if you null out your references properly, which does matter if your app needs to scale.
You don't get any difference at all if you null out local variables. In fact, you may even confuse the JIT into thinking that the variable lifetime is larger than it actually has to be (normally, it is determined by actual usage, not by lexical scope).
Yes, I'm old (Score:5, Insightful)
* Sorting algorithms
If you don't know them, you're not a programmer. If you don't ever implement them, you're likely shipping more library code than application code.
* Creating your own GUIs
Umm.. well actually..
* GO TO and spaghetti code
goto is considered harmful, but it doesn't mean it isn't useful. Spaghetti code, yeah, that's the norm.
* Manual multithreading
All the time. select() is your friend, learn it.
* Self-modifying code
Yup, I actually write asm code.. plus he mentions "modifying the code while it's running".. if you can't do that, you shouldn't be wielding a debugger, edit and continue, my ass.
* Memory management
Yeah, garbage collection is cheap and ubiquitous, and I'm one of the few people that has used C++ garbage collection libraries in serious projects.. that said, I've written my own implementations of malloc/free/realloc and gotten better memory performance. It's what real programmers do to make 64 gig of RAM enough for anyone.
* Working with punch cards
Meh, I'm not that old. But when I was a kid I wrote a lot of:
100 DATA 96,72,34,87,232,37,49,82,35,47,236,71,231,234,207,102,37,85,43,78,45,26,58,35,3
110 DATA 32,154,136,72,131,134,207,102,37,185,43,78,45,26,58,35,3,82,207,34,78,23,68,127
on the C64.
* Math and date conversions
Every day.
* Hungarian notation
Every day. How about we throw in some reverse polish notation too.. get a Polka going.
* Making code run faster
Every fucking day. If you don't do this then you're a dweeb who might as well be coding in php.
* Being patient
"Hey, we had a crash 42 hours into the run, can you take a look?"
"Sure, it'll take me about 120 hours to get to it with a debug build."
Self-modifying code has been a lose for a decade. (Score:5, Informative)
Self-modifying code
Yup, I actually write asm code.. plus he mentions "modifying the code while it's running".. if you can't do that, you shouldn't be wielding a debugger.
Code that generates code is occasionally necessary, but code that actually modifies itself locally, to "improve performance", has been obsolete for a decade.
IA-32 CPUs still support self-modifying code for backwards compatibility. (On most RISC machines, it's disallowed, and code is read-only, to simplify cache operations.) Superscalar IA-32 CPUs still support self-modifying code. But the performance is awful. Here's what self-modifying code looks like on a modern CPU:
Execution is going along, with maybe 10-20 instructions pre-fetched and a few operations running concurrently in the integer, floating point, and jump units. Alternate executions paths may be executing simultaneously, until the jump unit decides which path is being taken and cancels the speculative execution. The retirement unit looks at what's coming out of the various execution pipelines and commits the results back to memory, checking for conflicts.
Then the code stores into an instruction in the neighborhood of execution. The retirement unit detects a memory modification at the same address as a pre-fetched instruction. This triggers an event which looks much like an interrupt and has comparable overhead. The CPU stops loading new instructions. The pipelines are allowed to finish what they're doing, but the results are discarded. The execution units all go idle. The prefetched code registers are cleared. Only then is the store into the code is allowed to take place.
Then the CPU starts up, as if returning from an interrupt. Code is re-fetched. The pipelines refill. The execution units become busy again. Normal execution resumes.
Self-modifying code hasn't been a win for performance since the Intel 286 (PC-AT era, 1985) or so. It might not have hurt on a 386. Anything later, it's a lose.
Re: (Score:3, Informative)
A lot of RISC machines do support it, it's required and mandatory if only to load new exception handler routines, boot loaders, program loaders, etc. Even for debuggers you've got to drop a trap instruction at the breakpoints. Of course, if you never leave user mode then you may not ever have to worry about it.
I don't expect the average programmer to have to deal with this, cache flushing, pipeline synchronization, etc. But definately a lot of embedded programmers need to know it, and operating system wr
Re: (Score:3, Interesting)
I still remember little dribs and drabs, like "032 210 255" was the assembled code for JSR $FFD2
Re:Yes, I'm old (Score:4, Interesting)
I write web apps. I never have to sort anything, except when I ask the database to give me data in a certain order. Why would it be useful for me to implement and be intimately familiar with sorting algorithms? I haven't used them since college.
Re: (Score:3, Informative)
However, "making code run faster" is what you do after the code runs, and does what it's supposed to do, and is modular, flexible, and maintainable.
Yeah, and you say this like you've never experienced it. Honestly, if you're writing new code you're in the vast minority of programmers.. or you're just playing around. Most of us are working on code that was written years ago and has to keep doing what it does or the company will lose money.
I'm a web developer
Ahh, I see.
I'm.. not.
Re: (Score:3, Informative)
Being initially correct is far more important for nailing down what you are trying to do than being FAST.
Premature optimisation is a sure fire way to shoot yourself in the foot. Who cares if a function that is called on a rather minimal basis is slow but understandable and easily verifiable as CORRECT?
Write a prototype, *profile it*, THEN put on your optimisation hat.
I don't care how fast your code gives me incorrect output.
Memory Management (Score:3, Insightful)
Try overlays...
Back in the day we had do all the memory management by hand. Programs (FORTRAN) had a basic main "kernel" that controlled the overall flow and we grouped subprograms (subroutines and functions) into "overlays" that were swapped in as needed. I spent hours grouping subprograms into roughly equal sized chunks just to fit into core, all the while trying to minimize the number of swaps necessary. All the data was stored in huge COMMON blocks so it was available to the subprograms in every overlay. You'd be fired if you produced such code today.
Virtual memory is more valuable than full screen editors and garbage collection is just icing on a very tall layer cake...
radio in the computer case (Score:5, Interesting)
Circa 1984, when I did summer programming jobs at Digital Research (purveyors of CP/M), one of the programmers there showed me how you could put a transistor radio inside the case of your computer. You could tell what the computer was doing by listing to the sounds it picked up via the RF emissions from the computer. For instance, it would go into a certain loop, and you could tell because the radio would buzz like a fly.
Documentation was a lot harder to come by. If you wanted the documentation for X11, you could go to a big bookstore like Cody's in Berkeley, and they would have it in multiple hardcover volumes. Each volume was very expensive. The BSD documentation was available in the computer labs at UC Berkeley in the form of 6-foot-wide trays of printouts. (Unix man pages existed too, but since you were using an ADM3A terminal, it was often more convenient to walk over to the hardcopy.)
On the early microcomputers, there was no toolchain for programming other than MS BASIC in ROM. Assemblers and compilers didn't exist. Since BASIC was slow, if you wanted to write a fast program, you had to code it on paper in assembler and translate it by hand into machine code. But then in order to run your machine code, you were stuck because there was no actual operating system that would allow you to load it into memory from a peripheral such as a cassette tape drive. So you would first convert the machine code to a string of bytes expressed in decimal, and then write a BASIC program that would do a dummy assignment into a string variable like 10 A$="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx". Then you would write self-modifying code in BASIC that would find the location where the string literal "xxx...." was stored, and overwrite it with your machine code. So now if you gave the LIST command, it would display the program on the screen, with the string literal displayed as goofy unprintable characters. Then you would code the program so it would execute the machine code stored at the address of the variable A$. Finally you'd save the program onto cassette.
No programming language... (Score:4, Insightful)
You will never find a programming language that frees you from the burden of clarifying your thoughts.
http://www.xkcd.com/568/
The Story of Mel (Score:5, Informative)
Remember "inside out" coding? (Score:3, Informative)
"Top-down" coding produced readable but horribly inefficient code. Doesn't do any good for the code to work if it doesn't fit in the e-prom.
"Bottom up" code produced reasonably efficient spaghetti. Good luck remembering how it worked in 6 months.
"Inside-out" coding was the way to go.
You wrote your inside loops first, then the loop around that, then the loop around that. Assuming the problem was small enough that you could hold the whole thing in your head at one time, the "inside-out" technique guaranteed the most efficient code, and was moderately readable.
At least, that's the way I remember it. 'S been a long time...
Now, these new-fangled tools do all the optimizing for you. 'S taken all the fun outta coding.
swapping two values without a temporary variable (Score:5, Interesting)
y = x xor y
x = x xor y
Now you know!
Re:swapping two values without a temporary variabl (Score:4, Insightful)
Re: (Score:3, Insightful)
You're missing the point---it breaks when one of the variables is a reference to the other.
It's a neat algorithm, but the case in which it fails just goes to show that these skills aren't irrelevant. Yes, you should know what a reference is. Using your compiler and libraries as a crutch for your lack of understanding leads to unpleasant bugs.
Old school coding problems... (Score:3, Funny)
1. Writing on a slate. Man, did that compile slow!
2. When you heard "stack," it meant firewood.
3. The error message was a ruler across the knuckles.
4. Memory overloads. My own memory, I mean.
5. If you wanted to change your resolution, you had to wait until New Years.
6. Try coding when you're drinking the original mountain dew.
7. The rantings of code guru SFBM, the inventor of open Morse code.
They missed the Apple ][ (6502) 16 bit index (Score:3, Interesting)
Back around 1980, the most common piece of self modifying code was to implement a 16 bit index read/write/goto instruction in the Apple ]['s (and Atari and C64) 6502 processor.
The processor has an 8 bit index register but to allow it to access more than 256 byte addresses, you could either create 256 versions of the operation (each one accessing a different 256 byte address block in memory) or put the function in RAM and modify the instruction that selected the 256 byte address block.
Sorry, I know longer have the code and my 6502 manuals are packed away, but I'm sure somebody out there remembers and has an example.
myke
New Headaches (Score:4, Insightful)
The biggest "new" headache that will probably end up in such an article 20 years from now is web "GUIs", A.K.A. HTML-based interfaces. Just when I was starting to perfect the art of GUI design in the late 90's, the web came along and changed all the rules and added arbitrary limits. Things easy and natural in desktop GUI's are now awkward and backassward in a browser-based equivalent.
Yes, there are proprietary solutions, but the problem is that they are proprietary solutions and require users to keep Flash or Active-X-net-silver-fuckwhat or Crashlets or hacky JimiHavaScript up-to-date, making custom desktop app installs almost seem pleasant in comparison, even with the ol' DLL hell.
On a side note, I also came into the industry at the tail end of punched cards (at slower shops). Once the card copy machine punched the holes about 1/3 mm off, making them not read properly, but on *different* cards each pass thru. It's like including 0.5 with binary numbers, or 0.4999 and 0.5001 with a quantum jiggle.
Good Times
Re: (Score:3, Interesting)
However, specific notation on some things IS a good thing. Conventions like CONSTANTS, m_memberVariables, and so forth are good because they remind you that the variable in question is an exception to wha
Re:Hungarian Notation (Score:4, Insightful)
Full Hungarian notation is a bit redundant, precisely because everyone (for reasonable values of 'everyone') DOES use some form of IDE to code, and any non-epic-fail IDE will at the least tell you variable types when you mouse over them, or pop up a member list for a class/struct when you go to type them.
Um - Hungarian notation is for coding what the variable represents, not the type of variable it's represented by.
Anyone using iVariable or sVariable to indicate that the former is an int and the latter is a string is doing it wrong.
It's this misunderstanding that's resulted in HN's 'bad' reputation.
See http://www.joelonsoftware.com/articles/Wrong.html [joelonsoftware.com] for an example of how HN should be used.
Re: (Score:3, Insightful)
Re:Hungarian Notation (Score:5, Insightful)
Hungarian notation is bad because you are encoding type and scope information into the name, which makes it harder to change things later.
The fact that it is also one of the ugliest naming conventions is merely a secondary issue.
Re: (Score:3, Informative)
Actually, this is exactly the reason I think Hungarian is useful. If you change a variable from, say, an unsigned int to a signed int, you had better check every place you use that variable to make sure that you didn't assume something about the type that now requires a different check. For example, underflow/overflow, indexing into an array, etc... By making you do
Re:Hungarian Notation (Score:4, Insightful)
Three reasons.
1)Variables change type. And then you have to rename everything. Its a pain
2)The extra information it gives you is minimal. I want to know what data is in a variable, not the language type used to hold it. If the name of the variable is firstName, I don't need it to be called lpcstrzFirstName, I know it's a string. And the language type is rarely interesting- I want to know that the variable outsideTemp holds degrees farenheit, not that it's an integer. But Hungarian doesn't tell me that. (It also doesn't work even if I make a typedef for temperature- it'll still start with 'i').
3)It makes searching the code for a variable that much more annoying, because they all start with freaking 'i' and 'p'.
Re:Hungarian Notation (Score:5, Informative)
Good Hungarian notation does exactly that, actually. Check out Apps Hungarian [wikipedia.org], which encodes the semantic type of the data, rather than the language-level data type.
Of course stupid Hungarian notation is stupid. Stupid anything is stupid. Problem is, most people don't hear about the right approach.
Re:Hungarian Notation (Score:5, Interesting)
Re:Hungarian Notation (Score:4, Insightful)
Good Hungarian notation does exactly that, actually. Check out Apps Hungarian, which encodes the semantic type of the data, rather than the language-level data type.
Good explicitly LONG where appropriate variable names that don't conform to a complex set of rules that need to be memorized are ALWAYS a better solution.
# rwPosition : variable represents a row ("rw");
Awful! For one extra character you get rowPosition which is unambiguous and doesn't need to be looked up.
# usName : variable represents an unsafe string ("us"), which needs to be "sanitized" before it is used (e.g. see code injection and cross-site scripting for examples of attacks that can be caused by using raw user input)
unsafeName or unsafeNameString would be much better. It doesn't imply this name only applies in the U.S.A.
Re:Hungarian Notation (Score:4, Interesting)
Re:Hungarian Notation (Score:5, Insightful)
Really it has nothing to do with IDEs, but more compilers, good coding practice and OO principles. A few cons:
For a succinct summary: Hungarian Notation Considered Harmful [erngui.com]
Re:Hungarian Notation (Score:4, Funny)
I don't get what the big deal is with Hungarian Notation. Why do people consider it a bad thing?
The proper name is Hungarian Line Noise, which should answer your question.
Re:Eliminate Structured Programming? (Score:5, Insightful)
Actually, the worst spaghetti code I have ever seen (in 30+ years most of it in life-critical systems) is OO C++. It doesn't have to be that way, but I have seen examples that would embarrass the most hackish FORTRAN programmers.
I am alarmed at the religious fervor and non-functional dogma associated with modern programming practices. Even GOTOs have good applications - yes, you can always come up with some other way of doing it, by why and with how much extra futzing? But it's heresy.
Brett
Re: (Score:3, Insightful)
The worst I saw in my ~25 years, and I include old COBOL and BASIC crap, was not spagetti in the strict sense of the word. It was a 10000 line Java method written by a VB developer. There were no gotos, but the entire thing was nested ifs switches and for loops nested to over 10 layers deep. Oh, and you did read that right, it was a method - the entire class had a solitary static method full of copy and pasted chunks. He explained that it was OO because it was Java. I might forgive him if it was gigantic ne
Re: (Score:3, Insightful)
The one application of "goto" that I swear by is for cleaning up allocations on failure when coding in C.
Maintaining a huge library of legacy C code, one of the most common bugs we see is leaks due to people using multiple "return" statements and failing to clean up allocations. You can fairly reliably pick such a function at random and find a memory leak: people always get it wrong.
"goto cleanup;" however, is hard to mess up.
I've seen any number of clever tricks to avoid the "goto". Using "break" statement
Re:Eliminate Structured Programming? (Score:4, Interesting)
"goto cleanup;" however, is hard to mess up.
hehe, have a look at Ian Kent's code in autofs sometime.
His use of "goto cleanup;" is an infinite source of double free bugs.
OO isn't even different. (Score:5, Insightful)
There is no practical difference between OO code and structured code. The article assumed structured code means goto and gosub, but any Real Programmer knows that procedures (which are just gosubs by name rather than address) are still structured programming.
So what's OO? Each class is just a bunch of functions and procedures, with one entry point and one exit point for each - your standard structured programming methodology. The fact that there are different classes makes no difference. Calls between classes don't change the nature of a class any more than pipes between programs change the nature of programs.
I wasn't impressed by other claims, either. Garbage collection is still a major headache in coding, which is why there are so many debugging mallocs and so many re-implementations of malloc() for specialist purposes. Memory leaks are still far, far too common - indeed they're probably the number 1 cause of crashes these days.
Pointer arithmetic? Still very very common. If you want to access data in an internal database quickly, you don't use SQL. You use a hash lookup and offset your pointer.
Sorts? Who the hell uses a sort library? Sort libraries are necessarily generic, but applications often need to be efficient. Particularly if they're real-time or HPC. Even mundane programmers would not dream of using a generic library that includes sorts they'll never refer to in, say, an e-mail client or a game. They'll write their own.
One of the reasons people will choose a malloc() like hoard, or an accelerated library like liboil is that the standard stuff is crappy for anything but doing standard stuff. This isn't the fault of the glibc folks, it's the fault of computers for not being infinitely fast and the fault of code not being absolutely identical between tasks.
The reason a lot of these rules were developed was that you needed to be able to write reusable code that also had a high degree of correctness. Today, you STILL need to be able to write reusable code that also has a high degree of correctness. If anything, the need for correctness has increased as security flaws become all the more easily exploited, and the need for reusability has increased as code bases are often just too large to be refactored on every version. (Reusability is just as important between versions as it is between programs - a thing coders often forget, forcing horrible API and ABI breakages.)
The reason that software today is really no better, stability-wise, than it was 15-30 years ago is that new coders think they can ignore the old lessons because they're "doing something different", only to learn later on that really they aren't.
Re:OO isn't even different. (Score:5, Informative)
Even mundane programmers would not dream of using a generic library that includes sorts they'll never refer to in, say, an e-mail client or a game. They'll write their own.
Erm, why the hell not? Good programmers, even the best programmers (in fact especially the best programmers), will just use qsort() (or the equivalent for the language they're using). Then, IF performance on their lowest-spec target hardware is unacceptable, they will profile their code and find out what's taking the time. And then, IF it's the sorting algorithm that's the bottleneck, only THEN will they implement a more specific version. Anything else is a waste of time and an additional risk of introducing unnecessary bugs.
Unless we're really pushing the boundaries (and those boundaries are so far away with modern computers that 99% of applications can't even SEE them from their cosy seat in the middle of userland) the stock sorting algorithm your language provides will be plenty fast enough. If you're using a high-level interpreted language, you'll never beat it in efficiency.
What you're saying may have been true 15, or even 10 years ago, but it's certainly not true now.
Re: (Score:3, Interesting)
Yeah, that was odd. I could see if the final field of each assembly instruction was an address and everything was aligned to 2-word boundaries (msb-first) or you didn't use memory passed a certain boundary (lsb-first) then you could save memory by compacting all the instructions by one bit (and then packing them together). Same for registers, or if didn't use instructions with op-codes over a certain threshold. But if you were really saving one bit per instruction and you managed to compress 7k into 5k, the
Re:Intellisense and Debuggers (Score:4, Insightful)
Re:They're still here! (Score:4, Informative)
The reason people say C++ is slower and uses more memory is because it is. Not due to the language itself (except for one case), but due to how people use it and the mistakes they make
1)RTTI and exceptions- very slow. If you use them you will be slower than C. Of course most embedded systems avoid them like the plague. (This is the one case where it's a language fault)
2)Passing objects. Its a frequent mistake that people forget to pass const object& rather thn the object itself, causing extra constructors and destructors to be called. Honest but costly mistake.
3)The object oriented model and memory. In an object oriented model you tend to do a lot more memory copying. In C, if you have an OS function that returns a string (a char*), you'll use generally save that pointer somewhere, use it directly a few times, then free it. In C++ you'll take it, insert it into a string object (which will cause a copy), pass that object around (and even by reference thats less efficient than using a char* directly), probably call c_str() on it if you need to pass it back to the OS, then finally let the destructor free it. More time.
4)The object oriented model and hiding complexity- it can be very easy in an object oriented system to forget the true cost of an operation. Programmers think of x=y as a cheap operation, like it is with ints. With objects, it may be very expensive. Same with other operations that happen "automatically" like string concatenation using +. It can be easy to write code that doesn't look too bad, but really takes thousands of cycles.
5)Constructors, copy constructors, and operator =- some of these can be called in very unusual places, especially when they're being passed to and/or returned from a function. Read Scott Meyers for a list of all of them. If you had a function that was passed in two Foo objects, mainpulated them, created a new Foo object, set it equal to one of the two passed in, and returned that Foo object I doubt 1 in 10 programmers would correctly guess all of the times these would be called (and I'm not that 1- it's been way too long since I studied the issue). In C these would be at worst 4 memcpys (two for pass in, 1 for assignment, 1 for return). So C++ object quirks can eat up a lot of time in these situations.
All that doesn't mean you shouldn't use C++. But due to it you won't get the sheer execution speed you would in C.