We've all built features that looked great on paper but made zero sense once people tried them. That's what happens when we forget to "touch grass" - when we don't pause to see how our work fits into a user's real-world context. Always remember, it's easy to optimize for code. It's harder to optimize for people. Here are 4 short lessons for engineers:
1. Systems influence human behaviour (and vice versa)
How users interact with mobile apps, websites and desktop applications has been shaped by countless apps they’ve used before. These can be subtle or very obvious. For example, when a user hovers over a text and sees the cursor turning into a hand icon (☝🏾), the color changes and the text getting underlined, what’s the next action to expect? You guessed right! They click the text. It’s a subtle way browser conventions and websites for decades has shaped the users behavior. People don’t read, they scan and assume — your application shouldn’t be cognitively heavy for users lest they get frustruated. There are several tactics to go about producing a better experience for your users. You can explore concepts around progressive overload, nudges and friction, and intelligent defaults.
For applications in the same niche (eg. social media apps) there’s a “Most Advanced yet Acceptable principle” which states — “if you go too far from a user’s past experience, they reject it”. Ever wondered why the ♥️ is now the default icon for liking a post / comment / video? Now you do.
2. Users interact with your software based on past experiences with other software
Following up on the previous topic, it would do you some good to understand existing / older applications before trying to replace them. Lets step into product design for a bit. Have you ever used a faucet you’re not familiar with? You’re puzzled for a few seconds wondering “Is there a motion sensor?”, “Do I push or press the knob?”, “Do I turn it left?.. no right”, “What do I do?” . You were basically trying to figure out how it works based on past experiences with other faucets.
In software engineering, you can’t tell what experiences your user has had. It’s likely the user might have interacted with software that had poor UX and they’d begin to use yours with that same mental model. There’s a subtle consistency heuristic in the mind of the user — it worked like that before, it should work like that now.
Therefore, great design and software should anticipate misunderstanding and clarify them beforehand, it should embrace user assumptions and guide their behaviour without demanding attention. At the core, your job is to align the software with their brain — that includes whatever biases they have.
For example, if from an old system users clicked dashboard cards (with no clear click indicator) to route to a page with more details, you have to embrace it but with a cleaner approach; include a “View more →” button to your dashboard cards so that the users behave the same way without friction.
3. Know your softwares’ non-negotiables
Not all software features are the same. Understand how your organization’s teams work deeply to prioritize the features they need to. For example, an audit trail or a change history is crucial for teams that work on a same piece of data. It has to be clear who worked on what, when they did and what they did.
Roles and Permissions management is another non-negotiable feature in many enterprise software.
Some non-negotiable features that span across lots of domains include notifications (realtime or delayed), reporting, exporting data, searching and sorting data, analytics dashboards and authentication (authorization as well).
4. Configurability versus Logic
When building software systems for teams, you can’t have 100% team configurability. How do you decouple core logic from team-level configurability without everything becoming a mess? Where do you draw the line?
Expose flexibility where it matters. Enforce logic where it matters more.
The goal is not the let teams configure everything, but to design systems that:
- Expose a limited safe area for configuration
- Keep business-critical logic centralized and governed.
- Allow teams to customize shape of processes but you enforce movement and integrity of the processes.
⚡ Example: Expense Approval Workflow System
Imagine you’re building a company-wide expense approval system for a SaaS product.
Core logic (non-negotiable across all teams):
- Every expense must have an owner (user).
- Expenses above a certain threshold must go through at least one approval.
- Approval must be tracked with timestamp + approver identity.
- These rules ensure compliance, auditability, and system consistency.
Team-level configurability (per department):
- Marketing wants expenses auto-approved if under $100.
- Engineering wants a two-step approval for expenses above $1000.
- HR wants receipts required for any expense, no matter the amount.