Old-School Coding Techniques You May Not Miss
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 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.
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.
Contrary to the popular belief, there indeed is no God.
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
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.
Dunx
Converting caffeine into code since 1982
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
Be careful. People in masks cannot be trusted.
* 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."
How we know is more important than what we know.
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.
It's a small world and it smells funny; I'd buy another if it wasn't for the money; Take back what I paid (SoM)
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.
My mother, who was programming before a fair few of us (including me) were born, once told me this: 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.
:)
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.
Rampant carbon sequestration destroyed the Dinosaurs' tropical paradise. I'm here to help repair the damage.
>>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. =)
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.
A polar bear is a cartesian bear after a coordinate transform.
I think you've got the bar a little high there. I'd settle for not continuing to run into bugs that result because people wrote code that copies a string into a buffer without knowing if the buffer was big enough to hold the string. Or, not quite a bug, people who place arbitrary, and small, limits on the size of strings (or numbers) - cause god forbid that anyone have a name longer than 12 characters, or a feedback comment longer than 40 characters, or ...
The tyrant will always find a pretext for his tyranny - Aesop
Um, I'm pretty sure quicksort is still the go-to sort simply because it's the implementation that's built into almost every single programming environment. Then again honestly, I'd say that from the point of view of a pragmatic programmer... it doesn't matter. There's a built-in fuction (whether it's qsort() in the C standard library, or Arrays.Sort() in Java, or whatever) that will take your array and return it, sorted. If your app runs too slow and you profile it and it turns out the speed problem is in the sorting AND you can't find a better algorithm that doesn't depend so much on sorting... THEN you look at optimising it. Never forget the two cardinal rules of optimising:
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.
Rampant carbon sequestration destroyed the Dinosaurs' tropical paradise. I'm here to help repair the damage.