A Tale Of Two Features

(While this story is Based On True Events, it’s really a synthesis, and details have been changed to protect the innocent.)

Real Developers Ship[1].

Creators–those who create–face a significant challenge in completing their creation. I’m thinking specifically of two types of creation that I do–creating software and writing fiction–but the same applies to many other endeavors. We imagine perfection, and when things start to come together, what we have is not that. It’s something imperfect and flawed and real. Getting over the hump means admitting your own imperfection, your own humanity.

Real Creators Release.

The mantra is meant to remind us that the best design, most ambitious worlds, and the most flexible architectures are worthless if no one reads them or uses them. It also provides motivation during that last “5%”, the part that takes over half of the project time when you finally get there. And it reminds us that it’s okay for that last 5% to be hard. It’s okay for what you produce to be less than perfect, as long as it’s good enough.

This is a a tale of two software features. It was the best of intentions, it was the worst of intentions, it was the age of wisdom, it was the age of folly.

The software team I was on was tasked with shipping two minor but crucial features. One would send messages to our customers when their product shipped; another would let them track the status of their product before it shipped. Because of time crunches, two different subteams worked on these features, with different methodologies.

The Notification team worked out a flexible architecture for notifications, including the ability for our marketing team to come in and change messages on the fly, to send out messages for any reason, and to dynamically update content without having to rewrite the software. The goal was to let marketers put messages in the notifications: “Thanks for spending $30! Here’s a coupon!” Whatever they wanted.

The Status team, on the other hand, made a webpage that said “Order Status: In progress.” This required a lot of back-end work–gathering the actual data, figuring out what it meant, getting it to the servers–but in the end it just said “Status: In Progress.” or “Status: Shipped.” or “Status: Call customer support.”

Oh, how the Notification team laughed. “That’s it? What do you do when you want to change the message? That’s not an architecture, that’s a bunch of constants in a big file. You call yourselves Real Developers?”

After a month, the Status team shipped their feature. Customers were able to see whether or not their product was still being made, or whether it had shipped already, from anywhere in the world. They’d go to that ugly web page, see that ugly message, and–complete their task successfully.

Meanwhile, the Notifications team had run into a snag. The templating language they were using collided with the syntax they’d come up with for their macro language. If our marketers used dollar signs in their ad copy, the system would think it was a variable and come up with messages like:

Here's a coupon for you for spending #ERROR Variable NOT FOUND `30', in notif.tl, 308.

Marketers were of course supposed to type \$30 when they wanted to say ‘$30’. And there was doc! Also, the feature hadn’t shipped yet, because they were still arguing about the syntax of variables–should it be ${X} or $X? What if you had two variables in a row?

In month two, the Status team upgraded the message page. It now included more information about your product as we made it. There was a friendly icon, and if you got the ‘call customer service’ message it would also offer to let you email or chat with a live rep.

In month two, the Notification team sorted out their syntax differences by agreeing that all variables should be escaped by default. But this didn’t work for one of the managers, so they rewrote the whole thing to use XML. Now to write marketing copy required the trivial:

<companyname:string>Thank you for <companyname:action type="buy" tense="gerund" />  over <companyname:datalookup property="spend_amount" showas="numeric" prefix="$"> of merchandise!</companyname:string>

…which as anyone can see is clearly what marketers want to be doing all day.

In month three, the Status team revamped their architecture and added some templating capabilities. The product creation side had some new statuses they wanted to add, like “Delayed in Customs”, and the Status team decided it was time for some flexibility. They kept their tests work–did I mention testing? Both teams did testing, but the Status team did testing of a functioning product, whereas the Notifications team tested vaporware–and upgraded the backend behind the scenes. They worked with the product creation team to come up with a simple way to specify new statuses. Customers didn’t even notice the difference, except that occasionally a new, even more useful message would appear.

In month three, the Notifications team was broken up, the lead was canned, and the primary programmer was moved to another project. For all I know he’s messing that one up too. The worst part is that they never did get that feature shipped while I was working there, and for all I know customers are still waiting for info about their packages.

Real Artists Ship. Get something out there that is good enough to see whether it’s good enough. Don’t ship TOO early–that’s just laziness. You don’t serve a half-cooked omelet. But you do ship, and long before it’s perfect.


[1] You may be interested in Chuck Jazdzewski’s Fatherly Advice To Young Programmers, Jeff Atwood’s response to that, and Jeff’s follow-up description of the ‘version 1’ hurdle.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s