tl;dr I started working on a design early to speed things up. It ended up taking twice as long.
Some months ago, I worked on a simple React component — a save dialog with some advanced functionality. The UI designer I was collaborating with was busy, but I had a pretty good grasp of what needed to be done. To speed things up, we agreed that I'd start working from an unpolished version of the design. Once he finished the UI, we'd do a review and tweak the styles to match.
The save dialog was a simple form with a more complex section that depended on the type of file being saved. My instinct was to set up an interface and move the file-type-specific functionality into separate components. The main component would load up the appropriate subcomponent, let it do its thing and forward the result up along with the data from the rest of the form.
To me, this seemed like a clean solution. The file-type-specific details were encapsulated inside the relevant subcomponent. To support a new file type in the future, we'd add a new one.
I made a draft PR and moved on. Later, the designer pinged me with the final version of the UI. He made some good improvements. When I had a closer look at the Figma, I noticed that he moved one of the buttons to the left side of the form.
One of the file types allowed recording a short GIF before saving. In the rough designs, the record button was on the side of the component that was managed by the subcomponents in the code. Moving the button to the left meant the form had to be aware that the subcomponents could optionally record GIFs. And just like that, my little abstraction broke into a thousand pieces.
I pushed back, but honestly, I knew that he was right. The button made a lot more sense on the left. It was on the right side just because the design was unfinished at the time. He wasn't thinking about it.
As for me, I briefly considered taking out the big guns...
.button {
position: relative;
left: -30px;
top: 21px;
}
In the end, I had to restructure the whole thing and make the form aware of what the subcomponents were doing. It would become too convoluted otherwise. Moving the button took me about as long as to implement the dialog from scratch.
Lessons Learned
Changes in requirements/designs don't translate linearly into implementation. How difficult can it be to move a button? Well, that depends...
The problem is that it's non-linear in unexpected ways. It takes about 0.4223 seconds to move a button in Figma. Someone not familiar with the codebase will expect it will take a proportionate amount of time to do it in the code. Often, that's true. Occasionally, it's not true at all.
It works the other way around too. Sometimes, you can turn around complex work surprisingly fast. Maybe you've been diligently building a design system and a library of reusable components. The next time a product manager asks you to build a huge, complicated UI, you cash in on all that effort and get it done in record time.
Or maybe someone else had that exact problem before, and they built an open-source library that solves it. You're done after two hours of duct tape engineering, feeling like you should be asking for a raise.
Embrace the Uncertainty
The problem is that things like that are unpredictable from the outside. Unless you've analysed the work to a point where you pretty much know which lines in the code will have to change, you're dealing with some degree of risk.
In this scenario, the risk I took was to start working on an unfinished design. It could've gone either way.
It depends on what level of risk is appropriate in your situation and what you're comfortable with. In this case, it was just a save dialog. Although it was annoying having to redo it, it wasn't the end of the world. Larger decisions warrant more certainty.
Sometimes, you might be trying to predict how the requirements might change and accommodate those cases in advance. Again, that might turn out to be a smart idea. I've also seen some grave over-engineering when people tried to outsmart the spec.
Estimates are exactly that — estimates. Whether it's a formal estimate for a task or just your colleague wondering why is it taking you days to move a button 30px to the left.
Depending on the amount of risk you're looking for, you might be tempted to add more process. Have the developers do the estimates themselves. Set expectations, keep people accountable. Look for anomalies in burndown charts. That sort of thing.
However, making something less unpredictable doesn't make it predictable. Trying to get 'accurate estimates' just gives you a false sense of security. They'll be accurate until they aren't.
Anytime a software project is delayed for years, I assume their process involved having people give 'accurate estimates'.
I work at a small company which affects how I think about these things. I'm not saying that it's never worth reducing risk. But when you do it, you have to acknowledge the uncertainty. Only then you can have a productive conversation about how long the project will take.
Computers may be deterministic, but the process of building software really isn't.
Top comments (0)