Using the First-Run Experience to make you happy.

From Daring Fireball:

Apple is the one and only PC maker that sees the first-run experience as an opportunity to make you happy, rather than as an opportunity to make a few bucks by showing you ads and stuffing trialware down your throat.

How true.

Advertisers know about this. They know that when you sell something to someone–even something that won’t be replaced often, like a car–that they need to continue to advertise to you. It’s a halo effect: ads for BMW are targeted to BMW drivers to make them happy they bought a BMW, so they are more likely to recommend BMW, and so they are more likely to replace their older BMWs with a newer BMW. It’s called customer loyalty, and its built first and foremost by taking every opportunity you can to make the customer happy.

Computer manufacturers, however, don’t seem to remember this basic law of advertising, a law that was probably discovered by the Romans–if not by caveman. And so they abuse the hell out of you on the first boot, exchanging short-term gain of collecting a few bucks from advertisers for the happiness of their customers in making a multi-hundred or multi-thousand dollar purchase. The assumption is that happiness isn’t as important as making a few bucks.

But Apple has figured out this basic law of Happiness. So much so that when I first unboxed my Apple TV, I carefully took it out of the box, plugged it into the TV, configured the TV, used a flashlight to triple-check to make sure the TV was properly hooked up and the tuner was switched to the correct channel–all so I could make sure that the moment I plugged the Apple TV into the wall, full video and audio would work correctly from the millisecond power was appled.

Because I didn’t know what the Apple TV box would do when it was first turned on–but I knew that it would make me happy, and I didn’t want to miss a second of it.

The checking of the wires and verifying the component video and audio was correctly synced was well rewarded: when I plugged the Apple TV in, it made me happy.

And it is the same with the iPhone: I don’t know what the unboxing and first-run experience will be like–but I know it will make me happy. My present to my wife when I first get her an iPhone will be to leave it in the box, so she can also experience the same joy–a joy which is so rare when unboxing electronics that she so far has refused to unbox anything. Because she has learned, thanks to years of training, that unboxing and opening up a new gadget is not like christmas, but more like opening up the sealed container that has been living in the back of your refrigerator for the past year or so. You don’t know what to expect, but you know it will take work before you like it.

When Abbreviations Attack!

I have a bachelors of science degree from the California Institute of Technology.

Now one of the abbreviations for degree and major that I got used to was to write something like “BS/?”, where “?” is replaced with the abbreviation for your degree. So for example “BS/E&AS” means Bachelors of Science, Engineering and Applied Sciences. “BS/CE” means “Bachelors of Science, Chemical Engineering.” And “BS/AP”, Bachelors of Science, Applied Physics.

I have a BS in Mathematics. And when I applied for a new job at a company just spitting distance from me, I was in a hurry, so I scribbled down “BS/MA”: Bachelors of Science, Mathematics. My resume has it, but in the long form “B.Sc. Mathematics”; the on-line application I checked “four-year degree”–I’ve been very clear everywhere what I have–and during the interview everyone interviewed me from my (correct) resume, which they didn’t even bother to look at, since I graduated nearly 20 years ago.

I got a call last night from a field check company which wanted to verify an error on my application. They told me flatly that I did not have a Masters of Arts degree from Caltech; do I have an explanation? And so now what was a shoe-in job becomes a living nightmare as I get a quick course in security and application verification and the people who do it at Yahoo.

Damn, damn, damn, damn, damn…

Update: It appears not to have made a difference, which is as I thought it should. I’ve got my offer, which means I’ll be doing a lot more Java in the future–and will have plenty of Java idiosyncrocies to complain about in the future!

Nice Idea

Snagged from Daring Fireball: Adobe edits the development cycle

Probably the most effective thing we did was institute per-engineer bug limits: if any engineer’s bug count passes 20, they have to stop working on features and fix bugs instead. The basic idea is that we keep the bug count low as we go so that we can send out usable versions to alpha testers earlier in the cycle and we don’t have the bugalanch at the end.

The goal is to always have the product in a state where we could say “pencils down. You have x weeks to fix the remaining bugs and ship it”. The milestones are primarily measurement points, with the acceptance metric being quality instead of something like “all features in” or “UI Frozen”.

There are two things I’ve seen or heard of which I believe is a really nice idea, software management wise. This is one of them.

The other is the idea of the weekly team meeting. I know most people hate team meetings–and they can become obnoxious if you have a large team. But I’ve been on projects where we never held meetings–and on one project I couldn’t have picked out half of my teammates in a police lineup if I had a gun pointed at my head.

On the other hand, I think team meetings should be limited to one hour a week. Stand-ups (where everyone is supposed to meet for 15 minutes, like the huddle before a game play in football) strike me as a completely useless exercise that only makes managers feel good that they’re “doing something”, and team meetings that last more than an hour or meet more than once a week are also equally a waste of time.

Simple Rule Of Thumb

Lots and lots of column space has been devoted to the proper techniques for doing software management and software engineering.

I have one. It’s a simple one–but strangly one that I haven’t seen honored on any project I’ve worked on in a large colaborative environment, much to the detrement of the team. That rule of thumb is this:

If you are using an IDE, and you cannot simply open up the project file for the project you are working on and press “debug”, then your build process and project file is broken.

Now I’ve heard all sorts of objections to this rule of thumb on the projects I’ve worked on. “Oh, my project contains a bunch of DLLs which require special code in order to be hooked into the OS.” (Uh, DllRegisterServer, anyone? And the Visual C++ debugger will automatically run DllRegisterServer for you when you hit the debug button.) “Oh, my project is scattered across a whole bunch of different projects.” Then your build process is broken, since every modern IDE I’ve encountered can handle multiple projects. “Oh, I’m building something specialized like a device driver.” Okay, in that case I can see your point: the IDE tools may not be quite up to snuff. And one project I’m working on hooks the OS at a very low level–but really, how many people are working on low-level back-door OS hooking code? And shouldn’t that be segregated in such a way so that the majority if your code can operate even without the hooks?

By and large the biggest problems I’ve encountered which prevent a newbie from opening up a project and pressing the “debug” button is because the other developers just don’t care enough to make the build process simple. They cannot be bothered to look up how the IDE they’re using works; they cannot be bothered to read the documentation that describes how COM DLLs are loaded–and so they create these humongous piles of junk trying to solve a problem that was already solved with a more elegant–and IDE friendly–technique.

Fundamentally, if you cannot just open the IDE and hit “debug”, your project is broken. And if you cannot figure out how to make it so you can just hit the “debug” button, perhaps you need to spend some time figuring out why, rather than creating all sorts of weird workarounds because you’re too lazy to RTF (IDE) M.

Q&A

Q: All the cool kids are using Java 5.0 or later. Why are you using Java 1.4?
A: Because v1.4 runs on MacOS X v10.3, which means if you want your Java code to run on 10.3, you need to use Java 1.4.2. And because I’m a bit of a simplicity person: while generics, the new for(;;) loop syntax, and auto-boxing is cool (and nice and useful and all that), they don’t really matter to me all that much.

One of the reasons why such compiler-time tools are useful to many programmers (as I discover time and time to my chagrin where I work) is that many are too lazy to actually test their damned code by at least stepping through the newly written stuff before checking it in. So having auto-boxing and typesafe enums allows more stuff to be found at compile time because some programmers don’t bother to check it at run-time is a good thing: it just takes one idiot programmer who doesn’t check his work to ruin your whole day.

Me; I single-step through my code as I write it. In my opinion, if your project requires more steps to debug than opening up the project file in your IDE and pressing the “debug” button, the build process for your project is hopelessly broken and a defect should be filed immediately. So unless it means there is something subtle going on (like in the CIMMail project, natch, which causes one transaction in a thousand to screw up), or unless you misunderstood the specifications, your code will be relatively solid and reliable the first time around.

The Internet is held together by duct tape and bailing wire!

So I finally figured out what was wrong with my proxy code.

The World Wide Web is held together by duct tape and bailing wire! I hadn’t realized that HTTP/1.1 requests aren’t uniform across the Internet–or even on the same damned server. A request can ask for a /1.1 request and get a /1.0 response–and I wasn’t handling /1.0 responses well. Further, some servers go so far as to just close the damned connection rather than return a 404 error. (*sigh*) So after working through all of the niggly issues (thanks to Safari, which provides helpful diagnostic tools to allow me to find the things failing to load) and a ton of debugging statements, and I’ve finally arrived at a proxy server that appears to work.

(In fact, I posted this message through my proxy engine.)

The proxy isn’t the most efficient thing in the world: for example, my connection caching code is serializing requests that are being made in parallel to the same web server. (Thus, even though Safari happily opens up five separate threads to process requests faster, I catch them and funnel them through one connection.) So the net effect is a connection which is pretty slow.

And of course I’m not caching or doing any of the nice things proxy servers are supposed to do.

But it appears to work!

I’ll clean it up and post it later this weekend.

Update, two seconds later: I went to hit ‘publish’, and nothing. WTF? Okay, back to the drawing board. Apparently I’m mangling the POST message being made when I tried to submit this post.

WTF?

So I’m thinking of switching jobs because I hate the commute. Of course the best time to think about switching jobs is when you don’t need to nor really have to–in my case I’d be perfectly happy staying put for another 5 years, but honestly the drive is killing me. So I’m “exploring my options.”

One “exploration” involved talking to a head-hunter who then sent me to a site to take a stupid on-line test.

I get it: it’s a great screening mechanism to filter out the bozos who claim years of Java or SQL or C++ but who wouldn’t know the difference between a class and a struct or a select verses an update–and lord knows I’ve interviewed enough people where I work who claimed expert knowledge but who couldn’t write a function call to save his life.

But ohmygod that was the worst test-taking experience I’ve ever had. Perhaps I’m just old: it’s the first test I’ve ever taken on-line. But I like being able to go back and check my answers, and I like being able to run through the test out of order so I can spend extra time on the hard questions. The whole “you have three minutes and if you don’t hit the OK button we’re taking you to the next question” combined with the “hit the back button at your own dooooooom!!!” thing drove me bats. And that says nothing about staring at tables full of tiny tiny little text and a SQL statement and the question “how many values will this return? 8? 9? 11? 13?”

I have a headache.

Oddities while building an HTTP proxy.

I’m building an HTTP proxy. Because I can.

I’ve modified the HTTP classes within the common library to allow me to build an HTTP server; it’s just a matter of taking incoming requests and forwarding them, spitting back the response.

Or so I thought.

One web site, hosted at LunarPages, seems to be sending a forward request (302) in reply to a request I’m making–but for some reason the Location filed is being munged. Instead of setting the URL to something that looks like:

Location: http://www.chaosinmotion.com/forwardaddress.html

I seem to be getting something like:

Location: http://www.chaosinmotion.com:80, www.chaosinmotion.com/forwardaddress.html

What the hell?

Once I sort it out I’ll post it–because where I work they have the firewall from hell, and I want a proxy server running somewhere so I can get my e-mail.

Threads: A Clarification.

In a previous post I wrote:

Frankly, not only is it not thread safe, but the solution doesn’t even make any sense in a multi-threaded environment!

What are you trying to do here? Well, when someone comes along and changes the value, you’d like to tell everyone who cares what that value changed to. Simple enough, right? But in a multi-threaded environment, what does it mean when thread 1 changes the value when thread 2 also wants to change the value? Are the objects who want to be notified thread safe? What does it mean when a central value is changed twice by two threads? What is the semantics here?

I think this is worth clarifying in order to illustrate a basic point.

In the single-threaded single-process environment we’re all used to, the primary question a programmer should ask himself is “what am I trying to accomplish.” That is, if the purpose of the program is to display status in a window, then what you’re trying to accomplish is to display status in a window. Immediately from the above statement of intent, you can see that you’ll need something that gets the status you’re trying to display (a ‘CGetStatus’ class, say), you need a window (a ‘CWnd’ derived class which overrides OnPaint, say), and the usual syntactic and semantic fluff which makes a program, well, a program–such as a ‘CApp’, the code to handle the menu bar and the like. At this point you can start throwing darts at the design model board if you like: observer makes a good pattern, or some sort of timer loop or whatever. At this point even a so-so GUI programmer can visualize the program in his head and start visually laying out the resources and the class relationships.

But in a multi-threaded environment, we’ve added a new dimension: threads. And now we no longer need to just ask ourselves “what am I trying to accomplish”–but (and this is the key part) who (or rather, which thread) is trying to accomplish it?

And that’s why the observer design pattern fundamentally makes no sense in a multi-threaded environment. The observer pattern answers the question “what are we trying to accomplish” (notify listeners when a value changed), but not “who is trying to accomplish it?” So, without knowing ‘who’ (which thread), we don’t know if it’s acceptable to simply run the notification loop re-entrantly (ignoring threads entirely), or if we need to shunt the notification to a Swing UI thread (as was done in my previous example) or create a background thread or threads which handle the notifications.

Until we ask “who is trying to accomplish it”, then shoring up a design pattern (such as the observer pattern) to be “multi-thread safe” is sort of like (well, it actually is) trying to write software without knowing what we’re trying to write.