What’s software design? It’s about making technology easier and more valuable for people to use. Professional software designers do far more than “make software pretty.” They make sure that software works for people. They lead the development team in:
- Understanding the needs of the users
- Creating prototypes and testing them with users
- Deciding how the software will look and act
It’s an incredibly valuable skill set.
Working with a software designer throughout your project (not just at the end) can lead to better products.
What does software design look like?
This process can be hard to picture. So to illustrate, let’s take inspiration from Disney’s movie Moana. It’s about a young girl who will someday succeed her father as village leader. Unfortunately, her people are having a harder and harder time finding fish—their largest source of food. Let’s say Moana has an idea for a mobile app…
Moana is imagining a tool that will help her track the best fishing grounds. When her people catch fish, they could mark the time and location of the catch on a map. This record would help them understand when to move on to new fishing grounds. And it would help Moana track how much fish is being collected over time, so she would know when it’s time to train more fisherman.
The threat of running out of food is real. Moana needs a way to get ahead of demand in order to keep her village thriving. But how does she get started?
That’s a well-defined problem and a clear use case. But as always, there are a lot of unknowns between the idea and a piece of working software. To see how it might work, let’s follow this example through the software design steps I listed above.
1. Understand the needs of users.
We could jump right into designing interfaces. But we would be making a mountain of assumptions about how users will actually use the app and what features they’ll need. We might waste a lot of time and money creating something no one really needs.
Instead, software design starts by listening and observing. We visit our users in their environment—watching the actions, routines, and workarounds that have become part of their job.
In our example scenario, we have two main user types:
- The fishermen, who will record the what, where, and when of their catches
- Moana, our data analyst, who will use the information collected to make decisions for the village
As it’s imagined right now, the app would benefit Moana the most. Unfortunately, if the fishermen don’t find it helpful, they won’t use it. And the project will be a bust. Perhaps there is a feature fishermen would love to have. So we’ll talk with them—learning how they decide where to fish and what they’ve learned about fishing over the years.
When we do this research, we learn that when fishermen catch certain kinds of predatory fish, they know that the rest of the fish have moved away. So we might add a feature to note where predatory fish are found and recommend new areas to fish based on this information.
By getting a first-hand look at the needs of users and the environment where they will use the software, we learn what really matters to our audience. Then we can design with those scenarios and people in mind throughout the project.
This type of research-in-context yields valuable insights time and time again. On some projects, it helps us discover new features that are more relevant to the user than anything our team would have envisioned.
2. Create prototypes and test them with users.
Now we begin to put pencil to paper. We start with low-fidelity skeleton models of the interface, using simple shapes like rectangles, lines, and circles to represent images, text, and buttons. There are no colors, fonts, or branding applied at this point. We delay those decisions so we can move fast and learn what works and what doesn’t.
Prototypes also help us answer questions like:
- What information should be at the top of the page vs. the bottom?
- How would the user move through the application from one feature to the next?
- How do users react to our ideas? What’s working for them, and what needs improvement?
It’s time to go back to Moana and a few fishermen (to get multiple perspectives) with our prototype. We might do a think-aloud exercise, setting an interface on the table and giving the fisherman a scenario to talk through. We might say, “Show me how you would use this app to decide where to fish today.” They would tell us what they’re thinking and where they would click, which introduces the next wireframe, and so on.
Involving users early gives us incredibly valuable feedback—which we use to create another, better prototype. And the process repeats. This way of working (research, try some things, ask for feedback) gets us beyond one person’s preference. It keeps us focused on the things most important to the users.
3. Decide how the software will look and act.
Now that we’ve narrowed down our options and validated a direction with users, we can make it real.
Interface & interaction design
Building on our research, new insights, and user feedback, we turn the prototype into a detailed set of interface designs for each screen of the application. The goal is to make a complex process feel like a simple user experience. Throughout this step, we work closely with the development team to make sure our designs are feasible to build.
Visual design
Next, we create the brand and visual design for the application, developing the color palette, typography, tone of voice, illustrations, etc. Most companies we work with at Atomic have an established brand (a set of guidelines and design constraints to guide our work).
We’ll also create a style guide that describes the commonly-used patterns and elements of the design. For example:
- Interface patterns can help users understand the hierarchy of the software. For example, primary call-to-action buttons might be a bold color, while secondary call-to-action buttons use a lighter color or an outlined button.
- Experience patterns can create predictable responses to user actions. For example, an entire table should be clickable, not just the text in a single row.
Future software designers can use this guide to create new pages or features in a way that keeps the app’s visual design consistent.
Artifacts for the development team
Finally, as we finish designs, we share them with the developers to serve as a blueprint for the software they will build.
In some cases, we’ll continue testing these designs. As custom software projects are often long-term engagements with many milestones, it’s common to continue adding features and functionality which will also need to be prototyped, designed, and tested. This is what software designers do during the development phase of the project.
Why Is Software Design Important?
A user-centric approach to software design doesn’t begin with visualizing anything. It starts with understanding people and what they need. And that work is never done. Software continually evolves to adapt to the needs of our users and shifts in technology.
Moana asked for a fishing app that would help her and the fishermen in her village track where they were catching fish. By talking to fishermen, we found ways to make the app a valuable asset for them as well. We adapted our plan because it meant delivering a better product that worked for people.
Having a UX/UI designer as part of the software creation team can help anticipate what’s next and prioritize what’s needed. The result is a software application designed and built with purpose, backed by buy-in from its users, and supported by a plan for continuous improvement.
It’s unfortunate that we have so many names for what I think of UX design. For simplicity, I include UI in that term.
When I saw “software design” in the title, I was hoping for something on code design and/or software architecture, because that is something just as important but very neglected.
As a consultant, I see the same “design patterns” over and over again. I see code not describing the underlying domain, where database constructs or models from third party apis leaking through the code base all the way to the end user. I can’t imagine why code like this is the norm, other than we as a profession code by accident.
We don’t take the time to learn the domain, and then design our code to be practical in term of self documentation, ease of use, and maintenance. We don’t take advantages of well known techniques, architectures and patterns because we always think: This is simple, all we need is CRUD. While we forget things are only easy until we get the complete picture.
The following is way of topic for this article, but software developers (coders) know:
– There is only one persistence system that doesn’t loose data. That’s event sourcing. Which also takes away the persistence impedance mismatch. But we still insists on storing nothing but the latest snapshot of our state.
– Read and write support different needs. That’s why CQRS is a thing. But we don’t get much of it until we separate read and write into different models. Still, we insist on using the same model for everything, and think queries with a dozen joins is good.
– Explicit communication is better than implicit. But still we write code where absence of data means one specific thing. Or when combination of data means something special. Like always counting all orders over a specific amount to determine if someone is a “golden customer” instead of storing that information explicit.
– Related to event sourcing and CQRS (and Domain Driven Design), designing our domain objects around concepts of commands and events, gives us code where behavior is easy to test: A given command for a certain state should produce certain events. If idempotency is a thing, apply the same command twice and assert no events after the second one.
Sorry for the rant.