Design systems and the notorious design-engineering gap
Can we work together, after all?
One of the reasons to fund a design systems team is, essentially, to improve the design handoff. When a hypothetical design system is in place and is well-developed, the conversation between designers and engineers revolves around information and intent, while the structure and look are taken care of. That’s how it should be in theory; however, in practice, things are messier.
Back in September, when Donna organized the first chat about what’s going on behind the design systems, one of the topics that seemingly emerged out of nowhere but led to an active discussion was the gap between designers and engineers. Guests mentioned that they’ve seen lots of miscommunication going on between people holding either of the roles in the org. People started talking about their experience trying to make it work but not finding a solution.
Let’s talk a bit about people collaboratively building a product, in general, and then a bit about people collaboratively building a design system.
Non-deterministic explosion vs. deterministic reduction
It’s embarrassing that it took so long for me to figure this out, but after some time dealing with designers and engineers claiming, in various forms, that they can’t work together effectively, I came to realize it’s all about different tools they use and how these tools shape their thought process.
Design work is a lot about creating understanding of the problem on the team, coming up with a range of solutions to it, and iterating towards one that works. By “works” I mean something that will actually help the user get their job done, fit into the product so that it doesn’t feel foreign, and help the team improve the metrics that are important.
Design work is non-deterministic, at least in the beginning, and it requires a lot of assumptions in the beginning. If it were deterministic, I guess there would have already existed a generic enough algorithm that does it much faster than a human. Generative design is cool and these days quite promising, such as Designer, but I don’t see companies hiring fewer designers, which is partially because knowing how to design to solve a problem is more complex and more probabilistic than expressing the understanding of it in Figma. Sorting is easier than deciding how to sort.
Engineering work is relatively deterministic. Sure, at high enough level it’s indistinguishable from guesswork, but eventually the code has to pass unit tests and not raise any alerts on prod, and both are rather deterministic, both have short feedback loops and clear signals on whether it’s working or not.
Engineering work is also work towards adding structure to something. On meta level, the folder structure reflects how things ought to work, and the code is made to be readable, which is to be traceable by someone who needs to understand what’s going to happen.
The reason I’m talking about here and taking such a long route is because designers and engineers work towards fundamentally different purposes. While I appreciate engineers who care about the end user, the way they tell success is by looking at engineering metrics, and those are at least one layer of abstraction distant from the user. Just because there’s 0% error rate, does it mean the user is getting their job done more effectively than they could with a feature designed and/or engineered in a completely different way? Hard to tell, but 0% error rate seems like a good achievement already.
Open canvas thinking vs. version control thinking
Another realization came up when Amadeo, Lucas and I were talking about versioning in Figma. Why? Let me explain.
If there’s a component in Figma that is being used in many files, then changing this component is risky because it’s going to break the reflection of the UI design in those files. It’s not nice for older files that aren’t being actively used and are there only for the purpose of historical record, but it’s rather nasty for the files that are being worked on right now. If I’m working on something today and tomorrow see its layout completely broken because some component somewhere got updated, I just got a problem I didn’t plan for, — and no one likes unexpected problems, especially the ones that aren’t tied directly to the economic value of digital product development, i.e., actual people using actual product.
Now, Figma supports component versioning. But this doesn’t seem to fit a typical design workflow, which is a lot more about experimentation and breaking out of the norm, as opposed to making orderly changes in a properly versioned manner. Engineers think git, designers think blank canvas.
Engineers look at design, designers don’t look at code?
One idea that I heard someone say was, if I’m an engineer and I’m supposed to look at the designs, why isn’t designer supposed to look at the code? Sounds logically correct, but also not quite.
Designer’s output, such as a mockup, a prototype in code, a text doc, is a flat shadow of a multi-dimensional effort from the point where only the problem is known, vaguely, to the point where a bet is made, and that bet is a solution presented in a design. A designer is reducing the problem space to a solution.
An engineer’s equivalent of that would be not the code itself, but the user getting value from using the product. In a way, an engineer is expanding the solution space, going from the code to the actual product experience.
If product experience is the end result, the reason the code is being written in the first place, sounds like the designer is supposed to look at that? At least when the incentive system encourages that. But then, hey, isn’t that exactly what happens?
Okay, what does it all mean for design system work?
When designers and engineers come together in context of a design system, they genuinely want to create a solution that will solve the problem and scale together with the product and, hopefully, with the problem space. That is, if they are able to come up with a solution to a problem, when a similar problem comes up later, the distance from original to new solution is going to be always proportional to the distance from original to new problem. A new column in data? Our table component handles that. Wait, the data type is actually “person”? Cool, we have a “person info card” already, just gotta fit it into the table cell.
Knowing the differences in how designers and engineers approach their work, it should be easier to predict where things don’t go as either of the counterparts expect them to, — only at scale of the entire design system, which in turn is a reflection of (and to) the entire product.
If a design system is a hyperobject, then a typical mistake a designer or an engineer might make is seeing only a reflection of it into their “comfortable subspace”. We could do better!
Gonna sound cheesy, but it starts with empathy.
If I’m a designer and I fully understand what goal my engineering counterpart is pursuing, I can better craft the message and prioritize my work in a way that is going to make them appreciate what I’m doing for them and the team. If I intrinsically believe that I should be doing something else, well, at least I know for sure that other folks on the team don’t see it this way.
If I’m an engineer and I fully understand what gives my designer peer on the team most fulfillment, satisfaction, and a healthy amount of challenge, I can stop assuming wrong things and start listening more carefully.
So how to I bridge the gap, exactly?
A few things I found working well are coming together to collectively define what we talk about when we talk about the design system.
What is a component vs. a pattern? In the past, engineers would implicitly define a component as something that is tangible and usable on its own. Turned out, a piece of text and a date picker both fit this definition, and a date picker can contain text. Patterns were things that can be made out of many components, such that following them gives a promise of uniform and cohesive UI, but breaking out of them is also possible at zero cost for a team. So far so good, but is “button” a component or a pattern then? What about “calendar” or a “rich text editor” or even the aforementioned date picker?
What really is a foundation, or a base, of the design system vs. something that is added on top of it? Are design tokens the only thing that is fundamental to the system, or are there other things at different levels of granularity that belong in the foundation?
I found that being pedantic, precise and smart about these things help less. What helps more though is being inclusive and collaborative in the process of defining and distinguishing those.
For a design system team, and possibly also a broader group of people from the entire organization who are actively involved in building the design system, this collaborative approach means spending disproportionately more time than going an easier and more linear route of studying the subject and imposing definitions. But the more I’ve been part of going the collaborative route, the more I grew to appreciate it over force-masterminding things. Design system is, after all, result of cooperation of the entire org, under guidance and governance of the core team or teams, towards achieving a uniform shared understanding of how the product is and should be built.