Dear Log,
Now is the time for the telling of the horror story:
I always say that the worst code I ever "wrote", I didn't actually write -- I translated it. It was straight translation from BASIC code. Oh, but not just any BASIC code -- it was about a thousand lines of totally uncommented code that did some inscrutible scientific calculations that I needed to implement in Perl. Of course, the one person who wrote and understood that BASIC code, had long since gone mad, and no-one was available to explain any part of it to me.
It was in a BASIC dialect that ran only on Sharp programmable calculators! There were just 26 variables in the language, called "A" to "Z", all global of course. There was no gosub. There was no for/next. In fact, the only flow control structures in the language were an unconditional "goto line_number" and a conditional "goto line_number if condition". And that last "goto X if Y" was the only conditional structure in the language! So the code was NOT PRETTY.
After about a solid week of staring at this code, and plotting out what jumped to where, I figured out that the first half of the endless code was just for initialization and user-interaction, and had only one point of interaction with the real code that I needed to translate, which was the second half, which did all the figuring. So then I agonized over what to do with the second half. I eventually decided to just translate it line by line into Perl. It ended up being about 300 lines of code that looked like this:
......for pages and pages, with only the occasional lapse into deeply nested trig functions to break the monotony.
Label225:
goto Label230 if $q == 1;
goto Label235 if abs($a - $j)<90;
goto Label227 if abs($a - $j) == 90;
$q = 1;
goto Label205;
Label227:
$b = 1;
$a += 180 if $a == 0;
$k = $s + $h+$i;
$l = $c - $i;
goto Label500 if $l == 0;
$m = $a;
goto Label350 if $l>0;
goto Label450;
...
What does each variable A-Z mean (and they mere mostly all used!)? I have no idea. I only ever figured out that K, L, and M held the input parameters at the start, and at the end of this monolith of code, they magically held the output of the algorithm.
But it ran perfectly! All the test data whipped right thru, correct on every point. Because, you see, I am a superstar.
And then they wanted it translated into Lingo. I said "Have fun!"
So they got a "Lingo expert" to work on it. I gave him the Perl source for my implementation.
He said "I... don't really understand this".
I said "Neither do I!".
"But you wrote it!"
"No, I translated it. I could show you the 'original Klingon', but it wouldn't help. This Perl code is as clear as it gets."
"Hm."
"Well, not to get all zen and wu-tang and stuff, but there's understanding, and there's understanding. So this line, 'goto Label230 if $q == 1;', I understand what that does -- it sees if $q is 1, and if so, jumps to Label230."
"Why does it do that? What's $q's value mean?"
"I have no idea," I say.
He weeps quietly.
I say, "BUT...!"
"Yes? [sniff]"
"Can you translate 'goto Label230 if $q == 1;' into Lingo?"
"I... I don't know if there's a 'goto' in Lingo. I think there is."
"Well if there isn't, we'll think of something. But suppose there is. Could you translate 'goto Label230 if $q == 1;' then?"
"Sure", he said.
"And the next line is 'goto Label235 if abs($a - $j)<90;' -- could you translate that?"
"I... I guess."
"Well, start at the beginning, and proceed to the end, and it'll work!"
"It will?"
"Yes! If you translate each line right, and you do all of them, you'll have all the program translated! I did it from this creepy BASIC to Perl that way, and it worked for me" I said.
"Wow!"
"And here's a sheaf of test numbers you can run thru."
So the "Lingo expert" went and translated each line. And it didn't work. It never worked. He tried adding fudge factors here and there in the code to make some of the test numbers work. That didn't help, of course. And he was on the clock the whole time, every time they'd call him back to "correct" the code for the next emergency last-minute burn to the CDROMs it was supposed to go on. So he made a mint, for code that has never worked, and makes no more sense than mine. Apparently it just doesn't pay to get it right the first time. But don't get me started on that.
And my program worked, and still works -- no bugs found, ever. Even though I have no idea how it works, and no idea what any of it means.
On a very short-lived project that I was assigned to, my primary responsibility was to port a particular astrodynamics engine to Java from C. The program had previously been ported to C from Fortran, and to Fortran from some ungodly, unknown language for an old HP paper-tape computer. I was the first actual programmer to look at said program, and all the previous ports were exactly like you described: literal translations from one language to the next.
Function parameters were a through z. All local variables were declared like float r[412];, and used like r[53] = r[212] * r[81];. Not every index would be used, no index would be reused, and the indices were seemingly randomly chosen. All constants were handled as just numbers, many of which I was unable to track down. There was but one comment in the entire program - a four line assertion that some basic C construct did actually work. (Not that the logic worked, that the C itself was valid.)
They quickly decided that STK's engine would be money well-spent. (Perl, BTW, is their scripting language of choice.)
Re:The nightmares have returned
godoy on 2002-01-31T09:15:13
Indeed... It's funny how we all have passed through that.And that's funny how non-programmers choose their variables' names. This algorithm was gotten from an electrical circuits book and it's Portuguese title translates to "Electrical Circuits Course". Got it? No? They are teaching future engineers to write their programs in Basic and name their variables after A1, A2, A3,..., Z7, Z8, Z9.
It has just made me curious about what happens after Z9... Maybe AA1?;-)
The entry in my diary is like yours: variables with one letter and one number, loops using 'for', several GOTO and as the last line, a 'return'.
I'm translating the FFT algorithm to Perl and then I'll try doing the same for C...;o) I was originally going to translate it to C, but since I like Perl more, I've done that first.