Building a UI - Understand First


I was recently asked a question about UI implementation by a coworker. It’s a question that I’m asked with some regularity so I thought I’d share here for posterity.

The question typically goes something like this:

I’m working on implementing this UI. I received a mockup from our designer. I’m struggling. My path seems inefficient. I’m learning about requirements halfway through my build. I keep needing to refactor things. This is taking me so long. What can I do to avoid being in place again?

First, let’s frame a fairly standard scenario for someone building web applications on a team. You’re working with some design folks and product folks and ultimately you’re doing the work to implement a feature. There are typically some design artifacts at your disposal. Perhaps you’ve got some page mockups that have been approved by stakeholders that you’re referencing in your build. Maybe you’ve been in some conversations around this particular feature. Maybe you’ve even worked with the designer in charge of producing the design for this feature.

You’ve been tasked with building this new feature. How do you start?

There’s an instinct to give the mockups a quick look and then to dive right in to building. But don’t do it just yet. Hit the pause button for just a bit. Let’s take some time to really parse the design. This is really the root of all inefficiencies when we’re talking about building UI. An incorrect assumption early on can take you down an incorrect path for days that ends up causing you all sorts of re-work later on when you finally truly understand the requirement.

This can be the easiest thing to trip up on when your team is fantastic. You’ve got a high level of trust across the whole team. Lots of talented folks. Assumptions get made and problems ensue.

The applications we’re building on the web these days can get quite complicated. There is often lots if interactivity. Lots of different state. Different user types and roles. Reliance on other systems. Etc. This level of complexity is nearly impossible to convey in even the best, most thorough of mockups. And honestly, I’d argue that much of this complexity is not the place for mockup anyway. It’s up to developers to poke at a mockup and ensure it’s understood. Let’s spend some time with the design work.

I realize this is easier said than done. It’s not quite as straightforward as just looking at a mockup. You need to take a more “active viewing” approach. The crux of this is to uncover all that complexity (or as much as you can) early on. How you go about this can be different from person to person, project to project. There’s no single way that works for everyone and every project.

The actual tools and process you use during this phase are really up to you. Some people like to use a design tool and comment up/annotate a mockup digitally. Some like to just take some notes while they’re parsing. Some even like to print out the design on paper and annotate it with questions and ideas. You could even cut up the paper to help understand the individual pieces and their relation better. Point is, you do really need to figure out what’s best for your team, project, and the task you’re working on.

First things first, let’s look for all those places where there appears to be interactivity. That’s a very likely place for some sneaky complexity. Buttons, forms, and links are the super obvious places to focus. Often these can seem simple on the surface, but turn out to be more complex with a bit of poking. Perhaps you see a “Save” button with a little arrow icon next to the text. What actually happens when I click that button? Is that icon decorative and it just saves? Does that arrow reveal a sub-menu (maybe there are “Save” and “Save as” options). Or does it do something entirely different. Maybe there was a working session I wasn’t able to attend and a lot of the specific context for this feature got ironed out there. Basically, something like this may be accounted for by the design folks on our team, but maybe not. We can’t depend on that so let’s ask the question. Repeat until you feel like you’ve got a solid grasp on the interactivity of the feature.

It’s possible you may learn things along the way that don’t, on the surface, have a direct impact on the feature you’re building. But grasping the bigger picture can often help you to architect things in a way that allows for easier times going forward. Be considerate of how this feature fits into the system.

I’ll then start to look for possible changes in the state of the application. A very common situation you’ll encounter here are error states. What happens when there is an error of some kind? Another is related to whether or not a user is logged in. Or even further, does what role a user has change anything? Again, I’ll call out that it is nearly impossible for a visual design to demonstrate all possible states. Particularly if you’re working on a reasonably complex application. Get in there and raise the questions.

These are two pretty high level things to look for. How you approach this will change based on the work you’re doing. It’ll take some repetitions through this stuff to feel out the right approach for a given situation, but you’ll get there eventually. One specific, and kind of catch-all, recommendation of how you might go about this would be to just spend some time with the designer in charge of the design you’re working on prior to you actually coding the feature. Thirty minutes talking with someone can save you hours of effort later on. I’d always recommend this approach if possible.

Don’t get stuck here. Analysis paralysis is real and can rear it’s head during this time. I’m not talking about spending days here trying to parse all the details of a design. Just take a pause and do a bit of thoughtful review before diving into code. You might start to feel like you need to get “pen to paper” to really understand something. That’s cool too, but be sure to pop your head up and gain clarity as the questions arise during your build as well. The understanding doesn’t stop once you start coding.

I think it’s important to note here that you’re not going to uncover everything. You just aren’t. I promise you there’ll be some new things that’ll pop up during implementation and that’s totally fine. But we want to try and minimize those as much as possible and minimize their impact. We want to do our best to uncover the really impactful stuff early on.

The last thing I like to do is a bit more tactical and a bit less important at this phase, but can be helpful still. I try to notice the shared things (both in this feature and possibly to other places in the application). Is that a button type I’ve built before and is used somewhere else? Should it be? Is this common spacing here? Is this our brand color?

I’d caution too much thought early on here as that can cause some unnecessary abstraction, but at least having some thoughts and ideas prior to getting into the code will only help you out.

All of that said, I think approaching the actual UI build as a scratchpad or draft to start is a good approach. The patterns and useful abstractions will become more obvious. Just make sure you take the time to do the actual work to tidy up as you sort that stuff out. Working within some sort of design or style system is absolutely an evolution and the point here is to make sure you’re keeping that in mind as you start your build.

This is my high-level approach to implementing a UI. Or really, getting myself organized before I start to write UI code. As you can probably guess from this post, I’d argue that this is just as important as the actual code you write. By putting some thought and energy toward understanding early on you’ll save yourself so much time later on. And as a bonus, you’ll end up with a better result. It might feel like you’re not actually doing work while in this phase, but I can assure you it is work. In fact, I’d say it’s the most impactful work.