A programmer repairing a broken feedback loop between an old workbench and an automated structure that builds software

Software Craft Essay · 2026

Can Software Craft Be Passed On
in the Age of AI?

The classics still matter. What is changing is how their lessons become engineering judgment

21 min read Published August 7, 2026 Updated August 8, 2026

Abstract

The Art of Computer Programming, Code Complete, Refactoring, Design Patterns, and The Mythical Man-Month do not become irrelevant when AI can write code. The deeper risk is that programmers once turned the ideas in those books into intuition by implementing things, tracing failures, maintaining old systems, and living with the consequences. AI can let us skip that experience and arrive directly at something that looks finished.

The canon is not simply aging. Its path into practice is being interrupted. Sending the next generation back to an all-manual workflow would be pointless, and there is no virtue in preserving drudgery. What matters is preserving prediction, close contact with implementation, causal feedback, explanation, and long-term ownership. Unless those acts are designed into AI-assisted work, practical wisdom will slowly flatten into prompt vocabulary.

The part of programming culture worth passing on is not the ritual of typing code by hand. It is the ability to stay in direct contact with complexity. Classic books are compressed experience; our task is to build a learning loop in which that experience can expand again.

Part I · The canon does not contain answers

01A harder version of “Do these books still matter?”

I recently found myself asking a practical question: how useful are books such as Code Complete, Refactoring, and Design Patterns when AI can produce so much of the code? The easy answer is that they still teach us how to judge what AI writes. That is true, but it steps around the difficult part. How does someone who has never been trapped inside a bad codebase acquire the judgment to recognize one?

For many programmers of my generation, the feeling came before the terminology. Change one branch in a thousand-line method and an apparently unrelated feature fails. Follow an ambiguously named field through a dozen calls and you begin to sense that the design is wrong before you can explain why. Deploy a change to shared state without tests and you hesitate for a moment before pressing the button. That hesitation is already a form of knowledge. Books later gave names to what we had felt: divergent change, confused responsibility, hidden coupling. They turned experience into a vocabulary that could be examined and shared.

A young programmer today may follow a different route: describe the feature, generate an implementation, run the tests, and return any failures to the model. The defects and complexity remain, but the programmer may encounter them only through the model’s account. What gets delegated is not just the typing. It can also be the experience that teaches you where to look when something breaks.

The useful question, then, is no longer whether the classics are dated. It is where the experience that makes them intelligible will come from.

02One shelf holds several different kinds of craft

Calling all of these books guides to “writing clean code” misses most of what they contain. Together they span the distance from computation to organizational life.

What classic engineering work preserves
Layer Representative books and essays What they actually train
Computation and abstraction The Art of Computer Programming, SICP, “The Humble Programmer”[1][2][3] Respect for the cost of time, space, state, and abstraction
Construction Code Complete, The Pragmatic Programmer[4][5] Turning readability, defensive thinking, and responsibility into local choices
Safe change Refactoring, Working Effectively with Legacy Code[6][7] Changing a live system while feedback protects its behavior
Design language Design Patterns and the pattern literature it inspired[8] Describing context, forces, variation, and tradeoffs
Systems and organizations The Mythical Man-Month, Peopleware, “No Silver Bullet,” “Programming as Theory Building”[9] Conceptual integrity, communication cost, and shared mental models

Some of these books are too large to read straight through. Some use machines and languages that have long since disappeared. Modern type systems, frameworks, and delivery practices have absorbed or corrected parts of their advice. None of that makes them weightless. They preserve a history of how software learned to think: which failures exposed a weak idea, which practices survived contact with production, and which tradeoffs repeatedly proved expensive. Reading them gives us access to experience we did not have to acquire entirely on our own.

When Donald Knuth called programming an art, he was not appealing to mysterious talent. He meant the application of accumulated knowledge, skill, and ingenuity to real problems. TAOCP’s imaginary machine forces the reader to account for the cost of an algorithm. SICP offers a different lesson: change the evaluation model, representation of state, or abstraction boundary and the same problem becomes a different program. A capable tool can implement either version. It cannot remove the semantic and operational differences between them.

03A pattern is compressed accident history

Ask an AI to “improve this code with the Strategy pattern” and it can produce an interface, concrete strategies, a factory, and tests within seconds. The shape appears so cheaply that it is easy to forget why patterns exist.

A pattern usually earns a name after people meet the same tension across many systems. A behavior really does vary independently. An external dependency repeatedly leaks into the core. A thicket of conditionals is better understood as state transition. The name is an index into that experience. Behind it sit a context, competing forces, known consequences, and the cost of leaving the problem alone.

Take Strategy. It rarely begins with a desire for an elegant interface. More often, a billing function accumulates ordinary users, VIP rules, promotions, cross-border taxes, and refund behavior until each change risks breaking another case. Eventually someone separates the part that genuinely varies, how the charge is calculated, from the rest of the flow. The pattern gives a name to that recurring pressure. Generating the familiar class structure is easy. Understanding the pattern means recognizing whether the same pressure is actually present in your code.

That is why generating a pattern and understanding one are different acts. Generation reproduces a shape. Judgment asks whether there is a stable axis of change here, whether the cost of another indirection is lower than the cost of the expected change, and what evidence would justify deleting the abstraction later.

The canon is not a warehouse of standard answers. It is an index built from expensive failures.

That is also the transmission problem in miniature. We can copy the index perfectly. The experience to which it points cannot be downloaded.

Part II · AI changes how experience is formed

04The old feedback loop was inefficient, and effective

The traditional route into engineering judgment was slow and often frustrating. A programmer wrote code, a later requirement or production failure exposed a weakness, and the repair required tracing unfamiliar state, reading an overlooked module, adding tests, and changing the system in small steps. Review supplied another person’s perspective. Long-term maintenance revealed the delayed cost of short-term decisions. The classics then gave names and structure to those scattered experiences. This loop was inefficient, but it repeatedly connected a decision to its consequences.

Peter Naur’s 1985 essay “Programming as Theory Building” argued that programmers create more than program text. They develop a theory of how a problem in the world is solved by a particular system. When the original team leaves, the files and documentation may remain while that theory disappears, forcing maintainers to build it again.[9]

The argument lands differently now. Anyone who has inherited a well-documented system from a departed team knows the problem: each function may be readable while the reasons behind the boundaries remain obscure. A harmless-looking change can still violate an assumption that nobody wrote down. AI can explain every file on demand, but that does not mean the team shares a theory it can use when evidence is incomplete or constraints conflict. An explanation answers the current question. A theory lets maintainers make coherent decisions when there is no ready answer. The former can be generated; the latter has to be developed.

Two paths into software expertise: on one side a programmer learns through failure, tracing, repair, and maintenance; on the other a programmer directs automated machinery through a glass interface while the feedback loop breaks between delivery and understanding

Figure 1 · AI can shorten more than the delivery path. The old loop forced action through causality and brought consequences back into judgment. An AI loop optimized only for a working result can finish the delivery while leaving understanding outside the circuit.

05Completion and comprehension can now separate at scale

The speed gains from AI-assisted coding are real, and they are highly sensitive to the task. In a controlled 2022 experiment, participants with early GitHub Copilot access finished a standardized JavaScript HTTP server task 55.8 percent faster. The authors explicitly noted that the experiment did not measure collaboration or code quality in a large project.[11] METR studied experienced open-source developers working in repositories they knew well and found that early-2025 tools increased task time by 19 percent. Its 2026 update saw signals of a possible speedup from newer tools, but the researchers judged selection effects too serious for a reliable estimate of its size.[16]

These results do not settle whether AI is “really” faster. They show how much the answer depends on the task, the developer’s familiarity with the repository, and the generation of tools being tested. More importantly, completion speed and depth of understanding are different measures. Someone can ship a working feature quickly while knowing little about why it works or when it will fail. AI makes that separation possible at a scale that older forms of abstraction did not.

An observational study of 21 novice programmers found that 20 completed the assigned problem with generative AI. Students who were already struggling still showed familiar metacognitive problems, and some finished with an inflated sense of their own performance.[12] In another study, only 15 computer science graduate students performed brownfield programming tasks with and without Copilot. The tool helped them work faster and pass more tests, but did not improve their overall comprehension scores. The sample is small and the paper is a preprint, so it should not be treated as a universal law. Still, the performance-comprehension gap it observed is exactly the possibility that deserves attention.[13]

This separation is not entirely new. Copying an answer, using a framework, or calling a cloud API has always allowed programmers to skip lower layers. AI differs in reach. A single interaction can delegate interpretation of the requirement, architectural choices, implementation, tests, and diagnosis. The result may be useful and correct, but much of the reasoning path can remain invisible to the person who accepts it. The saved time is real. So is the lost opportunity to calibrate judgment against consequences.

06Three abilities can thin out without much pain

The first is a causal map. Someone who traces a difficult failure learns where state changes, how exceptions propagate, and why a seemingly redundant check may encode the memory of an earlier incident. Someone who sees only the final diff can know what the system contains without understanding what holds its behavior in place.

The second is calibration. Recognizing a code smell is not the same as deciding whether it matters now, whether two similar blocks express one concept or merely resemble each other, or whether an abstraction isolates real change rather than imagined change. Judgment develops when we make a prediction and compare it with the outcome. If AI supplies an apparently correct answer before we form a view of our own, that calibration step can disappear.

The third is authorship and responsibility. A mistake you make and later repair tends to change your next decision. When a model generates the code, fixes it, and explains the fix, it is easy to record the episode as “the model got this one wrong.” The immediate problem is solved, but nobody necessarily absorbs the lesson.

A survey of 319 knowledge workers found a related tension: greater confidence in generative AI was associated with less self-reported critical-thinking effort. The study did not suggest that thought simply vanished. It shifted toward verification, integration, and oversight. This was not a programming study, and its evidence was self-reported, so the result should be read cautiously. It nevertheless points to an important design problem: AI-assisted work needs new opportunities for active judgment because the old ones may not survive by default.[14]

07When practical wisdom becomes prompt vocabulary

The likely future is not one in which nobody mentions the classics. SOLID, DDD, Clean Architecture, Strategy, and Repository may become more common than ever in prompts and repositories. Every name will sound professional and each layer will have a plausible explanation. Nobody will be able to say which real force the structure is resisting.

“Refactor this according to SOLID and appropriate design patterns” can become an incantation. A twenty-line function turns into Factory, Manager, Provider, Handler, and Resolver. The tests remain green and every class has a plausible justification, yet a small change now requires navigating five files to reconstruct the original flow. The system is not simpler; its complexity has acquired more respectable names. AI makes that kind of abstraction cheap to produce, while the maintenance cost is deferred to another person or another quarter.

That is the cultural hollowing-out I worry about. The vocabulary survives while the experience that gives it meaning becomes thinner. A programmer may speak fluently about boundaries, cohesion, and dependency inversion, yet have no way into a race condition, a data mismatch, or a slow production path. Knowing the terms is useful. It is not the same as having learned when and how they matter.

Part III · Rereading the classics for an AI workflow

08The great big books teach respect for cost

TAOCP is not a handbook for everyday web development, nor should it be a barrier to entry. Engineers do not need to implement sorting in MMIX before using a standard library. Its durable value is the discipline of asking what lies behind an operation that appears simple: the model, proof, boundary conditions, and costs that libraries and hardware usually hide. It teaches respect for those costs without demanding that every reader reproduce the machinery by hand.

AI makes implementation cheap, which makes it easier to confuse generatable with understood. Code can run and pass its tests while hiding an algorithm that fails at a larger scale. Studying algorithms and models of computation is not an exercise in recalling more facts than a model. It gives us questions to ask: What happens when the input grows by an order of magnitude? Which invariants carry correctness? Do the assumptions still hold under different precision, memory, or concurrency constraints? When is a mature library enough, and when does the implementation or original paper need to be read? Those questions turn “it seems to work” into an account of why it works and where it may fail.

SICP likewise matters for more than Scheme. It trains the reader to look through syntax toward evaluation, composition, state, and interpretation. An agent that can write ten languages makes that ability more valuable, not less: surface differences grow ever easier to erase, while semantic differences will still demand payment at runtime.

09Refactoring should recover its meaning as an experiment

Of all the classics, Refactoring may have become more important. Fowler’s definition is deliberately narrow: improve internal structure through a sequence of small changes that preserve observable behavior. Small steps are a method of risk control, not an aesthetic preference. Tests are not only a final gate. They are feedback that says each step remains inside the known world.[6]

AI is very good at producing a cleaner-looking version of a module. In the same change it may replace an interface, upgrade a dependency, alter an exception, and add tests tailored to the new implementation. When a caller fails weeks later, the commit offers little help in locating the behavioral change because rewriting and refactoring were mixed together. Refactoring is safe precisely because observable behavior is held constant while the internal structure changes. Once a new behavior or implementation strategy enters the same step, the team loses that guarantee and makes the source of a regression harder to trace.

Working Effectively with Legacy Code adds another practical lesson: an old system usually lacks, before it lacks elegance, the seams that let you sense behavior and separate dependencies.[7] An AI-era team can turn that lesson into an explicit change contract. List observable behavior and unknown regions first. Add characterization tests. Restrict the write scope. Validate every small diff independently. Move to the next step only when the evidence permits it. The agent can perform much of the mechanical work; a human still defines what must not change.

10Treat every pattern as a falsifiable design hypothesis

Patterns do not need to be banned, and they should not be enabled by default. A better rule is to write each pattern as a hypothesis that reality is allowed to overturn.

Questions a pattern should answer before it enters the code

  • Context: Which responsibility or dependency is creating friction now?
  • Pressure: Which dimension has changed independently, or is supported by credible evidence that it will?
  • Minimum move: What is the smallest useful separation short of the full pattern?
  • Cost: What navigation, debugging, and testing cost will the indirection add?
  • Disconfirming evidence: What would show that the abstraction is wrong?
  • Deletion condition: If the anticipated change never appears, when should this layer be merged or removed?

Under this discipline, Strategy is a claim that there is a real axis of independent change, not merely a familiar set of class names. Adapter protects the core from the semantics of an external model. Observer trades an obvious call path for looser coupling in time and dependency; whether that trade is worthwhile depends on the context. AI is useful here because it can generate several candidate structures and counterexamples quickly. The engineer’s job is to compare them against evidence rather than reward the most recognizable pattern.

11Organizational classics remind us that code is not the whole system

The Mythical Man-Month, Peopleware, and Naur’s essay address different subjects, but they share an important premise: software is more than text. It is also a set of concepts, a communication structure, a working environment, and an allocation of responsibility. Faster local implementation does not remove any of these concerns. Code may be generated in minutes, but a team still has to decide whether it should be merged, who approves it, and who responds when it fails. Brooks’s “no silver bullet” remains relevant because much of the difficulty lies in deciding what to build and coordinating the people who build it.

DORA’s 2025 research describes AI as an amplifier of an organization’s existing capabilities. It can magnify strengths as well as weaknesses, so the returns depend on the system into which the tool is introduced.[15] A coherent repository gives an agent stable examples to follow. Fast tests and short feedback loops allow a team to absorb more change safely. Clear responsibility makes escalation possible when risk appears. In a team with vague boundaries, stale knowledge, and little shared understanding, AI can instead produce more locally plausible changes that fail to fit together. The tool does not create those conditions, but it can make their consequences arrive faster.

Reading the classics in the AI era therefore cannot remain a matter of individual taste. Their ideas need somewhere to attach: review, task design, incident analysis, architecture decisions, and team development. Otherwise the knowledge you finish reading still has nowhere to land.

Part IV · A new apprenticeship for software craft

12Restore feedback, not scarcity

Asking new programmers to avoid AI and write everything by hand for several years is neither realistic nor educational by itself. Much of the old friction was simple drudgery: looking up syntax, copying boilerplate, porting the same logic between frameworks, or waiting for a build. Removing that work is a genuine improvement.

Other kinds of friction are educational because they change the next decision. Predicting an outcome before acting, tracing a state transition personally, explaining an abstraction to another engineer, and maintaining a change months later all connect judgment with evidence. The aim is not to preserve pain. It is to remove drudgery without removing feedback.

Cognitive apprenticeship moves through modeling, coaching, scaffolding, articulation, reflection, and exploration, with support gradually withdrawn as the learner gains competence.[10] AI fits this model well. It can demonstrate how an expert traces a failure, provide progressively stronger hints, generate counterexamples, and compare several solutions. The least useful learning design reverses the sequence by supplying a polished answer before the learner has formed a model of the problem. The tool remains available, but the learner has little to do beyond accepting its output.

13Separate production mode from learning mode

A team does not have to sacrifice delivery speed on every task. It does have to admit that finishing work and building capability are different modes, then reserve explicit capacity for the second.

The same AI tools in two different modes
Dimension Production mode Learning mode
Goal Deliver efficiently within a risk boundary Build a transferable causal model and better judgment
AI role Implementer, researcher, validation runner Coach, adversary, hint provider, failure simulator
Human act Define constraints, review evidence, own release Predict first, trace personally, explain tradeoffs, compare outcomes
Task choice Automate low-risk mechanical work Select representative failures, legacy code, and boundary problems
Done means Functionality, tests, performance, rollback Can explain, modify, and recognize an incorrect transfer

For a novice, a vague “no-AI zone” is difficult to enforce and easy to experience as punishment. A difficulty budget is more precise: identify the parts of a task the learner must attempt before receiving a complete solution. In debugging, the learner can draw the call path and record a hypothesis before using AI to test it. In an algorithm exercise, they can state the complexity and invariants while AI provides hints in stages. More automation becomes available as the learner’s own model becomes stronger. The default should follow the person’s capability, not the tool’s capacity to generate.

Senior engineers are learning as well. They must divide large tasks into units an agent can complete and return with useful evidence, detect architectural drift in code that looks locally tidy, design validations whose success carries real information, and review a much larger volume of output without losing judgment. The classics provide a language for assessing these decisions. Current practice must adapt that language to a different means of production, and even experienced engineers are still learning how.

14Six feedback devices that fit into ordinary team life

Predict before generating. Write down the affected modules, highest-risk behavior, expected tests, and invariants before the prompt. Without a prediction, there is nothing to calibrate.
Write a refactoring contract. State observable behavior, permitted scope, and validation for every step. Do not let a large rewrite pass as a small refactor.
Keep human-led failure autopsies. For production incidents, races, and data errors, have people draw the timeline, call path, and state transitions before AI supplies counterexamples. An incident is not only a ticket to close. It is scarce teaching material.
Give every abstraction a record. Capture the pressure that justified a pattern, rejected alternatives, expected benefit, and deletion condition. Review why it exists, not just whether it has a respectable name.
Make understanding a deliverable. For an important change, the owner must be able to explain the critical path, failure modes, and rollback without AI. If that cannot be done, the work is not complete.
Carry ownership through time. Developers should maintain the systems they build with AI, join the on-call rotation, participate in review, and make the next change. Short-term choices become durable experience only when consequences cross quarter boundaries.
A programmer and an AI share a circular workbench moving through prediction, constrained generation, stress testing, human tracing, explanation, and long-term maintenance, with operational evidence feeding the next judgment

Figure 2 · A new feedback loop for AI-assisted work. AI can remain at the bench, but it cannot place the human outside the causal chain. Prediction, constrained action, verification, explanation, and ownership turn one delivery into judgment that can be reused on the next.

15Senior programmers will still need a nose for trouble

Teams also need better measures. If the scorecard includes only closed tickets and merge speed, the cost of understanding is easy to push into the future. Delivery metrics should be considered alongside less convenient questions: Where does rework cluster? How many people can explain a critical module without asking AI? How expensive is it to modify code generated three months ago? Did an incident produce a reusable test or rule? Does review catch semantic problems or merely improve presentation? These signals are imperfect, but they reveal whether a team is accumulating understanding or borrowing against its future.

None of this means everyone must master all of TAOCP or that senior engineers should write every function by hand. A healthy engineering culture is not a shared reading list or vocabulary. It consists of habits: respecting complexity, refusing to equate passing tests with understanding, deleting a failed abstraction instead of hiding it behind another layer, naming the behaviors that must not change, investigating a failure before blaming the model, and accepting responsibility for what happens after release. No single book contains those habits, but the best books help us recognize and practice them.

The books still belong in that culture, but the way we read them will change. The Art of Computer Programming can be read beside a profiler and a model-generated algorithm. Refactoring can become a protocol for agent changes. Design Patterns can become a review form for design hypotheses. The Mythical Man-Month and Peopleware can help a team resist the naïve arithmetic that more agents automatically mean more throughput. A classic no longer waits for the mythical month when we finally read it cover to cover. It supplies a longer history and a more accurate language at the moment a real problem makes us ready for it.

The next generation does not need to fall into every old hole. It does need to see how holes form and take responsibility for repairing the road.

AI is making implementation cheaper. That raises the value of knowing why a design works, what should not be generated, and who owns the result when it fails. Software craft will not disappear merely because less code is typed by hand, but it will not pass to the next generation simply because the classics remain on the shelf. It survives only if teams design understanding into the workflow, preserve feedback, and attach responsibility to real people.

A programmer does not need to repeat every old hardship to develop sound judgment. They do need direct contact with the system: enough to trace a failure, explain its cause, decide how to repair it, and live with the result. Keeping people inside that causal loop is how software craft can continue in the age of AI.

References and further reading

  1. Donald E. Knuth, The Art of Computer Programming, Stanford University.
  2. Harold Abelson, Gerald Jay Sussman, Julie Sussman, Structure and Interpretation of Computer Programs, MIT Press.
  3. Edsger W. Dijkstra, “The Humble Programmer”, ACM Turing Award Lecture, 1972.
  4. Steve McConnell, Code Complete, Second Edition, Microsoft Press, 2004.
  5. David Thomas and Andrew Hunt, The Pragmatic Programmer, 20th Anniversary Edition, 2019.
  6. Martin Fowler, Refactoring: Improving the Design of Existing Code, second edition, 2018.
  7. Michael Feathers, Working Effectively with Legacy Code, 2004.
  8. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, 1994.
  9. Peter Naur, “Programming as Theory Building”, 1985.
  10. Allan Collins, John Seely Brown, Susan E. Newman, “Cognitive Apprenticeship: Teaching the Craft of Reading, Writing, and Mathematics”, 1987.
  11. Sida Peng, Eirini Kalliamvakou, Peter Cihon, Mert Demirer, “The Impact of AI on Developer Productivity: Evidence from GitHub Copilot”, 2023.
  12. James Prather et al., “The Widening Gap: The Benefits and Harms of Generative AI for Novice Programmers”, ICER 2024.
  13. Yunhan Qiao et al., “Code Comprehension with GitHub Copilot: Performance Gains, Comprehension Trade-offs, and Behavioral Predictors in Brownfield Programming”, preprint, revised 2026.
  14. Hao-Ping Lee et al., “The Impact of Generative AI on Critical Thinking”, CHI 2025.
  15. DORA, State of AI-assisted Software Development 2025, Google Cloud, 2025.
  16. METR, early-2025 experienced open-source developer study and 2026 experiment-design update.