Tagged: mobile

On Swearing and UX Antipaterns

For the last few months, I've been curating a Tumblr of a very specific annoyance. I'll let Aral Balkan take credit for inspiring me.


Any modal message—full-screen or alert—that interrupts user flow to ask them to download your app suffers from #doorslam #ux antipattern.
@aral
Aral Balkan

First, a quick definition:

In software engineering, an anti-pattern (or antipattern) is a pattern used in social or business operations or software engineering that may be commonly used but is ineffective and/or counterproductive in practice.
Antipattern on Wikipedia

My tumblr is simply called "I Don't Want Your Fucking App".

It chronicles all those websites which - despite having a mobile web experience - are just desperate to get you to download their app. So desperate that they're willing to slam the door in your face.

Imagine, for a moment, that you are in a mall and decided to walk into a shoe shop. The assistant comes up to you and says "Good morning! Would you like to visit our website? It's so much better than our shop!"
How ridiculous would that be? And yet, that's what these websites do. They tell you to piss off and go elsewhere.

DoorSlam Collection

How It Should Work

Ideally, when a user visits your website, you should deliver the content to them in the most appropriate format. That's it.

If they're using Internet Explorer, you serve them up the correct CSS and JavaScript. If they're on a mobile device, serve them up the mobile or responsive version of the page.

If you do have an app, by all means let the user know - but don't take over the whole damn screen!

It really is that simple.

Apple have created an excellent way to create dismiss-able banners to promote your app.

When you throw up an interstitial, you're not only giving a terrible impression, you're also forcing the user to do more work than is necessary to get to the content they want.

The F-Bomb

Interestingly, the discussion on HackerNews focused mostly on the issue of swearing. Although I'm not usually one to swear for dramatic effect, I thought it would be amusing to have an over-the-top rant which over-uses swearing to the point of banality. It is, if you like, an exercise in over-reaction.

My sweary blog posts do seem to get the most attention. I wonder if it's because people are becoming too corporate. So worried about causing offence that their language becomes reduced to bland words that are calculated to be as emotionally neutral as possible.

I disagree with that mode of acting. I think it's perfectly acceptable be passionate and to let your language reflect that passion. Sure, the level of swearing that I've used is ridiculous - but it is employed to drive home the point. That's how I feel. That's how millions of us feel when we're confronted with repeated petty annoyances in our daily lives.

Swearing. It's not big, it's not clever, but it is authentic.

It's The Little Things Which Make An App

I've been a big fan of Ovo Energy since switching to them last year. They email me a PDF statement, pay me 3% interest on any overpayments, and have their call centre waiting times displayed prominently on their homepage.

So, when they announced their new app, I was expecting something a little bit special. And that's exactly what I've got.
image

An automatic torch to help you when you're rooting around in dark cupboards trying to read your meter. Brilliant.

So, not only does the app fulfil its main purpose (submit gas & electricity meter readings, see my bill, etc), someone has obviously taken the time to see how the app works in the real world. Sure, there are plenty of standalone torch apps in the world - but this is the first time I've seen one so thoughtfully integrated into an app.

Ultimately, this app is probably going to be used once per month. It needs to be simple enough to use that the customer doesn't have to relearn how to operate it every time. More than that - it needs to be delightful to use.

As much as we would all love our users to open our app several times a day, the reality is that they won't. That's why we need to concentrate not on beauty, not on overall UX, but on tiny moments of joy which reminds people why they should keep our app on their phone and keep coming back to it.

What Can Android Learn From Symbian's Security Model?

More bad news for Android owners. A huge Russian malware operation is infecting Android apps in the the Google Play Store. The malware - hopefully now removed - hijacks your personal details, and sends premium rate text messages to drive profits for its owners.

Nasty.

This is the price we pay for Android's open access policy. iPhone users can smirk all they want - but I like being able to run anything I desire on my phone, rather than be restricted to the puritanical walled garden of Apple's App Store.

The late lamented Symbian OS did many things wrong - but it had an interesting approach to keeping users secure from malicious apps.

The first time an app wanted to access a feature - like Internet, SMS, phonebook - the phone would prompt the user to grant the app permission.

Symbian Internet PermissionSymbian Internet Permission 2Symbian Secure Connection prompt

Now, the Symbian model wasn't without flaws. It would often forget that you'd granted an app permission or repeatedly ask annoying questions.

Is this what is needed for Android? the first time an app tries to access, say, the dialer - should Android say "Are you sure you want Angry Birds to make a phone call?"

Or, should Android take a leaf out of BlackBerry 10? When installing the app, the user can choose whether to grant certain permissions.

Finally, what about personal responsibility? The Android permission model is quite opaque to most users, it's true, but there are some basic precautions users can take.

I was recently hit by a "drive by installation". A malicious website automatically downloaded an app to my Android phone. When I clicked on it to install, this is what I got:

Legit App Permissions

If you think a Battery app needs all those permissions... I'm not sure encasing you in bubble-wrap is enough to keep you safe from yourself!

The price of freedom is eternal vigilance. Android needs to do more to allow users to enjoy their freedom.

Going down the Symbian path of insisting every app be signed by a third party and repetitively interrupting the user is probably not the right way to do things. What is clear from the current crop of malware is that simply telling the user of the permissions an app is requesting at installation time is insufficient.

Until Google makes things better for its users, it's worth installing an app like Permissions Denied which will allow you to see which apps have more access than they need - and restrict them if necessary.

Aggressively Defensive Programming

How much checking do we perform that our code is running as intended?

I found a curious bug this weekend, which made me think about some of the assumptions that we use when programming.

Imagine sorting an array using JavaScript.

var arr = [10, 5, 66, 8, 1, 3];
  1. arr.sort();

So far, so normal. Create an array of numbers, then sort that array. The result should always be [1, 3, 5, 8, 10, 66].

Would we ever need to do this?

if (arr[0] < arr[5]) {
  1.    // Do something
  2. } else {
  3.    // THIS SHOULD NEVER HAPPEN!
  4.    laws_of_physics_violated(arr);
  5. }

Sorting an array in this way should never trigger an existential crisis. But suppose it did.

A Brief Word on Android Fragmentation

Android fragmentation has never really bothered me. It's usually a case of sensibly designing a UI to flow correctly and checking the capabilities of a device. No more complex than designing for the web.

This weekend, my father and I spent the weekend building our first joint Android app - First Bid Bridge - it's a simple enough app that we decided to use a WebView and write the game logic in JavaScript.

All was going well until I tested the game on my Dad's phone. It didn't work. All the answers it produced were completely at odds with the answers on my phone.

Welcome To Facebook?

We tried this on every old phone I could find. Android 1.6, 2.3, 4.2 - they all worked. iPhone, Maemo, BlackBerry - hell, even my Internet TV worked flawlessly.

Painstakingly crawling through the logic, I found the problem. A "sorted" array was reversed on his phone! (Galaxy Ace running 2.3.6 for those who want to know.)

Diagnosing

Our app looks at a hand of cards. We split the hand into suits (Spade, Hearts, Diamonds, Clubs). We record how many cards are in each suit.

We then sort the hand by length - if two of the suits have the same length, they are sorted in the order Spades > Hearts > Diamonds > Clubs.

JavaScript allows us to define our own sorting function. Here's ours (in simplified form)

First, we sort by length:

suitsArray.sort(function(x, y)
  1. {
  2.  var o1 = x["length"];
  3.  var o2 = y["length"];
  4.  return o2-o1;
  5. });

Then, we sort by suit order (if the lengths are the same):

suitsArray.sort(function(x, y)
  1. {
  2.  var length1 = x["length"];
  3.  var length2 = y["length"];
  4.  
  5.  if (length1 == length2)
  6.  {
  7.   var suit1 = x["suit"];
  8.   var suit2 = y["suit"];
  9.  
  10.   if(suit1 == "spades")
  11.   {return false;}
  12.  
  13.   if(suit1 == "hearts")
  14.   {return false;}
  15.  
  16.   if(suit1 == "diamonds")
  17.   {return false;}
  18.  
  19.   return true;
  20.  }
  21. });

In every device I tried, this sort worked perfectly. Except on my dad's $@*&ing phone. ARGH! What was even worse, is that we were an hour's journey away from each other, so I couldn't debug on the device.

So, that's where I came up with the idea of Aggressively Defensive Programming. It may not be an original idea - but this is how it works.

Trust, but verify

"Доверяй, но проверяй" as the Russians would say.

Assume that your computer is crazy, possessed, or being zapped by cosmic radiation and check its compliance every step of the way.

Essentially, after every operation, you should verify that the operation has worked. In this case, we did this (simplified):

  1. // The above sort
  2.  
  3. if ((arr[0]["length"] == arr[1]["length"]) && (arr[1]["suit"] == "spades")) {
  4.    // Dammit!
  5.    // Sort the array manually
  6. } else {
  7.    // Carry on as normal
  8. }

Where Should This Be Used

There are four main scenarios where it makes sense to programs defensively.

  1. Your code has a real impact on human health (aeroplane, nuclear reactor, medical device).
  2. The computer you're running on is in a harsh environment and therefore liable to unpredictable behaviour (Mars Rover)
  3. A multithreaded environment where your code cannot lock resources for itself.
  4. You are running on an untrusted computer i.e. one other than your own.

For most of us, the first three are unlikely to trouble us. But the final one is interesting. Almost every piece of code we write will be run on a 3rd party's computer. One over which we have very little control.

But that's what we do when we release apps - or run websites. The code we have lovingly crafted is being run on machines which may have all manner of quirks.

How aggressive should we be with our defences? Do we assume that built in functions work - and only check ones we've written ourselves?

In Principia Mathematica Bertrand Russell famously provided proofs such as "1+1=2".
Principia_Mathematica_theorem_54-43

Is that what we need? Mathematically verify every computer our code runs on? That may be overkill. But I'm starting to come round to the idea of verifying every operation - even if just to throw an exception rather than proceeding in an error prone state.

I leave you with an instructional extract from Douglas Adam's Mostly Harmless:

On board the ship, everything was as it had been for millennia, deeply dark and Silent.

Click, hum.

At least, almost everything.

Click, click, hum.

Click, hum, click, hum, click, hum.

Click, click, click, click, click, hum.

Hmmm.

A low level supervising program woke up a slightly higher level supervising program deep in the ship's semi-somnolent cyberbrain and reported to it that whenever it went click all it got was a hum.

The higher level supervising program asked it what it was supposed to get, and the low level supervising program said that it couldn't remember exactly, but thought it was probably more of a sort of distant satisfied sigh, wasn't it? It didn't know what this hum was. Click, hum, click, hum. That was all it was getting.

The higher level supervising program considered this and didn't like it. It asked the low level supervising program what exactly it was supervising and the low level supervising program said it couldn't remember that either, just that it was something that was meant to go click, sigh every ten years or so, which usually happened without fail. It had tried to consult its error look-up table but couldn't find it, which was why it had alerted the higher level supervising program to the problem .

The higher level supervising program went to consult one of its own look-up tables to find out what the low level supervising program was meant to be supervising.

It couldn't find the look-up table .

Odd.

It looked again. All it got was an error message. It tried to look up the error message in its error message look-up table and couldn't find that either. It allowed a couple of nanoseconds to go by while it went through all this again. Then it woke up its sector function supervisor.

The sector function supervisor hit immediate problems. It called its supervising agent which hit problems too. Within a few millionths of a second virtual circuits that had lain dormant, some for years, some for centuries, were flaring into life throughout the ship. Something, somewhere, had gone terribly wrong, but none of the supervising programs could tell what it was. At every level, vital instructions were missing, and the instructions about what to do in the event of discovering that vital instructions were missing, were also missing.

Small modules of software - agents - surged through the logical pathways, grouping, consulting, re-grouping. They quickly established that the ship's memory, all the way back to its central mission module, was in tatters. No amount of interrogation could determine what it was that had happened. Even the central mission module itself seemed to be damaged.

This made the whole problem very simple to deal with. Replace the central mission module. There was another one, a backup, an exact duplicate of the original. It had to be physically replaced because, for safety reasons, there was no link whatsoever between the original and its backup. Once the central mission module was replaced it could itself supervise the reconstruction of the rest of the system in every detail, and all would be well.

Robots were instructed to bring the backup central mission module from the shielded strong room, where they guarded it, to the ship's logic chamber for installation.

This involved the lengthy exchange of emergency codes and protocols as the robots interrogated the agents as to the authenticity of the instructions. At last the robots were satisfied that all procedures were correct. They unpacked the backup central mission module from its storage housing, carried it out of the storage chamber, fell out of the ship and went spinning off into the void.

This provided the first major clue as to what it was that was wrong.

Further investigation quickly established what it was that had happened. A meteorite had knocked a large hole in the ship. The ship had not previously detected this because the meteorite had neatly knocked out that part of the ship's processing equipment which was supposed to detect if the ship had been hit by a meteorite.

Podcasting on the Voicemail

My new commute involves a lot of driving, which means I've started listening to podcasts again. One of my favourite mobile related podcasts is The Voicemail - it's a quick half hour chat between two mobile industry experts; Stefan Constantinescu and James Whatley.

Stefan has been travelling for the last few weeks, so James has been co-hosting with guests. I've never recorded a podcast before, so I badgered James for a guest slot and, last night, we recorded episode 40 of The Voicemail.

If you're an iMusic fan, listen to The Voicemail in iTunes - and please rate the show if you enjoyed it.
You can subscribe to the podcast feed.
Or, you can grab the MP3 of Episode 040 directly. (31.30 MB)

I say "y'know" a lot. That's very annoying.