Software engineering culture: mindset, teams, and action

Published: (December 22, 2025 at 05:24 PM EST)
10 min read
Source: Dev.to

Source: Dev.to

The mindset difference

A pattern I’ve seen across engineering teams: certain engineers deliver multiples more value. The multiplier isn’t in the features they ship; it’s in how their work compounds—making future development easier for other contributors, improving overall quality, and preparing the codebase for future needs.

When I recently came across the term “10x engineer,” it resonated with my experience, though not in the way the term is commonly discussed. The multiplier isn’t about lines of code or features shipped. It’s about the cumulative effect of fewer bugs, maintainable code, and solutions that serve the team long after the initial commit.

  • An engineer implements a capability as a reusable library rather than a one‑off solution.
  • Someone builds a more generic implementation that others can extend later.

These contributions are often subtle to non‑technical stakeholders—who frequently end up in management positions—but fairly obvious to other engineers who think similarly. The real differentiator is how these engineers make their whole team more effective.

Anticipation as a core skill

In my experience, anticipation is the key differentiator. It means foreseeing bugs, future needs, usage patterns, and performance bottlenecks, and coding accordingly—not just to improve one’s own output but for other engineers working on the same codebase. For some engineers, this becomes intuition rather than a checklist.

What anticipation looks like in practice

  • Configuration foresight – An engineer sees a pattern that will likely need to support multiple environments. Instead of hard‑coding values, they design the configuration structure to accommodate that from the start, not because a requirement exists, but because experience suggests it will.
  • Rich error handling – Another engineer implements error handling that captures enough context to debug production issues, because they’ve been on the other end of vague error messages at 2 a.m.

Anticipatory thinking also extends to consumer needs. When writing documentation or tutorials, engineers who excel at this consider what their readers already know and what they don’t, adjusting the level of detail accordingly. They anticipate the questions someone will have before they ask them.

Code‑level anticipation

  • Intent‑communicating names – Variable names that clarify purpose.
  • Granular functions – Functions broken down in ways that make the next change obvious.
  • Why‑focused comments – Comments that explain why a decision was made, not just what the code does.

These aren’t cosmetic choices; they directly affect how quickly other engineers can understand, modify, and extend the code.

The cost of these subtle choices is minimal—error handling that captures context, naming that communicates intent, structures flexible enough for likely next steps. The payoff compounds over time.

Empathy and user perspective

The ability to put oneself in the shoes of the end user is important. This comes naturally to some engineers, but others need to develop it deliberately. I’ve noticed this gap doesn’t correlate with seniority; experience in one domain doesn’t automatically translate to understanding users in another. Direct interaction with users helps developers grasp confusing features and behavior, making it easier to see problems from the user’s perspective.

How empathy manifests

  • Testing error states – Not just the happy path.
  • Questioning assumptions – Asking whether a technically sound feature actually solves the user’s problem.
  • Considering edge cases – Thinking about load, flaky networks, unexpected inputs.
  • Usability checks – UI developers using their own interface as a user would, testing usability rather than merely implementing specifications.

The lack of this perspective is equally visible: features that work perfectly in development but fail in production because real‑world usage wasn’t considered; interfaces that make sense to the builder but confuse everyone else; error messages that are technically accurate but give users no path forward.

Some engineers develop empathy naturally; others need direct exposure to users and production systems. Empathy has both innate and learned components. Training can help, and the software industry generally values such initiatives. For engineers where this doesn’t come naturally, checklists and processes provide a pragmatic approach. I’ve introduced these in several teams. The checklists help, but they never cover everything—so for some, user empathy remains a deliberate effort rather than intuition.

Pride and proactivity

Having pride in one’s work and caring about what gets delivered is a mindset rather than a skill. It shows up in details:

  • Clean code – Not because someone will review it, but because it matters to the person writing it.
  • Comprehensive tests – Because the engineer cares about correctness.
  • Thoughtful documentation – (the text cuts off here, but the idea is that pride leads to thorough, helpful docs).

Being proactive rather than reactive means building in ways that make future needs easier to address, not just fixing issues when they happen. Pride in work drives the subtle, high‑impact choices that compound into a stronger engineering culture.

TL;DR

  • Anticipation = building for the future you can see.
  • Empathy = building for the user you can’t see.
  • Team structure = the framework that lets those habits scale.
  • AI can amplify all three by surfacing patterns, surfacing user pain points, and suggesting structural improvements—provided we keep the human mindset at the core.

Proactivity

Engineers with a proactive mindset don’t wait for issues to be reported. They monitor production systems, notice patterns in support tickets, and fix problems before they escalate. They refactor code that works but is fragile because they know it will cause issues later.

There’s also the opposite pattern: engineers who do exactly what’s asked—nothing more. Their code meets requirements but ignores obvious edge cases. The work is technically complete but requires constant follow‑up to actually function in production. This isn’t malicious or lazy; it’s simply a different approach to the work.

The other side of the spectrum

Some engineers have a net‑negative contribution overall. This is uncomfortable to discuss, but it’s a real phenomenon. I first noticed this pattern in teams I was part of early in my career. Back then, it felt almost taboo to acknowledge. Over the years, as I saw the pattern repeat and found others discussing the same observation, it became clearer.

Engineers who seem to deliver on the surface often hide technical debt that other engineers must fix in the background. The problems compound over time.

  • Bugs, subtle regressions, and convoluted code that take hours to understand.
  • One developer spends five hours writing unclear code; four other developers each spend ten hours trying to figure out how it works.
  • Developers waste significant time dealing with poor code quality.

The pattern is recognizable once you know what to look for:

  • Code that works initially in production but starts breaking as usage grows or edge cases emerge.
  • Code that passes review but becomes a maintenance burden weeks later.
  • Changes that fix one issue but introduce two others.

Subtle regressions

These are especially insidious:

  • A change that works for the immediate use case but breaks edge cases that were previously handled.
  • An optimization that improves one scenario but degrades others.
  • A refactoring that simplifies the code the engineer understands but makes other parts more fragile.

Because these issues often surface long after the original work, tracing the connection is difficult.

Testing and DevOps

The DevOps model, where developers write their own tests, has a downside here. When engineers lack an anticipatory perspective, they tend to write happy‑path tests that don’t cover edge cases. A dedicated QA team with fresh eyes might catch what the original author missed. The efficiency gains from integrated testing can mask this gap.

Long‑term effect

  • Code review becomes more intensive—not because standards changed, but because trust erodes.
  • What should be a straightforward feature takes longer because the foundation is unreliable.

AI as amplifier

AI‑assisted development compounds these traits.

  • Effective engineers with strong anticipation and user empathy know what to look for in generated code. They ask the right questions:

    • Does this handle the edge cases?
    • Will this be maintainable?
    • Does this actually solve the user’s problem?

    They spot when something doesn’t fit, when the generated solution misses context that wasn’t in the prompt. They use AI to move faster while maintaining the judgment that made them effective in the first place, multiplying their impact.

  • Ineffective engineers simply produce more—more code, faster, with the same blind spots. The result is code that doesn’t align with real needs, edge cases ignored, and subtle bugs introduced because generated code was accepted without critical review. The maintenance burden grows faster, leading to more debugging and regressions. The cleanup may never happen, and the team slows down: new features take longer to build on a fragile foundation.

The variance between effective and ineffective engineers widens. What was a 10× difference becomes larger, and net‑negative contribution scales faster too.

Team organization matters

Individual mindset matters, but how teams are structured determines whether those individuals can be effective. I’ve seen projects with strong engineers struggle because of how work flows between teams.

End‑to‑end ownership

What works: end‑to‑end squads responsible for delivering full capabilities or missions. A capability often spans multiple services, libraries, and products. The squad implements across all of them rather than waiting for each component team to prioritize and deliver its piece.

  • This requires engineers with curious mindsets willing to learn and adapt.
  • They work across codebases they don’t fully own, understanding enough of each component to make meaningful contributions, even if they’re not the experts.

Ownership still matters. Each component has owners—engineers who maintain long‑term responsibility, review contributions, and ensure quality. It’s similar to open‑source, where maintainers accept pull requests from contributors. The end‑to‑end squad contributes; component owners review and merge. Both roles are necessary.

Benefits:

  • Faster velocity—squads don’t wait for five different teams to schedule their piece of the work.
  • Context stays intact because the same people carry the capability from start to finish.
  • When a customer complains about a feature, the squad that built it hears the feedback directly and can adjust quickly because they understand the full picture, even across component boundaries.

The handoff problem

The alternative pattern: multiple development teams plus separate design teams. This leads to endless debates, handoff issues, and a lack of overall ownership. Each transition introduces friction, delays, and gaps in knowledge, making it harder to deliver cohesive, high‑quality solutions.

Handoff costs

  • Specifications get misinterpreted.
  • Context gets lost.

When one development team builds a component, another integrates it, and a third extends it, each handoff loses context.

  • The first team doesn’t know how their code will be used.
  • The second team doesn’t understand the original design decisions.
  • The third team inherits assumptions they can’t see.

Each handoff makes the codebase more fragile and harder to evolve. It also diffuses responsibility—when something goes wrong, finger‑pointing replaces problem‑solving. No single person or team feels accountable for the end‑to‑end outcome.

Handoff‑heavy organizations develop defensive behaviors:

  • Extensive documentation to protect themselves.
  • Meetings to coordinate.
  • Rigid processes to prevent miscommunication.

The bureaucracy is a rational response to a dysfunctional structure, but it makes the dysfunction worse.

The Debate Trap

Too many teams also means endless debates. When four development teams need to align on an approach, each has different constraints, priorities, and contexts. Discussions become about finding consensus rather than finding the best solution.

Many architectural questions don’t have clear answers in the abstract. The right choice depends on specific requirements, team skills, operational capabilities, and a dozen other factors that are hard to reason about theoretically. Building something surfaces these factors quickly.

This doesn’t mean building without thinking. It means recognizing when discussion has diminishing returns:

  • When the same points are being rehashed.
  • When debates become theoretical or religious.
  • When decisions are blocked on hypothetical future requirements.

It’s time to build something and learn from reality. Teams that shipped features while others debated usually ended up with more refined solutions, improved through actual usage rather than speculation.

Different facets of culture

Mindset, team structure, and bias toward action are different aspects of software‑engineering culture. They don’t neatly cause each other, but they’re part of the same picture. AI makes the mindset gap more visible, widening the difference between engineers who anticipate and those who don’t.

  • Some engineers bring anticipation and empathy regardless of how teams are organized.
  • Some team structures work despite individual gaps in mindset.

When teams struggle to deliver, it’s usually one of these human factors:

  1. Engineers who don’t think beyond the immediate task.
  2. Structures that diffuse responsibility.
  3. Processes that reward debate over delivery.

As AI tools become more common, these fundamentals seem to matter more than ever. Teams with strong foundations can use them to move faster without sacrificing quality. Teams without those foundations tend to just accumulate technical debt faster.

Back to Blog

Related posts

Read more »

Slowness is a virtue

Slowness is a Virtue … at least when you're doing research, not development !Jakob Schwichtenberg's avatarhttps://substackcdn.com/image/fetch/$s_!nvCe!,w_36,h_...