I caught the Fundamentals of Software Engineering in the Age of AI workshop yesterday at the Arc of AI conference’s workshop day, led by Nathaniel Schutta (cloud architect at Thoughtworks, University of Minnesota instructor) and Dan Vega (Spring Developer Advocate at Broadcom, Java Champion).
Nate and Dan are the co-authors a book on the subject, Fundamentals of Software Engineering, and they’re out here workshopping the ideas with developers who are living through the same AI-saturated moment we all are.
Fair warning: this post is long. The session was dense, the conversation was good, and I took a lot of notes.
Here’s part two of several notes from the all-day session; you might want to get a coffee for this one. You can read the previous set of notes here.
How you got here doesn’t matter. That you got here does.
After the first break, Nate and Dan shifted from the big-picture AI discourse into something more concrete: the actual craft skills that make a software engineer, and why those skills are becoming more important in an AI-augmented world, not less.
Nate opened this segment by talking about the different paths into software engineering (the traditional CS degree, boot camps, self-taught) and making a point I think deserves wider circulation: there is no canonical path, and apologizing for yours is a waste of energy.
What matters, in his view, isn’t the credential. It’s whether you have the tinkering mindset. Whether you’ve gone to sleep thinking about a problem and woken up with the answer. Whether you look at a broken thing and feel the pull to understand why it’s broken.
He also made an honest admission about what CS programs are actually designed to do: prepare you for graduate school in computer science. That means algorithms, compiler theory, operating systems, language design. Practically useful for building production software? Debatable. Practically useful for becoming a researcher? Yes. Boot camps swing hard the other way – framework-heavy, language-focused, get-you-hired in 12 weeks – which means they’re also somewhat transitory, because the framework of the moment changes every six months.
Neither path gives you everything. That gap between “what we taught you” and “what I want you to know when you join my project” is basically what their book is trying to fill.
The skill we teach least is the one we use most: reading code
This was the section that hit me hardest, because I’ve thought about it before and never heard it stated this cleanly.
Nate’s observation: we teach people to write code almost exclusively. We spend essentially zero time teaching people to read code. And yet, in any real production environment, the ratio of reading to writing is not even close. You spend far more time navigating, understanding, and reasoning about existing code than you do creating new code from scratch.
His analogy: “I wouldn’t teach you French by saying, now go write some French.”
Reading code is hard for a few compounding reasons. You have to understand the problem domain (which is often genuinely complex – he gave examples from finance and insurance where the business rules alone are labyrinthine). You have to see the code through another person’s mental model. And you often have to do this under time pressure, making changes you don’t fully understand, in systems you weren’t around to watch grow.
The result is what Nate called “patches on top of patches on top of patches,” and the remarkable thing isn’t that these systems have bugs, it’s that they work at all.
There’s also the cognitive bias dimension. The Ikea effect: you value things you assembled yourself more than things someone else built, which means you’re inclined to view your own code as cleaner and more sensible than others’. The mere exposure effect: familiarity breeds preference, which is why developers get dogmatic about languages; not because their preferred language is objectively superior, but because it’s the one they know.
Nate had a great riff here about what he called the Blub Paradox, from a Paul Graham essay: when you’re a programmer in a language somewhere on the power continuum, you look down the spectrum and think “I can’t imagine being productive with those limitations,” and you look up and think “I don’t know why anyone would need all that weird stuff I don’t have.” The language you know well becomes your baseline for what’s normal. AI tools, interestingly, may be helping break this a bit. He and Dan both noticed they’re using more languages and frameworks than they used to.
The Lab: Reading an unfamiliar codebase without AI first
Dan ran the group through a hands-on exercise using the Spring Pet Clinic, a well-known sample Java/Spring application. The instructions were deliberately old-school: no AI tools yet. Just open the repo and start reading.
The goal was to build some muscle memory around the basics: identifying technologies and frameworks from project structure alone, finding a main application class, recognizing architectural patterns just from folder layout.
It’s a more sophisticated skill than it sounds. Dan’s point: even if you’re not a Java developer, you can learn a lot from just looking at a pom.xml. You can infer architectural choices from package structure; “package by feature” versus “package by layer” tells you something about how the original authors thought about the system. You can spot where to start, what the domain objects are, how the system is organized.
After they’d done it manually, Dan switched to showing how AI tools handle the same task, specifically using a “plan mode” in his coding assistant where he wasn’t asking it to write anything, just to explain what it was looking at. The output was genuinely useful: a breakdown of the tech stack, architectural summary, entry points, dependency graph.
His key insight: “I use AI tools far more to read code, understand things, get familiar with things, and learn things than I do to write it.”
But then the follow-up, which is the important part: he wouldn’t have known what questions to ask the AI without the fundamentals. Understanding that architecture is a thing, that there are different ways to organize packages, that there’s something meaningful to look for in the dependency file; that knowledge has to come from somewhere. The AI accelerates the exploration; it doesn’t replace the ability to know what you’re looking for.
AI can tell you what code is doing. It still can’t tell you if that’s right.
This is where the conversation got interesting. Nate made a distinction that I think is underappreciated:
These tools are now remarkably good at reverse-engineering legacy code and telling you what it does. Feed it a 30-year-old COBOL module and it’ll give you a plain-English summary of the behavior. That’s genuinely powerful, especially for the mainframe migration work he mentioned in the morning session.
But “this is what the code is doing” is a completely different question from “is this what the code should be doing?”
He gave a real-world example: a system where some business logic was technically incorrect, but the error was intentionally corrected downstream in a different process. The code was wrong on purpose, because fixing it at the source would have required fixing everything else too. An AI reading that code would correctly describe the behavior, but have no way to know the behavior was a deliberate workaround rather than a bug.
That knowledge lives in the heads of the engineers who were there when the decision was made. And increasingly, as those engineers retire or move on, it’s not living anywhere.
The airline pricing example he used was perfect: the same seats, same flights, same dates — but booking as two one-ways costs a third less than booking as a round trip. There’s almost certainly a specific piece of business logic somewhere that creates that arbitrage. An AI can describe that code. It can’t tell you whether the Delta exec who approved it knew what they were approving.
The sentinel knowledge problem, part two
Nate returned to a theme from the morning: we are starving the pipeline that creates the experts who can actually evaluate AI output. But in this session, he made it more concrete.
Senior engineers look at AI-generated code and immediately spot the issues: the approach that’ll work in a demo but fall over at scale, the pattern that was idiomatic three major versions ago, the security implication nobody mentioned. Junior engineers look at the same code and think it looks fine, because they don’t yet have the experience to know what “fine” looks like.
The concerning dynamic: juniors are increasingly using AI to learn, but learning by accepting AI output without the ability to critique it isn’t learning. It’s cargo cult programming. You’re learning to produce things that look like code without developing the underlying judgment about whether those things are good.
Nate’s line: “AI is the very eager junior developer, and you need to monitor their output closely.”
The economics sidebar: tokens, budgets, and the reality of scale
This wasn’t on the agenda, but it came up organically and it was one of the more grounded conversations of the day.
Nate described a real situation: an organization’s head of AI was approached by a developer who wanted the unlimited Claude Code tier. When asked how many tokens he needed, the answer was 60,000 a day. Response: show me that you’re generating not $300K of business value weekly, but a million dollars. Can you do that? No? Then no.
The scaling math is uncomfortable. A room full of developers (say, 5,000 at a larger company) each burning hundreds or thousands of dollars of tokens per week is a significant line item. And the current pricing reflects a subsidized market. When investors start demanding returns, those prices go up.
He drew an analogy to the Uber model: lose money for years, drive out competition, then raise prices. Except Uber’s “product” (a car ride) is a commodity. The switching costs for enterprise AI tooling embedded into CI/CD pipelines, developer workflows, and institutional processes are not trivial.
His read on Anthropic’s and OpenAI’s revenue vs. profit numbers: revenue is real. Profitability is not. People are seeing value in the product, but the product is priced below cost. That’s not a sustainable business model, and the reckoning will come.
On whether we’ve hit a plateau
Someone in the room asked whether the intelligence improvements we saw around late 2024/early 2025 would continue.
Nate’s take: we’re probably hitting a plateau on pure scaling. The exponential gains from “just make the model bigger” appear to be diminishing. Gary Marcus’s position that we’re approaching the limits of what scaling alone can achieve, strikes him as reasonable.
The “Mythos is so dangerous we can’t release it yet” announcements that keep appearing? He’s skeptical. Follow the incentives: the companies making those claims need their valuations justified.
He was slightly more philosophical about the longer tail – the sci-fi scenarios, the alignment concerns, the “what if it’s already smarter than it’s letting on” thread. He takes it seriously without catastrophizing. The honest version of his view: we don’t know what the motivations of these systems are, because the people who built them don’t fully understand how they work either. That warrants humility, not panic, but also not dismissal.
Bottom line from this session and the previous one
The throughline across the whole day, as best I can summarize it: these tools are genuinely powerful accelerants for people who already have the foundations. They are not a replacement for the foundations. They are an amplifier, and what you get out depends heavily on what you put in.
The code reading skills, the domain understanding, the architectural instincts, and the ability to ask the right questions. All of that still has to come from somewhere. What’s changed is that once you have it, you can go faster, do more, and explore more territory than you could alone.
That’s good. The part that’s bad is that we’re making decisions right now (who to hire, what to teach, what to outsource) based on the assumption that the foundations don’t matter anymore.
They matter. Probably more than they used to.
