Sunday, May 30, 2004

Logic for Licensing

Share Excel Spreadsheet Files over the Internet using Web BrowsersHaving some fun designing and implementing the BadBlue server's new licensing scheme. In a nutshell, the Excel sharing features allow browser-based remote users to update a Excel spreadsheets running on the server. The new licensing scheme limits the Excel collaboration features to a fixed number of "named users".

So to have Joe and Fred both update a spreadsheet, you'd need at least two "user licenses". You'll be able to order a "license pack" that will bump your licensed user count to the desired level. The "license pack" product simply comes in the form of a "license pack code", which gets emailed to you upon confirmation of the order.

The code works like this when you enter a new license pack code:

- Read the currently installed license packs
- Has the code already been installed?
- If so, set "UsersToAdd" to zero
- If not, set "UsersToAdd" to the encrypted value and save the new license pack code
- Bump the "LicensedUserCount" by "UsersToAdd"

One of the pages of the user-interface allows you to review your current licensed user count and see which codes have been installed.

When the product starts, it does the following:

- Set the "LicensedUserCount" to 1
- Read the currently installed license packs
- For each installed license pack...
- Decrypt each installed license pack code
- Bump the "LicensedUserCount" by "UsersToAdd"

The Enterprise Edition product, which includes the Excel sharing capability, will have a built-in licensed user count of 1. License packs will be sold in units of 5, 10, etc.

This is a new licensing model and one precipitated by a major investment in new features, which have been added by popular demand. In particular, a couple of accounting firms are trying to open up large legacy spreadsheets to the web without having to pay for a major application conversion.

This seems like a good alternative: users and business processes get to employ the same underlying Excel technology but open it up to anyone with a browser. The multi-user conflict resolution and audit-logging capabilites are pretty standard fare for this type of app. But one of the neatest new features is the ability to restrict which cells are visible and/or modifiable based upon the identity of the logged-on user.

There appear to be specific accounting situations in which this comes in handy. Say an auditor wants to comment on a spreadsheet without letting some of the data-entry folks see the comments. His notations are visible to certain users but invisible to the clerical users. Likewise, a law firm might want to place additional comments that aren't visible to either the auditors or anyone else. Oh, what a complex web we weave...

Anyhow, if you're interested in unlocking a spreadsheet by sharing it with browser-based users, give it a look.

BadBlue Tutorial - Excel Sharing FAQ (Share Excel Spreadsheets over the web, LAN or other network)

Saturday, May 29, 2004

The Accidental Project Manager by Patricia Ensworth is a survival guide for the person who suddenly becomes a software project leader without preparationIn a recent JOS post, an anonymous poster asked:

Where the heck are all of the good software engineering jobs? With good software companies? I'm not talking about a Crytsal Reports writer or business applications programmer/analyst or a stupid Access database programmer! I'm talking about C/C++ development of hardcore stuff like content creation, games, operating systems, utilities etc etc. I want to be on the team who makes Crystal Reports, Access, .NET, MS Windows, Adobe Photoshop, QuarkXPress, DreamWeaver, Norton Utilities etc etc..

Does anyone here work at these places? What does it take to get in? Can anyone else here identify with the "I hate business development stuff." It seems like all the fun stuff is gone or the positions are filled or some other such nonsense.

As someone who was fortunate enough to work on a couple of mainstream commercial applications, I can only respond, "it takes a career plan... persistence... luck... and skill."

So how did some midwestern hick debugging firmware at a process control company end up architecting a mass-market database package? It didn't happen overnight, that's for certain. I did it in stages. While at the process control company ("the O Corporation"), I started writing more and more code. I loved it. I wrote code all the time. Firmware. UI code for the color ISC terminal. I even wrote a VisiCalc-like spreadsheet for the PDP-11 (RSTS/E) for engineering calculations since DEC didn't offer one on that platform. Because I typed about 100 words-per-minute, I could crank out more code than most of the other guys. So I experimented constantly.

Interestingly, one of the reasons I left my first company was how I was treated. Even though my pay was abysmal, I didn't really mind because I made enough to live comfortably. I had amorphous goals for making more money, but nothing set in stone like, "I want to make $X my age 25 and $Y by age 30". I had been there several years when the pivotal event occurred.

My boss, Mike, at the time was generally a decent person but a tad reactionary and insecure. He was pissed about something and called me into his office. I walked in and he spat at me, "Sit down!" - everyone in that area of the engineering floor could hear it. I felt pretty low, almost like he was talking to a dog. But after a moment's hesitation, I obeyed and sat. In my mind, I was saying, "that's it - I don't need to be treated like a dog". I resigned in my head that day. And I had a real job offer a few weeks later and resigned for real... giving two weeks' notice. Of course, I never really told the president of the company why I was leaving. It was just very hard to describe that feeling of degradation.

That also taught me something about how I wanted to treat people if I ever got a software management job. For sure, I thought, life is too damn short to be treating anyone with disrespect. That goes for the president of the company down to the person who empties the trashcans. I've tried to abide by that philosophy. Anyhow...

I moved to PMC, the division of the Fortune 500 company. Rich Alden ran the Engineering group and was a very good leader. He was organized but not a micro-manager. He trusted his engineers because he had hired a talented group of guys. And they were fun people to be around.

Almost immediately after I was hired, our parent division ("Systems Division") received a huge contract from IBM for a large portion of a printer assembly plant. The factory control software fell on me, since I was the only Intel specialist in the place. It was a fantastic opportunity. I designed the real-time, multi-tasking OS, the scheduler, the controller, the user-interface (RS-232 to a terminal)... everything. It was a fantastic leanring experience and with my background, it was cake.

Systems Division in Cleveland and IBM in Charlotte seemed pretty impressed with the system. I met a wonderful project engineer in Cleveland: Topper Hill. A unique, funny character, Topper always wore a solid, bright red tie. Topper and I got along famously as we worked on integrating his mechanical pieces with the software. Topper took me to my first Armenian restaurant in east Cleveland and that was quite an experience. Ethnic cuisine at its best and the liquor wasn't bad either.

Unbeknownst to me, Topper was working on several projects, including one with folks from GMF Robotics in Detroit. A couple of the senior GMF folks were Jim Pelusi, a very bright Harvard MBA, and Hans Bukow, a Purdue master's grad. Both were confident, eloquent guys. Somehow, Jim and Hans mentioned to Topper that they were thinking about starting a software company. And they were looking for talent.

I don't know what Topper told them but the next thing I knew, Hans and Jim were sitting in my office at PMC in Cincinnati. They described their vision of a user-friendly system that would allow automated factories to be assembled quickly and easily. And they indicated that they had the connections to get the company funded. They wanted me to participate as a co-founder and help get the software off the ground. I would be the third employee.

I knew I wanted to work on more mainstream software than the "hidden glory" of process and discrete control equipment. I had a gut feel that this was one step closer. I told them I was "in". And within a period of a month, September 1987, I got married, started a new job and moved to Boston. No stress!

Even better, FASTech hadn't closed its first round of funding when the Stock Market Crash of '87 occurred. Talk about high blood pressure! To Jim's credit, his connections were solid and came through with a $970,000-or-so check just weeks later. They started hiring and selling; and I started coding.

Ever since Hans had expressed his vision to me... a user-interface that would make multi-tasking and real-time processing a breeze, I had a picture in my head of how it could be done. I mean I had it designed, completely. We had a few engineers there who either didn't believe that I could do it or that it could be done at all. One, Charlie, was a decent enough guy, but believed that I should "mathematically prove" that the system would work before I coded it up.

We would sit in meetings and I would listen to various suggestions, thoughts, criticisms mostly directed at me. I would listen patiently, nod, then grin. And then I would conclude the meeting with, "No". I was partially kidding, but basically I knew I could do it. Just get out of the way and let me work. It was innate. My meeting behavior was so negative that John and Charlie collaborated on the purchase of some "Doug-Bats". At the inevitable, meeting-concluding "No", they would beat me mercilessly with the foam bats. It was pretty funny.

I drank nine cups of coffee a day and typed 100 words a minute of raw C. There were days where I pounded out 1,000 lines of code -- all original -- in a day. I had to ramp down on the caffeine when my heart started racing at 100 bpm while lying in bed.

But within a year, we had shipped the first version of CellWorks (the product's name) to GM and Honeywell. It could be done, and we had done it. I must admit, though, that I was a bit let down after we shipped the product. I had created the flagship parts: the graphical UI, the logic engine, major pieces of the windowing system, and so on. I expected something. A promotion. A title change. A raise. A bonus. Whatever. Nada.

I started getting paranoid about the cost of living. I was making a not-so-great wage in Boston and housing seemed unattainable. My first child was on the way. Day-care would be unbelievably expensive. And I had heard nothing from Jim and Hans about a salary commensurate with my level and what I'd achieved. And other people were buying houses and seemingly getting ahead while I felt trapped.

I started looking around, working with Sophia Navickas (who now owns Lynx). I would heartily recommend her for anyone who needs a high-quality recruiter. I described what I was looking for in a new employer. She got me three interviews right off the bat:

1) with a minicomputer spreadsheet maker (I can't remember the company name, but the product was called 20-20). It was very popular at the time with DEC systems.
2) with Rational (not the CASE company), a very small development firm whose primary product was a C interpreter (seriously) for faster development. Compilers at the time weren't very quick.
3) with Alpha Software, a very small consumer database company with perhaps 18 employees.

#1 just felt wrong strategically. I hated DEC systems, loved PCs and felt DEC would be out of business soon. Shoulda shorted them when I had the chance. #2 had a great, friendly group of guys, but the product seemed too techie, too low-level. #3 had it all. A chance to work on consumer software. Small company, so a lot of hats could be worn by the right person. Richard and Selwyn Rabins, two very smart brothers -- both MIT grads -- were the principals. I got along very well with them. In my first interview, Richard had me cracking up with various filthy jokes. I think he was testing to see what kind of personality I had. No problem, I love filthy jokes.

So, Alpha it was. Consumer software. Finally. The company, through massive marketing expenditures, ended up selling a million-plus seats worth of database licenses. Pete and I got to architect a mass-market Windows database product. And it still kicks Access' butt in a lot of head-to-head computer mag reviews. Cian Chambliss is the head software guy now and he is a very talented developer. I'm still pretty proud, though, that we had a tiny development team compared to the hundreds of people and the reported $60 million that Microsoft spent getting Access 1.0 out the door. And we got it done.

So how'd I get there? Like I said. Career plan. Persistence. Luck. Skill. Damn, sorry... that's a long answer to a short question!

Friday, May 28, 2004 Books: The Blankenhorn Effect: How to Put Moore's Law to Work for YouJakob Nielsen speculates on personal computing power in the year 2034:

...According to Moore's Law, computer power doubles every 18 months, meaning that computers will be a million times more powerful by 2034. According to Nielsen's Law of Internet bandwidth, connectivity to the home grows by 50 percent per year; by 2034, we'll have 200,000 times more bandwidth. That same year, I'll own a computer that runs at 3PHz CPU speed, has a petabyte (a thousand terabytes) of memory, half an exabyte (a billion gigabytes) of hard disk-equivalent storage and connects to the Internet with a bandwidth of a quarter terabit (a trillion binary digits) per second...

...By 2034, we'll finally get decent computer displays, with a resolution of about 20,000 by 10,000 pixels.
By 2034, we'll finally get decent computer displays, with a resolution of about 20,000 pixels by 10,000 pixels (as opposed to the miserly 2048 pixels by 1536 pixels on my current monitor). Although welcomed, my predicted improvement factor of 200 here is relatively small; history shows that display technology has the most dismal improvement curve of any computer technology, except possibly batteries...

What he leaves unstated is the user-interface technology we might anticipate. My take: Research on spinal cord and nervous system injuries will lead to breakthrough interface technology that will not only empower the paralyzed to utilize their limbs... but also provide magnificent new user-interfaces for conventional users:

1) Body-worn computers will interact by reading gestures, eye movement, leg and arm movement (e.g., for game-play), etc.

2) Users will have the option of retrofitting a pluggable adapter into their body that will interact directly with their brain. A short, 30-minute (and almost painless) operation will safely allow direct interaction with a computer and the brain.

3) Future applications that harness the direct brain-to-computer interface will include recording of your vision, your hearing, etc. Recording of thoughts. Even playback of another's experiences or thoughts (a la Strange Days).

4) A wireless brain-to-computer interface (BCI) will also support retrieval of data (e.g., a Google-like seach for information)... browsing of web pages... and some fascinating advertisement technologies - everything will be inside your head.

5) New remote control capabilities spawned by BCI.

Sounds scary, but I think it will be commonplace and well-accepted in thirty years.

Thursday, May 27, 2004

Alpha Frisbee Golf, part 17

Disc Golf: All You Need to Know About the Game You Want to PlayPete's blog stirred a bunch of fun memories. He published a map of the Alpha Software frisbee golf course. I had forgotten the explicit rules that made it so tough (i.e., all concrete constituted a water hazard). He even pointed out an incident involving a lost frisbee:

Another time Doug got a Frisbee stuck on the roof of the building you approach at hole 9 and had to climb a tree to get on the roof and retrieve the disk. After the experience of watching him awkwardly climbing up and down I recall telling Doug, "I think I've just seen proof that man cannot have descended from apes..".

What's bizarre is I remember that exact incident, his comment, and everything. And the shameful thing is when I was a kid, I was pretty lithe and limber and I could scale a tree lickety-split. But, at that time, maybe 1991, I weighed about 225. I could say I was ripped and that I was wearing 32" jeans ("and they're loose!"). But that wouldn't be very accurate. I do remember being pretty blocky and struggling to get up the tree. It felt like it took five minutes of grunting, painful branch burns, stubby nubbins scratching my private parts, to climb about twelve feet off the ground. Of course, Pete was very helpful. He just laughed the entire time.

I did weigh 225, but I was trying to pack on pounds to change weight classes for the first (and last) powerlifting competition I ever participated in. There were three weight classes with which I was concerned. 198 - at the time, too heavy to get down to that level. 220 - which I had no shot at winning because there were a couple of really strong dudes in that class. And 242. There were very few people who ranged from 220-241. So I carbo-loaded all of the time and got my weight over 220. At a weight of 227, I ended up totalling 1200 (405 squat, 340 bench, 455 deadlift). While this was enough to win the class, it was such a laughable total for a serious powerlifting contest that I pretty much gave up ever thinking about competing.

But I was fortunate that Richard and Selwyn agreed to let me buy a bunch of weights for the small Alpha gym. With a budget of perhaps $600, I got some great stuff: a Titan competition bench, a power-rack, and about 400 some odd pounds of Olympic weights. The small gym, used mainly by Selwyn (for bike riding), Sean and myself was also the scene of a pretty scary lifting incident.

I used to bench all of the time without a spotter. Not a problem, unless you went heavy. Well, at that time, I was always going heavy. I would routinely crank out six reps at 285. Well, except for that one day where I had the music cranked up and the door closed. I was pounding out reps and was pushing up the sixth and last one. Uh oh. Couldn't get it locked out. No safety bars on the Titan bench. Panic started to set in. Re-doubled my effort and pushed harder. Now I was seeing stars, literally, and getting close to passing out.

So the bar, weighing close to 300 pounds, was sitting right on my chest. So tapped out, I couldn't move it a millimeter. I yelled, "Help!". No one could hear - the music was cranked and you can't scream real loud with all that weight on your chest. Yelled again. Sh*t. Nothing. Now I knew I was in trouble. With a lighter weight, I could have rolled it down my body without damaging vital organs and my reproductive parcel. But not with that much weight. Not possible without warping the kitschkes.

Or I could have tilted the bar and dumped the weight... if it didn't have collars. But it did. I was locked in.

Finally, I figured out that I could slide off the bench while tucking my head in to avoid the brace. So I jettisoned to the left of the bench. One side of the bar slammed into the ground, the other side hit the bench, and I was safe and sound on the floor next to the bench. Not a hair out of place. Wow.

I popped up just as Dave Mahoney came running in. "What the heck just happened?" More onlookers piled in to see what was going on. "Nothing to see here, just go about your business." I did finally explain, sheepishly, what had happened. Mahoney just looked at me like I was an idiot, "Ross, you came very close to becoming the poster-boy for the Use a Spotter campaign." How right he was.

Anyhow, it didn't feel very healthy carrying that much weight. After my Dad had his heart attack in 1997, I changed my diet completely. I got down to 179 while continuing to lift hard. At a body weight of about 183, I benched almost (325) as much as I did weighing 40 pounds more. Weird.

Anyhow, back to frisbee golf for a moment. What Pete didn't say is that we were very addicted to the sport. It was a blast. We played it in every kind of weather, year 'round. In fact, the frozen tundra of One North Avenue became the scene of the worst frisbee golf injury ever.

The fairways were like sheets of glass. The temperature was quite nippy. And JL, a large gentleman whose dimensions were about 5'9", 300, was playing in our foursome. On the sixth hole (a long Par 4), he flung his disc with reckless abandon and somehow slipped and became airborne. He was frozen horizontally in the air for what seemed like an entire second - several feet over the icy ground. And he landed with a "whump" that was audible from many yards away. He wasn't moving.

"Jim, you okay?" We rushed over. "Jim!"

"Unhknhhh. Unnnhkkh."

If you remember what Sergeant Hulka was trying to say in the movie Stripes when he fell off the tower, you've pretty much got the picture. I think he had just had the wind knocked out of him. But I don't remember him ever playing frisbee golf again. It took true dedication and a love for the game. And only a select few were born to play the Alpha version of frisbee golf.

Alpha Frisbee Golf

Wednesday, May 26, 2004


Search Engine Optimization for DummiesI was talking with Ted McConnell several years ago about search engine optimization. Ted is the head of P&G's IT Research Organization (or ITRO) and who, along with Terry McFadden, was one of the ultra-smart dudes I came across while hanging around the Chemed Center in downtown Cincinnati.

Anyhow, Ted told me about a few of his ideas for utilizing search engine optimization (SEO) techniques for marketing purposes. A lot of them were very clever and I hadn't heard about them being used before. One of his ideas I've modified and I'll share it here.

One of the keys to successful marketing on the web is to have a high ranking in a lot of good keyword phrases. Feel free to voice-over at this point, "Thanks, Captain Obvious!" But hear me out. In this context, "good" means commonly employed search terms used by your target audience. Sure, that's a key. But how, practically, is that achieved? Ah, there's the trick.

Imagine if you were selling baseball cards on the web. Wouldn't it be worthwhile to post some links to Amazon's books and collectibles related to baseball and card-collecting? And to have some good descriptions of each item? And, better yet, to augment those links with your Affiliate code?

So what I have done is combined meaningful links (say, to Amazon SKU's with my affiliate code) on certain of my pages with good excerpts of each item's description. This kills two birds with one stone:

- It generates lots of good keyword hits for the topics, driving traffic
- It generates affiliate bucks for purchasing more Amazon junk

Oh yeah. Thass' what I'm talking about. So click away on any Amazon SKU you see on these articles. My wish list seems to grow by the day, and Daddy needs a new pair of books.

BadBlue - Other Resources

Monday, May 24, 2004

Lemon Squares

How to be InvisibleI think the first person that I grabbed for the Alpha Software development team was Gerry Polucci, who is now the president of Mindstorm Technologies (see link at right). Gerry was right out of school (Comp. Sci. at U. Lowell) and I knew his Dad really well. Hanging out with his Dad, I knew Gerry pretty much throughout college and knew how talented he was.

One of the funny stories he likes to tell is his experience -- at age 16 -- with a U.K. game company that wanted to license a game he created. They flew him over to England and basically asked, "How much do you want for your game?". He said something to the effect, "Enough to make me comfortable for the rest of my life." After the laughter subsided, Gerry ended up back in the States without a deal.

I don't know if he still keeps his hand in these areas, but in his heyday, I would put him up against anyone in the world with respect to his knowledge of MFC and ATL. Aside from being a great developer, he is a very funny person.

At lunch time, we specialized in constructive exploits like playing frisbee golf. My hole-in-one on #2 still stands as one of my greatest athletic achievements, slicing a beautiful 141 gram shot through a maze of trees and clanging it off the Alpha Software sign. You may have seen it on ESPN Classic. They showed it right after a replay of Nicklaus winning the Masters.

Once in a while Gerry, Pete and a few others would walk in the woods past Mitre Corp. My terrifying experience at "the Cliff" still haunts me. It was an immense overhang over the Mitre parking lot. When Pete saw it (after my dramatic description of its daunting scale), he proceeded to walk down it, then back up. In Sperry Top-Siders. Okay, so maybe my perspective isn't so good.

Sometimes we would head over to the inimitable Burlington Mall. Home to Electronics Boutique, the endless Sears credit-card solicitations and... the bakery. Ah, the bakery. One day I received the following email from Gerry. Note the time that the email was sent.

To: Dave D, David M, Dave M, Pete L, Peter M, Doug R, Gerry P
From: Gerry Polucci
Subject: Warning!
Date: 5/16/95 Time: 2:49p

Lemon-squares are an extremely powerful bowel accelerant, and should not be consumed at work or any place greater than 50 feet away from an unoccupied toilet.

Further cautions:
Do not mix lemon-squares with coffee, this will result in the both famed and dreaded bowel-burst (also known as "The Clash of the Colons").

Mixing lemon-squares with ANY Burger-King food has proven deadly in all cases.

There are however several circumstances where the eating of lemon-squares is acceptable:

1. Any situation in which you're sure you are about to die and are not concerned with making a mess
2. When crossing the Amazon naked and being closely pursued by a school of piranha
3. Whenever solely in the presence of your Mother-in-Law
4. In Lemon-Square eating approved areas (i.e., the developers' lounge)
5. When taken hostage and attempting to convince your captors that you are dying from a rare and deadly African stomach virus that is easily communicable
6. When wearing a Depends undergarment while standing in a Hefty trash bag near a small pond or lake with a change of clothes. (CAUTION do not tie trash bag around waste. See Rectal Implosion).

This has been a public service announcement brought to you by the President's Council on Colon Health.

I'm not sure I ever knew what event precipitated this message. But I am certain I don't want to know. He could have simply said he needed to download some log files.

Sunday, May 23, 2004

Unifying HTML and Javascript

BadBlue Web Collaboration and Sharing Tools for Excel SpreadsheetsHave been working on a bunch of new features for BadBlue that relate to Excel collaboration.

The gist of the new features are to allow multiple users -- at different locations -- to modify the same Excel spreadsheet using only their browsers. The users don't have to have copies of Excel (in fact, they don't even need to be running Windows). There are a whole bunch of features related to multi-user conflict resolution, audit logging, cell-by-cell control of who gets to see and edit what, and a bunch of other stuff.

But implementing a rich, browser-based user-interface is challenging. As more and more features were added (based upon explicit requests from users), the amount of Javascript kept going up. Need to pop up an editor window? Javascript. Want to change the colors of a table's cell or its value "on the fly"? Javascript.

The conclusion I've come to is that HTML, as a browser markup language, doesn't have much value without Javascript. Yes, you can put up a static page with HTML and omit Javascript altogether.

But if you're doing a real application, well, you need Javascript.

Why is this important? Think about the HTML and XHTML DTD's. They really have no connection or knowledge of Javascript. Nor does Javascript have a consistent view of the HTML DTD. Need an example?

Consider how you change the contents of a table cell (an instantiated TD tag) on-the-fly:

opener.document.all ? opener.document.all[sCell] // IE4+
: opener.document.getElementById ? opener.document.getElementById(sCell) // NN6
: null;
if (cell != null) {
cell.innerHTML = "something";

Of course, if Javascript and the HTML DOM were integrated just a little bit better,

opener.document.table[2].tr[1].td[0] = "something";

or, if the table had a name attribute (doh!):[1].td[0] = "something";

or, if the table and the column each had name attributes:

opener.document.mytable.row[1].labelcolumn = "something";

In other words, why can't the HTML DOM and Javascript be completely integrated?

More importantly, why do we care about this from a strategic sense? Javascript and HTML, each operating in their own vacuum-like silos, benefits only thick-client vendors like Microsoft. The spectrum of user-interfaces available to web application designers ranges from just-plain shitty to a cut above mediocre.

An example of a web app that is pushing the limit is Google's Gmail. It might consist of 80% Javascript and 20% HTML. It is probably the most sophisticated web interface I've seen yet. It is very well done but it still doesn't approach the seamless usability of a desktop app.

A standards-based effort towards integrated HTML and Javascript (i.e., the W3C and ECMA form the necessary committees or initiatives to state what we have... and where we should be going) will bring rich, desktop-like applications to the web.

And who (except, perhaps, Microsoft) would argue against that?

BadBlue Excel Collaboration Tools for the Web

Saturday, May 22, 2004

Practical Jokers

Krakatoa : The Day the World Exploded: August 27, 1883I left the O Corporation after receiving a job offer from PMC. PMC was a division of a Fortune 500 company that specialized in motion control systems. Nearly every person in the small, Cincinnati office was either an electrical engineer or a software engineer.

The two funniest characters in the place were Tim and John. Tim was a really talented hardware guy. He couldn't write a lick of code (and was proud of it). For example, I once watched him write the following boot routine for one of his boards in assembler:

mov [r0 + 0], 0

mov [r0 + 1], 0

mov [r0 + 2], 0

mov [r0 + 3], 0


Loop, Tim, loop!

Tim, while growing up, was also famous for his "fireworks". Once, he patiently explained to me that he had gone to a junkyard with some friends, filled a hefty bag with pure oxygen and gasoline (while somehow preventing a static discharge), lit a fuse, ran like hell, and set off a monstrous explosion that mobilized police from several nearby towns. Don't try that at home, kids.

He was also notorious for an explosion of another type. One Friday a VP big-wig was visiting from corporate headquarters. A pizza lunch was generously brought in to the conference room so the VP could mingle with the commoners. Tim was the first to finish his lunch. He grabbed his plate, stood up and ripped a completely accidental fart that echoed from one end of the room to the other.

To this day, I have never seen a face turn that shade of purple, either before or since. And PMC employees still refer to that day as "The Great Pizza Fart of 1984".

John, his friend, was a combo hardware/software guy who was very skilled with autos. His sideline business involved buying Honda Civics with blown engines, rebuilding them and selling them to turn a quick $1k or $2K profit.

Tim and John were long-time buddies, but they loved to play practical jokes on each other. And, as these things sometimes do, the pranks got a little out of control.

I think it began with Tim "modifying" John's car by tying a short crowbar to the undercarriage with a steel cable. The idea being that the crowbar would drag on the ground for a while until sufficient speed was reached. At which point, the crowbar would start bouncing all over the place, slamming varying metal thingies under the car, and generally making a horrible racket - sounding something like your transmission had just fallen out.

Sure enough, John was driving home that afternoon and all hell broke loose under his car. "Cheezus! What the hell!" Pulling over on a busy street, he peered under the vehicle and instantly saw what was up. And he knew exactly who the culprit was.

A few days went by and Tim figured that either the stunt hadn't worked or John wasn't sure who'd done it. He was driving down I-71, during rush hour after work, when he heard squealing tires and horns sounding directly behind him. He looked in his rearview mirror and saw... thousands of pieces of paper flying everywhere, cars braking and swerving, just an unbelievable paper storm that seemed to be emanating from his car.

He managed to pull over to the side of the road. Checking his undercarriage, he saw what John had done. A "Yellow Pages" directory had been cabled to his car. It had just dragged along on the ground for a while, until sufficient friction had built up; it then started flinging pages, one by one in machine-gun fashion, everywhere.

At that point Tim decided that a "coupe de grace" was appropriate. One final payback so depraved, so horrible, that it would be the final act in their long-running series of pranks.

So one evening he and a few friends stayed late after work. John's hard-walled office was situated directly across the hall from the men's bathroom. Tim, with some expert mechanical help, re-routed the exhaust fan from directly over the toilet. He routed it into the HVAC for John's office, directly over the desk.

Things went back to normal, at least for a few days. John didn't notice anything. Must have been no one was stinking up the bathroom too badly. Finally, one Wednesday, John had a sales rep visiting and they were in his office with the door closed.

Tim watched as Jeff, a grizzled manufacturing guy known for eating all sorts of unhealthy slop, headed to the bathroom. Holy s**t... Tim knew Jeff had just had a nasty sausage lunch that had to be headed for oblivion. He watched as Jeff entered the bathroom and locked the door. And he waited. And waited.

Both doors remained closed for at least ten minutes. Finally, he heard the toilet flush, the sink run, and Jeff came out with a spring in his step. Not 30 seconds later, John and the customer burst out of his office. "CHEEZUS, WHAT THE HELL STINKS IN HERE!" John was freaking out, the sales rep was nauseated and had to leave. Tim tried to look innocent, so he turned away, doubled over in apoplectic laughter.

I never really found out how the "prank wars" ended. In fact, as far as I know, it could still be going on today. I do know this. If you happen to see either of them around, don't bother trying a practical joke on them. Biting off more you than can chew is the operative phrase.

Friday, May 21, 2004

How Zaxxon Taught Me to Program

ARCADE FEVER The Fan's Guide to The Golden Age of Video GamesI don't know many of you remember the arcade game Zaxxon. I do know that seeing Zaxxon for the first time -- in the mid-eighties -- transformed my feelings on user interface.

Until Zaxxon appeared, and even for a significant time thereafter, arcade games were centered in two-dimensional worlds. Space Invaders, Asteroids, Galaga, Qix... some of the names escape me, but they were flat. Stuck in a world that was one pixel deep.

But Zaxxon changed all of the ground rules, introducing a fascinating, unique and three dimensional landscape. And it opened up my eyes to alternative designs for even the relatively tame process-control software I worked on at that time.

Yes, I was still at the O Corporation (described in exquisitely boring detail in earlier blog entries). And one of our more advanced process control devices used a radioactive source (say, Cesium-137) and a matching detector to scan the width of plastic sheets. Here's a stupid-looking text "diagram" that imagines we are standing at the very end of the line looking forward as plastic sheeting comes toward us:

|| -> detector
----- Plastic Sheet -----
|| -> source

The sheet would be running in belt fashion toward the end of the line and the detector and source would move in tandem. The software we created would read the measurement signal from the detector, calculate the depth of the plastic sheet along its width, and render a pretty picture of it in 2D.


The whole point of our system, though, was not just to render the excess width (and, thus, expensive wastage), but to support real-time control of the width. The problem was the dimensional nature of the sheeting. The plastic was controlled by a series of bolts (around 32, I think). If you screwed a bolt down, less plastic came out at that point. And if you opened it up, more plastic came out.

Making sure the plastic was as flat as possible was the key. No waste, lots of money saved, happy bosses and fat bonus checks. Yeah, sure.

Anyhow, the early attempts at control just divided the width of the plastic into cross-sections, matched each section up with a bolt, and ran a straight PID feedback loop. What they quickly discovered was the "squish" effect. That is if you tried to respond to a bump in the plastic "web" by just screwing down on the bump using PID, you simply got two bumps on either side of the bolt. In other words, the plastic just kind of got "squished" down at that point and resurfaced elsewhere.

I was sent up to company "B" in upstate New York for a month to figure out how to tackle this issue. Luckily, it was the summer. If it had been winter, I might only be surfacing now as a frozen historical oddity like the ancient glacier-dude they found a while back in Switzerland. Only the archaelogists would be wondering about my pocket-protector and tape-covered glasses.

Anyhow, with a week to go, I still hadn't come any closer to a solution to the squish problem. I grew panicky. As I passed a local arcade, I started thinking about Zaxxon and its "3D belt" user interface. Was there a three-dimensional solution to the problem? What if we took adjacent bolts into the equation... and time-phased the bolt adjustment? In other words, could we take another dimension into account?

After a bunch of late night tinkering with the algorithm, I was ready for testing. We kicked off a few runs and, sure enough, the results were much better. We played around with the adjacent bolt algorithm and with the time-phasing. By Friday, we had results that were, for the first time, quite promising.

I learned from that experience the value of embracing new and different concepts, regardless of their origin, background or creators. And, if that meant more time in the arcades playing games, what's not to like?

Return-codes vs. Exception, Part 336

Rapid Application Development with MozillaToday I was, purely by accident, browsing the Mozilla documentation for details on their browser architecture. I stumbled upon the following section:

Exceptions / nsresult

Code execution can fail at runtime. One programming mechanism to deal with failure is to use exceptions. While Mozilla uses Exceptions in its JavaScript code portions, it does not in C++. One out of several reasons for this is exceptions haven't always been portable, so what was done in the past has stuck. Mozilla C++ code uses return codes to simulate exceptions. That means, while in JavaScript you can use try-catch blocks, in C++ you should check the return code whenever you call an interface method. That return code is of type nsresult. For this reason, the logical return type, as defined in the IDL file, is mapped to an additional method parameter in the C++ code.

The nsresult type is intended to transport additional failure reasons. Instead of simply reporting failure or success, an integer type is used instead, to allow for defining a lot of different error codes...

While I realize their solution is specific to C++, I thought it was worth noting.

Mozilla Exceptions / nsresult

The Pantheon

In the Name of the FatherHe's alive! A.J. Quinnell, among the finest adventure novelists I've ever read, recently emerged in public on a fan's web site. AJQ is a pen name. Many of the other hard-core Quinnell fans figured he had passed on, since his most recently announced book ("The Scalpel") never made it to print and had been scheduled for release years ago.

You may know Quinnell from the popular movie Man on Fire. But the book has been out for more than twenty years. It introduces Creasy, the quiet and deadly ex-mercenary with a penchant for serious revenge. A whole series of Creasy books exist, but are mostly out of print in the U.S. A six month effort of international purchases over the web brought me the entire collection of both Creasy and non-Creasy books.

So imagine my surprise when I read this on Tony's site:

After having maintained this web site for 8 years and never having heard a word from A.J. Quinnell himself, imagine my surprise and excitement, when I received what appeared to be an email, with an attached letter from him. I have done some research and am satisfied that this is a genuine letter from A.J. Quinnell. The letter is reproduced below...

I was greatly interested to read Quinnell's book recommendations:

...American writer Charles McCarry whose 2 books 'Tears of autumn' and 'The secret lovers' I regard as masterpieces. Of course they are out of print, but if you can find them I urge you to do so. I also like Len Deightons early books, particularly 'Funeral in Berlin' and 'Horse under water'...

I was also excited to read that a new Creasy book is (hopefully) coming out soon. The working title is Priests of a dead God. There will also be a Creasy preqel, covering his experiences in Korea and Vietnam.

If you're wondering why myself and the other Quinnell fan-boys are so excited, it's simply this. With C.S. Forester, Raymond Chandler, and Lee Child, A. J. Quinnell ranks at the pinnacle of "The Pantheon". Those are the novelists who have never failed to write exquisite works of action and adventure. You can't go wrong with your purchase of any of their books *.


* And, no, Vince Flynn, we booted you out of the Pantheon with your release of "Executive Power".

Thursday, May 20, 2004

Return-codes vs. Exceptions, Part 228

Measures for Excellence: Reliable Software on Time, Within Budget (Yourdon Press Computing Series)Pete's blog had a good critique of my last blog entry on return-codes versus exceptions. The examples were quite accurate, though...

I guess I'm beating a horse that's not only dead, but is already sleeping with the fishes (and Big Pussy) in the Hudson river... but,

I had comments inserted (the "// log" lines) where logging and instrumentation would go... the idea being that we could reconstruct a series of faults from the lowest level as we audited or unit-tested the code. I'm not sure how we would do that in Pete's examples - feedback?

The idea is that we end up with a log like this:

11:01:00 TableDebits.Lock failed for table 'ade1201' (layer 3)
11:01:00 Table 'ade1201' update failed - locking fault - rolled back (layer 2)
11:01:00 "Transfer failed, please try again later" (layer 1, the UI)

Again, this is a highly simplified example, but hopefully that indicates the kind of detailed logging/instrumentation I'd like to see at every step of the way.

Wednesday, May 19, 2004

Return-codes vs. Exceptions, Part 129

User Interface Design for ProgrammersThere's been an ongoing debate in the software development world regarding whether return-codes or exceptions should be used. Here's a brief recap.

Joel lists several good reasons why return-codes are preferred over exceptions:

#1 "They (exceptions) are invisible in the source code" - thus, they are difficult to maintain ("...even careful code inspection doesn't reveal potential bugs")

#2 "They create too many possible exit points for a function" - effective cleanup code is predicated upon predictable unwinding of state as a method or function terminates

Joel continues, "...I consider exceptions to be no better than "goto's", considered harmful since the 1960s, in that they create an abrupt jump from one point of code to another. In fact they are significantly worse than goto's..."

Sergio states (regarding Joel), "His stance against exceptions as a method for handling abnormal program behaviour is just plain wrong. Joel recommends using error return codes, and dealing with them immediatly. There are two big problems with this approach:

It places abnormal behaviour treatment inline with normal execution. It hurts code readability.

Without exceptions, dealing with code transactions and rollbacks produces an imense tangling of ifs or procedure calls.

There is a valid discussion open on whether exceptions should be checked or unchecked, but the mechanism itself is, for me, proven..."

Ned agrees with Sergio, "Exceptions keep the code clean". At least he provides some examples.

And, in a recent interview, James Gosling had some interesting things to say. He wasn't speaking directly about exceptions versus return-codes, but he had some salient points that relate to the mission-critical software world.

"You talk to people in banks, where large quantities of money get lost if there's a problem. They take failure very seriously. The spookiest folks are the people who have been doing real time software for a long time. I've spent a certain amount of time with that crowd. By and large these folks are very conservative and very careful. A lot of them know what it's like to go visit the family of the deceased and explain the bug to them. There are a number of places that have policies that if a test pilot augers in, then once it's all figured out what happened, the people who engineered the thing that failed have to go explain it to the family. I've actually only met one person who has ever actually had to do that. That would change your attitude about dealing with failure really quickly"

Here's my take: Joel is dead-on. I'll tackle Sergio's item number one first. Look: we (the software development community) have a problem with software quality. I don't think I'll get much disagreement on this fact. Software quality, in general, sucks. The reason for this is that many developers are too lazy to instrument, monitor and and respond to all sorts of strange conditions.

In other words, many of us are undisciplined. We're more worried about "readability" (and I disagree with that contention as well - but I'll get to that) than whether or not or software will kill anyone, debit the wrong account by a million bucks, or screw up the actuarial table for 83 year-old transvestites.

Like it or not, dealing with aberrant conditions is a contract we agree to when we decide to be professional and responsible software developers. Treating "abnormal behaviour inline with normal execution" is a misstatement. We need to deal with the unexpected. And the best place to do it is the place where you can "unwind" the logic that's gone bad.

My guess is that Sergio never wrote a database engine or other mission-critical, system-level code. This is the kind of logic you'd implement (it's a simplified example only, so please don't send me syntax error, faulty logic, or "you coulda used diagnostic macros" messages):

do { try {

if ((rc = != OK) {
// log
bUnwindTableCreditsOpen = TRUE;

if ((rc = tableCredits.lock()) != OK) {
// log
bUnwindTableCreditsLock = TRUE;

if ((rc = != OK) {
// log
bUnwindTableDebitsOpen = TRUE;

if ((rc = tableDebits.lock()) != OK) {
// log
bUnwindowTableDebitsLock = TRUE;

if ((rc = ::IntegralTransaction(tableCredits, tableDebits, curAmount)) != 0) {
// log

} catch (...) {
// catch miscellaneous exceptions here
} } while (0);

if (bUnwindTableDebitsUnlock) {
if (bUnwindTableDebitsOpen) {
if (bUnwindTableCreditsLock) {
if (bUnwindTableCreditsOpen) {
return (rc);

Can you imagine trying to unwind these kinds of "abnormal events" outside the scope of the method that was orchestrating this sort of activity? It wouldn't be fun.

And my take is that readability isn't compromised here. No one is espousing tons of nested if's or other convoluted logic to keep track of state. Do it the easy way. If you have to throw an exception, do it. Right to the bottom of your method. Or, if you can't, hit the "break" (pun intended). Either way, you can start unwinding based upon your current state without compromising the integrity of an 84 year-old transvestite's term-life premium.

Trust no one. Check everything. Log everything. Go forth and prosper.

Tuesday, May 18, 2004

A bald-faced bug

The Enemy - Lee ChildAny developer has their "toughest bug they ever cracked" story. I'm no different.

Those of you who know me know that I'm hair-challenged. Thinning on top. Approaching cleanhead status. Alright, I'm basically bald. This is the story of how I got bald over the period of two days. Ripping out clumps of hair in frustration. Cats and dogs, sleeping together. Total chaos.

I had this small utility program I'd created in ANSI C running on a mid-range HP/UX server. Mid-eighties. The program was no more than five or six hundred lines in length. It read some input files and did some calculations for motion control. I think it created pre-planned routes for a high-speed turning machine that cut specially shaped pistons for Cadillac. Either that or it was routing air traffic over LaGuardia.

Anyhow, the program would do some complicated calculations and run for a while. Most of the time it would work. In fact, it might work perfectly forty times in a row. But on the forty-first run, it would crash. And it was completely random. It might work forty times, crash twice, work another five times, crash, then work fifty times.

I threw in printf's to isolate the location of the crash (no IDE's available on the HP/UX back then, Jimbo). It was crashing in RANDOM FRICKING LOCATIONS every time. WTF?

I analyzed the time-of-day of each crash. Nothing. It didn't seem to be time-based.

I analyzed the input data. The same data file would crash sometimes and not crash other times.

Exasperated, I started stripping out large chunks of code. The math calculations got stripped out, over several iterations, until there were no calculations whatsoever. Still crashed. Cheezus. What in the...?

I excised the up-front error-checking. Nada. Same results. And it was crashing in random locations!

Now all I had the was the loop that read the input file and pre-processed the data for calculation. Ripped out the pre-processor part. ARGGHHHGH! It still crashed.

All that remained was a loop and an fscanf that read the raw input data into the initial data variables. I removed the fscanf.

It worked. Well, it better, given that the whole damn program was just a freaking loop now. Something in the fscanf was toasting something else, given the random location of the crashes.

Long story short: one of the data items was overranging fscanf's load of a variable. Just one in a series of eight or nine. And since HP/UX's I/O subsystem was handling the fscanf (to give time back to the system)... the subsystem was occasionally blowing away my process - randomly, just to ratchet up the fun factor.

So... the I/O subsystem was randomly crashing the application code. Hey, HP/UX designer! Nice separation of process and system code! Okay, that's my frustration talking, it really wasn't their fault.

Lesson learned: separate steps wherever possible. For example, read input data into a buffer, _then_ sscanf it. Don't mask too many operations in the interest of "more elegant" code. You might end up, ahem, hair-challenged.

Paranoid, anal, whatever

Encyclopedia of Wireless TelecommunicationsI was talking with M today about a billing problem he encountered with his mobile phone. Seems there was a not-so-slight bug in their minute-tallying code. If you dialed a number, hung up, and then dialed again... both calls were charged. And the first call generally would get billed 30 or 40 minutes. Uhm, that's not right. Enough people complained that they not only retroactively repaired the bills... but they even fixed the billing software. Go figure.

As we discussed this problem, one of my most disastrous software screwups popped into my head. All of the intentional mental blocks I'd thrown up had failed. And even the fail-safes had failed. It was all coming back to me... all the pain, adrenaline shock, and pure horror. The reason why almost anyone who's ever reviewed my source code has said one thing.

"Damn, you are one anal SOB."

Ah, pull up a chair, youngster, and let me tell you a story of why I check every error condition, log every bizarre, impossible situation, and even alphabetize my class members and methods with perfect tab alignment throughout. Maybe that last part is going overboard a bit. Nonetheless...

I was still at my first job, at the O Corporation (see previous blog entry for more mundane, pointless detail). I'd been there a year or two, and was getting pretty good at all sorts of real-time, assembly level hacks. One of our products needed to be able to communicate over a dialup line. This predated the Internet. Hell, it predated modems. All we had available for data communications were Anderson-Jacobsen (click for picture) acoustic couplers.

Basically, the A-Js were the precursors of modern dialup modems. You could get a blistering 110 to 300 baud transfer rates out of 'em. We were like, "300 baud? NFW! That's awesome!".

One of our products had been deployed in Chilicothe, Ohio. Way too far to drive on a regular basis. So one guy rigged up the product to accept dialup calls using his A-J. His system would wait for a call, bundle up some data and send it back to the caller.

I wrote the management side. Created a serial "driver" to talk to the A-J (we didn't have no stinkin' COM ports then, biatch, we're talking raw UART control code). Then added a layer to harness the awesome power of the A-J through the equivalent of control strings (similar to Hayes AT codes). And lastly, added the scheduler and control logic that would dial up the remote system, request the data, and save it into a text database for my batch reporting tools.

Oh, this was going to be sweet. It was too damn cool. A couple of tests later, I was ready to rock. It looked like it was working perfectly. This was a Friday, so I scheduled a collection job and took off for the weekend.

Came in Monday. Wow, it had worked. We'd collected all the data. I was pumped! I hardly noticed that the modem was still connected. Hmmm. That's weird. Just a fluke. I'll just recycle it, no problem.

A week later, the receptionist called. "Do you realize one of your phone lines had a long-distance charge of $2,100 on it?".

"Well, I didn't do that. Sounds like a problem with the phone company."

I hung up and four gallons of adrenaline got pumped into my stomach as I realized that the modem had been on that entire weekend. The VP of Engineering was walking over. Oh s**t. This wasn't going to be good. He'd obviously heard the news.

"What the heck happened to your phone bill, Ross?"

"Uh, not sure, sir. I think... I think... my software neglected to hangup the A-J."

"Well, you're damn lucky." Huh? Why? "Because the receptionist sweet-talked the Bell customer service people and convinced them they had a problem with their billing. They reversed the charge." Wheeeeew. That was quite a relief.

So call me Paranoid. Anal. Whatever. That debacle forced me to be ultra-careful. All of those "that can't happen" conditions? I check 'em and log 'em. I don't want the equivalent of a four-figure phone bill on my watch.

Encyclopedia of Wireless Telecommunications

Monday, May 17, 2004

First Job
Microcomputers and Microprocessors: The 8080, 8085, and Z-80 Programming, Interfacing, and Troubleshooting (3rd Edition)My first job -- after graduating with a degree in Computer Science -- was at the O Corporation. O is an abbreviation that protects both the guilty and the innocent. My title was "Systems Programmer", but my real role was to find and fix bugs in the company's mainstay product: an Intel 8080-based process measurement and control system.

The systems themselves varied from single-processor with maybe 8K of RAM to multi-processor (Multibus-based) with two or three processors and perhaps 24K of RAM. 4K of RAM was used as global storage, accessible to all of the processors.

The advanced models, of course, used the multi-processor configurations. The extra processors were there to support a CRT (black and white, with 320 x 240 pixel resolution, I think) display of the process. Those were the really expensive models, so often customers opted for the base units that displayed the key metrics using seven-segment displays on the front panel.

To develop, we used Intel MDS-80 development systems (arguably, the first personal computers) running the ISIS Operating System. We would modify the 8080 assembler source code (using 8" floppies), run an assembler on the code, then swap in a linker floppy and create the final image. The end result would get burned onto an EPROM (erasable, programmable read-only-memory for the hardware-challenged). Had a bug in the code? That's where the fun came in.

Debugging on some of these systems (especially those without CRT's) was - uhmmm - entertaining. One of the sharp hardware guys had come up with a device called a CAM box, which strapped into the bus and allowed you to read memory addresses onto a seven-segment display. You could even change the contents of RAM.

Bob Frantz, I believe, was the original (very smart) software designer who had come up with much of the architecture. As an aside, he bequeathed all of his original Dr. Dobb's Journals to me -- which I still have -- upon his retirement. But he had written the system's original real-time OS (pre-emptive, multitasking and fit in perhaps 1K or so of code) and designed much of the architecture. Another sharp developer, Dave H., was also a key contributor. One of the clever aspects of the system involved a call table placed into RAM. The major tasks and services all vectored through the call table.

Using the CAM box, if you placed a C9 (a "return" instruction) in the right place in the call table, you could disable a misbehaving service. Putting a C3 back (a "jump", followed by the address) turned the service back on. You could also write some debugging values to the minimal amount of spare RAM and then inspect the values through the CAM box. Let's just say that debugging through the CAM box on the plant floor was... not quite as smooth a user-experience as using Visual Studio's integrated debugger. But it worked. And, boy, did I learn a lot.

I ended up leaving the company for technology-related reasons. Shortly after I joined, they acquired a division of another company that also developed high-end process control software. Their entire architecture was based on DEC PDP-11's. The new guys convinced management to develop the next generation products using DEC hardware (e.g., MicroVAXes). I wrote memo after memo espousing a PC-based architecture. When I didn't get my way... I resigned and moved on to another company.

The original company is still in business and, to this day, cranks out process control equipment. Albeit as a division of a much larger company. I think, in retrospect, the PC decision impacted their ability to remain independent. But that's just my opinion and I could be wrong. Books: Microcomputers and Microprocessors: The 8080, 8085, and Z-80 Programming, Interfacing, and Troubleshooting (3rd Edition)

Stupid White Man

Fat and stupid is no way to go through life, son.

Perhaps the most serene irony to be found in Hollywood is that the most phony, disingenuous person in the whole town is the avowed outsider, the self-righteous everyman. It’s impressive to see one man be so heroically ridiculous, a man who manages to be

1. A radical socialist who lives in a palatial New York apartment and sends his daughter to one of the most expensive private schools in the country.

2. A blowhard who pretends to advocate the views of the average American despite holding opinions that the majority of Americans find absurd.

3. A polemicist against President Bush for manufacturing “fictitious elections” who makes fictitious “documentaries,” lies pathologically in his writing and interviews, and actively doctors his past statements to avoid looking silly.

Stupid White Man

Sunday, May 16, 2004

The Seven Stages of Targeted Marketing

Jump Start Your Business Brain: Win More, Lose Less, and Make More Money with Your New Products, Services, Sales & AdvertisingThe seven stages of targeted marketing are described in this brief and compelling article directed at those of us who are marketing-stunted.

"The 7 stages, involving a mixture of tele-research, direct mail and telesales, are listed below. Each stage will be described in more detail later in this article:

Selection of key target market sectors: identifying what types of customers you want to do business with.

List research: compiling lists of potential customers.

Telephone research: to ensure that the information gained from the lists is accurate, and to get any supplementary information not included in the mailing lists.

Prospect selection: based on the lists and telephone research, to eliminate any inappropriate prospects and / or to produce a smaller, manageable sub-list for this particular mailing.

Mailshot: sending out a letter and appropriate sales literature to the selected prospects.

Telephone follow-up: this is where you really go for whatever it is you are wanting - a sales meeting, a trial order, the opportunity to quote... whatever is your objective.

Recording, measuring, monitoring: so that you know what has worked, what has not, what actions you need to take next."

Targeted marketing: how to do it

The Beale Codes
The Code Book: The Science of Secrecy from Ancient Egypt to Quantum Cryptography"It was in the month of January, 1820, while keeping the Washington Hotel, that I first saw and became acquainted with Beale. In company with two others, he came to my house seeking entertainment for himself and friends. Being assured of a comfortable provision for themselves and their horses, Beale stated his intention of remaining for the winter, should nothing occur to alter his plans, but that the gentlemen accompanying him would leave in a few days for Richmond, near which place they resided, and that they were anxious to reach their homes, from which they had long been absent. They all appeared to be gentlemen, well born, and well educated, with refined and courteous manners and with a free and independent air, which rendered then peculiarly attractive. After remaining a week or ten days, the two left, after expressions of satisfaction with their visit. Beale, who remained, soon became a favored and popular guest; his social disposition and friendly demeanor rendered him extremely popular with every one, particularly the ladies, and a pleasant and friendly intercourse was quickly established between them.

"In person, he was about six feet in height, with jet black eyes and hair of the same color, worn longer than was the style at that time. His form was symmetrical, and gave evidence of unusual strength and activity; but his distinguishing feature was a dark and swarthy complexion, as if much exposure to the sun and weather had thoroughly tanned and discolored him; this, however, did not detract from his appearance, and I thought him the handsomest man I had ever seen. Altogether, he was a model of manly beauty, favored by the ladies and envied by men. To the first he was reverentially tender and polite; to the latter, affable and courteous, when they kept within bounds, but, if they were supercilious or presuming, the lion was aroused, and woe to the man who offended him. Instances of this character occurred more than once while he was my guest, and always resulted in his demanding and receiving an apology. His character soon became universally known, and he was no longer troubled by impertinence.

"Such a man was Thomas J. Beale, as he appeared in 1820, and in his subsequent visit to my house. He registered simply from Virginia, but I am of the impression he was from some western portion of the State. Curiously enough, he never adverted to his family or to his antecedents, nor did I question him concerning them, as I would have done had I dreamed of the interest that in the future would attach to his name.

"He remained with me until about the latter end of the following March, when he left, with the same friends who first accompanied him to my house, and who had returned some days before.

"After this I heard nothing from him until January, 1822, when he once more made his appearance, the same genial and popular gentleman as before, but, if possible, darker and swarthier than ever. His welcome was a genuine one, as all were delighted to see him.

"In the spring, at about the same time, he again left, but before doing so, handed me this box, as he said, contained papers of value and importance; and which he desired to leave in my charge until called for hereafter. Of course, I did not decline to receive them, but little imagined their importance until his letter from St. Louis was received. This letter I carefully preserved, and it will be given with these papers. The box was of iron, carefully locked, and of such weight as to render it a safe depository for articles of value. I placed it in a safe and secure place, where it could not be disturbed until such time as it should be demanded by its owner. The letter alluded to above was the last communication I ever received from Beale, and I never saw him again. I can only suppose that he was killed by Indians, afar from his home, though nothing was heard of his death. His companions, too, must all have shared his fate, as no one has ever demanded the box or claimed his effects. The box was left in my hands in the Spring of 1822, and by authority of his letter, I should have examined its contents in 1832, ten years thereafter, having heard nothing from Beale in the meantime; but it was not until 1845, some twenty-three years after it came into my possession, that I decided upon opening it. During that year I had the lock broken, and with the exception of the two letters addressed to myself, and some old receipts, found only some unintelligible papers, covered with figures, and totally incomprehensible to me...

"According to his letter, these papers convey all the information necessary to find the treasure he has concealed, and upon you devolves the responsibility of recovering it. Should you succeed you will be amply compensated for your work, and others near and dear to me will likewise be benefitted. The end is worth all your exertions, and I have every hope that success will reward your efforts."
Lynchburg, Va., January 5th, 1822.

Dear Mr. Morriss. - You will find in one of the papers, written in cipher, the names of all my associates, who are each entitled to an equal part of our treasure, and opposite to the names of each one will be found the names and residences of the relatives and others, to whom they devise their respective portions. From this you will be enabled to carry out the wishes of all by distributing the portion of each to the parties designated. This will not be difficult, as their residences are given, and they can easily be found.

The two letters given above were all the box contained that were intelligible; the others, consisted of papers closely covered with figures, which were, of course, unmeaning until they could be deciphered. To do this was the task to which I now devoted myself, and with but partial success...

To enable my readers to understand the paper "No. 2," the only one I was ever able to decipher, I herewith give the Declaration of Independence, with the words numbered consecutively, by the assistance of which that paper's hidden meaning was made plain:

...By comparing the foregoing numbers with the corresponding numbers of the initial letters of the consecutive words in the Declaration of Independence, the translation will be found to be as follows:

I have deposited in the county of Bedford, about four miles from Buford's, in an excavation or vault, six feet below the surface of the ground, the following articles, belonging jointly to the parties whose names are given in number "3," herewith:

The first deposit consisted of one thousand and fourteen pounds of gold, and three thousand eight hundred and twelve pounds of silver, deposited November, 1819. The second was made December, 1821, and consisted of nineteen hundred and seven pounds of gold, and twelve hundred and eighty-eight pounds of silver; also jewels, obtained in St. Louis in exchange for silver to save transportation, and valued at $13,000.

The above is securely packed in iron pots, with iron covers. The vault is roughly lined with stone, and the vessels rest on solid stone, and are covered with others. Paper number "1" describes the exact locality of the vault so that no difficulty will be had in finding it.

The following is the paper which, according to Beale's statement, describes the exact locality of the vault, and is marked "1." It is to this that I have devoted most of my time, but, unfortunately, without success...

The Beale Codes

Saturday, May 15, 2004

Quine = Self-Reproducing Code

Metamagical Themas: Questing for the Essence of Mind and PatternI received a note from AG regarding self-reproducing code. "I presume by now you have seen a kazillions of these"...

...quine: /kwi:n/ /n./ [from the name of the logician Willard van Orman Quine, via Douglas Hofstadter] A program that generates a copy of its own source text as its complete output. Devising the shortest possible quine in some given programming language is a common hackish amusement. Here is one classic quine:

((lambda (x)
(list x (list (quote quote) x)))
(lambda (x)
(list x (list (quote quote) x)))))

This one works in LISP or Scheme. It's relatively easy to write quines in other languages such as Postscript which readily handle programs as data; much harder (and thus more challenging!) in languages like C which do not. Here is a classic C quine for ASCII machines:


For excruciatingly exact quinishness, remove the interior line breaks...

The Quine Page

Thursday, May 13, 2004

Van.. Hell... zing...

Van Helsing, by Kevin RyanThe Filthy Critic has posted a priceless review of the new movie Van Helsing. Enjoy it for the obscene language. Revel in the outrageous metaphor. Hell, just read it.

What a f**king turd. F**k you, Hollywood. How the f**k can you release something so soulless, witless and pointless? How f**king greedy do you need to be?

Van Helsing is as crappy, loud and stupid as the Harelip at the Arvada City Hall Open House's free hot dog barbecue. It's all disorienting squealing and howling and shoving hands down uneasy city firefighters' pants.

Van Helsing is the kind of movie that people who hate movies make. It's not a good movie, it's not even a bad one that somebody cares about. It's just a steaming pile of s**t, a mass-marketing stunt dressed up like entertainment. It'll be a blockbuster, but no for reason other than sheer force of will and heavy marketing that keeps telling us it's an event. If this is an event, so is the time I ate too many sulfites at the Soup Plantation and sat on the can wringing my bowels like a handtowel...

Van Helsing - The Filthy Critic

Francis Bacon's Steganography

Complete TragediesThe whole world is still buzzing over the controversy: was Francis Bacon really the author of Shakespeare's works? Uhm, well, perhaps that's an overstatement. Anyhow, came across a very intriguing series of articles on Bacon's supposed use of steganography (hiding an encrypted message within another message). It begins with Mark Twain's description of a barely literate Shakespeare.

There is also considerable doubt about the facts of Shakespeare's own life. Let us read what Mark Twain had to say about that (From Is Shakespeare Dead?, 1909):

He was born on the 23rd of April, 1564.
Of good farmer-class parents who could not read, could not write, could not sign their names.
At Stratford, a small back settlement which in that day was shabby and unclean, and densely illiterate. Of the nineteen important men charged with the government of the town, thirteen had to "make their mark" in attesting important documents, because they could not write their names.
Of the first eighteen years of his life nothing is known. They are a blank.
On the 27th of November (1582) William Shakespeare took out a license to marry Anne Whateley.
Next day William Shakespeare took out a license to marry Anne Hathaway. She was eight years his senior.
William Shakespeare married Anne Hathaway. In a hurry. By grace of a reluctantly granted dispensation there was but one publication of the banns.
Within six months the first child was born.
About two (blank) years followed, during which period nothing at all happened to Shakespeare, so far as anybody knows.
Then came twins--1585. February.
Two blank years follow.
Then--1587--he makes a ten-year visit to London, leaving the family behind.
Five blank years follow. During this period nothing happened to him, as far as anybody actually knows.
Then--1592--there is mention of him as an actor.
Next year--1593--his name appears in the official list of players.
Next year--1594--he played before the queen. A detail of no consequence: other obscurities did it every year of the forty-five of her reign. And remained obscure.
Three pretty full years follow. Full of play-acting. Then.
In 1597 he bought New Place, Stratford.
Thirteen or fourteen busy years follow; years in which he accumulated money, and also reputation as actor and manager.
Meantime his name, liberally and variously spelt, had become associated with a number of great plays and poems, as (ostensibly) author of the same.
Some of these, in these years and later, were pirated, but he made no protest.
Then--1610-11--he returned to Stratford and settled down for good and all, and busied himself in lending money, trading in tithes, trading in land and houses; shirking a debt of forty-one shillings, borrowed by his wife during his long desertion of his family; suing debtors for shillings and coppers; being sued himself for shillings and coppers; and acting as a confederate to a neighbor who tried to rob the town of its rights in a certain common, and did not succeed.
He lived five or six years--till 1616--in the joy of these elevated pursuits. . .
When Shakespeare died in Stratford it was not an event. It made no more stir in England than the death of any other forgotten theatre-actor would have made. Nobody came down from London; there were no lamenting poems, no eulogies, no national tears--there was merely silence, and nothing more. A striking contrast to what happened when Ben Jonson and Francis Bacon, and Spenser, and Raleigh and the other distinguished literary folk of Shakespeare's time passed from life! No praiseful voice was lifted for the lost Bard of Avon; even Ben Jonson waited seven years before he lifted his.
So far as anybody actually knows and can prove, Shakespeare of Stratford-on-Avon never wrote a play in his life.
So far as anybody knows and can prove he never wrote a letter to anybody in his life.
So far as any one knows, he received only one letter during his life.
So far as anyone can know and can prove, Shakespeare of Stratford wrote only one poem during his life. This one is authentic. He did write that one--a fact which stands undisputed; he wrote the whole of it; he wrote the whole of it out of his own head. He commanded that this work of art be engraved upon his tomb, and he was obeyed. There it abides to this day. This is it:

Good frend for Iesus sake forbeare
to digg the dust encloased heare!
Blest be ye man yt spares thes stones
And curst be he yt moves my bones.

Who wrote the Works?

Shrugs and the Cervical Spine

Strength Training AnatomyI never realized what toll the years of lifting were taking on my spine. Now, after having had a disc fusion surgery, I see this terrific article on reducing strength training injuries. Just in time! Sweet! It really is one of the best I've ever seen. What I'm guessing is that years of heavy shrugs, deadlifts and rows -- all with the head tilted forward -- conspired to make the trauma I received while playing basketball worse. I reiterate my recommendation: never have 180 lbs. land on your head. It really doesn't feel very good at all. Anyhow, for anyone training with weights of any significance, do yourself a favor and check this out.

...Exercises in which the head is allowed to nod or protrude forward may contribute to cervical spine injury by either promoting the postural defect... or by predisposing the athlete to cervical disc problems. The tendency to jut the head forward in exercises such as shrugs..., behind the neck presses..., behind the neck pulldowns, lateral shoulder raises..., triceps extensions, curls, incline leg presses, and abdominal crunches promotes the development of the rounded shoulder, forward head posture. This posture is associated with abnormal mechanical function of the cervical spine...

Minimizing Weight Training Injuries in Bodybuilders and Athletes

Because you just can't get enough self-reproducing code...

Logic, Sets, and Recursion by Robert L. CauseyTobias from PHPwizard wrote me regarding an earlier blog entry on self-reproducing code. He uses a printf to achieve the necessary recursion for self-reproduction. Way, way more elegant than the clunky approach I wrote over lunch one day. Anyhow, here 'tis:

I used these as signatures back in 1999 or 2000:

<?$p = '<?$p = %c%s%c; printf($p,39,$p,39);?>'; printf($p,39,$p,39);?>

Another self-printing signature:


This is unrelated, but cool: :)
Mandelbrot, takes less than a second with PHP 5.0, took 3.5 seconds to execute with PHP 4.0.1 and 13.5 seconds with 3.0:

$s.=chr(30+$c),$a+=0.0503)for($x= /* Tobias Ratschiller */
$y=$c=0;++$c<90&$x*$x+$y*$y<4;$y= /* */

MSDN opines on network security... and it's pretty good!

Windows(R) XP Professional SecurityLooking for a good overall picture of network security? Not sure you've had enough formal coverage of all the threats in the wilds of cyberspace? MSDN, of all places, has a pretty good backgrounder on the topology of network security.

Web Security Threats and Countermeasures

Fast Track: How To Implement Web Application Security

Wednesday, May 12, 2004

Plan of Attack by Bob WoodwardHave been engaging in a good email discussion with B regarding Larry Abraham's articles (see a prevous blog entry entitled "The clash of civilizations and the great Caliphate"). His comments:

> I read the Larry Abraham stuff you cited and, while I found the thesis
> to be interesting, I have to say the guy's off the deep end. His focus
> on the Judeo-Christian/Western viewpoint greatly reduces the relevance
> for me. While I come from that tradition, one needs to remember that
> there are over 2+ billion people that just don't give a s**t. We only
> care and may be alarmed because we hold some religious views very dear.
> It is these same 2+ billion folks that will end up eating our economic
> lunch in the coming 20-30 years.
> What we in the US face is an inability to even start thinking and
> planning for energy independence. It's that simple. With that, 90% of
> this religious jihad bulls**t falls away. Combine that with a sane
> policy toward the middle-east and Larry's scenario fails to have any
> plausiblity...not that there is much there to begin with.
> Sure, I think his analysis might be indicative of the state of radical
> areas of Islam. Sure, there is history here that goes back a thousand
> years. Why do you think Bush's handlers reacted so strongly when he
> called the War in Iraq/Afghanistan a "Crusade"?
> However, Larry's so partisan with respect to his views of U.S.
> politics that it's clearly a cry from his political perspective.
> Further, he is allowing the jihadists to frame the situation. They want
> us to see it that way and to be very frightened about it. I may have
> bought Larry's thesis were it not for the crazy alarmism and the
> pot-shots at the non-GOP politicians involved. Any article that calls
> out "Liberals" or "Conservatives" loses credibility quickly with me.
> The problem with the US is that we live in a pseudo-representative
> oligarchy. Without fundamental change in our system, things will
> continue forward regardless of the stuffed suits that reside in offices
> in DC. Big money (esp. Oil) and special interests drive what's
> happening. We're at "War" because we have too many foreign
> entanglements based upon our need for energy. That won't change until
> those in power change. Invading another couple countries won't solve
> the problem (though I do agree that Pakistan would have been a better
> choice than Iraq). The scary thing for me is that there are people,
> like the bulk of the current administration, that think in black and
> white terms. They have no second thoughts about using words like
> "crusade", "evil-doers", or "new world order". I'm sorry, but reality
> isn't like that. I also have little respect for the academics that want
> to change facts based upon what the definition of "is" is. There must
> be some balance.
> What we need to do is attack the problem at it's source. If we
> weren't such gluttons for oil, the middle east and people like Bin Laden
> wouldn't have the $$ necessary to mess with us. You take out Osama or
> the heads of other terrorist groups and three more people will step up
> to take their place. Attack their captial pipeline and they become a
> nuisance rather than a threat. That pipeline should be attacked at the
> source. We are its largest source and hold within our power the ability
> to change.

My response was:

Good note. I don't disagree with a thing you've said. But the timeframe for
the type of fundamental changes you've described extends well beyond our
lifespans (IMO).

Reduce our dependence on foreign oil? Sure. Eradicate the influence that
special interests have on law-makers? Absolutely.

But if we started today, we're looking at 20+ years to implement just those two
keystone tenets. Let's start the education process today to show Americans that
really don't need to drive Hummers and Land Cruisers. But that's gonna take a

And, in the mean time, do we tolerate a potential nuclear or WMD threat to our
cities and our families? And what's to say that the religious fanatics would
stop their shenanigans even _if_ we reduced our dependence on their oil to zero?
My guess is they wouldn't stop for a second.

I don't put this in religious terms at all. I put this in terms of:

Capitalist sons-of-bitches vs. Insane, suicidal, murderous sons-of-bitches

I don't give a s**t what their religion is. I do know they want to kill
everyone that isn't like them. Who do _you_ want to win that battle?