
Teaching Programming in the Age of AI
This reflection stems from ongoing conversations with colleagues across computer science departments, as we collectively grapple with fundamental questions about how AI will (vs should) reshape our pedagogical approaches. I share these thoughts as an invitation for broader dialogue within the whole academic community.
Most university programming courses still follow the template we inherited: memorize syntax, decode cryptic error messages unaided, write boilerplate until the patterns stick. This made sense when it was how we all learned. It makes less sense now that our students can get working code from a few sentences of plain English.
I learned recursion through formal logical constructs:
That experience shaped how I think about computation, and I value it. But our field has spent decades trying to lower the barrier to entry, for good reason. I remember my undergraduate cohort — roughly 80% of us struggled through the entire course, and many never finished. The programming language design community has done serious work since then. Languages like Python and JavaScript embody what designers call "low floor, high ceiling": accessible enough that beginners can do something meaningful within hours, capable enough that experts can build serious systems. Students today benefit from that intentional design effort.
So the tension isn't really about AI making programming "too easy". It's that when students know they can get working code from a natural language prompt, asking them to spend a week on syntax drills starts to feel arbitrary rather than foundational.
There's a useful frame for thinking about this in the research on "flow" — that state where learning happens because the challenge matches your skill level. Programs like the Hour of Code have shown how well this works for onboarding new programmers.
Traditional flow state optimization balances skill and challenge for sustained learning engagement.
AI reshapes this balance. Tasks that used to require genuine skill — handling complex syntax, parsing error messages, producing boilerplate — are now handled routinely by AI tools. The old flow channel gets absorbed into "stuff the machine does for you". If we want to keep students in that productive learning zone, we need to push toward the challenges AI can't handle well: decomposing ambiguous problems, reading and evaluating code critically, reasoning about systems at scale.
AI assistance shifts the traditional flow channel, requiring programming education to target higher-level challenges for optimal learning engagement.
As AI takes over syntax and boilerplate generation, our courses need to spend more time on the analytical and design skills that separate a good developer from someone who can prompt a code generator. We're seeing early moves in this direction across many institutions, but we don't yet have enough research on what transition strategies actually work. That gap needs filling before we can move beyond intuition.
Greg Wilson makes a point in "Teaching Tech Together" that I keep coming back to: you are not your learners. We naturally teach from our own experiences, assuming the struggles that shaped us will shape our students in the same way. Wilson calls this the "expert blind spot" — experienced programmers routinely misjudge what beginners actually need. And in programming education specifically, we tend to cling to old approaches even as the tools and context shift around us.
The closest historical parallel is probably mathematics education and the calculator. When calculators became widely available, there was genuine worry that students would lose essential computational skills. The math education community didn't ignore calculators, and they didn't abandon fundamentals either. They became more strategic. We still teach multiplication tables in elementary school and calculus in high school — the concepts that require human understanding haven't changed. What shifted was the emphasis. Less time on computational mechanics, more on strategy: which tools work for which problems, how to approach multi-step solutions, when to apply different methods, and why certain approaches outperform others.
Programming education is at a similar inflection point. The question is whether we'll be as thoughtful about it as the math educators were.
What Students Need to Learn Now
In a world where AI handles much of the code generation, several skills become more important than they used to be.
Students need to get good at reading and evaluating code they didn't write. When a significant chunk of the code in a project comes from an AI tool, the ability to quickly assess what it does, spot its limitations, and identify where it could be improved becomes a core professional skill rather than an occasional one.
Problem formulation matters more too. AI assistants are sensitive to how you frame a request. Students who can break a complex problem into well-defined sub-problems and articulate constraints clearly will get dramatically better results from AI tools than those who can't. This is a teachable skill, and we should be teaching it.
Testing and validation need more curricular space. When you wrote every line yourself, you had at least some intuition about where the bugs might be. With generated code, that intuition is gone. Students need systematic approaches to verifying that implementations actually solve the intended problem, including edge cases the generator may not have considered.
And systems-level thinking — understanding how components interact, how things behave at scale, how pieces integrate — becomes more critical as AI makes it easier to produce individual components quickly. The hard part was always making things work together, and AI hasn't changed that much.
Live coding sessions can evolve along these lines. Rather than watching an instructor type out a solution, students could participate in "live problem-solving" — working through decomposition, discussing tradeoffs in approach, testing systematically, debugging methodically, and thinking about how a component fits into a larger system. This is closer to what professional programming actually looks like.
Rubber-duck debugging offers another interesting adaptation. The traditional technique — explaining your code line by line to an inanimate object to force yourself to think carefully — has proven surprisingly effective for decades. Now we can use AI as an interactive debugging partner. The student explains their code, and the AI responds with clarifying questions, suggests edge cases worth considering, and helps them articulate their reasoning. Done right, the AI acts as a "provocateur" — challenging assumptions and pushing deeper thinking about logic and design — rather than just handing over a fix.
Peer instruction fits naturally here too. When students examine AI-generated code together, discussing what it gets right, what it misses, how they'd improve it, the conversation tends to be richer than traditional code reviews because no one in the group wrote it — everyone can evaluate it without ego getting in the way.
Building on What Works
Wilson's reminder that "you are not your learners" isn't a call to throw everything out. The systematic thinking, problem decomposition, and logical reasoning we've always taught are more important than ever — they're precisely the skills AI can't replace. What needs updating is how we develop these skills and what role we give AI tools in the classroom.
The calculator analogy is instructive here in one more way: mathematics education got stronger through that transition. The field didn't weaken because students stopped doing long division by hand past a certain grade level. It focused more energy on the parts of mathematical thinking that actually matter for problem-solving. Programming education has the same opportunity. We can preserve what works — the deep engagement with computational thinking, the emphasis on careful reasoning — while letting go of the parts that have become busywork in an AI-assisted world.
This will take experimentation, and we'll get some things wrong. But the worst outcome would be to keep teaching exactly as we do now while the world our students are entering changes around them.
I'd love to hear your thoughts — reach out to keep the conversation going.
