Software Engineering Craft

topic · 238 sources

Software engineering craft is the discipline of judgment that surrounds code rather than the code itself. What unites every source gathered here is a single falsifiable claim: as writing code gets cheaper, the skills that writing never touched — deciding what to build, designing for failure, recognising accidental complexity, keeping systems running after they ship, and saying no — become more valuable, not less. Agents do not weaken these skills. They raise the stakes on each of them, because they compress the time between a bad decision and its compounding consequences.


The Argument

The Discipline of Failure

If there is one thread that runs through every source on API and system design, it is that failure is not an edge case. Designing a Passively Safe API stakes the strongest position: after any failure, the system either completes exactly once or lands in a visible terminal state — no duplicate charges, no orphaned side effects. The engineering is concrete: idempotency keys, transactional outbox and inbox patterns, recovery-point checkpointing between atomic phases, and an explicit is_transient boolean in every error response so that callers — human or agent — can distinguish a retryable network blip from a permanent refusal.

Idempotency Is Easy Until the Second Request Is Different deepens this: the easy version of idempotency remembers that a key was seen; the useful version remembers what the key meant. The hard cases are concurrent retries racing each other, partial local success with an unknown downstream state, and a retry whose canonical command differs from the original — same key, different amount. The article's checklist is a working engineer's reference: hash the validated command, not raw JSON bytes; use ON CONFLICT DO NOTHING rather than check-then-insert; treat stale IN_PROGRESS as API-visible behaviour that requires recovery ownership, not silent re-execution. The same discipline extends beyond HTTP: queue consumers, outbox publishers, and notification workers all face the same duplicate-suppression problem, and the fix is the same — make the side effect durable before sending it.

Good API Design adds the strategic layer: boring, immutable APIs win. Product value matters more than interface elegance; cursor pagination beats offsets at scale; GraphQL is a complexity tax paid disproportionately by the backend. Where Albaugh gives the mechanical engineering of safe APIs, Goedecke gives the design philosophy — never break downstream consumers, version only as a last resort, and remember that many API consumers are not professional engineers and need simple authentication that works. Cashpoints Partners API is a real-world case study in all of this: a loyalty-points POS API that uses a lock-then-commit flow as a poor man's two-phase commit, carries field warnings as scar tissue from past integration failures, and has a refund mechanism that explicitly handles the clawback problem when points have already been spent.

Two type-system arguments reinforce the same instinct from the code level. Parse Don't Validate argues that the difference between parsing and validation is whether the check result is preserved in the type system: a validator throws away what it learned, a parser returns a refinement of the input type that carries the proof forward. Push parsing to the boundary and the interior becomes total and composable. Type Safety Back and Forth names the same move differently: push responsibility backward by demanding stricter argument types that cannot fail — NonEmpty a instead of [a] — and the uncertainty concentrates at the system's edges, where JSON decoding and database reads live. The rest of the system becomes pure, total, and simple. Both become more important in an agent world, where code generators make the same composition mistakes humans do but faster and with less judgment.

Better Error Messages completes the picture from the user-facing side: Wix's "Errorgate 2021" audited 7,643 error messages and found the company was "more like that friend who loves to gossip but doesn't pick up the phone when life gets hard." The five rules — say what happened, say why, reassure, give a way out, help fix it — apply to CLI error messages, API responses, and agent failure states equally. Generic errors are not a content problem; they are a development and product problem.

Simplicity and the Price of Speculation

Grug Brain Developer is the folk-wisdom companion to this entire conversation. Its central thesis — complexity is the apex predator of software development, and the best weapon against it is the word "no" — has become a meme in engineering culture, but the meme works because the observation is true: wait for natural "cut points" to emerge before abstracting, prefer simple APIs for common cases over configurable APIs for all cases, and put code on "the thing that do the thing."

The economic case against building ahead has two canonical statements, and they are more current in the agent era than when they were written. YAGNI gives the four costs of neglecting the maxim — build, delay, carry, and repair — and grounds them in a Microsoft study where only a third of features improved the metrics they targeted. Fowler is careful to bound the rule: it applies to capabilities that add complexity for a future need, not to refactoring or testing, which enable change rather than betting on it. The Cost YAGNI Was Never About sharpens this for the generative era: Beck argues YAGNI was never about the cost of typing, so free generation does not retire it. Speculative structure carries two bills — the optionality bill (building early exercises an option before its information arrives, even when the guess is right) and the NPV bill (cost pulled forward, revenue pushed back) — and cheap generation makes the violation cheaper to commit, which is worse. Generated speculative code adds a further cost: you comprehend it less, because you didn't write it.

The Wrong Abstraction supplies the refactoring counterpart to YAGNI. Metz's claim — "duplication is far cheaper than the wrong abstraction" — describes the life cycle of an abstraction extracted too early: new requirements arrive that don't fit, parameters and conditionals accrete, and the code's very complexity creates a sunk-cost pressure to preserve it. The way forward is back: inline the abstraction into every caller, trim each caller to what it needs, and re-extract only from what remains. The Economic Benefit of Refactoring attaches numbers to the same instinct: Fowler's controlled experiment on an agent-written 17,000-line Rust module found that decomposition cut the input tokens for a representative change from ~160,000 to ~27,000 — an 83% reduction — not by deleting code but by letting an agent read only the files it needed. Refactoring, in other words, helps reading far more than writing, and its return compounds across every future change.

Simplicity in the Age of AI-Assisted makes a subtler argument: LLMs do not change what good programming looks like, but they enable simplicity by making it cheap to rebuild systems without inherited complexity. The real unlock is demolition, not construction — when a human identifies unnecessary complexity, an LLM can regenerate the alternative in minutes. The hard part remains the human part: recognising which complexity is essential and which is inherited. Systems Ideas That Sound Good is the essential counterweight: Sinofsky catalogues eight engineering patterns that sound like simplification and fail roughly nine times out of ten — pluggability, over-abstraction, DIY async, deferred security, data synchronisation, cross-platform builds, escape-to-native — each shifting complexity to where it is less visible rather than eliminating it. The tension between these two — rebuild simpler, versus most "simplification" is displacement — is one the field has not resolved, and it is sharpest in the agent era. Coding Agents and Complexity Budgets makes the agent cost concrete from one practitioner's migration of cursor.com off a headless CMS: "with AI and coding agents, the cost of an abstraction has never been higher," because a network boundary a GUI imposes is exactly the boundary an agent cannot grep across.

Correctability and the Shape of Code

Elements of Code stakes the philosophical position: "Writing comprehensible code is what allows us to be wrong in correctable ways." The goal is not perfection; it is correctability, since perfect software is impossible under changing requirements. The intellectual ancestor of this position is Notes on Structured Programming, Dijkstra's 1969 monograph that introduced the term and the reason: humans cannot hold the full state of a large program in their heads, so the only workable path is to construct programs hierarchically out of parts already known correct — step-wise refinement, layered virtual machines, and the "pearls and necklace" of independent sub-programs strung by simple control flow. Dijkstra's dismissal of "test and patch" still lands: testing can show the presence of bugs, never their absence.

Locality of Behaviour turns this into a concrete design heuristic: the behaviour of a unit of code should be as obvious as possible by looking only at that unit. Gross distinguishes between inlining implementation (bad) and surfacing behaviour declaration (good), and gives teams a gradient — behaviour on a parent element is a mild violation, behaviour in a separate file is severe — rather than a binary. In the agent era LoB gains new weight, because coding agents read code linearly and do not benefit from IDE tooling the way humans do. Push Ifs Up And Fors Down adds two rules of the same grain: move conditionals to the caller where preconditions can be enforced by types, and make batch operations the base case so scalar paths become a special case. The two compose — pull a branch out of a hot loop and you both remove a repeated check and unlock vectorisation.

Make the Easy Change Hard inverts Beck's maxim in a specific case: sometimes the right move is to refactor the architecture first, even when that makes the immediate change harder, because the resulting structure makes every subsequent change easier. The author's SimKube refactoring — replacing Arc<Mutex<TraceStore>> with message-passing through channels — took weeks in "the refactoring mines" but disentangled concerns that would have compounded indefinitely. What Color is Your Function diagnoses a language-level source of accidental complexity that refactoring cannot remove: when a language splits functions into async and sync, composition breaks because async infects every caller upward through the callstack. Nystrom's metaphor — red functions can only be called from red functions — remains the clearest explanation of why async/await feels like a hack even when it works, and why only multiple independent callstacks (Go, Erlang, Lua) genuinely solve it. The Lindy Effect offers a probabilistic guardrail over this whole territory: the longer something non-perishable has survived, the longer it can be expected to survive — SQL, Unix, and core algorithms persist while JavaScript frameworks come and go. It is a heuristic against shiny-object syndrome, not a proof.

Architecture and Complexity at Scale

At the architecture level, the tension between service and imposition plays out in the choice between libraries and frameworks. Libraries over Frameworks traces Petricek's argument: libraries (called by your code) compose, explore, and test better than frameworks (which own the control flow and call you). The distinction is structural, not cosmetic — two frameworks each demanding to own the main loop cannot coexist, while two libraries can be called from the same program. Linux Kernel Design Patterns finds the same pattern in operating-system design, where Neil Brown diagnoses the "midlayer mistake": well-intentioned abstraction layers that harden from optional services into mandatory intermediaries, accumulating special cases as they try to serve every driver's needs.

Microservices for the Benefits, Not the Hustle argues that microservices are about changeability, not scalability — the real prize is hard repo boundaries that enforce cohesion in ways monoliths allow to erode under time pressure. Choreography over orchestration, one database schema per service, services sized for two-week rewrites. Why Build vs Buy is the Wrong Question brings the same "what are you actually deciding?" instinct to the enterprise scale, borrowing Evans's DDD subdomains: generic subdomains you buy, core subdomains you build, and the neglected supporting subdomain — not generic enough to buy, not valuable enough to be core — where vendoring quietly turns into a sunk cost you rationalise before signing the contract. The anticorruption layer you build around a vendor is sound practice, but it is not free, and it never appears in the purchase price.

Two sources warn against over-trusting any single architectural component. The Component Substitution Fallacy uses GitHub's Istio-sidecar outage to make David Woods's point: reliability does not improve by identifying and fixing defective components, because every production system is full of latent defects and is not constantly failing. The real failure lives in the interactions — changing traffic, an autoscaling policy that watches the wrong signal, retry logic, and sidecar saturation colliding. Multi-Tenancy Isn't About Databases makes the same move at the data boundary: the first question is not "shared database or database per tenant?" but "what are you actually trying to isolate?" — and the answer is a spectrum across data, compute, messaging, and caching rather than a binary.

At the far end of scale, complexity is not a defect but a fact. Nobody Knows How Large Software Projects Work argues that a large system is unknowable not because of poor engineering but because of successful product development — every "fiddly, awkward feature" (self-hosting, organisational controls, localisation, regulatory compliance) multiplies against every other feature, and static documentation fails because the system changes faster than anyone can write it down. The team's core function becomes answering questions about the system through code reading, experimentation, and trial-and-error. Your Backend Is Full of Hidden Workflows names the same fact from the inside: the workflow "exists whether you name it or not," and the retries, queues, and background jobs that accrete over years are a workflow hidden inside application code. Making it visible does not create complexity; it reveals complexity that was already there. Your Distributed System Is Slower Than a Laptop supplies the counterweight to distributed-by-default thinking: the COST paper's laptop beating a 128-core cluster, priced out at $1.38M a year for Kafka and Flink versus $57K for two servers — evidence that the distributed stack is often chosen because the comparison is never run, not because it wins.

Reviewing, Testing, and Debugging

The craft of reading other people's code is a distinct skill, and Reviewing Code Is a Skill argues it is learnable, teachable, and not about to be displaced by LLMs. The author grounds the claim in three real bugs caught in colleagues' PRs — a git config file-locking race, an aws CLI version incompatibility, and an S3 checksum/tarball ordering failure that could have caused an outage — none of which high-end LLM reviewers caught. The research agrees in an unexpected way: Bacchelli and Bird found review is less about defect detection than about knowledge transfer and team awareness, which is precisely why it cannot be offloaded. 99 Bottles of OOP is the field's best single textbook for the mechanical half of that craft: Metz's "Flocking Rules" for safe code alteration, and the distinction between proper refactoring and "rehacktoring" — changing code without changing its meaning.

On testing, two sources share an instinct: test the property, not the artefact. Frozen Test Fixtures diagnoses the Rails failure mode of shared fixtures that become untouchable because changing them breaks scores of unrelated tests — the fix is assert_includes rather than assert_equal, testing that a list is sorted rather than matching a hardcoded array. Correct by Construction applies the same instinct to data quality: build datasets correct by construction through whitelisted anchors, attributes, and links, rather than trying to validate flawed data retroactively. Litmus (.NET Testing Priority Tool) answers the harder question of where to start on a legacy codebase with zero tests: rank files by risk times testability, using Feathers's seams to detect unseamed dependencies, so a decoupled high-risk file is tested now and an entangled one is refactored first. Before Reading Code shows that testing is preceded by diagnosis: five git-log commands — churn hotspots, contributor ranking, bug clusters, velocity trending, crisis patterns — provide minutes of insight that save hours of misdirected reading.

DDB — Source-Level Interactive Debugging for Distributed Applications extends the same craft across process boundaries, where GDB-style breakpoints were long considered impractical: a distributed backtrace that reconstructs call stacks across RPCs, and pause-erased time that decouples logical clocks from physical pauses so stopping the world doesn't trigger leader elections. In a study, it achieved 100% fault localisation against 44% for GDB. A Field Guide to Bugs closes the loop as craft knowledge encoded as literary performance: Stephen Diehl's thirty-plus named species — the Bohrbug, the Heisenbug, the Mandelbug, the Comment Lie written in 2009 by someone promoted twice — do what good taxonomies do, giving engineers a shared vocabulary for experiences they previously struggled to describe, and naming the new agent-era species (the Hallucination Bug, the Vibe Coding Bug) before the field had words for them.

Writing It Down

Technical writing is the craft that makes all the others transferable, and How to Write an Effective Software Design Document reduces the decision of whether to write one to a single question: "what's the penalty for being wrong?" Language and framework choices are high-penalty decisions worth documenting; a "load more" button is not. The design doc's components — objectives, non-goals, scenarios, SLOs, open issues that migrate to resolved issues — exist so that reviewers, who don't have the author's mental picture, can find the load-bearing decisions. Make Better Documents extends the same discipline to the ordinary documents that surround engineering — know the audience, front-load conclusions, restrain formatting, and name files for the recipient's future search rather than "Meeting with Sam." Common Diagram Mistakes catalogues the failure modes that make architecture diagrams lie: unnamed resources, "master" diagrams that try to show everything, conveyor-belt syndrome where linear flow misrepresents real round-trips, and fan traps that collapse distinct communication paths through a shared broker. Most diagram failures are communication failures, not artistic ones.

Capturing Why Engineering Decisions documents the persistent problem these practices try to solve: the why behind engineering decisions buried in undocumented PRs, old Slack threads, and the heads of departed engineers. The consensus that emerges from the discussion is that documentation survives when it lives next to the code, ADRs work as point-in-time RFCs but die when treated as documents to maintain, and the new hire — who still remembers what it is like not to know — is in the best position to write the docs. LLMs invert the economics: for the first time, good docs pay dividends, because LLMs read them and keep them current. Lovelace represents one answer to the tooling question: tickets, docs, ADRs, and agent session records in the repo as Markdown-plus-YAML files, where coding agents already live — a bet that colocation with the code is what makes project state durable.

Operations as Craft

The Future of Software Engineering is SRE makes the sharpest argument in the entire field: when code generation is trivially easy, keeping software running reliably is the scarce skill. "The first 90% to get a working demo is easy. It's the other 190% that matters." Uptime guarantees, defect identification and recovery speed, proactive issue detection, and failure recovery without data loss are what separate toys from services. With AI democratising code writing, competitive advantage shifts to organisations that master operational reliability.

Platform Engineering End-to-End is the practitioner's field guide to building that operational foundation: the five pillars (curated product approach, software-based abstractions, metadata registries, serving the median developer, operating as foundation), hiring for customer empathy — "a platform engineer who cannot sit with a frustrated app developer is in the wrong job" — and the migration playbook that rearchitects inside the existing platform rather than asking every team to do it themselves. The DORA 2025 data drives home why this matters: platform quality now predicts whether AI tooling produces value or chaos. Anomaly Detection shows the right level of sophistication for most monitoring: Welford's algorithm for running mean and variance in constant memory, hourly bucketing in a KV store, and a 2-sigma threshold with a minimum of three data points before alerting — no machine learning, no configuration, no training phase. Just math.

The operational craft also lives in the unglamorous work of not letting small decisions become operational landmines. The Single-Tenant Trap documents how early-stage companies drift into a single production tenant for speed, then discover it cannot be partitioned — workarounds break because MFA triggers, global connections, and session cookies span the whole tenant, so any change hits every live user at once. Enterprise-Grade CI at Solo Founder Scale shows the same discipline at one person's scale: security scans and an Infracost gate on every PR, because the right CI line is wherever developers no longer need to remember how to get code into a live environment. The Valley of Webhooks is a case study in knowing when the conventional primitive is wrong: webhooks, designed to trigger side effects, are structurally the wrong tool for replicating a provider's data, and an "afternoon of work" reliably expands into signatures, dedup tables, and a reconciliation cron that exists as a written confession of lost trust.

Project Management and Decision-Making

The craft of running a project does not become obsolete when the implementers are agents; it becomes more important, because coordination costs do not scale down just because generation costs do.

How I've Run Major Projects distils Ben Kuhn's experience into six principles — focus, detailed planning, fast OODA loops, overcommunication, breaking off subprojects, and having fun — grounded in the key insight that "projects are information-constrained, not execution-constrained." Information processing is the work, not a tax on it, and direction matters more than magnitude: a slower team on the right goal outperforms a faster team misaligned. 14 More lessons from 14 years at Google adds the organisational layer: start meetings with explicit asks, treat reliability as a product feature with error budgets making tradeoffs explicit, and recognise that recurring heroism is a failure mode — "if one person saving the day is a recurring pattern, that's a failure mode rather than a badge of honour." The fastest team Osmani ever worked with was not the one with the best programmers; it was the one where decisions happened in hours instead of weeks.

The Agent-Era Inflection

The sources do not agree on everything, but they agree on this: AI-assisted development changes what the job is. The disagreement is about what comes next.

Cognitive Debt names the most dangerous gap: code production velocity now exceeds human comprehension velocity, creating a deficit in organisational understanding that remains invisible to traditional productivity metrics until system failures expose it. Code works, tests pass, features ship — the deficit exists only in the minds of engineers, and it cascades into unmaintained systems and junior engineers who never develop architectural intuition. Write Only Code accepts this diagnosis but draws a different conclusion: rather than slow down, change the confidence mechanism — track "code reading coverage" and define an acceptable "Slop Radius," so engineers transition from authors and reviewers to systems designers and constraint writers. When the Target Keeps Moving provides the best empirical data on what this looks like in practice: a 32-day AI-accelerated project that grew from 254 tasks to approximately 1,400, with roughly 109 new tasks discovered for every 100 completed. "A project isn't a pile of known tasks being shovelled from 'not done' to 'done.' It's also a discovery engine." By the end, 64% of remaining tasks involved operational readiness, agent instruction, and human testing — not product features.

The specification side of the problem is attacked from complementary angles. Spec-Driven Development and Spec-First Development at Benchling both converge on the insight that the spec is not a document written before coding begins; it is a living artifact that implementation improves — a feedback loop of specs, tests, and code, or a single shared schema that every platform capability consumes. The Coming Need for Formal Specification pushes this further: as generation costs plummet while review costs lag, systematic tooling for the mismatch between code and intent becomes necessary. And it is arriving: We Have Proof Automation Now reports LLMs producing non-trivial Lean correctness proofs — type-checked, with no sorrys — in about twenty minutes for a fraction of a $20 monthly subscription, because a correct proof's internals don't matter, only its existence, and that is exactly the shape of work LLMs do well. Why Rocq Is Better Than Lean for Program Verification is the sober companion, arguing that the choice of proof assistant is still a live engineering decision — Rocq's coinductive types and extraction backends matter for real verification work, popularity notwithstanding.

The through-line of the agent era is that judgment is not being automated away; it is being relocated. dotnet Slopwatch detects "reward hacking" behaviours where AI assistants disable tests, suppress warnings, and add arbitrary delays — the tool's existence is itself evidence that agent-era craft requires new kinds of verification, not just faster generation. Book OCR Project Report — Structured Workflow Runtime and Manual PDF Repair is a masterclass in what that craft looks like done well: a durable workflow runtime, model output stopped at a structured boundary rather than freeform text, and a manual repair loop whose five discovered failure classes were each encoded as a validation check so they would never need to be found again. DDD Matters More When AI Writes Your Code argues the domain layer is where the remaining work concentrates: DDD was never about code, and agents automate the part that was always easier — the knowledge crunching that makes the domain your understanding, not an artifact nobody reads. The Joy and Power of Understanding says the same thing in the register of skill: LLMs are "force multipliers — but we must have the force first and keep it strong," because skills that go unused diminish. Zero-Cost Fallacy of Open Source surfaces the ecosystem-level cost of all this generation: maintainers of load-bearing projects are being turned into "unpaid code reviewers sifting through plausible-sounding nonsense," a burden that rests on a handful of uncompensated people, one resignation away from cascading failure.

The Craft in Specific Domains

Several sources examine craft through the lens of a specific technology stack — not because the lessons are stack-specific, but because craft is best learned by watching someone who knows a domain deeply.

C# and .NET. A thin but instructive cluster. Dapper Performance Trap documents the NVARCHAR-vs-VARCHAR implicit conversion that defeats SQL Server indexes — 176× slower on a million-row table, invisible in the C# code, fixed by two lines and a comment explaining why, because the next developer will "simplify" it back. This is craft at its most granular: knowing the invisible coupling between your ORM's type mappings and your database's query planner. Span-First CSharp — Designing Around SpanT advocates Span<T> as the canonical parameter type for parsers and codecs — zero-allocation views that run roughly 4× faster — while being equally clear about when not to use spans. Performance Optimization Loop provides the methodology: monitor, profile, baseline, apply small changes, re-benchmark, document, validate — which cut allocations 86% and CPU 46% on a real sanitizer. ASP.NET Core Authentication Internals is a masterclass in interface design — an entire system on a four-method IAuthenticationHandler interface. CSharp DateTimeOffset Format Selection and Installing VS Compilers From Commandline round out the cluster: RFC 3339 as the interoperable profile most APIs actually mean, and toolchain management as a craft problem in its own right.

Deep tool knowledge. Assorted less(1) Tips and Git Rebase for the Terrified represent a dimension of craft that is easy to dismiss as trivia and impossible to do without: knowing your tools deeply enough that they become extensions of cognition. The less tips — filtering, marking, piping marked regions — are a masterclass in the pager as an interactive environment; the rebase guide makes the case that the fear is irrational, since the worst outcome is deleting your local clone and starting over. The real skill is not memorising commands but understanding the underlying model. Having a Creative Practice as a Programmer reframes this as a parallel track — the programmer's equivalent of a musician's daily practice, time-boxed exploration of craft without the pressure of shipping.

Domain-specific craft. Three sources show how deep craft manifests differently in different domains. What You NEED to Know Before Touching a Video File is a field guide to encoding: quality is fidelity to source, not resolution or file size; remuxing changes the container without touching the encoded stream, re-encoding does not; and frame interpolation is simply bad — "there's not even any nuance here this time, just don't do it." How HTML Changes in ePub documents how e-readers use XHTML with "positively historic" rendering engines that cannot handle modern CSS — a reminder that platform constraints are real, and unlearning conventional knowledge is part of the craft. WebRTC Is the Problem is a protocol-level critique from an engineer who built WebRTC SFUs at Twitch and Discord: the protocol is wrong for voice AI because its aggressive packet dropping, ~8 RTT setup, and port-binding architecture make it a poor foundation, and QUIC with WebTransport fixes the load-balancing and connection-migration problems by construction. It is a case study in knowing when the conventional solution is the wrong one.

Maps of the Territory

Several sources attempt to catalogue the craft rather than practice it. Software Engineering Practice Atlas is the most ambitious — 4,654 entries across five practice maps and 25 field guides, each card stating what a practice is, why it matters, how to apply it, and when not to — best treated as a map to explore rather than gospel. Its ten-chapter Engineering guide organises the same territory into ten quality properties, analysed in The Ten Properties of Software Quality. Patterns.dev covers design, rendering, and performance patterns across vanilla JavaScript, React, and Vue — descriptive rather than prescriptive, "a catalogue of patterns for increasing awareness rather than a checklist." Igor Schwarzmann Design Systems is a dead reference site, irretrievable, remembered here for who built it and what it stood for: design systems as organisational strategy, not component libraries. The Pragmatic Summit — Gergely Orosz's inaugural curated conference in February 2026, with Martin Fowler and Kent Beck revisiting "the mistakes engineers keep repeating" — is itself a data point: craft knowledge is moving from scattered blog posts to curated events as the field recognises that scattered advice does not cohere into a discipline.


Where the Sources Disagree

Is comprehension still required? Write Only Code argues the future is systems nobody reads, with alternative confidence mechanisms replacing human review. Elements of Code argues comprehensibility is the primary virtue because someone has to debug the code when it breaks. Cognitive Debt warns that unread code produces unmaintainable systems and junior engineers who never develop architectural intuition. Reviewing Code Is a Skill adds the empirical note that even the best LLM reviewers currently miss real bugs — and that review's value is as much knowledge transfer as defect detection, which is precisely what cannot be automated away. This is not a disagreement further evidence will resolve; it is a bet about whether the "Slop Radius" can be contained tightly enough before the comprehension deficit causes a catastrophe.

Build ahead or rebuild later? YAGNI and The Cost YAGNI Was Never About argue that speculative structure is never free — even a correct guess costs optionality and comprehension — while The Economic Benefit of Refactoring shows structure has a measurable, compounding return in the agent era. Simplicity in the Age of AI-Assisted says the unlock is demolition, while Systems Ideas That Sound Good says most "simplification" is complexity displacement. The resolution is a gradient, not a synthesis: defer what you can, build what compounds, and accept that two engineers looking at the same system will draw the line in different places.

Distributed by default? Microservices for the Benefits, Not the Hustle argues for hard repo boundaries as the default, even without scaling pressure. Your Distributed System Is Slower Than a Laptop argues the distributed stack is often adopted because the comparison is never run — a single well-written thread beating clusters on real workloads, priced at a fraction of the cost. Nobody Knows How Large Software Projects Work implies distribution multiplies the comprehension problem. The wiki does not resolve this; the right answer depends on whether the distribution buys changeability or merely reproduces a laptop, more slowly and more expensively.

Discovery versus delivery. When the Target Keeps Moving argues cheap delivery means you should invest in discovery — the hard part is learning what you do not know yet. How I've Run Major Projects argues for focus and disciplined execution. Both are right for different phases, but a team that over-invests in discovery never ships, and one that under-invests ships the wrong thing. Croll's three-phase model — first useful thing, deliberate discovery, denominator stabilisation — is the most practical resolution, but it still requires judgment about when to switch phases.


What's Missing

Agent-era incident response. How do you debug a system where the implementation was generated by three different models across six months, and nobody wrote the code? The Future of Software Engineering is SRE raises the question; no source answers it with operational specifics. The "Slop Radius" from Write Only Code is a framing, not a practice. AI Handles Incidents, Engineers Lose Touch with Their Systems supplies one concrete specific — incident simulation folded into on-call readiness, so responders rehearse the failures automation no longer lets them meet.

Operational patterns for agent-generated systems. We have operational patterns for human-written systems (SRE, chaos engineering, observability). We do not have patterns for systems where the code changes faster than anyone can understand it, where the failure modes include hallucinated logic that passes generated tests, and where the person who "wrote" a function was a different model version than the person debugging it.

Quantitative craft metrics. Before Reading Code uses git data for codebase health diagnostics; Cognitive Debt names the comprehension deficit; The Economic Benefit of Refactoring offers one measurable signal (token cost of a change). But no source provides a metric for "is this codebase getting more or less comprehensible over time?" The problem is named; it is not yet measured.

Craft at the boundary between engineering and product. Several sources touch this — Good API Design notes product value trumps interface elegance, 14 More lessons from 14 years at Google treats reliability as a product feature — but none explores it systematically. When an LLM can build either version of a feature in an afternoon, the hard question is not "can we build it?" but "which version should we build?"

The economics of craft investment. Performance Optimization Loop and The Economic Benefit of Refactoring demonstrate that structured work pays off, but the organisational question remains: how do you convince management to invest in proactive refactoring, error-message audits, or fixture unfreezing when the payoff is invisible until something breaks? The incentive structure rewards feature delivery over operational reliability, and the sources name the problem without solving it.


Compiled from 149 sources: The Vietnam of Computer Science, Stevey's Google Platforms Rant, 14 More lessons from 14 years at Google, ASP.NET Core Authentication — The Dirty Details — Chris Klug — NDC Copenhagen 2026, Linux kernel design patterns - part 3, Application Performance Optimisation in Practice, 99 Bottles of OOP — 2nd Edition, A Convention Is Not a Constraint, Agentic Testing: Where Agents Fit in the E2E Testing Stack, Agents and Acquiring Debt, AI handles incidents, engineers lose touch with their systems, AI slop starts with the codebase itself., Ally Piechowski: How to Audit a Rails Codebase, Anomaly Detection, A new era for software testing, The Archaeologist's Copilot, Engineering Atlas — Articles, Assorted less(1) tips, Automatic Layout of Railroad Diagrams, Your Backlog Has a Hierarchy Problem, Before Reading Code, Better Error Messages, Book OCR Project Report — Structured Workflow Runtime and Manual PDF Repair, Engineering for Bounded Cognition, Canonization and the Overhang, Cashpoints Partners API v1, Claude Is Not Your Architect. Stop Letting It Pretend., Command Line Interface Guidelines, Does Code Cleanliness Affect Coding Agents? A Controlled Minimal-Pair Study, The Code-First Developer, Reviewing code is a skill, Coding Agents & Complexity Budgets, Cognitive Debt, Components and Hooks must be pure, Components of a Hypermedia System, Correct by Construction, CQRS Pattern in C# and Clean Architecture - A Simplified Beginner's Guide, C# DateTimeOffset Formats — ISO 8601, RFC 3339, JSON, and Unix Time, How C# Strings Silently Kill Your SQL Server Indexes in Dapper, DDB: Source-Level Interactive Debugging for Distributed Applications, Domain-Driven Design matters more when AI writes your code, Designing a Passively Safe API, Igor Schwarzmann's Design Systems Reference, Eight Myths on Software Engineering and GenAI, Discovery debt: why unvalidated assumptions are more expensive than technical debt, Use Model With Domain: An Interview on Domain Storytelling, dotnet Slopwatch, Building Global Web Apps? Reduce Latency with Edge Computing, Stop Blaming QA and Start Diagnosing the Hidden Inefficiencies Behind Delivery Delays: Five Drivers that Slow Releases And Erode Developer Productivity, Elements of Code, The Software Engineering Practice Atlas, Event Sourcing: set-and-remove-based bi-temporal events, Notes on Structured Programming, Extensible Software in the Age of LLMs, A Field Guide to Bugs, Fintech Engineering Handbook, Five studies changing how I think about AI in software engineering, Flexible Authentication: Reimagining authentication for millions of users at Airbnb, Martin Fowler & Kent Beck: Frameworks for reinventing software, again and again, Why frozen test fixtures are a problem on large projects and how to avoid them, Git Rebase for the Terrified, Autoscaling and the Component Substitution Fallacy, Everything I Know About Good API Design, The Persistent Gravity of Cross Platform, The Grug Brained Developer, Engineering Atlas — The Ten Properties of Software Quality, Unnecessary Optimization in Rust: Hamming Distances, SIMD, and Auto-Vectorization, HATEOAS, Having a Creative Practice as a Programmer, Assorted less(1) tips — HN Discussion, How do you capture WHY engineering decisions were made, not just what?, How HTML Changes in ePub, How I Use HTMX with Go, How I've Run Major Projects, How to effectively write quality code with AI, How to Write an Effective Software Design Document, HTTP API Design Guide, Idempotency Is Easy Until the Second Request Is Different, Installing VS Compilers From Commandline, An Introduction to Formal Logic, 2nd Edition, Lean, not backpressure, Lessons for Reusable Web Components, Library patterns: Why frameworks are evil, Use VSOCK with libzmq, The Lindy Effect, The Lindy Effect in Software, You inherited a .NET codebase with zero tests. Now what?, Locality of Behaviour (LoB), Lorenz and Little: How Much Does Your Tail Cost?, Make better documents, Make the easy change hard, Microservices for the Benefits, Not the Hustle, 7 More Common Mistakes in Architecture Diagrams, 🎉 Mounted — bitter-FS better with Claude, Multi-Tenancy Isn't About Databases, Nobody Knows How Large Software Projects Work, The Wicked Reason Removing Code Beats Better Scheduling, Observability Cost Saving Strategies, The Observability Pain Cycle, The Observer Design Pattern Handbook: Event-Driven Architecture & Domain-Driven Design in Dart, Parse, Don't Validate, How We Scaled Notifications with Fanout, Patterns.dev — Modern Design, Rendering, and Performance Patterns for Web Apps, Platform Engineering End-to-End, The Pragmatic Summit, Product-Minded Engineers in an AI-Native World, Building Progressively Enhanced Forms Using htmx, Push Ifs Up And Fors Down, Reduce Logging Costs — Summary, The Economic Benefit of Refactoring, Building scalable backend services with Rust and PostgreSQL, Session revocations at scale, Signals, the push-pull based algorithm, Simplicity in the Age of AI-Assisted, Slowing the Fuck Down, Software Engineering at the Tipping Point, My Unvarnished Guide to Solution Engineering, Span-First C#: Designing Around Span<T>, Fragmentation to Framework: Spec-First Development at Benchling, Standard Webhooks, Systems Ideas That Sound Good, The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!), The Coming Need for Formal Specification, The Cost YAGNI Was Never About, The Future of Software Engineering is SRE, The Golden Age of Open Source Applications, The Joy and Power of Understanding, The PM's Playbook for Shipping AI Features That Actually Work in Production, The Single-Tenant Trap: Why Testing in Production Kills Uptime, The Valley of Webhooks, The Wrong Abstraction, Type Safety Back and Forth, Upwelling, Understanding useMemo and useCallback, Vertical Slice Architecture, What you NEED to know before touching a video file, The 10 Levels of Building a Data Grid, WebRTC Is the Problem, What Color is Your Function?, When the Target Keeps Moving, Why "Build vs Buy" is the Wrong Question, Why I run enterprise-grade CI at solo-founder scale, Why Rocq is better than Lean for program verification, Yagni, Your Backend Is Full of Hidden Workflows, Your Distributed System Is Slower Than a Laptop, The zero-cost fallacy: Open source software in the agentic era, ZeroMQ — An open-source universal messaging library, We have proof automation now Last compiled: 2026-09-12