I spend the majority of my day writing, through usually on Teams or Slack rather than a blog. Occasionally I’ll turn one of these threads into something more refined and post it here.

Josh Black Josh Black

Designing like an Engineer

Listen carefully, scope your goal, then test your solution

Designers and Engineers have a lot in common, they’re cut from the same cloth. They’re quite close family but they’re definitely good friends - they share the same interests and their approaches to work are almost identical. 

Regardless if you’re an illustrator working on a new marketing campaign for a startup or a java programmer building a trading pipeline for a bank, projects and pitches usually begin with a kickoff meeting with your new client. Beyond the initial ‘vibe check’ to figure out if you’ll both get along and be able to deliver good work, your objective in this session is to be a spy. By this I don’t mean steal their secrets and sell them to the competition next door - your goal is to listen beyond what your client is asking you to do and figure out what they actually want. Some clients are incredibly clear and know exactly what they want down to a tee, but in my experience most are juggling a mix of desired outcome, timelines, politics & budgets and they’re asking for the benefit of your experience to figure out whats practical. Listen carefully, ask open-ended questions, then gather and distill that information so you can walk away with enough to design an effective solution. 

To do this, you need to do a few things:

  1. Diagnose the Problem — What’s the challenge you need to tackle?

  2. Distill the Goal — What is it? What will it do? How will we tell if it worked?

  3. Define the Scope — Define what it can and can’t be.

  4. (Optionally) Iterate — Try it out and adapt.


By running through these things, your design process will be hyper-focused, and you won’t waste time chasing bad ideas.

1. Diagnose the Problem

Most often, clients are experts in their own domain but they need assistance to convert that expertise into a product. A chef may have a Michelin star but they’ll still need an industrial designer to bring out their own line of cookware. This is why you’re here, you’re equal parts translator and builder, you bring the how to their what.

Whats the challenge you want to tackle?

Both design and engineering are problem-solving. With every project, you’ll have a set of challenges you’ll need to surface and address for your client. After all, that’s what they’re paying for. Here’s what you need to know to diagnose the problem you’re trying to solve: the who, how, and what.

Who is the Target Audience (The User) and why is this important to them? Why do they care?

Its rare that your client has just one user in mind, usually there’re a few with potentially competing interests and objectives, and targeting all of them can make a project needlessly complex for diminishing return. Work with your client to identify the top three kinds of users and prioritize the most important one - what will give you the biggest bang for your buck.


What does this project need to communicate? How should the audience feel after?

If there are too many objectives in play, prioritize and define the hierarchy with them. This will be like pulling teeth, but its necessary and demonstrates that you’re a partner in the project - rather than just pushing pixels or writing lines of code, you’re collaborating with your client to provide clarity.


Now you have an objective, how will it be executed? In what context? What part of the sales cycle is the user?

Depending on the context, a user or potential customer will engage with your solution in a different way. Is this a new customer and you’re working on a YouTube pre-roll ad? You need to hook them in 5 seconds or they’ll skip. Are they existing customers and you need to demonstrate you’re listening to their feedback? You can take your time and ship features they’ve asked for. I’ve often seen this in action at hackdays and game jams - a project could be technically impressive but not very flashy and would be judged less favorably than something with more visual panache.

Its important to pay attention to the sales cycle here too. Depending on what stage the customer is in, they’ll have different needs and intentions. If it’s early in the sales cycle — they need to be made aware. If it’s late– they’re ready to buy.


Now you’ve explored who the customer is, what you’re trying to do for them and broadly how you’re going to do it, you’ve identified your challenge. That probably took a lot of discussion - time to refine those conversations down into a goal.

2. Distill the Goal

Once you’ve got an idea of the problem your client wants to solve, the next job is to distill that conversation into a goal - a north star that everyone can agree on regardless of expertise.

If you ask a client “whats your goal?” without first discussing the problem they’re actually trying to solve you’ll find they’re quick to give you a goal, and that goal is almost always not the best way to tackle the challenge. 

Most people, myself included, are prone to solution-izing - using their own domain expertise to try to solve a problem in another domain. To give credit due credit sometimes these solutions are great. I’ve been pleasantly surprised more than once at how good doctors are at solving mechanical engineering problems (I suppose we’re just different kinds of machines). Far more often though these solutions fall short. Instinctively an experienced designer or engineer will have a quick internal-giggle at the proposed solution, but hear your client out - while their solution might be terrible they’ve encoded a lot of subtext into it about whats important to them. Deconstruct it, then help them prioritize what they want and give guidance on the tradeoffs.

Your goal should be one sentence that everyone can agree on, more than one sentence and the interpretation gets fuzzy leading to equally fuzzy solutions. It should not only include the deliverable outcome (the thing your client is ultimately paying you for), but also the main reason you’re undertaking the project, and some way to measure how successful you were at achieving that goal. Often goals will have a time component, but they don’t always have to.

Your goal should follow: “This <X> will <Y> so we can <Z>”


A couple of examples from projects I’ve worked on:

“This chat widget will let customers talk to us directly so we can get product feedback faster”

“This teaser will announce our new game at E3 so we can build hype for release next year”

“This keypad should be quick to release so we can test the waters in the desk accessories market”

Now you’re all on the same page about your goal and how to measure success, you’re likely already figuring out a plan in your head before the meetings even finished. Hold that energy, there’s one last step.

3. Define the Scope

Problem-solving & design thinking take a lot of time and effort. Even if you’ve identified the challenge you’re taking on and agreed the goal you’re all working towards, its easy to spin your wheels exploring solutions in an unbounded problem space. You’ll save a huge amount of time and effort by narrowing the possibilities of what’s valuable to explore before you begin. Its a balancing act, but you’ll spend less time theorizing about problems a client may have in the future and can focus the solution they need now.

So how do you filter out possible solutions? There are a few key questions you can ask:

  • What the boundaries we need to work within?

  • What are the absolute no-gos?

  • What can it look like?

  • What can it sound like?

  • What should it feel like?

As before when discussing the goal with your client, things will get tricky here and you’ll need to look out for coded language; words like “Modern”, “Efficient” or the perennial “Magical”. These are words that have a lot of room for subjective interpretation, “Modern” to a coder working on AI tools is worlds apart from what a potter making fine tableware thinks of as modern. Get specific with examples and break it down into simple language.

A client who wants their mobile app project to be “Efficient” could mean that they want it to be technically efficient, a very small download that uses little memory and gets the job done quickly. Equally, they could be switching “efficient” for “responsive” aiming for an app that feels very quick to use, so adding fast animations to make the app feel quicker with the tradeoff of a larger app install size might be the way to go.

Again, use your detective skills, if an answer doesn’t feel like the full picture, dig a little deeper into the wording. Your whole goal might change, but its worth finding that out now rather than a year into a project.

4. (Optionally) Iterate

One of the best ways to figure out if your solution is a good one is by actually trying it out. 

This is pretty common in the tech and advertising worlds, building an “MVP” and iterating based on feedback or running many campaign variants to figure out whats landing best. This it can be a lot tricker when you’re dealing with physical products and minimum order quantities though. 

Iterating doesn’t always have to mean shipping to customers, you can often do it internally even if you’re dealing with physical products - you’ll see this often at product companies like Apple or Ikea before they ship at scale. The key is to build a version of the project that fulfills all of the criteria you set out in your goal, then use the last part of your goal to measure its effectiveness and use the feedback to make another attempt. 

Speed is the important factor - the goal and type of project you’re working on will dictate what you’re able to change to enable you to iterate quickly. Sometimes this can mean sacrificing fit-and-finish producing a lower fidelity version of the product to test functionality, something that still fulfills your goal but perhaps isn’t as elegant. Other times this might be a much more refined version of the product with a lot of attention paid to how it feels to use, but lacking functionality (an experience prototype vs. a service prototype). Each give valuable information that will help you and your client refine the solution further, potentially leading to a follow-up project. 

Review

You now have the essential building blocks to create an effective solution. Let’s quickly review the key steps:

  1. Diagnose the Problem — What’s the challenge you need to tackle?

  2. Distill the Goal — What is it? What will it do? How will we tell if it worked?

  3. Define the Scope — Define what it can and can’t be.

  4. (Optionally) Iterate — Try it out and adapt.

With these things established, you now have a clear, narrow target to hit when you begin designing. This is the blueprint for you and your team to follow, something you all agree with, a banner for you to work under and measure your success. The goal should drive everything you create and should be filtered by the criteria you’ve collectively established.

Read More
Josh Black Josh Black

Debates and Arguments

What to do when an unstoppable force meets an immovable object in a technical discussion

A colleague of mine recently suggested building a new service as a Lambda function rather than the traditional stateful service the company would normally build. As is usually the case when a new tool is put forward to the group, there’ll be a few strong opinions to the pro, a few strong opinions to the con, with the rest of the team with no strong opinion either way waiting to swayed to one side or the other.

This is not uncommon for most of the teams I’ve worked with, its rare for an engineering team to be always totally of the same mind about new tools and a bit of debate is healthy for a project. Whats also unfortunately common though is when two strong opinions lock horns in a seemingly intractable way - unstoppable force meets immovable object, with a mix of bored and slightly uncomfortable developers waiting for the dust to settle. There’s a subtle art to nudging calls like this back to being useful discussion and away from battles of tech ideology.

Find the problem

The first step is to break down the argument into problems and solutions. Ask “What problems does this tool solve for us?”. “Why should we use a Lambda function when we usually spin up an EC2 instance to run a java service?”.

This feels obvious of course, but the act of listing the problems a tool purports to solve and the problems a team believes it has highlights disagreement in a team about what the problems actually are. Sometimes I’ll try to introduce a tool to solve a theoretical problem that doesn’t exist yet, other times I’ll be ignorant of a major problem the team has and dismiss a tool as over-engineering. Am I introducing a Lambda function because I’m optimizing for bursts of simple requests at peak times with no load the rest of the day? Does my colleague believe I’m trying to build a service to handle a constant load with stateful data?

In these disagreements is often hidden the reason behind strong like or dislike of a tool by developers who are otherwise generally in agreement. Each are trying to choose a tool to solve a problem as best they can, but they’re solving fundamentally different problems without realizing it - the tool solves one of these problems well and another poorly. Once everyone’s on the same page about the problem you’re trying to solve, you can have a productive discussion about tools to solve that problem.


“I just need something quick to grab data from Dynamo and serve back to the dashboard a couple of times a day, It feels wasteful to leave a service idling 90% of the time”.

Problems you can’t measure

Developers are almost always predisposed to think in terms of technical first-order effects of tools - size, speed, amount of boilerplate code. This is natural, they’re easy to measure and progress feels more tangible when it can be quantified, even if more meaningful changes aren’t as easily charted. Its common for example to track a metric like “unit test line coverage” to gauge how good your automated testing is rather than asking “do these tests make you confident - would you be stressed if we released this with no manual testing?” - the latter is usually a much better indicator. 

The benefits of many tools are in the less-technical or even the non-technical second-order effects. Does choosing this tool make hiring easier? Do other engineers in the org already use this tool? Is it better to build something perfect in-house and risk it being orphaned when engineers leave the organization, or go off-the-shelf and risk the tool a product is built around becoming abandonware?


“A Java service does make sense, but we lost most of our Java devs in the layoff, if we do small Lambda functions we could have the Javascript and Ruby devs help with backend services”

Not all experience is equal

Once you’ve gathered your list of the problems the team face and the problems the tool might solve, move on to asking “How well does the tool solve our problems?”.  Tools often shine on a handful of these problems and leave much to be desired on others. This isn’t necessarily a reason to dismiss the tool out of hand, but neither is it a reason to adopt it. 

This is the second area where objections tend to get shaken out. A developer may have had a really poor experience with a tool and believe the drawbacks they faced weren’t worth the benefits on another project. How a tool is used is just as important as the choice of tool itself - seeing a tool used badly on a project makes it all to easy to discount using it again on another totally different project. Most people loathe Jira, but typically its because its being used badly, not because Jira itself is objectively bad.


“I had to do Lambda at my last company, yeah its cheap and it scales well but it was so slow, we were getting 10 second response times to requests!”

Tabs or spaces

If you’re paying close attention, there’s also chance to discover differences of opinion on what developers find painful here - one developer may prize terseness of code, where another cares more about readability, so a tool introducing a lot of boilerplate code will be the bane of one engineer and only a mild inconvenience to another. 

List these opinions regardless of if people agree terse code is better or worse. Its easy to be drawn off-track here, the objective is simply to record these opinions not agree on them, nows not the time to decide once and for all if tabs are better than spaces.


“James likes that we could have many tiny single-responsibility functions and we could write them in multiple languages, Dan thinks its better to have one bigger service to enforce Java as our primary language even if we’re short on Java devs right now.”

The alternatives

Finally, once the preceding questions are answered, move onto finding alternatives with extreme prejudice. This may feel needlessly hostile to the proponent of the tool, but they should also participate in this exercise too. Often I’ll suggest a tool because I think it’d solve a problem perfectly, but after peeling away many layers of post-rationalization I realize its because I just really enjoyed using it, and that there’s a better choice thats just less fun. Once you get into the habit of this, there’s almost a perverse sense of pride in trying to rip your own idea to shreds to see if theres a better choice lurking.


“We’ve got another Java service that handles data from that Dynamo DB, couldn’t we just extend that, rather than creating a new service or using Lambda functions?”

ADRs are your friend

The important thing with all of these steps is to do it in the open and in good faith, embrace loud opinions but don’t let them soak up the whole meeting - make them feel heard, record them, then bring the discussion back to the questions above. Oh and - document it, it doesn’t need to be war and peace lost forever to the Confluence black hole, but recording a quick ADR in your repo with the reasoning and the alternatives is great for team members who weren’t lucky enough to get the live performance. 

Its been my experience that even if they don’t really like a tool, a developer who at least understands the reasoning behind why it was chosen will embrace it much moreso than one who doesn’t. Instead of complaints at every retro and gentle acts sabotage, they redirect their energy productively into finding a better alternative to the benefit of the entire team. Give them space to do this - usually the best way to convince someone that their pet theory won’t work is letting them try it and convince themselves instead. And if they were right, even better, you’ve just found a better solution to the problem - win-win.

Read More
Josh Black Josh Black

The Long Road is the shortest route

Why “wasted work” isn’t always wasted time for a team

Years ago Ruby on Rails was all the rage - anybody who was anybody was talking about using it, or founding some startup or another with it. I’d been doing a lot of freelance work and hackdays so being able to spin something up quickly that could stand up in production was attractive. So too was being a part of the in-crowd of rails devs who seemed to know where all the exciting work was at. 

My first experience of sitting down to learn Rails was terrible. I got a couple of chapters through “The Rails 3 Way” before feeling an almost magnetic repulsion from it. This wasn’t a reflection on the excellent book - the further I got the more Rails felt like magic, and not the good kind. I had very little understanding of what was being done and to what end. It was a feeling not unlike being blindfolded and arriving at a destination with no knowledge of exactly where I was or how I got there, other than hearing the ocean somewhere on the way.

This lack of understanding turned quickly to dislike, which turned to objection and finally dismissal of Rails as bullshit. It must be, I reasoned, one of those hype frameworks I’d been warned about, all mouth and no trousers. This is a distressingly easy argument to make from a position of little understanding, and makes for easy dismissal of future advocates as foolish, having already personally determined it to be a waste of time.

I settled on Sinatra as an alternative and quickly became enamored. In contrast to Rails, Sinatra felt like I was in control of the machine, I could see the oil temperature fine-tune things to keep it humming along. I built a great number of projects with Sinatra, picking up additional tools and reusing code for common tasks like user management, routing and auth, and found myself quite naturally falling into an MVC pattern without a solid understanding of what an MVC pattern actually was.

It was about this time a freelance project had me looking at Ruby on Rails again, and it made a disconcerting amount more sense. Implementation that would’ve taken half a day in my Sinatra bootstrap project took an hour in Rails. Enjoyment slowly replaced the disorientation I’d felt before, so much so that I began using it to bootstrap hackday projects. It was a gift, like I’d fallen in love with an enemy.


Why the about-face? Rails had remained largely unchanged, the projects I was working on were similar. The primary difference was my understanding of exactly what problems Rails was meant to solve. In the beginning Rails was a sledgehammer to crack a walnut, a much more unwieldy tool than I needed, dismissing it was the correct course. But over time as the nature of my problems changed, cracking 1000 walnuts a minute rather than one a day, Rails looked much more reasonable a tool. I had to experience those problems before I had an appreciation for the ease Rails afforded me, to take the long road there before taking the highway back. 

I’ve come across similar problems with teams frequently as a contract engineer. With the benefit of experience it’s easy for myself or a colleague to put forward a tool, but nonetheless find general disagreement from the rest of a team. Telling a skeptical team why a tool is great is seldom an argument winner and, time permitting, I’ve found it to be a valuable exercise to let the team go down what you believe to be the wrong road for a while. 

Given time to see where this route leads, it either transpires the team were right and you simply backed the wrong horse, or more often, a team begin to feel the pain of the problems the tool you suggested solves, changing their mind about the tool in the process. 

First-hand experience is generally more powerful than vicarious experience. While on the surface its more time-efficient to tell engineers why something is better, taking the time to allow a team to feel the pain and understand it pays dividends in the long run - if not in your own organization than in neighboring ones. And in the cases where you’re wrong? All the better, the team has gained a superior tool to tackle a problem and you’ve learned a better way to solve the problem - nobody’s right about everything.

Read More