This is a cut/paste of the UXmag article series. Must be shorter, more integrated together, and integrate with the book as well.

Make sure I add in the dive watch photo and example. Pull from decks.

I’ve been designing, both in print and digital, for over twenty years.

Lately I've been feeling that for much of that time I have done a more mediocre job than most clients and users give me credit for, and have, in many ways, lucked out when I make good designs.

For about six years now I have worked as a UX designer for agencies, and as a consultant. Working and talking with many different people, for many different organizations, I have heard a lot of people express similar feelings. We don’t really know how to get to good design, and tend to rely on hiring more good people and hoping for the best.

It seems like many strict processes don’t turn out reliably good results, no matter how long they take. Why is that?

Designing for Perfection

What I’ll call the traditional way to design is to address every possible aspect of the system and to seek perfection in everything. I have watched this method grow out of print media—where everything was at fixed scale and of reasonable depth—and classic human factors—which uses very intense analysis to build controls for mechanical systems like those found in aircraft, where failure is more often than not a real catastrophe.

If you think you are cutting edge because you do digital design, you may need to think again. Anyone designing in Photoshop or Fireworks embraces this same print-era pursuit of perfection when they draw a precise comp for every screen of an app or site. In mobile design I see anything from two to seven comps drawn for each page, as the same precision is exercised for each screen size or aspect ratio. Designing for iOS only? You still need iPhone 4S and below, iPhone 5, and iPad, in each orientation—minimum.

Technical design and information architecture also fall into this trap with processes based around use case analysis. Even if your process or organization doesn’t strictly do that, or calls it something other than a use case, the principle is the same: you’re seeking to understand and control every aspect of the system. Lists of use cases are generally hundreds of items long, and each has to be addressed with clearly defined system behaviors.

Iterating for Efficiency

Aside from the large size of these deliverables, this traditional approach doesn’t work for a couple reasons. First, systems are far too complex and diverse (or fragmented if you wish). It is mathematically impractical to address every use case, so we fake it and pick a few on the happy path of the most likely cases. When considering the available combinations of choices a user could truly make on many systems, combinatorial variations are in the billions. I did some rough math on one project and determined the documentation and analysis would take longer than the course of human history up to that time to complete. (If you take, say, 100 functional modes that can be combined uniformly, and work without serious breaks and get approval from your product owner quickly, then it would have taken over 8,000 years to specify every possible state.)

"Fail faster" and similar iterative-centric buzzwords only work well in scientific disciplines tweet this

Pixel-perfect design is likewise impossible in this diverse environment; in just a single month late last year I did a quick survey and found around 40 newly-launched mobile handsets or tablets with 40 different screen sizes and almost 30 different resolutions. It would take years to design for every one of these screen sizes, and the very next week the world has already moved on with more devices launched. Insisting that one platform is best and ignoring the others is not the answer, by the way, and seems to be leading to lots of apps that don’t even work when you rotate the screen.

The current, state-of-the-art processes for addressing these concerns involves various iterative methodologies, such as Agile. These are mostly development processes applied (or forced) onto UX design disciplines that focus on breaking work up into smaller chunks. In principle, each deliverable is something that can be analyzed or designed, and complexity emerges over time in a controlled manner as iterations add to it. In practice, many of these methodologies become simply incremental processes, which means the same work as always is now done in phases.

Lean methods build on these with principles of doing the most important work first, and allowing products to evolve organically. Practically, these approaches end up disregarding design and, seeking speed over quality, don’t really move us forward from a UX point of view.

Learning Nothing from Failure

The concept of "fail faster" and similar iterative-centric buzzwords only work well in scientific disciplines. As humans, we are inclined to evaluate the results of activities, designs, and events in the past as being more predictable than they were before they took place.

This hindsight bias means you have an illusion of understanding what went wrong which may not be accurate. This “I knew it all along” effect means people tend to remember past events as being predictable at the time those events happened. Our memory is inaccurate; we remember only the events or information that back our pre-existing worldview.

It doesn’t mean failure is bad. Science and more formal engineering disciplines apply it well, and have done it this way for centuries. But you have to have clear goals, expected outcomes, and some control over variables. Then you have to take the time to measure (without bias) and accurately communicate the results. More formalized “post-mortem” reviews like the U.S. military after action review help to tease out these issues in less technical areas like project management and team interaction.

In design and software development, speed kills. Without stopping to make sure we are doing the right thing, we rapidly make the same mistakes not once but over and over again.

I find it easy to integrate these analytical methods into the design process. Even when working alone, and without formal evaluation it is worth looking at mistakes, changes and past iterations to see why the failure occurred or the change was required.

As designers and developers we forget to look up to see where we are in the bigger picture. We try to block things out into pixels and comfortable code templates. We need to step back occasionally, just for a minute, and think in broad brushstrokes. How are our detailed decisions impacting the way the whole product works, and the way it will integrate with users’ lives?

Constraints

There are many pressures put on design and implementation teams. A lot of them are specific to industries, organizations, or projects. Often, when I come into an organization to consult, I find that many elements that are assumed to be constraints are actually variables, or at least arguable. I’d stipulate that the real constraints are:

Arbitrary Complexity: Most systems are so complex that they cannot be modeled with pencil and paper (or whiteboard, or flowchart, or wireframe) in sufficient detail to execute design. Systems All the Way Down: The complex application or website is embedded into a much more complex OS, in a differently-complex device, running on a vastly complex network, carried by a person with their own needs and behaviors, living in a world of other people and really complex systems. You cannot predict what might happen to these variables and how they will affect your little part of the world. Networks of Delay: Everything is connected now, but traditional network models fail us. Instead, we have built a giant, distributed supercomputer that we all carry windows into in our pockets. Our devices, apps, and websites just delay and interfere with access to this information, to varying degrees. Anything that reduces delay is good. Anything that gets in the way or exposes edges of the network is bad. Systems are Fault-Intolerant: Right now, technical systems (software, data) fundamentally expect perfect information and absolute precision in computation. They are intolerant of imprecision, missing data, and failures to connect unless that behavior is also precisely designed. Users are Fault-Intolerant: While people are great at estimating, fudging, and getting by, they don’t like to use tools that break or cause them to work harder. Very simple gaps in “look and feel” can induce familiarity discomfort similar to the uncanny valley of anthropomorphized representations. At the very least, you will encounter reduced satisfaction and trust. Often, that means users will give up and use a competitor’s product or service. Bound to Fail

Relatively few people have been working on other methods that try to address some of these issues by being more flexible, working like the products, and working with the environments we design for. These methods and principles are less unified and are left without a single name. All of these methods are based on designs that are less scale-dependent (so work on multiple screen sizes); are more modular to encourage re-use; and annotate heavily to assure better coordination with implementation and quality assurance.

In the past decade or two, resilience engineering has become an important technical practice area. Resilience in this sense is the ability of a system to absorb disruptions without tipping over to a new kind of order. A building, when exposed to too much lateral ground movement, settles into a state of “rubble on the ground” unless you design it to resist this disruption adequately. Services like Google, Facebook, Etsy, Flickr, Yahoo!, and Amazon use resilience engineering teams and principles not to make sure their data centers stay running, but to assure that when failures occur, the end users don’t notice.

Our systems are embedded in other technical systems, embedded into complex systems: like the user carrying it around, who may be subject to rain, and traffic delays, and screaming babies. We can’t predict every failure point, but can plan to fail gracefully instead.

Embracing Errors and Complexity

Building on flexible UX design methods, mixed with these principles of resilience engineering, I propose another approach to designing for these constraints of complexity, error, delay, and intolerance. Instead of fighting these, we can design better systems by embracing failure and uncertainty.

In 1952, computing pioneer John Von Neumann called computational errors “an essential part of the process” of computing. This was almost forgotten for decades with the advent of the high-reliability computers we work on today. But increasing amounts of data and the need for power conservation are creating a need for unique solutions that leverage probabilistic design and ignore unused data or let small errors occur in computing.

This is surprisingly not new even to visual and graphic design. The technical methods of printing machinery have inherent inaccuracies and behaviors that make certain apparently possible designs insufficiently reliable for mass production. Print design has to account for ink being placed in the slightly wrong place, for overlaps on adjacent layers, and for slight errors in binding, folding or trimming.

In print (and package design) these are all considered tolerances, or normal variations, not errors. Accounting for overlaps and inaccuracies in ink placement is a whole (very specialized) practice area called trapping. I have books on my shelf dedicated just to trapping.

For the UX practice to account for tolerances and normal variation instead of lamenting fragmentation, complexity, and error means letting go of perfect solutions to create better, more robust systems and solutions. We need to embrace the messiness and complexity of systems—and of real life.

To apply these approaches to interaction design, with all the additional complexities, really doesn’t call for anything new. We already do many of these things, but need to switch from considering them as discrete tasks to seeing them as principles that are applied regularly and repeatedly throughout the process of designing any project.

Here are some things we can do to design for imperfection:

Assume the Unknown: No matter how many questions you ask or how much research you do, there will be behaviors you cannot predict or understand. This will keep happening. A minor change or a shift in trends will cause use of your system to change. Think Systematically: All the data we gather on personas and the concepts we use to develop storyboards are not inputs to the design process, they are the design process. Systems thinking is about setting aside constraints and considering how the people, paperwork, email, data storage, and every other part make up the whole. So, in every phase of the project, explicitly discuss the user, your expectations of their behaviors and needs, and how those are met in every way. Use and Make Patterns and Guidelines: Art and science both evolve by building on what has come before. Use existing patterns by understanding how they apply to your work. Create patterns for your product rather than screens. Design and document each widget to be as generalized as possible so you re-use and re-apply instead of designing each interaction from scratch. Analyze and Focus: Admit you do not know a lot about the pressures, behaviors, and inputs of the user and customer. But don’t just throw your hands in the air and design for those you do know. List out likely needs, uses, and behaviors, classified in a way that they can cover not specific actions (We’re not modeling use cases) but classes that the design can respond to. Rank these by their chance of happening and focus on the high-chance classes. Conclusion

These are not steps in a process but constant activities carried out regularly throughout design and—if you can get everyone to play along—execution. I’ll take a closer look at these activities in action in a future article. For now, keep in mind that this is very much not a process. Design tools do not really matter, as long as you are flexible enough to consider whatever tool is needed, and to solve problems as they arise, not as they are constrained by your tools.

If you’ve tried any of these approaches or have any thoughts on what’s been discussed here, please comment below.

PART TWO HERE. BOLT THEM TOGETHER

As designers and developers we forget to look up to see where we are in the bigger picture, blocking things out into pixels and comfortable code templates.

I believe that we should embrace errors and complexity. We need to step back and think in broad brushstrokes. How are our detailed decisions impacting the way the whole product works, and the way it will integrate with users’ lives?

I suggested that designers follow four guidelines when taking the nuanced approach I described:

Assume the Unknown: No matter how many questions you ask or how much research you do, there will be behaviors you cannot predict or understand. This will keep happening. A minor change or a shift in trends will cause use of your system to change. Think Systematically: All the data we gather on personas and the concepts we use to develop storyboards are not inputs to the design process, they are the design process. In every phase of the project, explicitly discuss the user, your expectations of their behaviors and needs, and how those are met in every way. Use and Make Patterns and Guidelines: Art and science both evolve by building on what has come before. Use existing patterns by understanding how they apply to your work. Create patterns for your product rather than screens. Analyze and Focus: Admit you do not know a lot about the pressures, behaviors, and inputs of the user and customer. But don’t just throw your hands in the air and design for those you do know. For this follow-up article, I’d like to discuss examples of designing for imperfection in action, using the example of a small startup I’m a part of called FoundHub.

Assume the Unknown

My involvement in FoundHub started in my favorite way: the moment the idea was a gleam in the eyes of the other founders, I was invited in. FoundHub is designed to be a local product-finding service, and it was clear that the challenges weren’t so much technical, rather the product needed to be appealing and easy to use.

I started with essentially no understanding of their concept, which was actually great. It reminded me to be explicit about asking questions and defining the audience, business goals, and expected user goals. From this, the whole team was able to understand that key attributes were location and immediacy. This screamed mobile and caused us to focus on mobile compatibility first.

We need to embrace the messiness of systems, our users, and the world outside tweet this

Our design could easily have been made absolutely rigid, with us trying to guide the user through the process, and solve every issue. But instead we all agreed that there was great potential for users to use the system in unexpected ways, so we essentially left gaps. Discovery of features and supporting optional entry of information are both key. The datastore allows as much arbitrary data storage and retrieval as is practical.

Think Systematically

When I was first brought on, it was assumed FoundHub would be a traditional website. I think partly because that matched the technical skill and general comfort zone of the others involved with it.

The conversations we had about audience, scope, and goals reopened up the whole project to discussion. Aside from the shift of focus to mobile devices, a goal-driven discussion led to new ideas, like experiments with image uploading, and a network of reminders on multiple channels.

Not all of this has been implemented, but planning for these features has future-proofed the design and allowed for the creation of APIs and databases. Planning for UX-centric features went hand-in-hand with avoiding technical debt. So far this has facilitated clean and quick iterating on the system—adding features instead of reworking them—and ew're confident it will continue to forge a steady march forward.

Use and Make Patterns and Guidelines

As quickly as we moved on this project, it was critical to create documentation so we could keep track of what decisions had actually been made. In the end, I did mess up a bit on consistency. Moving at high speed it was very easy to make decisions about design with only a few components in mind.

Luckily, as I just said, the other part of this speedy design was iterative development and speedy change. As I became aware of inconsistencies and flaws, I created patterns, style guidelines, and redesigned concepts, so when the time came we were ready to fix everything.

UI and technical consistency go hand in hand, so eventually it became clear that the first designs were also difficult to update and maintain. Right now, we’re in the middle of redesigning the whole presentation layer. Being able to refer to a handful of repeatable patterns for color, type, interaction, and actions, results in many pages being all but automatically designed; there’s only one way the components go together, and it all works out.

Analyze and Focus

My kids routinely do what all children do: they don't clean their room; they leave the wet bathmat on the floor; they leave the cereal box out. The typical response is "oh, I forgot..." Lately, that's struck me: their expectations parallel those of most adults. Following the rules is about memorizing, and complying with, a long checklist of appropriate behaviors.

I remind them that I don't remember anything, either. I have a terrible memory for processes and steps and procedures. So what remember instead is to turn around and look over my shoulder. Just like you look before crossing the street, you should make sure the bathroom looks neat before you leave it after a shower, or that the changes to the website make sense to every user.

As I designed FoundHub (and each time I am sent a revised build) I walk through it like an end user would, trying to make no assumptions based on what I know about the system.

Does the information architecture make sense? As we added items, the answer, at least once, was “no” and I had to push to change the menu. What about errors? Can the user get out of them and complete their tasks? Over time, I have been working on eliminating errors, often with fairly robust changes to the system expectations. Throw away the happy path. What if, instead of the home page, users pop into a random page from a Google search or shared link? A nice feature of having many phones to test on is that I can press the Share button every once in a while, and switch to a new handset. It didn’t always work, so we figured out why, and fixed it. Are we lying? Does the structure or language obscure the true organization, data, or structure of the system or process? It is very easy to get caught up in jargon, or decide some technical feature is too much for the user and obscure it. For FoundHub, we had some very open conversations about privacy, and decided to not just be non-evil, but to tell everyone about it. I spent a week writing friendly, human-centric terms and conditions—not just for legal purposes but so we were never lying to or deceiving the customers. Whenever new information, new issues, or a new idea comes along, I try to remember to assume the unknown, think systematically, and to make and use patterns and guidelines.

Executing on the Eternal Backlog

You might work within a larger organization of mostly IT-centric types, but all of your great ideas and processes are of very limited value if you cannot get everyone else on board.

Considering the unknowns means planning for the future, which meshes perfectly with existing processes and methodologies. The backlog of features for future iterations in agile processes inherently deals with the future, and even with uncertainty. Features in the future are only as defined as they need to be, and become more nailed-down as they need to be worked.

As any feature is explored or built, more problems and ideas are often generated, which are simply turned into their own features in the future. Even without external feedback, the inherent uncertainty of design and execution yields an almost inexhaustible supply of work.

For years now I have been using the backlog—or similar lists of features—as a place to store features, expectations, and ideas for the target experience, or the ultimate goal of the product. This target state is not fixed, so defining it past very general goals is hard to do. A shared vision that derives from an ocean of features allows everyone on the team to be prepared for the future, and over time to address them in new iterations and releases or with new product ideas.

Modularity to Avoid Complexity

You might have noticed that implementing the whole design as individual features empowers the principles of component-based modular (or maybe even object oriented) design and development. This is really the only way to attack the vast complexity of systems in an ordered manner.

For FoundHub, the form to post a new find has several thousand basic outcomes depending on user inputs and selections. Defining them all is clearly impractical, so instead each field is defined individually. They are already discrete elements, so this is easy and natural. In development, it speeds time to usable code, as dependencies are cut down. Now, you aren’t building a form, but a field, and as soon as there’s a submit button you can start testing it.

This translates across the process: making another unit test is a really useful part of the developer’s workflow. And the only change is one of conception. Instead of considering features entirely from the business point of view, or to make math easier when assigning features to iterations, you just need to make them smaller and atomic. That’s entirely about analysis and planning and how people work: not processes, methodologies or technologies.

Not incidentally, careful design of modules massively reduces total work, as re-use of these means you tend to have fewer total components to design, or build.

Conclusion

I said that development methodologies like agile tend to account for an eternal cycle of uncertainty, something that’s true for many contemporary processes and methodologies. But practically, it will only happen if the team understands complexity and believes in solving it by designing for imperfection and error.

If you embrace the principles outlined above, your job is not to push new processes on everyone, but to get everyone to let go of old ways of thinking. Remind everyone we cannot force the perfect solution to exist, and can create better, more robust systems and solutions. We need to allow users to play, explore, share, and discover. We need to account for distraction, boredom, and error.

We need to embrace the messiness and complexity of systems, our users, and the world outside the whiteboard and our computers.

This article was most most-recently inspired by Gary Anthes’ article "Inexact Design: Beyond Fault Tolerance" on probabilistic design of ICs in the April 2013 edition of Communications of the ACM.

Resilience Design (last edited 2015-12-29 22:05:49 by shoobe01)