This video must be seen to be believed.

From the poster’s description:

Microsoft sent this tape to retailers to explain the benefits of Windows 386. Boring until the 7 minute mark when the production is taken over by crack-smoking monkeys.

Via Josh.

My wife Chunhui was born and raised in Jinan, China.  One of the fun challenges of an American-Chinese marriage is to recognize the subtle cultural differences so that you don’t unintentionally violate the other person’s cultural assumptions and mores.  Recently we had an interesting discussion with another American-Chinese couple on the different customs with regards to finishing ones meal.

We observed that in American culture, you’re expected to take what food you want from the center of the table, and finish what you take.  In Chinese culture, you can take food from the table, but other people at the table are just as likely to eagerly give you food in a spirit of generosity, especially if they think you like something.  What makes your Chinese friends and family think that you like something?  If you finish it!

This can easily lead to some crossed cultural wires.  Americans feel culturally-obligated to finish what they take, and Chinese people feel culturally-obligated to give more food to someone who seems to enjoy it.  The trick is that when you want to be done with a particular dish, you simply leave a small but visible portion of the food on your plate, so none of your Chinese friends and family assume that you want more.  This way you don’t overeat, and you don’t get into an awkward “No, I really am full!” conversation with your Chinese friends and family as they try to put more food on your plate.

Marcus Aurelius begins his Meditations by giving thanks for the qualities he gained through observation of others who exhibited those qualities. On a much humbler scale, I recently reflected that my personality has changed as a result of observing the constructive behavior of my project leaders.

One example of this happened at the end of 2006. The day before we were supposed to freeze code for the year, I assisted another developer on a late-breaking severe defect. Unfortunately we didn’t test the fix adequately and it led to another defect which I discovered two hours after the final scheduled build completed. Sleep-deprived and stressed, I forgot about the code freeze and delivered a fix to the second defect. Fifteen minutes after delivering the patch, one of our senior technical people sent out an email reminding everyone that the codebase was frozen. I felt horrible because I’d committed a major faux pas at the most critical period in the development cycle. With great embarrassment, I sent a follow-up email to the project, notifying them of my mistake.

The next morning I came into the RTP lab for the end-game planning call with the PMC and component leads. I went to a meeting room and found John Wiegand and Scott Rich, who at this point were fully aware of the mistake I made. With a sheepish smile, I asked “Can I buy anyone a coffee?” Scott replied “You’re not forgiven that easily. What you did last night requires coffee and donuts.” John said, “Well, we all screw up from time to time, and the important thing is that you recognized the mistake and, to look at the positive aspect of it, the feature now works.” And that was that. In the end it turned out that there were a few other lingering bugs in the final scheduled build so we did one more build and all was well.

Another example was my mid-year checkpoint with Erich Gamma, reviewing the progress on the subsystem that I lead. My team was struggling at the time. In some very new technical territory, we were progressing more slowly than anyone would have liked. I was dreading the call, because Erich’s sort of a professional hero of mine, so I really wasn’t looking forward to hearing him tell me that things weren’t going well. But the call wasn’t like that at all. He began by reflecting on the things we’d accomplished and what had gone well. Only after a few minutes of discussing accomplishments did he gently segue into the discussion of areas that needed improvement. We prioritized a list of architectural features and user scenarios, and then worked through the details of what my team would need from other teams to succeed. I left the call feeling energized about what I was confident we could achieve, and over the past six months, I’m confident that we’ve met or exceeded those expectations.

Some excerpts below.  Click on the person’s name for the full content.

Grady:

There’s a phrase from systems engineering that applies here, the principal of least astonishment. When an abstraction fails, a well-designed one will (hopefully) fail in predictable ways. It’s when an abstraction fails and it fails in an unexpected way that we have evidence of a leaky abstraction. Unfortunately, I don’t think this kind of behavior is avoidable, although it is the case that tracing down the roots of such failures and then refactoring the stuff at those roots will generally lead to a better separation of concerns. The problem is, in software, we generally never take the time to do that refactoring, and so we occasionally continue to be astonished at the most inopportune times.

Josh:

I’ve struggled with this issue too.

I haven’t come to any concrete conclusions either other than to emphasize that abstraction *costs*.

And not only does it cost, but it usually costs *more* than we think it does – because the person designing the abstraction is not the same person who has to invest the effort to learn how the abstraction works later on.

Abhijit:

According to Joel all abstractions are leaky. When this happens transparency helps. Both are required, because I believe people who need to know about abstraction and transparency are different. Abstraction is for users, transparency is for problem solvers.

After finishing Brand‘s How Buildings Learn a few weeks ago, I picked up another Brand book: The Clock of the Long Now which discusses (among other things) how one would design a clock intended to keep accurate time for 10,000 years. Chapter 11 lists the key design principles that the clock’s principal designer decided were most important to the clock’s success or failure. The principle that caught my eye was transparency.

(segue from discussion of clock design to software design)

Transparency is the quality of how easy (or hard) it is to understand how a mechanism works. Upon reflection, one of the reasons that I favor the pure Ajax/REST web architecture I described earlier is because it’s easy to mentally separate into three parts (browser, wire, server) and it’s easy to understand how these parts interact (HTTP requests from browser to server via wire; HTTP responses from server to browser via wire). Why is this ability to compartmentalize subsystems desirable? Because it’s easy to debug when something inevitably goes wrong.

But there’s a tension here; abstraction in software is supposed to be a good thing. The pace at which we can develop software has increased substantially for those of us who don’t have to worry about (for instance) pointers, packets, and concurrent access to persistent storage. Yet anyone who’s tried to debug a problem within an überframework will tell you that it’s hard to figure out where the error’s occurring (their code or your code), let alone fix it. This tension was described in Joel Spolsky’s the Law of Leaky Abstractions article. Net: all abstractions are imperfect, and when a mechanism underlying an abstraction fails, it’s difficult to understand and remediate the problem since the abstraction previously allowed you to remain blissfully ignorant of the underlying mechanism.

So from a design point of view, both abstraction and transparency have merit. Abstraction reduces the amount of detail one needs to master in order to accomplish a task or apply a concept. Transparency makes it easy for new team members to understand the flow of the system and allows developers and administrators to quickly track down and resolve problems. So how to find a balance between these two qualities?

I have some not-fully-formed thoughts on this question, so I’ll save them for a later entry, but I’d be happy to hear others’ thoughts in the meantime.

Related to yesterday’s post, I just caught up on the comments to Peter Gurevich’s (MS IE Performance PM) guidance to avoid using closures in IE. Matt Kruse had a perfect, concise response which I feel compelled to quote here verbatim:

Closures don’t cause memory leaks.

Browsers that have garbage collection bugs (IE6) and continue to retain those bugs in new versions (IE7) cause memory leaks.

Closures are an extremely powerful and useful programming technique. It’s unfortunate that you would recommend against their use simply because your browser has a bug that causes a memory leak.

A huge amount of time has been spent by the js community to detect, resolve, and work around these IE memory leaks. It’s too bad this was required, and will continue to be required as long as MS refuses to fix the problem.

Hopefully IE’s market share will continue to drop and we can begin to ignore these memory leaks because every other browser out there handles closures just fine.

+1.