Cultivating a product mindset
Why engineers make better decisions when they think like product builders. A guide for engineers evolving from code-first to problem-first thinking.
As we advance in our careers, we can benefit from basing our technical decisions on a deep understanding of the problem space and fostering empathy for our users. It’s likely that in your job, there are product managers, UX researchers, and marketing professionals thinking deeply about these concerns. We can serve as better counterparts and decision-making partners when we also adopt some of the same thinking principles.
As software engineers, we start our careers driven by our curiosity for computer science and exciting technological innovation happening in our industry. The most beautiful part of developing software is the creative freedom enabled by the absence of physical constraints. In practice, however, the boundaries of software development are of economical nature. Most of the code that we write serves a business and businesses face time and financial constraints, and competing priorities. These conditions limit the amount of time that we can dedicate to implement an idea and create risks about the cost of maintaining them in the long term.
For this reason, we should weigh costs, risks, and benefits of our technical decisions. For example, what are the non obvious maintenance costs of an architectural choice? We should also focus on understanding our users and guiding our limited resources towards features that actually solve their problems. The following sections expand on a few tools that can help us with that.
Understanding of the problem space
A good problem definition describes what we aim to achieve and the hurdles that stand on the way. It helps us simplify solutions but most importantly avoid an incorrect one. Not understanding the problem is costly in any type of creative endeavor. Particularly in the beginning, we have to make decisions that are not easily reversible. For example, we could choose the wrong tech stack, design a bad architecture, or implement a feature that nobody needs.
I find two mental models to be very useful tools to improve our understanding of the problem space : First principles thinking and second order thinking. The former helps us to break down problems into essential and irreducible aspects. The latter helps us to uncover the obscure aspects of a user flow by thinking beyond the immediate consequences of their actions. The following questions turn these principles into practical tools to dissect a problem that we are solving with our software product:
Why does this problem exist in the first place?
Are we building this because it’s genuinely needed, or because “that’s how it’s done” in this domain?
What are the absolute minimum inputs and outputs this system must have?
If we were to rebuild this entire domain from scratch with today’s technology, what would we keep and what would we discard?
If we had 10× the budget, would we solve the same problem? If we had 1/10th?
What are we implicitly saying “no” to by saying “yes” to this?
What’s the second-order cost of taking the “easy” path now?
Finally, experimentation and quick iteration are good companions to deep thinking but they can’t replace it. We can always iterate quickly towards the wrong solution. That’s why it is important to treat problem understanding and solution exploration as two different phases.
User empathy and dogfooding
We spend most of our careers working on products that we don’t need. In some cases, we are lucky enough to work in products that solve a problem for us. Regardless of our current situation, it’s critical that we either use our own product or dedicate time to understand what our users do, want, think, and feel about it. There are many techniques that helps us refine our understanding of the users’ needs like creating user personas, writing use case documents, and software stories.
Using our own product is also a practical way of identifying quality issues and opportunities to improve existing workflows. In the tech industry, we call this practice “dogfooding”. Dogfooding helps us to sharpen our focus and narrow down our efforts to problems that actually affect users. It helps us to learn the language that our users use to talk about their workflows which leads to better communication with product managers and designers.
These are some of the good and bad practices that I’ve learned over the years when putting dogfooding in practice:
Identify gaps in the user documentation by identifying missing steps when performing a task with your product.
Encourage teammates to dogfood a feature that you are developing by recording a demo of the feature and broadcasting your interest in public channels.
Provide a tool to collect feedback in a single knowledge base. Ideally, this tool allows categorizing the feedback by releases and calculate different metrics.
Don’t fall into the trap of believing that our own experience is fully representative of other users which can create a false sense of confidence.
Shifting our mindset from fully technical folks to product-minded engineers helps us amplify our contributions from just building the product to also defining it. As AI-powered tools automate more steps of the software development lifecycle, the industry starts to have expectations from engineers to be able to think about a product end-to-end and wear many hats during the process. Cultivating a product mindset can help us evolve our career in this direction.


