I consider myself both software developer and a pilot. I was lucky enough to have the chance to earn my private pilot certificate in 2011. I fly small, single engine aircraft and they aren’t that very sexy, but I think being up there looking down is one of the coolest things I’ll ever get to do.
Being a software guy who cares a great deal about user experience and usability, I really enjoyed flying aircraft equipped with the “glass cockpit” of the Garmin G1000. Sure, I was also trained on the standard “six pack” of “steam gauges” (the old gauges with the dials), but have done most of my flying in planes with computerized avionics. When you’re in command of a plane (even a small plane), you find quickly that you have a lot of duties. You are required to simultaneously fly a prescribed heading and altitude, maintain a correct airspeed, watch for traffic, ensure that you are tuned to the correct communication and navigation frequencies (both primary and standby), watch your engine for anomalies, properly monitor fuel/oil mixture, properly trim control surfaces, communicate with ATC (air traffic control) and other aircraft, watch for weather issues, oh yeah – not run out of fuel, and try to squeeze in some sight seeing along the way. When you are juggling the myriad duties in the air, you become very appreciative of the work that went into your aircraft’s flight avionics.
After flying for a while, I have distilled a few of the things that I have learned from interacting with flight systems into three simple lessons that can be applied to all software, regardless of the domain.
1. Users Don’t Want to Hunt for Data
As you can see from the image in this post, pilots have to deal with an incredible amount of data. In an instant, a pilot needs to have access to his airspeed, altitude, attitude, heading, comm frequencies, nav frequencies, transponder code, altimeter (barometric pressure) setting, waypoints, nearest airport, weather, engine temperature, oil pressure, fuel level, and other bits of information. If a pilot had to dig through layers of user interface (UI) for that information, there would be no way that he could properly and safely pilot the plane. In the old days, the answer to this was to distill the data to just the pieces critical to flight. The answer then was the “six pack” of steam gauges. From these, you could see your airspeed, attitude, altitude, turn coordinator, heading, and vertical speed indicator.
This smaller set of data kept many pilots safely in the right place for many years, but during those years, pilots were also fiddling with paper charts and approach plates and were calling back to ATC for weather updates.
The new glass cockpits have managed to improve on the tried-and-true analog gauges by skillfully presenting the pilot with data through an intuitive UI. The user can gather any data necessary for flight at a glance and can view potential weather hazards on the secondary display, the multi-function display (MFD). The pilot does have to interact with the system to enter headings, frequencies, squawk codes, and look up airport information, but the information is never more than a few intuitive entries away.
When considering the experience our users will have with the software that we write, we must consider how to get them the information that they need with as little pain as possible and without data over-saturation. We might ask, what is crucial for the user to have at hand at all times (like airspeed and altitude)? What can be called up on demand (like airport layouts)? What is the quickest way to get the user to the data they need with the fewest interactions? What can I infer about the user’s current behavior that will help me serve them up what they will need next more quickly?
2. Interaction Must Be Intuitive
With both analog and digital interfaces, the pilot has to enter information into the aircraft. On old systems, the pilot has to “dial in” the altimeter settings and frequencies. On newer systems, the pilot still has to enter these values, but with a common set of controls. Further, on new avionics, the number of knobs and switches are small, but their mode of use is expanded based on the current context of the display. This allows for a simpler human-avionics interface, which help the pilot by limiting his choice of input device. There is usually only one or two ways to enter data, which helps speed training and makes flying safer through a simple, straight-forward interface.
Another example of this simplification of input is my old, Windows Phone from 2004 versus my iPhone 5 from today. My old Windows Phone from 10 years ago had a clunky interface. It had menus and sub menus and a tiny screen and required a stylus just to navigate menus. It was an attempt to force an old menu paradigm from a larger PC into a tiny screen form factor. It was painful. Fast forward to the iPhone 5 that I carry today with iOS7. It is sleek. It is intuitive. The entire device has all of 4 buttons. My interaction with the iPhone is much more enjoyable because I don’t have to carry around a stylus. Menus are context-aware. Apps are single-task specific. I’m never more than a few gestures away from what I want.
No matter what the industry is for which we write our software, we have to construct the path of least resistance between users and their content. It is our duty to the user to minimize the interaction they have to make with a machine to get what they need.
3. Software Must Perform Properly Every Time
The week before my checkride with the FAA examiner for my pilot certificate, my instructor and I taxied to runway 36 at the Madison County Executive airport (MDQ). I taxied into position, made my radio call, and firewalled the throttle. By about 1000 feet down the runway, I knew something was wrong. From my training, I instinctively called out the airspeed as it climbed to my rotation speed. However, this time there was no airspeed to call out. The G1000’s airspeed indicator had no reading at all. With about 5000 feet of runway left, I made the split-second decision to abort the takeoff, cut the throttle and slowly apply the brakes. My instructor and I decided to call off our flying until maintenance could look over the aircraft. Later that day, when I returned to the airport, I was informed that the person who had rented the aircraft before me had forgotten to put the pitot tube (the tube that takes in air to determine airspeed) cover back on and the aircraft technician had found that a tiny bug had made its home within the tiny orifice.
This was a minor incident, of course, but it proves the point that people rely on systems to provide them with the data they need to accomplish their task. I was counting on the software to properly tell me my speed and it didn’t, or couldn’t, so I wasn’t able to fly. Thankfully, the software in the cockpit was designed to degrade gracefully, which is something we should build into all of our software systems. I could have taken off, circled, and landed safely and the rest of the data provided by the system would have been available.
Aircraft systems are an extreme example of systems that require a high level of redundancy and availability. The same can be said of other systems, like telecom switches and medical devices. Regardless of the system, we should design our software such that it is of high quality, is highly resilient, and degrades gracefully when something goes wrong.
These are just three lessons that we should strive to apply to our creating software. I’m sure that more could be gleaned, but if we were to follow only these three, our software would be more usable and robust and our customers would be the happy beneficiaries.