goto LabelHELL;

TorgoX on 2002-01-31T07:00:23

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:

...
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;
...
...for pages and pages, with only the occasional lapse into deeply nested trig functions to break the monotony.

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.


The nightmares have returned

Whammo on 2002-01-31T08:51:46

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.

That

pudge on 2002-01-31T15:44:23

is a fantastic story!

wow

yDNA Barak on 2005-04-20T01:46:58

That was a fun read. Um, thanks. Now I don't feel so bad about everyday hell.

I had something less horrorific

wickline on 2005-06-05T20:51:24

happen several years ago. I wanted to create http://colorlab.wickline.org/ and found a site that showed colorblind versions of the websafe colors and referenced HCIRN as the source. I asked them for their code, which they were kind enough to provide.

The code was provided in two forms: Java that didn't work, and a spreadsheet that did work. Neither form was clear to read. Since the spreadsheet worked, I started off with a literal translation of that document. Instead of your Label200 things, I had oodles of variables like $E3 and $F45 referencing the contents of spreadsheet cells. The translation worked.

Of course it looked decidedly nasty. I trimmed dead paths in the code, removed variables that were calculated but never used, and cut out some repeated calculations that were always run on the same inputs. It was still a mess of course.

I spent some time educating myself about color spaces and tracked down the credited source of the algorithm the spreadsheet was intended to embody. Eventually I was able to start putting variable names from the broken Java onto the translated spreadsheet code, reworking the spreadsheet code into something that fit the rough form of the Java code.

I never did bother to figure out what the bug was in the Java code was because once the translation got sufficiently far enough away from the spreadsheet version and looked a bit more like perl code, I kept morphing the code in a more perl-like direction to make it easier for me to read.

Then I translated the whole mess to javascript.

The result is in http://colorlab.wickline.org/colorblind/colorlab/engine.js at the function color_blind_sims() and in the lookup tables above there. If you scroll up to Color_rgb_from_xyz() you can find a reference to a slight difference in the constants supplied in the spreadsheet versus the java code.

I was lucky enough to have had two code sources (although only one worked), a reference to the algorithm which was being used, and reference material discussing the problem domain. If I hadn't have had all of that, I suspect that the code would still exist as a nice black box full of $E3 and $F45 variable names :)

-matt