Some time ago, I helped build a small translation feature. Our users regularly needed to translate some of their assets, and we figured it would be straightforward to integrate translation right into our platform. In the morning, I received a UI design file and got to work.
In our backend, translation was already available as a reusable primitive. Based on that, implementing a user-facing endpoint for translating this specific kind of asset took less than an hour.
As for the frontend, there already was a context menu for each asset. The UI design featured a new “Translate to...” menu item, which was supposed to bring up a submenu of available languages.
Unfortunately, our component library didn’t support submenus yet. For a moment, I was stuck; in my experience, getting submenus working just right is non-trivial, and I felt chasing robust submenus right now would only yield marginal value (if any).
However, our component library did have dialogs, so I went and made the new menu item open a separate dialog for language selection instead, which worked well. I shared a screenshot, explained how submenus are probably not worth it, everyone agreed, happy merging.
The feature landed in our staging environment in about two hours, which was a nice turnaround due to fast pipelines and robust tooling. We were able to play with it, adjusted some details, and were ready for production before lunch.
This small anecdote may sound like “just another day at the office”, but in my experience, there are plenty of potential failure modes here:
- Not even looking for more economical alternatives, missing an opportunity
- Taking on the submenus without informing anyone, risking a delay
- Rushing the submenus, risking bugs
- Handing the issue back to the UI designer to come up with alternatives
- Insisting on the marginally better design, even if high effort
- Not seeing that submenus can follow in a later iteration
- Delegating the UI work to the maintainers of the component library
- Complaining about it as a planning mistake
I’ve been guilty of all of these in similar situations. I know any of those decisions could have meant days of additional lead time for this one simple task, without adding significant value. If you do dozens of such tasks, costs compound quickly.
While there is no silver bullet for avoiding such inefficiencies altogether, I believe the one thing we got right this time was sharing the design process, beyond the handover of the UI design file, and beyond our individual roles. In the words of one of the most important American designers of the 20th century:
Here is one of the few effective keys to the design problem: the ability of the designer to recognize as many of the constraints as possible, [their] willingness and enthusiasm for working within these constraints. The constraints of price, size, strength, balance, time and so forth. Each problem has its own peculiar list. — Charles Eames
Rather than thinking in terms of planning and resources after the design phase, we saw timing and effort as design constraints to work with, and made significant adjustments to our initial design based on these, even late in the process.
In software development, you want this to happen, and often. This is how you win back efficiency lost to unknown unknowns, and save opportunity costs better spent on chasing the next big thing.
To me, this is the ideal of cross-functional work: Embracing constraints from outside our bubble, taking an economic perspective, and designing together. ∎