UX Designers are from Mars, Developers are from Venus: A Character Study of the Software Engineer

Sam J Horodezky
11 min readMar 17, 2016

--

As UX designers, we know there’s just something different about the way software developers think. What’s important to us doesn’t mean much to them. And no matter how hard we try to teach them, they just don’t get it! You can hole up a bunch of engineers for days and drill them in usability heuristics, but it doesn’t seem to work.

I will argue in this article that there are multiple causes for this disconnect. Based on personal observation, I believe that the differences in thinking between the two groups are very deep and entrenched, but that they can be largely explained by the skills and traits that are required by two different disciplines. Software engineers are trained to think qualitatively differently than those with a Design pedigree.

At the highest level, this article is a character study on the software engineer from the perspective of the UX designer. However, it does serve some other more practical purposes. I found personally that understanding errors made by engineers shed considerable light on what constitutes good design, and why. Finally, understanding the types of design errors that engineers are predisposed to make helps us anticipate them ahead of time, and combat them when they surface.

Engineers Create in their own Image

As designers, we generate personas to help guide our creative process. We are trained to empathize with the user, and we know that the user’s preferences are not the same as our personal preferences. Most personas that we design for will, all things considered, have a preference for simplicity.

Engineers are quite the opposite. Having not been trained on the notion of empathy, engineers tend towards building things that they would want to use. And the things that they want to use are complicated — sometimes very complicated. Essentially, they are control freaks.

How does this need for control manifest itself in design activities? Engineers want their software to have many dials, switches, and knobs. But as designers, we all know that complexity of an interface is correlated with the number of functions provided: the more knobs and dials you add to a design, the more it degrades. So here we have what is probably the eternal conflict between Engineers and Designers: the Engineer wants functionality to give the user control, and the Designer wants to cut functionality to the simplest level possible.

My observation has been that engineers often have trouble deciding which functions are less important even though they agree that the total number of features is too high. ‘Cool’ features tend to magically appear in software, whether or not the feature is specified anywhere in the requirements. Sometimes this involves a subtle change, such as the placement of a highlight when a particular condition is met, and sometimes it involves the wholesale fabrication of a dial or knob. There is an infinite set of requirements that are not stated in the formal requirements, and this very fact is used to justify the addition: “The spec doesn’t say what to do in this case,” or worse, “Well, the spec doesn’t say that a green triangle shouldn’t appear here”. If you have 10 engineers each do this once per project, then you have ten extra ‘features’ that were not part of the original design. Feature creep becomes an inherent property of the development process.

Trade-Off Calibration

Trade-off analysis works very differently for UX designers than it does software engineers. Success and failure are fuzzy concepts in human psychology, but not to machines. Both disciplines ultimately develop some tolerance for errors in the design, but the tolerances are not calibrated the same way.

Designers know ahead of time that some features in a UI are going to be more obvious than others. There are going to be some tasks that are harder to complete than others. We even have the luxury of deciding whether or not to address certain cases at all. We weigh the potential benefits of a solution with any penalty the solution might incur on the overall UI. In this trade-off analysis, the UI designer will sometimes opt, knowingly, for failure.

This set of circumstances leads to a mindset collision when developers and designers get together. Has this ever happened to you?: an engineer identifies an edge case that the UI accommodates poorly or not at all. You perform a tradeoff analysis and determine that the edge case applies 2% of the time, but that any solution would degrade the user experience the remaining 98% of the time. You opt for no change. The engineer goes off in a huff, complaining that UX designers don’t make any sense and they don’t know what they are doing.

This example highlights a difference in our two disciplines: 98% of users are able a task, the design could very well be considered a success; however, if a piece of code worked 98% of the time it would not be commercial quality.

I have observed engineers attempt to radically redesign an entire feature on the basis of a single edge case. More broadly, the engineer’s approach to a design will be to design a solution that accommodates all of the requirements equally well, resulting in a least common denominator solution. The UX designer approaching the same problem would not treat each function equally, but rather prioritize each feature and then design accordingly. Some of the less important features may be hard to use or might even fall out of the design entirely, whereas the high priority features will have more prominence and increased usability.

UX designers are concerned with maximizing user success for high frequency use cases. Software engineers also make trade-off decisions, but they are less tolerant of failure in the minority cases.

On Consistent Consistency

One of the workhorses of usability is consistency. The good news is that engineers dig consistency and look for ways to have more of it. The bad news is that engineers and designers don’t agree on what consistency is. Engineers pine for consistency at the code level; designers want consistency at the psychological level.

Consider the difference between adding the first item to an empty list, and adding all the subsequent items. From a designer perspective it is easy to imagine that we would wish an empty list to look different than a list that has items in it, for example it might be grayed out, or present text explaining that the list is empty. However, this means the first entry is treated differently than other at the code level, and is therefore inconsistent to an engineer. It is exactly this type of inconsistency that drives some software developers crazy.

Another main area where we run into problems with our programming brethren is with the implementation of psychologically intuitive concepts such as ‘open’, ‘close’, and ‘undo.’ To the user, these have meanings that are very clear across different contexts. However to an engineer, opening a spreadsheet application is going to invoke a totally different set of actions than opening a word processing application. Since many processes combine to cause any broad concept such as ‘open’ to occur, there is considerable opportunity for there to be a misunderstanding between the psychological meaning and the underlying technical implementation.

From my own work experience, I have a perfect example of this disconnect between psychological and technical meanings: once I worked on a mobile feature called keyguard, a piece of functionality that locks the buttons on a mobile phone while it is in your pocket so that it doesn’t butt-dial. If keyguard is on, pressing buttons on the keypad caused a dialogue to pop up and say “The phone is locked. Pressing keys will have no effect”. A developer once argued with me that this text was inconsistent, because pressing the keys did have an effect: it caused the dialogue to become visible. Here, the cognitive meaning of ‘no effect’ is quite different then the technical one.

These types of consistency clashes are unavoidable. The developer needs to inhabit a techno-centric world in order to tend to the needs of the compiler; the user interface designer needs to inhabit a user-centric world in order tend to the needs of the mind.

Opportunity Knocks

Early in my career I worked with a bunch of no-nonsense engineers to design a map application that showed a large amount of complex and highly technical information. In textbook fashion the project lead insisted on a torrent of controls and features, and my entreaties for relief were largely unsuccessful. The result was an eye-pleasing interface, stuffed to the gills with options, and ready to break.

The map had a thick border, where we had embedded some basic tools to allow the user to pan and zoom. One day, an icon appeared in randomly selected location on the border. The function of the icon was unknown to me, but I observed that it was the same icon that we were using elsewhere in the interface.

I hunted down an explanation for the aberrant icon. What had happened is that the engineers had determined that they required another feature, but they knew that if they came to me I would respond that there were too many features already. So they came up with a fix themselves. (I did not realize it at the time, but we desperately needed a Product Manager.)

The solution was totally absurd. As designers, we take it for granted that objects in an interface bear relationships to each other and to cognitive representations in the mind; we attempt to maximize the use of visual affordances, and pay careful attention to the impact that a local change will have on the overall balance. The engineers took into account none of these considerations: they simply found an icon, slapped it on an empty space, and called it a day.

This type of design is called an opportunistic design: just using whatever is available rather than carefully accommodating the old and the new.

Looking around at some other tools that I assume engineers must have designed, I see the very same tendency. Words and icons are placed together haphazardly, functions are grouped together in a way that reflects some aspect of the engineering process (such as the underlying API or the order in which the functions were implemented), and the UI components (radio button, menu item, wizard) are used inappropriately.

There are two primary reasons that we see this type of approach emerge from the engineering mind. There is definitely an aspect of opportunism which is inherently sanctioned by coding technique. As a general principal, software developers want to be as economical as possible with the use of memory, and as a result they often like to squeeze bits into places, reuse memory locations, and generally take space in the memory stack where it is available. Really scrappy coding, especially on devices that have limited memory, is valorized either because it is necessary or occasionally because it is clever. So the idea of using whatever space is available could seem very attractive to any programmer that has a bent towards memory efficiency. Opportunism might therefore be seen as the product of inappropriate transfer of economical coding practices to the field of UX Design.

I do think it is overly charitable to ascribe too much of opportunistic design to economical programming tendencies. The bigger reason that we see this type of design approach in countless products is because it is manifestly easier. If we look back to my example with the icon, it was very straightforward to appropriate an existing icon and paste it in an empty space. Even had I consented to adding the desired feature, I would have probably insisted on a brand new UI mechanism, which in turn would have been much more work to code and debug.

More generally speaking, as designers when we are asked to add a new feature to an existing product we don’t just look to see if there is a place we can jam it on. We carefully assess what cognitive affordances are needed and what set of controls map best to those affordances. Sometimes it really might be as easy as adding another menu item or button to the existing framework. But just as often, it is not. This is a simmering tension we see between engineers and designers — and in fact, between designers and anyone who cares about how long it takes to develop something and how difficult the resulting code might be to maintain. We’ve all been in the uncomfortable position of being the one who wants to create something new to accommodate a small feature, but the work to implement it seems out of proportion to the overall impact of the feature.

This brings us face to face with our greatest demon: good UX Design really is harder to implement. Cognitive affordances do not translate at all to ease of coding, and as we saw in the previous section, psychological consistency and code consistency are not the same thing. As designers, we need to admit that our designs create more work for developers. They may even make the code base more difficult to maintain and debug. Only once we admit this can we have frank discussions about the trade-off between a new proposed design and the resulting complexity. This trade-off discussion should be the hallmark of a good Product organization.

I wish I could say that all the time we should pick the best design, but that is not true. There’s no point in conducting a trade-off analysis if the result is always the same. On the other hand, as one of my mentors (who was an engineer by trade) used to say: “There’s never enough time to do something right, but there’s always time to do it over.” If we deliberately pick poor designs because they are easy to build, then we’ll just end up eventually building a better design later.

Seeing the Forest for the Trees

Enforcing consistency across a sizable user interface is difficult, and it requires complex interactions between rules and multiple trade off evaluations. In general, it takes more software engineers to implement a feature than it takes designers to specify it — it’s an unusual company that has a bigger UX team than a development team. The result is that the designer has oversight over a larger piece of work than the individual engineer. Therefore, it falls to the designer to enforce global consistencies that ripple throughout the whole design and impact areas that a developer might spend months implementing.

If consistency uniformly appeared as a force for the good, this would not be a problem. But enforcing global consistency can require a designer to pick a different solution than if that piece was being analyzed in isolation. For example, let’s say that the design team has agreed that ‘providing prominent breadcrumbs’ is a high priority design rule across the entire product. The act of providing breadcrumbs could involve the demotion of a feature that otherwise would have occupied that prominent position.

The engineer working on that feature will not necessarily see justification in this trade-off. In my experience, the longer the explanation is about the application of a global rule to a local situation, the less likely any engineer is to believe it. Often I have had the experience of thinking that someone was seeing my lips move but not hearing the sound stream generated by my larynx.

But this is all understandable and natural. No engineer wants to see a sub-optimal design for the area that he is working on, or see work placed in a less glamorous location. This same tension appears in design teams too. A designer on a large team wants to do something that is in conflict with a global rule, because the designer feels more affinity to the specific feature she or he is working on than the global integrity of the product.

We have already discussed many ways in which designers think differently than engineers. In this case difference in perspective can yield more opportunities for disagreement.

Concluding Blows

Part of what makes software developers think differently from us is what enables them to be excellent in their own field. In this article, I have lightly lampooned software engineer’s behavior, but it is with love. I know and appreciate what a group of intelligent, dedicated developers can achieve. Engineers need to think with a certain logical precision, and they need to be able to process and view what they create in a manner that supports clean and orderly development practices. We shouldn’t want them any other way.

The purpose of enumerating the fundamental differences between Designers and Engineers is that the understanding provides a meaningful explanation for why we are so often at each other’s throats. The differences are common, pervasive, and inevitable.

And on a practical level, understanding the engineering mind allows us to fight the good fight on our quest for design excellence. A good design does not mean much if it is not implemented. The more we can understand and empathize with our developers, the more we can anticipate their objections, and ultimately come to a fair common understanding on design topics.

Many thanks to Clif Scott and Tony Tsoi.

--

--

Sam J Horodezky

Founder of UX Consultancy Strathearn Design (www.sdesign.io). Lives in Toronto, father of 3 vivacious children.