Skip to content

Delivering Behavior

May 17, 2012

My practice has evolved quite a bit over the last two years. I’ve delivered entire web and mobile apps, fully functional and styled based on a visual design provided by a partner or 3rd party. That means they hand me a stack of wireframe sketches and some PSDs, and I do the coding, slicing, and style crafting. Lately, though, I’ve been feeling the focus of my business shift toward delivering behavior only, leaving the style crafting to someone else. This is not to say that I don’t enjoy it nor that I do not feel competent, just that I am still excited about information architecture and system behavior design. Adjusting margins and drop shadows wears me down, but I could do UX and ORM all day and stay for more.

Tests Guarantee Behavior, not Style or Layout

A big reason for the focus on delivering behavior is testability. One can easily prove that a system behaves as designed by including a set of test cases for each feature. Running the tests regularly is an effective mechanism for identifying defective behavior. However, there is no way to test browser rendering, style sheets, or any visual effect. The best I can do is use CSS selectors to confirm the presence of key markup elements and classes, and even that feels like overkill. Additionally, if I want to confirm the layout of components, there is nothing I can do in an automated test. The simple reality is a human must review each page to verify its layout and appearance.

Clear Deliverable Boundaries

A thorn in the side of my business since my very first client has been the issue of deliverable boundaries. Three times over the course of two years, I’ve encountered clients who either stop paying and keep asking for more work or complain about the work I delivered and refuse to pay on the grounds of “unsatisfactory work product.” In every case, it is not a functional issue, but a visual one. There is some style issue that isn’t perfect in the eyes of the client, and they latch onto that notion of perfection and lose sight of the behavioral deliverables. By delivering behavior only, this effect is largely avoided.

RESTful API Design for Mobile App Integration

April 13, 2012

Last year, I wrote a post about nested RESTful collections. Since then, I’ve learned a lot more about RESTful design, especially as it pertains to the interaction layer between a web service and a mobile app. Most of my earlier designs follow the thin client approach, where the mobile app is assumed to be always connected, usually by slower 3G networks. If your goal is to deliver a usable app in a very short time, thin client architecture is an excellent way to achieve that. There is no caching on the device’s non-volatile storage, so everything lives in memory. Any time the user taps the refresh icon, the app makes a request to the API and displays the results to the user. This is very close to the web browser model, so the controllers that were built for web interactivity via browser can be easily retrofitted to include support for JSON or XML (or any other format, for that matter). As projects evolved, though, and I heard more and more clients ask for offline support – the ability to cache data locally on device, accessible even when the device has no connectivity.

Thick vs Thin Client

A thick client design changes the architecture dramatically and has its own set of pitfalls and gotchas. Now, instead of storing immutable data in memory and replacing objects instead of updating and saving them, data must be cached in a persistent store on-device and modified as needed. We can (and should) still follow functional programming best practices of immutable in-memory objects to provide content asynchronously to the user interface (UI), but there are some extra things we need to consider. All or almost all user experience (UX) professionals agree that people can not interact with large collections without pagination, search, or filtering. Nobody likes to scroll through a seemingly endless list of 10k items, especially when mobile devices can only reasonably display 5-10 items at a time. With a thin client, this typically implies a lazy loading design, where the web service client component only loads as much data as the user can scroll through in a few seconds. As the user approaches the end of the list of loaded items, the web service client loads the next set of items, just in time for the user to encounter them in the list. With a thick client, it is often desirable to sync with the remote service rarely, pulling large sets of items in the background and storing them locally. As the size of a collection grows, so does the amount of time required to pull all the data. The UI components don’t change much. They simply adjust to draw their data from the local store instead of the remote service. However, the sync process for a thick client is dramatically different from that of a thin client.

Extending the Previous Real-World Example

In the post mentioned above, I gave an example of a playlist service with songs that can belong to multiple playlists. With a thin client, the app would only make narrowly bounded requests for items relavent to a specific user action. When the user navigates to a list of playlists and refreshes the list. The app must retrieve a list of Playlists, like this:

GET /playlists.json

Now, the user taps on an item to see the Songs associated with it, so the app must retrieve all the Songs for the given Playlist, like this:

GET /playlists/1/songs.json

Say, for sake of discussion, the web service architecture has a join model to associate Songs to Playlists and that this model is called SongAssignment. In a thin client, the client need never know about the SongAssignment model because it only cares about Songs and Playlists. That’s what the user will be interacting with. The API has nested collections to hide the join model, focusing instead on the relationship between Playlist and Song as defined in the resource path. In a thick client, though, all the data is synced at once, so the client must be aware of the SongAssignment model, so it can connect everything after sync, which might look something like this:

GET /playlists.json
GET /songs.json
GET /song_assignments.json

It is then the web service client’s responsibility to map all the Songs to Playlists by using the information conveyed in the collection of SongAssignment objects. Then, following the same user interaction idiom from above, the app queries the local store for Playlists and displays the results in a list. When the user taps a Playlist item, the app queries the local store again for SongAssignments associated with the selected Playlist, aggregate the songId from each of those objects, and retrieve the appropriate Songs from the local store. Again, the UI follows the same basic pattern, loading content into memory as immutable objects and using that to populate the display, but in place of the remote API calls, the app draws from the local store.

Optimizing The Sync Process

As collections grow larger over time, the sync process slows down. When there are hundreds or even thousands of items in the collection, this presents a significant problem, especially for mobile devices on slower networks. One simple way to mitigate this issue is to save time stamps for each RESTful endpoint being synced and enable a query string param to filter the collection, like this:

GET /playlists.json?since=201204132116

This way, the web service can use the param to prune out records whose updatedAt timestamp is older than the provided timestamp, in this case 13 Apr 2012 4:16pm EST. Upon successful sync, the web service client simply updates the “last sync” timestamp for this endpoint to the updatedAt value of the most recent item in the resulting collection.

Further Discussion

This post has focused on the high level architectural considerations for pulling data from a remote web service API. There’s still the nagging issue of how to push data back to the service after the user has modified it locally. That’s a substantially more involved topic that I will save for a later post.

Fun With QR Codes

March 30, 2012

I have seen examples of creative and highly effective use of QR codes before, even sculptures in 3D. I know they get a bad rep from the haters, even to the extent of this admittedly hilarious blog, but they can be an efficient way to get the exposure your product needs. Any print advertiser will tell you how hard it can be to inspire people to type in a URL. With QR code scanners available on all mobile devices now, it’s much more convenient to scan and go.

Since I have a fledgling product in Uptimetry, I have been experimenting with creative marketing strategies. This particular product serves a very tight vertical. It is targeted at developers, IT managers, and the folks responsible for guaranteeing infrastructure availability – uptime, in the industry parlance. Even more specifically than that, it’s aimed at only one of a few popular protocols – web. I’m fortunate that the audience is technical professionals, as they are more receptive to QR codes than the general public. Still, communicating what my product does in a clever and intriguing way is a critical aspect of maintaining competitive edge in a fast growth market. Since its inception last year, I’ve seen three competing services enter the arena.

First Impression is Everything

In a world of instant messaging via Twitter, Facebook, Skype, or SMS, consumer demand has never been higher for real-time curated news. The print world, with its 12-18hr lag, is struggling to keep up. Advertising is no longer bordering on pushy – it’s downright intrusive. We’re inundated with uninteresting irrelevant ads everywhere we look, in the digital and physical world alike. Marketing pros have relied on emotion to drive consumer behavior for over 75yrs. They’ll be the first to tell you that first impression is everything.

Instead of printing some random ugly black and white noise grid, I took a tip from BBC and Wikipedia and started trying to embed a visual, human-readable message in the QR code. The Wikipedia example is really effective at integrating the digital benefit of a scannable code with the perceptual benefit of a branded experience. However, I quickly encountered a non-trivial issue.

Resolution is Limited

Even in the eyes of savvy mobile device owners, QR codes are ugly and pixellated. This is because the size of the code scales directly with the square root of the number of characters in the message it represents. Most URLs are less than 64 characters, many less than 32. Shortened URLs can be as few as 16. That means the associated QR codes typically require very low resolution. Even using padding techniques, a 256 character URL results in a fairly low resolution image. In order to embed readable text into the code, we need at least two pixels outline to differentiate the text, plus the font itself needs to have type with at least two pixels at its thinnest point. Then, there are areas of the QR code that can not be modified, so the text needs to fit around those.

It was clear I wasn’t going to fit my entire brand in the code. So, my goal was to get to the heart of my product in as few characters as possible. I needed something that conveyed exactly what Uptimetry does, in a language that its intended audience will instantly understand. Fortunately, I found one that works well and fits in six characters – HTTP OK.

Grayscale is Your Friend

In my experimentation, I initially tried using a pure black-and-white bitmap, thinking the contrast was important for the QR code scanner to correctly interpret the code. I stumbled upon the grayscale quite accidentally when I fat-fingered the image mode select in Photoshop. My first impression was “hey, that’s not nearly as harsh as the bitmap. I wonder if it scans.” It scanned just fine.

The Result

I’m very pleased with the first draft. It gets the job done, and that’s all that matters in the end. The sole purpose of this effort was to produce a QR code that could be integrated into print advertising for distribution as a networking tool at conferences. I’m sure it can be made prettier, but I needed to prove it was possible first. It’s also not quite as stable as I’d like, but it does scan. Give it a try!

QR Code showing the words HTTP OK

Using Gestures Effectively

March 10, 2012

Gesture-based interaction is without a doubt the most exciting development in human-machine interface design of the last decade. The introduction of two-, three-, four-, and even five-finger multitouch gestures in the Mac and iOS product lines has contributed significantly to the success of both. The numbers speak for themselves. During the new iPad announcement this week, Apple mentioned the quarterly sales for iPads were higher than the collective sales of all the products offered by each of the big PC manufacturers. Consumers bought more iPads than all HP PC products combined, more than all Dell PC products combined, and more than all Acer PC products combined. People are quickly embracing the iPad, with its multitouch usability. They’re also choosing Mac laptops over Windows-based products because of the baked-in support for gestures in the Mac OS X experience.

So, how can designers take advantage of gestures to add richness to their user experience? Consider these aspects:

1. Affordance

Probably the most important aspect of usability design is affordance – the degree to which a component describes its behavior visually. Gestures are events in time. They don’t have any visual presentation at all. As a result, they have no affordance. This means the gesture can not be the only mechanism that triggers an action. They must be coupled with on-screen controls that perform the same function.

2. Ambiguity

When adding a gesture, it’s important to be aware of the system-wide gestures supported by the platform. Otherwise, there is a risk of ambiguity, where one or another or both actions occur when the gesture is triggered. Also, it’s important to have clear distinction of gesture direction. For example, it’s possible to add a “swipe up” gesture to a scrolling list view, but to do so would introduce ambiguity. Sometimes, a swipe would cause the view to scroll. Other times, a scroll action might trigger the gesture. This is a bad idea. It’s best to limit gestures to directions orthogonal (perpendicular) to scrolling. Even in that case, gestures don’t always work, since “swipe to delete” is an iOS SDK feature.

3. Relevance

When assigning a behavior to a gesture, ask yourself what feels most natural as a user. One common use of gestures is swipe left/right to navigate to the next/prev item in a collection. This feels natural, especially when the gesture is on a detail view of a single item in the collection, visible only after tapping an item in a summary list view. The context of the collection is fresh in the user’s mind, so there remains a strong desire to traverse the collection. If they must tap a “back” button to seek another item in the collection, that quickly becomes tedious. By adding next/prev buttons in the detail view and enabling swipe left/right, the collection interaction feels much more fluid and natural. Swipe up/down would not feel natural. Similarly, swipe left/right to select different tabs in a tabbed layout doesn’t feel natural.

Conclusion: Let the user decide

Designers will always push the envelope to give users new options, new interactivity metaphors they would never have asked for. Sometimes, users embrace new designs, and sometimes they prefer the familiar. In the end, the goal is to satisfy the needs of many. If the designers do their job well, users will discover gestures and decide for themselves whether or not to use them. Some users will prefer gestures. Others will prefer on-screen controls. If they don’t discover them or don’t use them after discovering them, that is not an indication of failure of the design. It is merely an expression of preference.

The Time Has Come To Seek an Apprentice

February 16, 2012

Over the past twelve years, I’ve made my way from lowly code monkey to systems engineer to tech lead all the way up to architect, engineering VP, and CTO. I’m really pleased with my professional life so far, and I’m comfortable doing what I do. Now, though, I find my career at a threshold. Where two years ago, I was struggling to keep one contract going, now I am actively turning away work because I simply don’t have enough resources to accept new projects. My lead times are now approaching six months. While I’m enthralled to have such an honor, I’m not ready to scale to fifty employees. I’m not interested in hiring a team of junior-to-mid-level geeks to do all the work for me. I like doing the work. I like being hands-on. Moreover, I don’t want to suffer through client-facing failure resulting from ineffective oversight, nor do I want to be the micromanaging douchebag that I would need to be in order to deliver the level of quality I expect from myself. I’ve come to realize this means I need one dedicated apprentice.

I like the idea of focusing my efforts on building an efficient working relationship with a single person, helping them learn and improve their skills, and working together as a pair. I love offering faster project schedules to clients for only a marginally higher cost. To do this means to place a great deal of faith, trust, and hope in one person – to put all your eggs in one basket, as it were.

So to those reading this, I issue this challenge: if you’re tired of the same old day-after-day mundane existence, being ordered around when you know the boss is an idiot and you could do things so much better, get in touch. Give me a reason to believe that you can take the ball and not only push it down the field, but shove it down the throats of the defense as you point at the scoreboard and gloat. Show me that you want something better, something impossible. I guarantee you I can show you the impossible every day, and together we will find a way through it. Because that’s what I do. I deliver miracles, one at a time, for a lot of money.

To be clear, I’m hiring one person. There is one slot available. If you want to work with some of the best architects, designers, developers, and promoters in the world, I can guarantee you that level of access. But you need to bring your A-game, because your contributions will be scrutinized by hundreds of thousands of people. So, if you’re a college student, recent grad, or seasoned developer who just really loves mobile software and want to find a way out of the corporate world into a leaner, more agile environment, please contact me.

Designing a Universal Mobile App

December 7, 2011

Earlier this year, I gave a talk on universal binary design at the Suncoast iOS meetup (slides available here). The talk focused on two Migrant Studios apps (Uptimetry, a productivity/utility app, and Pucker, an OpenGL action/puzzle game). Both apps follow the universal binary approach, where one bundled executable file runs on both iPhone and iPad form factors. Uptimetry has the same user interactivity model on both devices. It looks and acts the same on both the phone and tablet form factors. Pucker has the same underlying game engine on both devices, but dramatically different interactivity rules, taking advantage of additional screen size on the tablet device. Both apps are designed to reuse code wherever possible, allowing common behavior to be defined in code shared by both phone- and tablet-specific implementations.

That’s part of the story – iOS. What about Android?

When I first started working with Android, I found it challenging, as there didn’t seem to be any overlap between the “iOS way” and the “Android way” in terms of user interactivity. All the iOS platforms have only a single hardware button, which universally exits whatever app is in the foreground. The Android platforms have home, menu, and back buttons, as well as cursor controls (up, down, left, right, ok). The on-screen component design is dramatically different when the user has access to hardware buttons in addition to the software buttons and other controls displayed on a touch-enabled screen.

After a time, I began to realize where the decoupling is. At its core, a software application is largely defined by its object model. The objects and their relationships with each other define the basis for a language, a set of rules that govern the conversation between the user and the data. This is the essence of interactivity. In nearly every case, the user is creating, reading, updating, or destroying an object and/or modifying its relationships to other objects. The conversation that takes place could be transcribed as a journal of operations, mutating and reorganizing objects and collections.

The importance of a web service API

In a typical mobile app, the object model mirrors that of its web service counterpart. This implies a transport layer, designed to convey information between the mobile app and the web service. The transport layer is the decoupling point. By distilling the conversation into discrete platform-agnostic messages, using open standards-based tools, the system can be cleanly broken up into functional components. The web service API paradigm solves this beautifully. Sure, the code looks different on the iOS and Android platforms. One is ObjC; one is Java. At their core, though, they both do the same thing – ferrying structured information between the app and the web service.

Highlighting key use cases

The goal of all mobile apps is to provide the user with a simple, easy-to-use way to access information, make informed decisions, and take action. If you’re building an app to allow users to check the status of their home appliances, chances are you don’t need to include the ability to tweet about the ambient temperature of your living room (nobody cares anyway). Your users need to see the current value of their thermostat setting and have options to increase it, decrease it, or manually enter a different value. That’s a label, two buttons, and a spinner control; or maybe just a label and a slider. Then, if needed, add a cancel/confirm prompt whenever changes are made. Simple, elegant, and laser-focused. More importantly, the emphasis is on the behavior – getting something done quickly and efficiently.

Set ambient temperature to 70F

Just as we have conversations while interacting with each other, we have them while interacting with machines as well. We don’t usually speak verbal commands to our machines (at least not yet, and the thought of sitting on an airplane listening to 50 people try to dictate emails or tell fart jokes to Siri is not appealing). We usually touch, type, or click to convey our intent. Equally compelling is this: just as we bound the discussion through verbal and non-verbal cues, we are constrained by the presentation of options on an app interface. The machine bounds the discussion by offering a limited set of options. Your interface can leverage this to guide the conversation with the user.

You can offer lots of options and have an open-ended discussion, or you can offer only a few and have a brief, goal-oriented chat. Knowing precisely - within the context of the mobile experience - what your user’s main goals are and how they want to achieve them will help you deliver a usable mobile app and not just a mobile-enabled version of your web or desktop app. More importantly, these goals transcend the device, applying to the mobile experience as a whole, meaning your iOS and Android apps can do the same things, but still maintain the themes and pre-baked interactivity idioms provided by each platform.

Web Service API Essentials

November 7, 2011

After spending the past 15 years of my life building web applications, many of which included some capacity for client-server messaging beyond the browser, I’ve seen a lot of attempts to solve the puzzle. Some folks fail utterly at this task, while others merely miss the mark. Occasionally, I come across a solution that is not only functional, but also elegant in its design and implementation. I could rant for pages, perhaps scores of pages, about the failures and how they lead to developer frustration and slow development to a crawl, but I’ll save that for another time. Now, I’d like to talk about the techniques that bring about graceful, refined web services that are easy to learn, use, and integrate into other apps.

Know your user, the developer.

It took me ten years at least, working in the information systems world, to realize that the key to great design is to understand the people who use the product and their core motivation. Knowing what is most important to the end user is critical to managing development projects. As a result, a significant part of the development effort is invested in pursuit of a basic understanding of the user’s core needs. One can not simply ask for these things. The user may not be conscious of their needs. They may even lie to you, as they do to themselves, believing they need something they really don’t need or even something counterproductive. In API development, though, your user is another developer, so you might think you can assume a minimum level of knowledge about how web services work.

Don’t do that. If you assume anything about your user, set the bar as low as possible. Document everything as plainly and thoroughly as you can. Developers love reading documentation, learning the rules, so they can turn around and apply them to their relevant need. Remember, a developer is reading your documentation specifically because they intend to integrate your API into their system. This will likely make your company money, and in many cases will make their company money as well. This is often the purpose of the API integration project – to increase revenue by attracting new users with a new feature.

Embrace naming standards.

Wherever you stand on the convention vs configuration debate, there are some really valuable lessons to be learned from the convention camp. At an architectural level, a web service is typically an interface layer for interacting with objects or collections of objects. If a significant class in the object model is Song and another is Playlist and you’d like to expose the ability to add and remove Songs from a Playlist, it makes sense that GET /playlists/1/songs shows me only Songs associated with Playlist 1. If I want to see the same collection in XML or JSON, I simply append .xml or .json, respectively, to the path. This is significantly better than GET /cgi-bin/my_servlet.jsp?cmd=list&playlistId=1&format=xml.

There are also situations where custom actions beyond basic Create-Read-Update-Delete (CRUD) are desirable. Sometimes, these actions can be simulated by simply updating an object. For example, instead of having a custom publish action, one might simply update the record, setting the published_at column. Adding a non-standard action adds complexity to the controller and functional tests, as well as the web client code for interacting with this resource. In contrast, using existing standard actions means less code required on the client.

Provide details. Be specific. 

Remember you’re building a request processing system, probably a synchronous one. Your user (the developer) needs to know exactly what your system expects and what it will return, in success and failure cases. If you expect a given schema, with nested objects connoting their associative relationship, you must provide this schema, preferably with an example of sending a request and receiving a response. If there are required fields, note them in the schema. If there is any validation on the request data, describe it in the context of the relevant field. If there are query string parameters your action accepts, describe them and how they are used by the controller.

Paginate collections.

In some rare exceptions, it’s not necessary to paginate a collection. For example, if you have an object model validation that eliminates the possibility that there could be more than ten objects in the collection, pagination is unnecessary. In almost every other case, though, it’s a requirement. Pagination sets an upper bound on database overhead, server memory, and processing time of every collection request. The additional development time on the server and client sides are well outweighed by the benefits to bandwidth, availability, and overall performance of your API.

Minimize and document hidden and/or triggered behavior.

There are many good reasons to introduce hidden or triggered behavior. Maybe you want to update an associated record when another is updated. Maybe you need to create stub placeholder records to satisfy data integrity when creating a central record. Maybe you want to trigger some background task to perform some aggregation function. Whatever you do, document it. If creation of a Song automatically creates a Playlist with a default name and adds the Song to the Playlist and you don’t document it, I promise you a developer (or a hundred) will email you to ask you why there’s a phantom Playlist in their account. They might even think they’ve been hacked. You can’t predict or overestimate the shit storm you will bring upon yourself if your API is not crystal clear and easy to use. Every line of documentation you write will save you support time.

Use OAuth.

If the purpose of your API is to give your users the ability to allow your app to interact with other apps on their behalf, you would be a fool to use anything but OAuth. It is the gold standard for B2B integration. Authorizations are completely controlled by the user. A user need only authenticate once to grant indefinite secure access to a certified 3rd party, and they can cancel the approval at any time. You will need to build the OAuth provider and a management portal for consumers to register, but as with pagination, the investment is well worth the benefit.

Test your controllers. Include all supported formats.

Most important of all, publish a functional API. If your API doesn’t work as advertised, your developers may jump ship before they even get settled in. I can say from personal experience (the inspiration for this piece, as it turns out) that trying to work with an API pales in comparison to actually working with an API. If my first impression of your API is “I did what your docs say, and it’s borked,” or worse still “I can’t figure out how to sign in because the docs say ‘to sign in, you must be signed in’ and provide no explanation of how to do that,” there’s a real chance I won’t contact you to work through it. Instead, I’ll move on to your competitor, or worse for you, I’ll build a competitor app.

Apple Says App Store Subscriptions Are Media Only

September 12, 2011

After weeks of development and testing, confirming that my app, Uptimetry (website, app store), correctly processes payments using Apple’s new auto-renewing subscription in-app purchase framework, I submitted to the App Store. Then, after an extended review period, my app was rejected. The rejection letter stated simply that my in-app purchase type was invalid. After some digging, I discovered this meant they would prefer I use a non-renewing subscription type for this app. I engaged in a dialog with the reviewer, asking for clarification on why exactly my monthly recurring service (provided by an external system) was not suited to be an auto-renewing subscription type. The answer I got was “I can’t help you. File an appeal.” So I did.

Several weeks later, I received a phone call from Apple regarding my appeal. Their explanation seemed astonishing to me. They rejected the appeal, standing on the initial position that despite the clearly recurring nature of my product, it was being delivered not in the form of visual or audio media, such as a magazine or streaming video, but in the form of a service. They also acknowledged that Netflix doesn’t even offer the ability to purchase and/or modify your subscription through their iPhone or iPad app. I almost pointed out that this was a tacit admission of failing to enforce the widely scrutinized policy forcing developers to offer subscriptions through their iOS apps if the same subscriptions are available through external channels. I thought better of it, preferring a more diplomatic solution.

I championed the notion that to prompt the user repeatedly to renew their subscription would be far more of a burden than asking them to manually cancel future renewals for their active subscription(s). I made the case that especially in my situation, the auto-renewing feature was adding value to the user’s experience. The whole point of Uptimetry is to monitor your web resources and guarantee they are always being served correctly with the desired content. I want my customers to trust me to keep a watchful eye on their assets, informing them at the first sign of trouble. If they receive an email every month asking them to renew and prompting them to open the app and update their subscription, that’s going to get old fast. If instead, the system simply processed their renewal automatically through their iTunes account and pushed updated subscription data to their device, their service would remain uninterrupted until they manually cancel their subscription renewal and the active subscription expires.

Why Not Annual?

You might be thinking “ok, sure, monthly renewal notices are annoying, but that just promotes purchase of an annual subscription.” As I spoke with Apple’s appeal representative, I argued further that an auto-renewing monthly term is better than a non-renewing annual term because it gives the customer frequent opportunities to modify their subscription, but saves them from frequent reminders. For Uptimetry, this is key. A user might start using the monitoring service with a few URLs, so they buy the Micro plan. Then, as time goes by, they realize they need to monitor a few more, so they need to upgrade to the Medium plan. With an annual plan, they’re locked in and can not upgrade without committing to the new service level for a full year. With a monthly plan, they can buy a plan with a higher or lower service level any time, and the commitment is limited to a month. All they need do is cancel renewal of plans they wish to drop, and they will naturally expire. This additive subscription system makes it easy for customers to combine multiple subscriptions as needed to match their needs.

Product vs Service

This all begs the question, “what is the difference between digital product delivery and digital service delivery?” In the case of products, a specific digital item, such as an app or song, is transferred to the customer, granting unlimited future use. The license agreement in this case is simple. The customer agrees not to distribute copies to other people. Often, there is no cost associated with delivering a digital product, as there are no materials required to produce it and no shipping costs required to deliver it. In the case of services, though, the field widens. Digital services can be more than simply data storage and hosting. Often, they perform actions on behalf of the customer, such as waiting on hold while seeking customer service with a third party (FastCustomer), monitoring a web server to adjust its hosting parameters to match the real-time load (HireFire), or searching CraigsList for specific items and sending notifications when matches are found (CraigsCrawler). Digital services represent a unique corner of the market, as they deliver value to customers and cost almost nothing.

Line in the Sand

Apple has clearly made a policy decision here. They have decided they will allow auto-renewing subscriptions for digital media products, such as music, magazines, newspapers, and video, but digital services are expected to be provided on a non-renewing basis. While there is clearly an appropriate use for non-renewing subscriptions, this distinction between media and non-media seems arbitrary, especially given there is no mention of it in the developer guides. Speaking as an iOS developer who is heavily invested in App Store subscriptions and in-app purchasing, I sincerely hope Apple re-evaluates this position. I realize that the digital service market is still defining itself. I do not expect them to be ahead of the curve in all aspects of the industry, but this feels more like a block than a fumble.

Rock Solid Piracy Prevention

August 1, 2011

For years, piracy has been commonplace among the 18-24 crowd. Services like Napster, Kazaa, and LimeWire made it easy to find and download music, movies, and TV shows. The quality was never as good as a DVD. Sometimes, there was even a silhouette of a theater patron as they walked in front of the camera on their way to the bathroom. If you’re trying to capture the complete essence of the movie theater experience, complete with baby crying and cell phone conversations, I’d say there is no substitute for a zero day cam, recorded clandestinely in the back of the theater on opening night. Most people, though, want the high quality DVD experience.

I’ve seen and heard a wide spectrum of pirated digital media over the last ten years. I’m not going to tell you how I found any of it, as the simple act of explaining how I found it is apparently illegal, thanks to the DMCA. Needless to say, it’s out there, and readily available if you know where to look. And it’s not just music and video. If you need a copy of Microsoft Office, you can find one with a well-defined query and be downloading in minutes. If, on the other hand, you’re looking for something more obscure, like a PC game from 1994, you’ll probably find it and be unable to download it quickly. App piracy is a population contest. The most popular apps download quickly, while less popular ones take longer, possibly days or even weeks. Generally, though, you can find whatever you want if you look hard enough.

So, how do software companies make any money with all this piracy? The reality is software sales in brick-and-mortars are declining as vendors move to virtual product delivery workflows, where customers buy apps and content directly on their Playstation, Xbox, or mobile device. Many are also adopting a subscription-based business model. Metered service is a surefire way to prevent piracy. Give away your app for free and charge a recurring fee to access content and features. Even a jailbroken app can’t hack through the iTunes in-app purchasing system. If metering doesn’t fit your business, a consumable or non-consumable product may be more appropriate. Instead of an up-front price that can be avoided on a jailbroken device, give the app away and include a one-time activation fee as a non-consumable product.

Piracy will continue to thrive as long as there is some benefit to be found in its pursuit. By shifting the focus of your business model from an up-front purchase to a freemium model, you guarantee your apps have rock solid immunity from pirates.

How To Guarantee Success in Product Development

July 14, 2011

You’ve heard it before – frustrated project managers or executives, maybe even yourself, complaining about work products and deliverables that didn’t match their expectations. Often, this has nothing to do with the competence of the vendor or consultant. It is a direct result of incorrect or incomplete communication. Sometimes, it’s a language barrier or cultural dissonance, such as the use of unfamiliar terminology or idiom. Other times, it’s the inability or unwillingness of the client to endure the sometimes frustratingly tedious process of confirming clear understanding of their project’s needs. Confirmation is a critical component of communication, without which there is little hope of a positive outcome. One challenging scenario that illustrates this well is the toxic attitude that the listener “should just get it.”

Communication problems are almost always compounded with time, if not addressed. If the entire project duration is a few months or more, the risk of failure due to divergent understanding is significant. If expectations go unmet for more than a week or two, the client begins to develop a negative impression of the contractor’s value. This strains the relationship. It’s easy to see how this strain can grow over time, eventually culminating in a product review wherein the client expresses a strong negative reaction to the delivered work, claiming it is “nothing like what [they] asked for.” If these reviews only happen once or twice over the course of a project spanning several months, the reaction can be very strong, so strong even as to result in irreparable damage to the working relationship. All of this risk can be mitigated by organizing the project into small discrete iterations. This is the essence of the agile development methodology.

By breaking up the effort into one- or two-week boundaries, the total risk to the client is capped at the cost of two weeks of labor. At the beginning of each iteration, both client and contractor agree to the features to be delivered. Then, at the end of the iteration, the client has an opportunity to evaluate the quality of service or work product. If the value represented in deliverables does not match the client’s expectations conveyed at the outset, there are two options: termination of the working relationship or reconciliation in a subsequent iteration cycle. In the case of reconciliation, the contractor has an opportunity to react to divergence of understanding quickly, rolling over the unsatisfied requirements to the next iteration cycle.

There is no set of working policies that will guarantee that the work product is delivered as desired, but by following a strictly bounded iteration-based product development methodology, the risk to all parties is minimized. By focusing the effort into discrete, well-defined goals, the task of tracking and managing project progress can be greatly simplified. More importantly, this approach increases the level of communication between the principal parties, resulting in a greater sense of clarity and confidence across the board.

Follow

Get every new post delivered to your Inbox.

Join 60 other followers