
The Worst Programming Environment in the World? - jloughry
https://github.com/jloughry/BANCStar/blob/master/README.md
======
jim_lawless
From the write-up:

"BANCStar actually came with a "screen generator" that was supposed to be used
to construct applications. But the 5.1c version of the generator was so
limited that experienced programmers soon began to pry off the covers and
modify directly the intermediate code that the run-time module actually
executed."

All of the numbers you're looking at are an object code for a VM that
(apparently) allowed for user-defined screens in the BancStar product.
Programmers found themselves reverse-engineering the meanings of the different
numbers and began to build the text-format object-code by hand.

This doesn't appear to have ever been intended to be a programming environment
in this form.

~~~
shmageggy
I feel like this is an important point. One could easily say "omg look at this
horrible programming language I have to deal with --

30001000: 55

30001001: 8b ec

30001003: 6a ff

30001005: 68 90 10 00 30

3000100a: 68 91 dc 4c 30"

When it's just x86 and nobody is supposed to be using it directly. Of course,
we have workable tools that sit on top of machine code so we don't have to,
and apparently that wasn't the case for OP, but I think that's more of a
statement about their inability to do the one thing makes progress in
computing possible: create abstractions.

~~~
jrochkind1
There was certainly a time that people wrote assembler, and even machine code,
directly.

People of course still do write assembler directly (but not as much as they
used to!), but I don't think many have written machine code directly for a
while. (Maybe for some specialized hardware?).

But yeah, it's good to note that this underlying sort of vm code wasn't
intended to be written by humans... but I wouldn't say the customers were
wrong, exactly, to successfully use it to do high business value things with
the product they were locked into, that they couldn't otherwise.

It does make one think how happy the customers would have been if the vendor
had provided an actually intended fleible scripting or 'macro' language, and
then to think about the aspects of the market that still didn't lead to the
vendor doing so.

------
rwmj
Kind of reminds me of MUMPS, which is a real bunch of crazy that I had to use
for a time.

[https://en.wikipedia.org/wiki/MUMPS](https://en.wikipedia.org/wiki/MUMPS)

Edit: The examples on the wikipedia page make it look less crazy than it is.
For example every keyword can be abbreviated to a single letter, and _was_
abbreviated to a single letter in the code I had to read. Also, each variable
is connected to a global database which (in 1990) had no ACID properties or
staging system, so better hope your undebugged program didn't delete any
patient data (or worse, randomly modify it).

~~~
x0x0
oh, and if we're discussing a certain emr company in madison...

in the beginning, in the 70s or so, ram was very tight and the source was
interpreted, not compiled; variable names were shortened to save memory. So
the oldest core routines have single letter variable names

variables aren't declared; when you use a name, the interpreter just travels
up the call stack looking for somewhere that variable is defined. so if you
accidentally use the wrong name, especially with the strong bias to very short
variable names, in nested enough code you will find that variable. This led to
some amazing bugs

the prefix of the command to delete a node in the internal db (really just
global sparse arrays) deleted everything. A coworker fat fingered that in a
customer's prod systems and took down a hospital chain you've heard of. I just
heard him wail, "Oh SHIT" and sprint out of our office; I later found out he
ran for the recovery team.

they also had 15mm lines of vb6

oh, and they love h1b slave labor. Bring them over, abuse them, threaten to
fire them if they don't work their asses off, and leave them with no
transferable job skills. I presume the ceo uses her billions to salve her
conscience.

~~~
aaronbrethorst
That same company refused to even consider me for a job after I graduated from
the University of Minnesota because they thought my GPA was too low. So
instead, I ended up in Seattle at Microsoft where I managed a good chunk of
the Visual Studio IDE.

It wasn't until years later that I realized I'd totally dodged a bullet.

~~~
saryant
I once got an email from them rejecting me for a job there.

I had never applied...

~~~
aaronbrethorst
You might even say that's...Epic.

Or not. I'd recommend not.

~~~
chris_wot
Ah, thanks! You filled in the final piece of the puzzle.

------
jbgreer
And I thought 'EZ-C' was bad. Still, it was the worst I've used. As far as I
know, a large retailer still uses the data format and libraries from an awful
"4th generation language" called 'EZ-C'.

Fun parts: There were a fixed number of variables. All variables were global.
There were two control structures: if/then and goto

Imagine a Point-Of-Sale application written in such. A 100,000+ line Point-of-
Sale program. Imagine the fun of chasing down re-use of a variable with no
debugger.

EZ-C was supposed to be a simple language with built-in screen handling (via
curses) and data file handling (with variant records and multiple indices).
The theory was that you wrote code in EZ-C and debugged it, since the simpler
syntax would reduce errors. EZ-C came with a program that would comple your
source and link against EZ-C libraries. The best of all possible worlds - a
nice interpreted language that compiled for blazing fast speed!

That was the theory. In practice, the compiler was broken, and so all programs
ran via an interpreter called 'dparse'.

So (and I can hear you saying) I started to do what many of you would do: I
started to write my own parser with the idea of building a compiler for the
language. And that's when Mike, one of the older developers/admins/jack-of-
all-trades/wise elders, stopped me. "Don't do that," he said, "because if you
do that, we'll never stop writing in EZ-C."

And so I stopped immediately.

~~~
jloughry
> Fun parts: There were a fixed number of variables. All variables were
> global. There were two control structures: if/then and goto

It's just like BANCStar! I forgot to mention that one of the most useful
features of the LIST annotator was to generate a cross-reference listing. That
feature alone made the practice of re-using working-storage variables _much_
safer, because you could compare the cross-reference indexes of two different
programs at a glance easily. I strongly encourage the development of that kind
of safety/error-detection/error-prevention tool in any environment whenever
possible.

Seriously, your Mike sounds like a wise person.

------
demallien
I Thought I'd repost some of losethos's comment, seeing as he is hell-banned,
but the comment was quite relevant.

losethos: Smart American kids my age had C64s and Apple IIs. We all entered
6502 machine code into DATA statements in BASIC programs. Everyone did it. It
seems so fantastical and primitive to a monkey, doesn't it. Generally, we used
monitor program to disassemble and assemblers, though you had to buy an
assembler. Every store had magazines with BASIC programs full of DATA
statements with graphic and machine code data. People typed it in. We had xsum
bytes on blocks.

~~~
Lagged2Death
_Smart American kids my age had C64s and Apple IIs. We all entered 6502
machine code into DATA statements in BASIC programs._

Yeah, but (similarly to the 'environment' that is the subject of the post)
those DATA statements contained the output of some sort of tool. Nobody
_wrote_ machine code this way.

~~~
vidarh
> Nobody wrote machine code this way.

I'd be careful about that claim.

It was not _that_ unusual to "hand assemble" programs, as it was not that
unusual to remember the codes. The 6502 has less than 60 documented opcodes
(and quite a few undocumented ones with various weird but in some cases
somewhat usable behaviour) and only a few addressing modes, and all opcodes
are single byte, so knowing most or even all of them doesn't take that much
exposure.

Some of those values are so ingrained that I still remember the decimal
values, despite the fact that the moment I started using tools to work with
assembly on the C64, it was all hex

e.g. 169 decimal is "load accumulator immediate" (LDA #[8 bit operand) on the
6502. (or A9 in hex)

~~~
Lagged2Death
_It was not that unusual to "hand assemble" programs, as it was not that
unusual to remember the codes._

Yeah, I grew up with 6502s, too.

You'll think I'm weaseling out here, but "hand assembly" isn't what I was
talking about.

I feel the original comment implies that some people, intending to write
significant machine code, sat down with BASIC and started typing in DATA
statements. And I don't think _that_ happened to any significant degree.

As in the case of the "programming environment" under discussion, machine
language routines force-fed into BASIC DATA statements were the output of
another tool or process -- whether assembled by hand or by machine -- and were
an intermediate form that was never intended to be editable.

------
truebosko
This reminds me of one of the things we work with in our company, Amadeus
EDIFACTs. I want to buy the person who initially wrote the parsing for it at
our workplace a beer.

Example snippet, with fake data (AIR-
BLK791;7A;;232;0750058720;1A1216900;007501\r\nAMD 0750068617;1/1;
\r\nGW759208;1A1216900\r\nNXC1A
4O0ORDT030;0751;XYZC7213P;67502886;XYZC7213P;67502886;XYZC7213P;67502886;XYZC7213P;67502886;;;;;;;;;;;;;;;;;;;;;;TA
4O0ORDT\r\nA-LACSA;LR 1330\r\nB-TTP/INV/T3/RT\r\nC-7906/
1833SEGS-1173LGSU-B-9--\r\nD-127531;121751;121751\r\nG-X
;;XYZXYZ;\r\nH-001;002OYYZ; ... continued)

~~~
berkut
Sigh.... I'd forgotten about this (used to do this in a previous job)

Parsing airline flight bookings straight from raw sockets was not fun.

Thing is, it does the job, and if you watch users requesting and making
bookings with the system (or other similar travel service bookings using
things like VT320 terminals), I'd bet a web interface couldn't actually be
faster. But only if you know how to use it.

Rather ironically, about 4 years ago, they added a "web service" to this which
just wrapped the console output directly in a single set of XML tags - I kid
you not - no attempt to nicely separate atoms into separate tags.

~~~
nikatwork
Someone needs to invent a word for the job of gluing together horrific data
formats and/or scrubbing that data with regex and trying to semantically parse
it.

Anyone who hasn't had this job during their programming career is very lucky.

"Poogrokking"?

~~~
jloughry
The _Oxford English Dictionary_ needs to know about this word.

------
adamnemecek
Reminds me of this ol' gem.

[http://thedailywtf.com/Articles/We-Use-
BobX.aspx](http://thedailywtf.com/Articles/We-Use-BobX.aspx)

But yeah, BANCStar still probably takes the cake.

~~~
chris_wot
I did a search for bobx... It brought up some... Interesting... Results!

------
hkmurakami
_I 'm not too worried about revealing a lot of proprietary information here,
as only about ten people in the world can read this code:_

and here I thought my friend's quip, "they're only about 500 of us in the
world" who can write in the Q programming language (for kx systems, another
financial system) was mind-boggling. (Q is also knows for having incredibly
terse, nearly unreadable syntax)

~~~
RBerenguel
Lately I've been giving J a shot, and if Q is anything like it (IIRC Q comes
from K and K is a parent of J via APL) it definitely is...

~~~
doublec
Q isn't too bad depending on how it's written. The book "Q for Mortals" is a
good read. [http://www.amazon.com/For-Mortals-Tutorial-In-
Programming/dp...](http://www.amazon.com/For-Mortals-Tutorial-In-
Programming/dp/1434829014)

~~~
RBerenguel
Problem is, I don't want to tangle with a non-for-commercial use language (and
I can't pay.) At least with the GPL (J) I could do what I need behind the
scenes and use the language as I see fit.

But I'd love to give Q a go, just for geekiness.

------
qznc
Just write a simple assembler or compiler yourself?

~~~
ballard
That was my first thought (after looking for existing solutions). REPL and
[https://github.com/ajaxorg/cloud9](https://github.com/ajaxorg/cloud9) for
bonus points.

Also:
[http://www.oocities.org/connorbd/tarpit/bancstar.html](http://www.oocities.org/connorbd/tarpit/bancstar.html)

------
VLM
Well, lets get crackin' and see if we can reverse engineer this bad boy. I've
done a lot of assembly and only a little direct bare machine language coding.

There's no lines without a first column, unlike pretty much all the others. I
theorize the first column is opcode. You're running a lot of 3001 so I'm
guessing thats "load" and it seems like you're clearing something a lot and
occasionally stuffing real values in.

The second to last column looks kind of binary flag-y to me. Like LSB and 2LSB
somehow team up to mean "zero flag". In fact I'm guessing opcode 8500 is a
conditional skip.

The second column has a strange affinity to 1316 and its neighbor, and
occasionally uses totally different class of numbers. So I'm guessing its the
equivalent of variable name or more likely memory address.

I have a gut level guess the 11000 series opcodes are some kind of ALU op.
Probably add. And you can add a constant, and condition codes in the 2nd to
last column do things based on add result.

Another gut level guess... you're using signed ints and the last column is
some kind of conditional jump and the OS lives in the upper half of memory
which would be a negative number as per the last statement returning to the
OS. I think you put your global libraries in the 30000 range and this module
or whatever happens to live around reserved range of 22000 ish.

Then again maybe its crystal clear and if you just translate it into octal,
you'll see PDP-8 instructions. Probably not, but...

I have this gut level guess this is a practical joke, like I'm supposed to
recognize based on pattern matching that its a recursive implementation of a
factorial.

~~~
RBerenguel
3001 is block conditional according to the post...

~~~
VLM
Well, thats interesting. I was working out of the wikipedia page not the
github with more content.

I see the last column is for constant numerics and zero = 10000, interesting.
I bet making a deposit or withdrawl of more than 10000 at a time takes some
interesting code (or more likely, the UI hardcodes only 4 spaces)

Per the writeup, I imagine having 7 programmers on staff helped figure out
what to do.

~~~
RBerenguel
Well, I think this is nightmarish, from a purely context-switching type of
thinking. I don't mind using letter opcodes, strings then are pretty clear to
distinguish. But come on, number opcodes? Add 5 to B and store in AX (or
whatever) turns into a nightmare of numbers. Of course, after a while you
probably "get" that 3001 is a conditional. But I wonder how this affects the
way you feel numbers from now on: what do BANCStar programmers think about the
2000 effect, 3001 Final Odissey (heh) or the TV show 24?

------
lisper
And these are the people that we trust to handle our money. Sometimes it
amazes me that the whole financial system hasn't already collapsed in a
smoldering heap.

~~~
seldo
Well, it sort of did in 2007. But that wasn't a software error.

------
ars
This doesn't seem that bad.

It's basically machine language (i.e. lower level than assembler). I remember
programming in machine language on an Apple II - I had no assembler, just a
photocopied table of the OP codes, and I calculated them myself and entered
the hex numbers and ran it.

I wrote part of a tetris clone that way (although never finished it).

~~~
demallien
Exactly. My very first thought was why on Earth would you even bother trying
to program using that? Write an assembler, and then write a C compiler, for
goodness sake!

------
sgt
With COBOL as the obvious alternative (at the time) for financial
applications, then I have to ask; why on earth would any sane company choose
this programming language?

~~~
JanezStupar
The real question is why haven't they written a library in a higher level
language.

They have to be smart guys. If they didn't do it then there must be a good
reason which is unfortunately ommited. Or they did it and this article is
misleading and baity.

~~~
jloughry
Most of the people on the project were vocationally trained ex-mainframe
programmers. You could say there was a general lack of awareness that there
was any other way to do things.

------
mrbill
From Wikipedia: "The BANCStar 10.0 release changed the "Screen Code" format to
binary, and rearranged the numeric codes into an opcode with a variable number
of parameter integers. The 10.0 opcode encoded a bit mapped length value that
indicated the length of the command in words."

------
kunil
I am a regular brainf*ck programmer and very interested in esoteric languages
but this is beyond my expectations.

Maybe writing some kind of compiler would be a better idea. Or at least add a
comment support and character check and more user friendly labels. They
probably did that though (I hope they did).

------
mistercow
So, who's up for writing an LLVM backend?

------
stesch
I thought RPG/400 and XSLT were bad. This is worse.

~~~
mindcrime
I'm OK with XSLT, but programming in RPG/400 using the SEU is somewhat akin to
reading from the Necronomic%^^&$@#a-483&#&@^H NO CARRIER

------
kalleboo
Reminds me of the scripting system for the custom scenario editor for the
computer game "Realmz". You had a list of 8 text fields to enter numeric
commands in, and 8 fields for arguments. There was a dropdown to use for
reference for what the commands meant. If you needed your script to be longer
than 8 commands, you had to create "sub-macros" and call those.

I can't find a screenshot of the macro editing screen, but here's a different
screen from the level editor to give you an idea
[http://rlmz.org/divinityscreens/divinity05.gif](http://rlmz.org/divinityscreens/divinity05.gif)

------
rurounijones
Language? Maybe

Environment? The default Uniface "IDE" (Version 7 when I saw it in action) is
a monstrosity that is surely given to programmers sent to hell.

~~~
jloughry
Well...I used the word "environment" thoughtfully. It wasn't just the
language, it was the dot-matrix printouts on continuous fan-fold paper (with
no line numbers, you _didn 't_ want to get pages out of order), the hands-full
of different coloured highlighter pens, the ring binder stuffed full of dog-
eared photocopied pages (and pages and pages) of magic numbers, and the ever-
present feeling of terror when you had to pick a "safe" working storage
variable to steal the use of for a while.

God, I miss it.

------
alextingle
Still better than M4 though, right?

~~~
marcosdumay
Better than Blankspace, without a doubt.

------
6d0debc071
I don't want to seem mean or anything. So, please don't take offence ^^; but:
why didn't you parse it a more readable format and change it back into
goobledigook when you wanted to use it?

~~~
jloughry
That's a good question, and a fair one. I did take a few stabs at it, but
other programmers resisted any changes to their workflow that would have been
required if a different source code representation were used. _They really
could read that code by sight._ The LIST annotator slotted right into their
workflow by highlighting the numbers they wanted to focus on---the English-
like representation to the right was almost completely ignored---the arrows
and boldface highlighting in the numeric listing, along with the line numbers,
were what they used. Editing still had to be done on the raw numeric files, in
KEDIT.

Of all the tools I tried introducing, LIST was the only one that was adopted.
It took off spectacularly well and was beloved.

------
antihero
Out of interest - for languages as horrendous at this, could someone not
create an abstraction language, that essentially could compile to it, or be
decompiled from it?

I mean, even if it was a simple abstraction that just made it a little more
readable. Like ASM vs machine code.

------
anon_indian
The worst for me has been sitting thousands of miles away working on a VDI,
watching the screen refresh line by line with every change in code. We spend 8
to 10 hours for 3 hours of productive work. :-(

------
gothep
While we are on the topic of programming infernos:
[http://en.wikipedia.org/wiki/Malbolge](http://en.wikipedia.org/wiki/Malbolge)

------
Tomis02
Nice try, but emacs already has a command for that.

------
Pxtl
... okay, somebody finally beat ASP.Net webforms.

~~~
andrewflnr
I have to say that, having done Webforms over the summer, it's pretty bad but
not _that_ bad. Webforms does have some (a few) strengths. There are a lot of
simple apps where the "just freaking synchronize it" model works well. You
could probably got most of the benefit/ease[0] with some stuff on top of, say,
Django.

[0] Notice I didn't say "simplicity". ;)

------
boomlinde
Why wouldn't you write an intermediate language? Just a preprocessor for
keywords and labels would do, I think.

------
mikesmullin3
it would be trivial to make a some mnemonics and a compiler for the custom
machine code.

------
rhapsodyv
And I tought I had suffered with c++ builer years ago

------
ebbv
This seems like a case of people choosing to do something terrible than
someone designing something terrible on purpose, though.

------
moriantur
This language should not exist.

~~~
eksith
Absurdities exist just so we can observe the absurdity. This is more a
historical curiosity at this point, but I'm glad that it does exist. Just so I
can be curious about it.

------
Nux
Title slightly misleading for non-programmers.

I imagined soemthing like programming for Al-Qaeda with a pistol pointed at
you. :-)

~~~
lotharbot
> _" slightly misleading for non-programmers."_

You're on Hacker News.

~~~
KC8ZKF
Hence he has to overanalyze the headline.

