How to Think About the Problem Before Thinking About the Solution
Part Two of the Series: Building the Right Software Systems
"If I had an hour to solve a problem, I'd spend 55 minutes understanding the problem and 5 minutes thinking about the solution."
— A quote commonly attributed to Albert Einstein
One of the most common mistakes in software development is that teams start discussing solutions before they truly understand the problem. The team gathers, the code editor is opened, and the usual questions begin:
- Should we use Microservices?
- Do we need Redis?
- Is GraphQL better than REST?
- Should we build it with .NET or Laravel?
But there's a far more important question that often goes unasked:
What problem are we actually trying to solve?
If the answer isn't clear, the quality of the solution won't matter much, because you might end up building an excellent system... for the wrong problem.
Don't Fall in Love with the Solution
Many engineers fall into a dangerous trap: becoming attached to a particular solution before understanding the problem. One engineer is excited about Event Sourcing. Another wants Kubernetes. A third believes Microservices are the answer to everything. But technology is not the goal, it's simply a tool.
There is no universally good or bad tool. There are only tools that are appropriate for a particular context.
A good engineer doesn't begin by asking: "Which technology should I use?"
Instead, they ask: "What does this project actually need?"
Understand the Business Before You Write Code
Software is never the end goal. It is a means to help a business, an organization, a team, or an individual accomplish their work more effectively. Before designing the database or writing your first API, ask yourself:
- What is the user trying to accomplish?
- What problem are they facing today?
- Why do they need this system?
- What would success look like for them?
Every line of code should have a business reason behind it—not simply because it seems like a good idea.
Don't Start with the Database
A common mistake is making database design the very first step of a project: Orders, Users, Products, Invoices etc.
The team then starts defining relationships between these tables. But are we even sure these are the right entities? Maybe not. Because we still haven't understood the problem.
Instead, begin by understanding the business processes inside the system.
- How does an order begin?
- Who approves it?
- When is it considered complete?
- When can it be canceled?
- What are its different states?
Once you understand the workflow, the database becomes a natural outcome—not the starting point.
Think About Workflows, Not Screens
Many projects are designed around screens:
- Login screen
- Products screen
- Orders screen
- Reports screen
But users don't think in terms of screens. They think about the task they're trying to accomplish. Take an online store as an example.
A user doesn't think:
"I'll go to the checkout screen."
They think:
"I want to buy this product."
The difference seems small, but it completely changes how you design the system.
Write the Scenario Before Writing the Code
Before development begins, try writing the user's journey.
For example:
- The customer visits the website.
- They select a product.
- They add it to the shopping cart.
- They choose a payment method.
- Inventory is verified.
- The order is created.
- A confirmation message is sent.
Notice that we haven't written a single line of code. Yet we already understand the system much better. Writing scenarios often exposes gaps that would otherwise remain hidden until implementation.
Don't Design Only for the Happy Path
The happy path is the easiest part. But real systems don't operate under perfect conditions. Ask yourself:
- What if the payment fails?
- What if the product goes out of stock during checkout?
- What if the connection is lost?
- What if the user submits the same request twice?
- What if the customer cancels the order after payment?
These are the questions that distinguish a mature system from one that only works when everything goes as expected.
Don't Try to Predict the Entire Future
On the other hand, there's another common mistake. Some teams try to design a system capable of solving every problem that might appear over the next ten years. As a result, the architecture becomes unnecessarily complicated from day one. That's also a mistake.
The goal isn't to build a system for every possible scenario. The goal is to build a system that can adapt as requirements change. There's a big difference between:
- A flexible design.
- An overly complex design driven by fear of the future.
Ask "Why?" More Than Once
When a customer requests a new feature, don't stop at what they ask for.
Ask: Why?
Suppose they say: "I need an Export Data button."
Ask: Why?
They might answer: "Because the accountant needs it."
Ask again: Why?
"Because they send a weekly report."
Ask once more: Why?
"Because the system doesn't display the report in the format they need."
Suddenly, you discover that the real problem isn't exporting data. It's how reports are presented.
Had you implemented the original request immediately, you would have treated the symptom instead of solving the underlying problem.
Technology Changes... The Problem Remains
Ten years ago, there were technologies that were considered the future of the industry. Today, some have disappeared. Others have changed completely. Ten years from now, the same thing will happen again. But the right way of thinking will remain unchanged. Invest more time in understanding problems than in memorizing tools.
An engineer who understands problems can learn any technology. An engineer who only memorizes technologies loses value every time the industry changes.
Practical Guidelines
Before writing the first line of code, always ask yourself:
- Do I truly understand the problem?
- Do I know who the user is?
- Do I know what success looks like?
- Do I fully understand the business workflow?
- Have I considered unexpected scenarios?
- Am I building what the business needs—or what I simply want to experiment with?
If you can't confidently answer these questions, it's too early to start coding.
Conclusion
The best engineers are not those who write code the fastest. They are the ones who spend enough time understanding the problem before choosing a solution. Every architectural decision, every database design, and every API should be the reflection of a well-understood problem—not simply a showcase for the latest technology.
In the next article, we'll move to the next step after understanding the problem: how to divide a system into clear components with well-defined responsibilities. Because the quality of a system depends not only on what it does, but also on how it is organized internally.



