KISS in practice.

I was having a conversation with a co-worker, where I complained that the biggest problem with some of the code we’re working on is that it was over-engineered. I reminded him of Gall’s Law:

“A complex system that works is invariably found to have evolved from a simple system that worked. The inverse proposition also appears to be true: A complex system designed from scratch never works and cannot be made to work. You have to start over, beginning with a working simple system.”

He asked me a question about client-server interaction, and rather than shooting off a 140 character reply it seems to make sense to answer the question more fully here.

To summarize, we are building an application that communicates to a remote server using JSON over HTTP. The remote system is built on top of Drupal. (Honestly it’s not how I would have done it, because there seems to be too many moving parts already–but the folks who built the server assure me that Drupal is God, and who am I to complain?)

Now on an error there are several things that can go wrong. The remote server can return a 4xx or a 5xx HTTP error. It can return a JSON error. Or it could return an HTML formatted error (I guess they have some flag turned on which translates all remote errors into human-readable error messages.) The client is hardened against all of these return possibilities, of course, and is also hardened against a network failure or against a server being unresponsive.

So here’s the question: how should the client respond to these wide variety of errors?

On the server side, of course, there needs to be logging. We even do some device-level logging, and a mechanism is in place on our iPhone client to transmit that log in the background to the server if there is a problem. Because clearly from a developer’s perspective a 404 is not a 501 is not a 505 is not a “server is unresponsive” is not an “illegal character in the API” is not a “network down” error. So clearly we need to know what is going on so we can fix it.

But what does the end user need to know?

In my mind, handling this is very simple: what can the user affect?

In the case of a mobile device, the user can retry again later, or he can make sure he’s got good network reception. Period.

So in the event of a failure, the client’s behavior should be simple: if a connection fails, then test to see if the network is up. If the network is down, tell the user “I’m unable to talk to the remote server because your network is down.” And if the network is up, tell the user “Sorry, a problem occurred while talking to the server.”

And that’s it.

If the network is down, the user can try to turn it on: he can take the device out of airplane mode, or move to where he has reception, or turn on the WiFi. But it’s up to the user–we just have to tell him “Um, the network is down.” And let him decide how he wants to handle the problem–or even if he wants to handle the problem: it could be he clicked on our application while at 38,000 feet over the Atlantic.

If we can’t hit the server, but the network is up, then there is nothing the user can do about it. All we can do as software developers is make sure whomever is maintaining the servers that they should investigate the outage. All we can tell the user, however, is “sorry, no dice; try again later.”

And hope to hell our servers are reliable enough we don’t drive users away.

Making it more complex is silly. It doesn’t serve the user who may be stressed out by messages he can do nothing about anyway.

Okay, Google: what were you thinking?!?

To my fuzzy little brain, the core of a ‘view’ object, be it an NSView, a JComponent, or a HWND object is simple: it’s a rectangular piece of screen real estate. It can draw into its piece of screen real estate. It gets called when it needs to be redrawn and when it is optionally clicked on. It gets called when its location inside the superview is changed. And it can have the ‘keyboard focus’ (whatever the hell you want to call that), so that keystrokes and menu commands are routed to it. And ideally it is embedded in a hierarchy of other views, and has a well designed event subsystem which allows unhandled events to be forwarded to the appropriate parent view or to other event handler abstractions in the system.

So to my fuzzy little brain, the Google Android OS should, when the aspect ratio of the screen is changed by opening the keyboard, send some sort of ‘size changed’ message. And perhaps as part of the message I can either just resize my children or, in a dramatic (but unlikely) case tear down and rebuild my contents–such as having a list view turn into a map view.

So when I read the following here:

Unless you specify otherwise, a configuration change (such as a change in screen orientation, language, input devices, etc) will cause your current activity to be destroyed, going through the normal activity lifecycle process of onPause(), onStop(), and onDestroy() as appropriate. If the activity had been in the foreground or visible to the user, once onDestroy() is called in that instance then a new instance of the activity will be created, with whatever savedInstanceState the previous instance had generated from onSaveInstanceState(Bundle).

This is done because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources, including layouts, drawables, and strings. Because activities must already know how to save their state and re-create themselves from that state, this is a convenient way to have an activity restart itself with a new configuration.

(Emphasis mine.)

WT(bloody)F?!?

Valid format values for declare-styleable/attr tags

Meh. Wasted an hour trying to sort this out.

The answer happened to be buried in some Android code. The fact that Android is open source is a cool thing–but I shouldn’t have to dig through that source kit just to figure out the answer to something that could be better documented.

When declaring a <declare-styleable> <attr> tag, you supply a name for the new attribute for your custom class, and you provide a format. Well, I couldn’t find the valid values for the format attribute in the documentation. But I did find them here.

And those values?

  • reference
  • string
  • color
  • dimension
  • boolean
  • integer
  • float
  • fraction
  • enum
  • flag

It also appears from the source code that this field is optional, and I presume if it is left blank, either one of two things will happen: this will default as a resource reference, or the format is only used for type checking, and this can be any value. I dunno; I haven’t tried it.

On the off-chance someone knows the answer, could they leave it in the comments?

Things wrong with the Google Android UI

It has been my experience that most software developers, and many product managers for that matter, have absolutely no sense of UI design. After playing a little bit with the Google Android Dev phone, the following things immediately jump out at me that are just wrong about the gPhone.

(1) How many different ways do you need to get your e-mail?

On the home screen you have the “Browser” icon which takes you to the mobile version of Google, where at the top there is an e-mail tab. To your typical user, this is the way you get your e-mail. Buried under the tab which reveals all the applications beyond the basic 4, you also find a Gmail program which can be used to get your Google e-mail, and an Email application which can be configured to get your Google e-mail via IMAP.

Do you need three separate and equivalent (in terms of number of taps) ways to get your e-mail?

Yes, the first two methods only get your Gmail; the last tool can be configured to get other e-mail. But honestly, would it hurt to have a unified e-mail mechanism?

(2) Incoming messages are not obvious.

When you get an e-mail, the upper left status bar shows a small icon representing the fact that you have a new message. It’s unclear what that icon represents: how am I supposed to know a little ‘@’ sign means I have new mail?

What’s odd about the incoming message status bar is that behind that status bar, if you touch the top bar and slide down to the bottom of the phone, is hidden a notification system which tells you of all of your incoming notifications. But there is nothing on the bar indicating that it can be slid down like this!

Meanwhile the front of the phone has a ton of screen real estate being devoted to–displaying a blue ocean scene.

(3) There is no clear indication in the application launcher icons (hidden by the tab at the bottom of the display) as to which applications have received a notification.

On the iPhone, a small badge is used in order to determine if there are messages associated with an application; thus, if you have waiting SMS messages, the SMS icon has a number indicating the number of messages. Similarly for e-mail.

The Google phone, however, does not provide any such indicator: if you get a message you can launch the application that handles that message by clicking the notification line in the notification window (if you’re smart enough to divine the fact that a notification window can be found there), but otherwise, all you know is the phone rang, a little mail icon (for SMS) or @ sign (for e-mail) is sitting in the upper corner, and God knows which application you should open to handle the messages.

(4) There is no note taking system for the Google phone.

Yeah, people bitched when there was no to-do list manager on the iPhone, and that makes sense to me: you have a to-do list in a synchronized Calendar, so why can’t I get that to-do list on my phone? But the Google phone doesn’t even have a notepad. A big, beautiful keyboard and no way to take notes?

Yes, you can download third-party notepads to the Google phone, just as you can download third-party to-do programs on the iPhone. But seriously…

(5) Likewise, as a video player, you can play–YouTube videos.

Thanks. But I’d like to watch the latest episode of Battlestar Galactica.

(6) When the phone turned on from sleep, the display shows status, the network, the time (as a digital display) and a message to press the menu key to unlock the phone. Once the phone is turned on, you go to a primary screen with four icons–dial, contacts, browser and maps–and a beautifully rendered analog clock.

But here’s the thing. Say I’m pulling the device out of my pocket and checking the time. I’ll press a button, see the digital time, then let the display go to sleep again.

If I bother to unlock the phone, I’m going to use an application–either I’m going to make a phone call or I’m going to run a Tetris clone. So why force me to go through three taps–the third to expand the launcher–in order to play a game?

I suggest the analog clock in the middle of the display is completely useless: the time is also displayed in the upper left corner–and the only reason why I can see for having a beautifully rendered analog clock and a digital clock on the same screen is because Google thinks I’m 5 years old and still learning what the big hand means and what the little hand means.

Apple solves this problem by having a row of icons clearly delineated at the bottom of the screen that are fixed from screen to screen: the ‘Phone’ (which includes the contacts list), ‘Mail’ (and not three separate mail programs), ‘Safari’ (for browsing) and ‘iPod’ (for playing music and videos). But rather than wasting the rest of the real estate on the top of the display with a useless clock and a pretty seascape, the iPhone displays a 4×4 grid of other applications you may wish to run.

Yes, I know these are minor nit-picky minor things–perhaps nearly not worth even noting. But that’s the whole point of user interface design: there needs to be a coherent whole, some unified thought, a way to clearly indicate to the user using a consistent symbolic visual language what to do. When I see an icon in a rectangle I know if I touch it something represented by that icon will happen.

But Google has violated a number of these things: how am I supposed to know that by sliding the top down I’ll get the notification manager? And why–outside the possibility of separate development teams competing on providing e-mail and not talking to each other–is there three ways to get my e-mail?

And that’s the point: each of these tiny little pointless and nearly irrelevant little nit-picky things are exactly those things that turn a good user experience into a insanely great user experience.

And the Google phone: it’s good. Better than Windows Mobile.

But it’s not insanely great.

So you have an iPhone 3G and want to use the SIM on the Google Android dev phone.

The steps I found on the ‘net seems to work.

Remove the SIM card from your iPhone and insert it into the Google Android developer phone. When you start the phone for the first time, when the phone asks for your Google account, you need to press the menu button, and select “APN”. Add a new APN entry on the Dev phone with the following settings:

Name: att
APN: wap.cingular
Password: CINGULAR1

All other fields are left blank. Click menu, save, then work your way back to the login prompt, and sign in as usual.

It appears the good news is that once you get the phone set up, it will operate (albeit without phone or 3G wireless) without the SIM card, which makes the phone useful in a limited fashion for development. And if you do need to test the card on 3G, you can just move the SIM card back–though unfortunately it’s a real pain in the ass to extract the SIM card from the Google phone without tweezers. (On the other hand it’s impossible to remove from the iPhone without a pin, so I guess they’re even.)

h/t