Steven's Knowledge

Pragmatic Mindset

Habits and attitudes that make the daily practice of programming sustainable

Pragmatic Mindset

Most of the practices in this section describe what to do with code. This page describes how to think about doing it. The habits are drawn primarily from The Pragmatic Programmer, with the consistent observation that the difference between effective and ineffective engineers is rarely talent — it is mindset.

The themes recur in every engineering culture that holds up over time: take responsibility, fight entropy, learn continuously, prefer small deliberate steps to large ones.

Take Responsibility

The greatest of all weaknesses is the fear of appearing weak.

Responsibility is the foundation. The person who shipped the change owns its consequences — not the framework, not the previous developer, not the ambiguous spec. When something goes wrong, the response that matters is "what can I do about it now?"

The phrase to avoid is "the cat ate my source code" — a stand-in for any excuse that explains why the work is not done without offering a path forward. Excuses do not improve outcomes; options do.

In practice:

  • When you commit to a deadline, deliver — or escalate as soon as you know you cannot.
  • When a defect ships, fix it — and find the cause, not the blame.
  • When a system you depend on breaks, work around it; do not let your own work block on someone else's repair forever.
  • When you find yourself blaming the tools, the language, the customer, or the past — pause. The blame may be accurate; the response is still yours.

Responsibility is not perfectionism. It is the refusal to let outcomes drift just because the cause was not yours.

Fight Entropy — The Broken Window Theory

The criminologist James Q. Wilson observed that a building with one broken window, left unrepaired, soon has many. The signal that nobody cares invites further damage.

Software exhibits the same dynamic:

  • A single TODO that nobody acts on accumulates company.
  • A single hack that nobody fixes invites more hacks.
  • A single inconsistent style choice teaches the next contributor that consistency is not enforced.

The remedy is to fix the first window. A small, visible commitment to quality — addressing a TODO when you pass it, restoring a convention when you spot the deviation — sets the standard for what the next contributor will do.

The opposite is also true: the moment a team decides "we'll fix it later," later does not come. The window stays broken; another joins it.

The pragmatic discipline: when you touch code, leave it slightly better than you found it. Not "rewrite it," not "refactor everything in scope" — just one small improvement, every time. The cumulative effect over a year is substantial; the per-change cost is invisible.

Good-Enough Software

Perfectionism is a failure mode. Software that ships imperfect and is used is more valuable than software that is polished and unshipped. The Pragmatic Programmer's phrase:

Make quality a requirements issue.

What "good enough" means depends on the context — a satellite control system has different bars than a marketing landing page — but the determination is part of the job. Two failure modes:

  • Shipping below the bar. Defects that cost users, reputation, or future velocity.
  • Polishing above the bar. Time spent on quality that no one perceives, while real problems wait.

Both are unprofessional. The professional engineer knows where the bar is for the work in front of them, hits it, and moves on.

The corollary: the bar is not fixed. A prototype's bar is "demonstrates the idea." A production system's bar is much higher. A safety-critical system's higher still. Calibrate to the work, not to a personal preference.

Programming Deliberately, Not by Coincidence

The Pragmatic Programmer names the failure mode: programming by coincidence. The code works, but the author cannot fully explain why. They tweaked it until the symptoms went away; they kept the version that produced the right output; they trust the result without understanding it.

The trouble: when the inputs change slightly, or when a refactor disturbs the coincidence, the code breaks in ways the author cannot diagnose. The code was never correct; it was lucky.

The remedy is to insist on understanding:

  • Read the documentation. Most "mysterious" library behavior is documented.
  • When a fix works, ask why it works. If you cannot explain it, you have not fixed the bug.
  • Distinguish between "I know this is correct" and "the tests pass." They are not the same.
  • When you find yourself trying random combinations, stop. Step back. Form a hypothesis. Test it.

Deliberate programming is slower per change in the short term and dramatically faster over weeks. Coincidental programming pays for itself in escalating mystery.

Knowledge Portfolio

Skills depreciate. A language, framework, or tool that was central five years ago may be marginal today; one that did not exist five years ago may now be unavoidable. The engineer who stops learning is making a slow career-ending bet.

The pragmatic prescription is to treat knowledge as an investment portfolio:

  • Diversify. Know more than one language, more than one paradigm, more than one stack. Each adds tools to think with, not just tools to code with.
  • Invest regularly. A small amount of learning weekly compounds; cramming during a crisis does not.
  • Take calculated risks. Try the unproven thing on a small project before betting a critical one on it.
  • Rebalance occasionally. Drop tools whose value has decayed; pick up ones whose time has come.

The learning does not have to be heroic. A book a month, a non-trivial side project a year, a regular practice of reading other people's code is enough to outpace most engineers who are coasting on what they learned five years ago.

Communicate

Code is communication with future readers. Engineering work is also communication with current colleagues, stakeholders, and users. The technical work is necessary; without communication, the technical work does not become value.

A few habits:

  • Know your audience. A status update for an executive should not look like a status update for a peer engineer.
  • Be concise. Respect the reader's time. The first sentence should answer the most important question; everything else is detail.
  • Be precise. Vague language produces vague decisions. "It might be slow sometimes" is not actionable; "P99 latency exceeded the 200ms target on 12% of requests last week" is.
  • Document decisions, not just code. A future reader rarely wonders what the code does — they can read it. They wonder why it does it that way. Decision records, design notes, and PR descriptions answer the question.
  • Ask, don't guess. When the requirements are unclear, the cheapest hour is the one spent asking; the most expensive is the week spent building the wrong thing.

Most of what makes a senior engineer senior is not the technical skill — it is the communication. The technical skill is necessary; without it, communication is empty.

Small Steps

Don't outrun your headlights.

Drive only as fast as you can stop within the distance you can see. The principle applies to engineering directly: take steps small enough that, if a step turns out to be wrong, the cost of reversing it is acceptable.

Practical applications:

  • Small commits. Each commit does one thing. Reverting one is a single operation.
  • Small PRs. Each PR can be reviewed thoroughly. Reviewers catch bugs the author missed.
  • Small refactors. Each refactor is a candidate to land on its own. Large refactors split into many landable pieces.
  • Small experiments. When the right answer is unclear, build a tracer-bullet version that proves the path; then expand.
  • Small deploys. Each deploy carries less risk; each is reversible; each makes the next one safer.

The consistent pattern is to optimize for recovery rather than correctness on the first try. Software is rarely correct on the first try; the question is how cheaply mistakes can be undone.

Don't Live with Broken Code

When a test breaks, fix it before doing anything else. When a build flakes, debug the flake. When a warning appears, address it.

The reason is the broken-window principle applied to the inner loop: a team that tolerates one broken test learns to ignore failures. The next failure is invisible against the noise. The signal that quality is non-negotiable is the team's daily practice, not its written policies.

Concretely:

  • Treat a red CI as an emergency, not a normal state.
  • Treat flaky tests as defects, not as background noise.
  • Fix warnings; do not silence them.
  • When a build script breaks, fix the script; do not work around it.

Curiosity

The engineers who improve fastest share a single trait: they ask why. Why does this work? Why doesn't that? Why was it built that way? Why do the conventions of this codebase look like this?

Most of these questions have boring answers — historical accident, deadline, somebody's preference at a forgotten meeting. A few have interesting answers that change how you think. You cannot tell which is which without asking.

The curiosity does not need to be expressed in research projects. It is enough to maintain the habit of:

  • Reading the documentation when you use a tool, not just the first hit on Stack Overflow.
  • Tracing a function call you do not understand into the library, not just trusting it.
  • Asking colleagues about decisions you find puzzling, in good faith.
  • Following up on the "huh, that's weird" reaction instead of moving past it.

The compounding effect over years is enormous. The engineer who is curious for a decade is dramatically more capable than the engineer who is not, even if both started from the same place.

Pride in Workmanship

The final attitude is pride. The work you do should bear your name without embarrassment. Sign your name on it — literally, in commit messages and changelogs; figuratively, in the standard you hold yourself to.

The pragmatic test: would you be willing to defend this change in front of an engineer you respect? If yes, ship it. If no, the answer is to fix the change, not to ship it anyway and hope no one notices.

The standard is internal, not external. Most code is not reviewed by anyone you would want to impress. Hold the standard anyway. The codebase you contribute to year after year is the cumulative product of every "good enough for now" decision; the work you sign up for is the work you will inherit.

Pre-Commit Checklist

  • If something went wrong, did you take responsibility for the response — not the cause?
  • When you touched the code, did you leave it slightly better than you found it?
  • Is the work calibrated to the bar this project requires, neither below nor above?
  • If a fix works, can you explain why it works?
  • Are you taking small enough steps that an error can be undone cheaply?
  • Is the broken test, the failed CI, the flaky build — addressed, or accepted?
  • Would you be willing to defend this commit in front of an engineer you respect?

On this page