Sunday, August 9, 2009

The Case For Apple (well, the iPhone) in < 5 points

This sensationalist article from Jason Calicanis inspired me to put keyboard to template. I'm not that original, as this rebuttal by @marcoarment is a great start.

Calicanis's basic premise is that Apple is destroying the internet by being anticompetitive with the iPhone, though he also includes a bunch of tangential rants (see the rebuttal above) that have nothing to do with that anti-competitive practice.

What really irks me is that everyone's complaining exactly the things that have revolutionized the mobile device as a platform, the mobile web, and mobile app distribution. From the company that builds their OS on Unix, and their browser on an OSS project.

1. It's only "anti-competitive" because Apple's created the only worthwhile game in town. Nobody else had come close to building such a great platform for development, user experience, and distribution as the App Store.

2. Before the App Store, there was a fractured and un-addressable market. You *literally* have to "know someone" to get your "app" published by a mobile carrier, even today. Palm tried an "open" marketplace for apps on the old Palm Pilot devices, and it was a disaster: as a result, Palm's OS crashed all the time, was slow, and sucked batteries dry in minutes. And I tried writing code for my VX once, it was no fun. I've also written 2 serious apps for the Blackberry. Each one ran on a single *model* of Blackberry, was horribly difficult to build, and getting them distributed was impossibly difficult.

3. Google Voice? It's AT&T. Is this a question? Look at motives. Apple profits by selling more iPhones, and making them the platform of choice for consumer app development (and thus making them more sticky for customers). AT&T profits by finding ways to make you talk for more minutes, and send more expensive texts. Apple has no motive to pick a fight with Google over Voice. AT&T *literally* becomes irrelevant if your iPhone (or iTouch) can make calls without its network.

4. My last point here, one that I've made before, is that Apple works iteratively. Anybody remember what a horrible, unstable, unusable, slow piece of crap OSX 1.0 was? Anybody remember iPhone OS 1.0? Anybody notice that every year, the computers get both faster & better, and cheaper? Expect that the App Store process will get better with time. It always has so far, and it will continue to do so.

I'll leave you with a story...

I was (by blind luck) one of the first 4000-or so "beta" iPhone developers back in the Spring/Summer of 2008.

I had just left my last startup, was utterly burned out, but convinced my next step was going to involve the yet-to-be-released iPhone SDK. Somehow ignorant of the "application" process fiasco already in the media, I signed up for an iPhone dev account, and waited for my login credentials. After only the "thanks for your application" email from Apple, I looked around at forums online, and could not find one single story of someone's application being approved. Just weeks of nothingness from Apple. So, crushed, I in stead read everything I could find about Jailbreaking, downloaded some crazy firmware-hack, and jailbroke my phone. I jailbroke the phone, and downloaded someone's hacked toolchain.

It all took about 48 hours, being careful to back things up, researching which techniques were likely reversible, which might fry my expensive new toy. On the evening of that second day, I got an email from Apple approving my developer application, with a link to pay my $99.00 and sign up. I un-jailbroke my phone, logged into Apple gleefully, and proceeded to check out. So I paid my $99.00. But there was no change to my account. There was no link to follow. There was no instructional email. I was baffled.

I twittered my frustration. I read more forums. I pulled out my hair. I wrote Python code. 2 days later, I got another email: click here to activate your iPhone dev account. Sure enough, I clicked it, and was able to log in and download the SDK. Soon I had an example app up and running in the simulator on my Mac. Next step: test it on the actual device! Following the instructions, I need a certificate to do that. There's no such link anywhere on the site yet.

Once again, I'm at an impasse. By now, however, I'm not frustrated- I've learned to wait a few days. Sure enough, it wasn't long before I had an app running on my phone, using the GPS, talking to the internet, and taking photos.

This microcosm perfectly mirrors the state of current affairs. I was watching Apple, day by day, roll out their developer system. Each time I got to a new step, that's all there *was* for me to do. I had to wait until the next day to take another.

I wish people could see the big picture with Apple. We're only on day 2. Give them a week or two.

Monday, July 6, 2009

A Single-Instance Case against Obj-C Categories

This will be brief.

In Obj-C, there's this very cool feature called a Category, that lets you add functionality to an existing class. Note that this is not the same as extending the class, which results in a newly minted "subclass". It lets you add functionality to existing classes, whether you originally defined them or not.

Now, I love Categories. I've done lots of cool, otherwise-complicated things with them in my iPhone code.

However, I ran into a serious bug that took away an evening for me because between iPhone OS 2.x and 3.0, one of my Categories (on NSMutableArray, to be exact), came into conflict with one of Apple's. In a nutshell, I added -(id)pop; to NSMutableArray+GameChanger.h, though this was a 'pop' function for a FIFO queue, whereas it seemed that Apple had implemented 'pop' for a traditional FILO stack. I only discovered this because there was a bug where the Navigation Bar views in my app went insane, and I sat down and read all of the documentation on how they function, only to realize they were using an array for a stack, which jogged my memory about my little 'pop' function.

At the very least, the compiler should have warned me that my 'pop' function conflicted with another category. Then again, there are a lot of strange ugly things about Obj-C & XCode that I wish Apple would work on (Obj-C 3.0, anyone)? That's another post.

Tuesday, June 23, 2009

Being Done: Quality as an Engineering Function

I won't hire another Quality Assurance Engineer in my career if I can help it.

I don't have a problem with the people who fill these roles, and in fact one of my fondest memories as a manager was of the "QA" team at ShopWiki. I'll come back to that later.

It's a systemic thing. QA represents a safety-net for engineering. Coders who've been in-industry for any amount of time build up a habitual laziness with the quality of their code. They lean heavily on shitty terms like "code-complete", and "feature-complete." They don't talk about being done.

Let's talk about "done". First idea I want to murder with a meat-cleaver: "software is never done." Bullshit. Every version of my software is "done". It doesn't have every feature in it that I want, and it has bugs, but it's done. Most people think "done" means there's nothing left to do. I don't. I think "done" means that I've executed something fully. Explain? Ok: it means that what is there, works, to the best of my ability and knowledge.

I want to take on another platitude: "programmers can't test their own code because they're not objective enough." A former manager of mine, when we were discussing these concepts together, asked me: when you're working on a freelance project (I'd just gotten done a summer building iPhone and BlackBerry apps for hire), how is it that you were able to release (relatively) bug-free software at the end of the day? The answer is that I had to, because my paycheck depended on it, so I did.

Ok, so we need to get things "done", and I call bullshit on programmers not being able to accomplish this on their own. But that doesn't mean it's easy. Here are some tricks I use to approximate "done"-ness in my own output.
  • I ask myself what I viscerally fear my client / boss / business partner is going to do with my software. You know the answer: it's that nag in the back of your mind about that hack you used to work around a bad design decision, or it's that you know there was a big 'TODO:' somewhere about validating form inputs for a page somewhere. Confront it, fix it, until you're not scared at all.
  • spend time being your user. At GameChanger, we build our website and iPhone app on the same APIs that our partners will use. We go to little league games regularly and try to score them with our software, in real conditions.
  • limit your scope. I want this on my gravestone (right after "loving husband & father"). Do only a few things, but do them right. And don't move on until you either drop a feature from the current scope or you would bet your career on it.
  • figure out what you live or die on. For us at GameChanger, it's intuitiveness and ease of use. For the app I wrote for BlackBook magazine, it was sexy UI. Don't compromise here. Particularly powerful trick: never allow regression in your core feature.
  • make engineers take full responsibility for their quality. There's no substitute for being on the line personally for what goes in front of your customers.
So no "QA" for me. I am willing to hire smart semi-technical people to do other stuff, though. The team I mentioned above functioned more like triage than QA- they hunted for problems, reacted to user feedback and researched root causes to help Engineering out, and often performed more research than testing. I was proud of what that team did, and I think they added a lot of value to the organization.

I've still got a lot to think about, and would love some more ideas on how to build this kind of quality-centric engineering into an organization while still adhering to loose process (agile, lean, continuous deployment, cool stuff like that). Any and all comments welcome / appreciated.

Saturday, April 4, 2009

The case against Easy Progress

Sitting here on my couch trying to figure out which GameChanger feature to work on next. Bouncing around adding in a few simple menu items, a cancel button at one point during the scoring of a base-hit, maybe playing with some UI alternatives around undo-flow. But something feels wrong, and I know what it is. I'm avoiding working on some deep API-refactoring that I have to do for live scoring. But it's 10:00pm on a Saturday, and I spent the day out with the family unloading some old furniture, buying toys for the little-one, grocery and hardware-shopping. I just want some easy wins.

I remember sitting down with a junior PM at a former employer, and he was asking me what should go onto the upcoming iteration schedule. He suggested Important Feature A, Important Feature B, and then maybe some bugs. So far so good. Since, he continued, A & B were "big rocks", why not fill up the rest of our time with whatever the developers thought were quick wins?

I told him that was a terrible way to prioritize. Two big reasons why it doesn't work.

1. Developers are notoriously bad at knowing the difference between "easy" and "impossible." There's plenty of discussion of this problem already.

2. More interestingly, I don't ever believe you should prioritize something easy over something important. Rather, I said, put everything in our system in absolute order. Give us the next 5 bugs in terms of importance to our users, and your priorities. We'll figure out what we can do from that list.

Most of the time, people do this to see the illusion of rapid progress- and I'm guilty of exactly that. But it's just an illusion: would you really want fancier buttons, if some of them don't work?

Half the time the "easy wins" are of debatable merit in the first place. In fact, once you finish some of the "hard wins", some of those "easy wins" are likely unnecessary anyway. Too much changes in the lifecycle of software to justify wasting energy on anything non-essential.

My IM status right now is "direction over velocity," and I want to live that.

Thursday, January 22, 2009

Iterative Product Development, and why I'm an Apple Fanboy

I've been illustrating my points about iterative development for a while by using the iPhone as an example.  The shpeel goes something like this:

When Jobs got up on stage and presented the much-anticipated iPhone in early 2007, there were almost an equal amount of grimacing head-shaking as there was gushing praise for the device.  The main crux of the argument centered around the featureset.  It wasn't 3G, in stead using already-antiquated Edge wireless.  It didn't have a physical keyboard.  No push mail.  No cut & paste functionality.  No replaceable battery.  No Flash.  No developer support.

But it sold a million devices on its debut weekend, and by November 2008 had become the #2 device in the smartphone market, second only to BlackBerry giant RIM.  Palm.  Microsoft.  Years in this industry.  Apple won.  Recent momentum seems to imply that it's going to stay that way (RIM's BlackBerry is not really unseatable as a dedicated corporate email appliance, no matter Apple's corporate strategy).

Why did it sell?  The featureset it DID have was impressive enough that a large part of the market bought it anyway.  The design was amazing.  The iPod features were, for that market, far above the competition.  The browser had a slow connection, but gave the most desktop-like feel ever seen on a phone.  The core interface design was so flawless that it felt like a new category of device.

Now, if Apple had simply left it like that, those "missing features" would eventually have allowed Microsoft and Palm and RIM to push them back out of the market.  But of course, Apple followed quickly with the 3G iPhone, with push mail, corporate features, more memory, and an application store.  Note that it was still missing cut&paste, Flash, removable battery, background processing, etc.

To return to iterative development, what I saw was a commitment to delivering the featureset that the market needs at the time that it needs it, and no more.  Version 1.0 had everything right that needed to be right, and skimped on everything else.  That's classic modern software design practice.  Deliver the next most important feature with high quality.  When I'm writing software, I try to do the same thing.

And finally, this has a lot to do with why I'm a fanboy.  I don't buy an iPhone for the featureset it has alone.  I bought one because I could see where the platform was going.  I trust that Apple will continue to develop that platform and give me an even better experience with every release, and give me a better platform as a developer with each release.  Until Apple stops delivering on that promise, in their desktop MacOS, or in their mobile MacOS, or in any of their software, I will continue to buy their products.  I will continue to develop for their platforms.

Wednesday, December 24, 2008

Rich Dad Programming, or: Technology Asset Building

Throwing away working code is a programming sin.  Slow?  Tune it.  Cluttered?  Refactor it.  Obtuse?  Document it.  The underlying philosophy is that even for a minimally complex application, there is a tremendous amount of business knowledge embedded in every innocuous line, along with the man-years of testing that went into ensuring its current performance, reliability, and general correctness.  Technology can be slowly polished, but that business logic is pure gold.

So my team at Conductor is gearing up to rewrite 3 different apps over the next few months.  We are in a place where little of our existing code-base is reliable enough to build around, leaving us little choice.

I'm not going to get into what went wrong to get us here, but I am convinced that managing our technological balance sheet will get us out.  The realization came to me when I was contemplating Higher One, a company I left 5 years ago, at which the majority of the code I wrote is still running, largely unmodified, in the core of a large financial system.  Somehow, what I did back then as a young engineer has survived and produced consistent returns.  We spent our time there developing Technologies that solved specific business problems, one after another, and those solutions survive still.

Specifically, I realized that our teams here need to start building "tech assets," which have long-term returns, and to minimize ongoing debt.  I want to build technological wealth.

So I'm taking this very literally.  We just had a planning meeting where we laid out 6 months of a product redesign, and I took the featureset and mapped that to a set of Assets to build.  The Assets are the technological blocks that will be the underpinning of the new product.  Big hairy "modules" like SalesForce integration, Authentication, an Ad Trafficking state machine, Activity Auditing, User Management & Permissions, etc.  In our UI code, which is a clientside JavaScript app, we're building out JSON-handling frameworks, message dispatching, and rendering layers.  The goal of each of these Asset projects is to build a unit of functionality, wrap it in iron-clad unit tests, and build a mini-prototype demonstrating the functionality.

2 months into the project, we'll start working on Features.  By that time, we should just be plugging things in and bickering over button corner style.  And next time, even if we shift direction rapidly or redesign the UI (like we are now), we should be able to repurpose our core Assets for new features and related products.  Effectively, having a stable of reliable assets reduces the actual cost of all future development.  That's how I define ROI in software development.  Assets yield technological wealth and, hopefully, cold hard cash returns, too.