Skip to main content
Test Double company logo
Services
Pragmatic Services Overview
Holistic software investment consulting
Acccelerate Software Delivery
Balance efficiency and quality
Improve Product Impact
Drive results that matter
Upgrade Rails Seamlessly
Update Ruby and Rails versions
Scale DevOps
Dev experience and infrastructure
Technical Recruitment
Build tech & product teams
Case Studies
Solutions
Legacy Modernization
Renovate legacy software systems
Pragmatic AI
Solve business problems without hype
Technical & Product Assessments
Uncover root causes & improvements
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say Hello
Test Double logo
Menu
Services
BackGrid of dots icon
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Impact
Drive results that matter
Cycle icon
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Case Studies
Solutions
Solutions
Legacy Modernization
Renovate legacy software systems
Pragmatic AI
Solve business problems without hype
Technical & Product Assessments
Uncover root causes & improvements
About
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say hello
Developers
Developers
Developers
Communication & teams

Software engineering and AI: Finding the plot(again)

What do you do with the time saved using AI? River Bailey explores multiple threads while exploring the possibilities.
River Lynn Bailey
|
July 15, 2026
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

I recently wrote a post titled "In the age of AI, we're still in this together." That piece was about the harder side of working with agentic coding tools—not the tooling itself, but the deconstruction of how we see ourselves and what we value as software engineers. I leaned on something Engagement Partner Mike Doel said about identity-based habits running deeper than process or outcome habits, and how this moment is asking all of us who spent decades building an identity as programmers to reassess that identity.

Since writing that, I've kept pulling on the same thread. I've been reading about the "Product Engineer" idea over at productengineer.org. And I paired that with older writing on what "quality" actually means in working software—especially Industrial Logic's "Sufficient Design" post from 2010. All of these, together, have started to reshape how I see myself in the new world of agentic coding and tooling, and how I want to work going forward.

I believe, somewhere along the way, I lost the plot of what software engineering is supposed to be in service of. Working with AI tooling every day has forced me to work on re-thinking my role, and doing that means I need to re-find the missing plot.

Where the thought started

I had a random thought one night that I dropped into our internal Slack the next morning:

Agentic coding may be helping me see how I had previously "lost the plot" with software engineering, regarding code quality vs shipping products, and has me specifically thinking about Industrial Logic's "sufficient design" post from 2010.
I know I have a tendency to be an over-engineer. And I've always had pride in my ability to make a good API that hides complexity and improves developer productivity around a specific area of code. But, with all the agentic coding I'm doing these days, I started thinking about this post again and what it might really mean in the emerging world of agentic coding

The questions I asked of my coworkers were:

  1. Did I lose the plot of software engineering vs product delivery?
  2. Have I really been focused on delivering what matters most—working software with sufficient design?
  3. Or, have I been too engrossed in writing what I considered "clean code", to ship sufficient designs?

There's also one foundational question underneath all of that. How do I find the right balance when so much of my day-to-day work is now happening through an agentic loop?

How coworker responses shifted my perspective on agentic coding 

What I got back from my coworkers turned into one of the more useful conversations I've had this year. I want to walk through the parts that hit hardest, because each one moved my thinking somewhere.

The same arc, twenty years on

Principal Consultant Dave Mosher mirrored almost exactly the arc I've been on. He talked about starting in 1996 and being incentivized to learn whatever he could because he wanted to solve a problem. Then around 2008 came the software craftsmanship movement, and for a while he felt like he, too, had lost the plot:

for a while I felt like I too lost the plot because my focus was less on how to create something that solved a problem and more just how to create something with high quality and craft.

He landed in "outcomes over outputs" by about 2020, and now leans into the simplest thing that can solve the problem for someone else as his primary measure of success. He layers on quality after figuring out the right thing to build.

That arc is the arc I think I’m on: solve problems, become obsessed with craft, slowly remember that craft was supposed to be in service of the problem.

Where the over-engineering came from

Senior Software Consultant A.J. Hekman named something I've been circling for years without putting into words:

I think some of the emphasis on over engineering was a defensive reaction to the pain of working with poorly engineered applications, plus the pain and cost of major refactoring to fix it.

That is at least partially where my own over-engineering tendency came from. Most of my career has been an attempt to never feel that pain again. A.J. went on to flag a fear I share:

My fear is LLMs let us go down the wrong path for much longer, and we don't feel the "pain" of working with bad code. It may get to a point it's impossible to untangle, or it might just be a single request to fix. I'm not sure which it will be yet.

That fear is one that keeps pulling me back toward the over-engineering instinct, even when I'm trying to put it down.

Documentation as the load-bearing thing

Operations Director Mike Jansen pushed the conversation toward documentation:

Maybe this means we need to have better documentation about how systems should behave that lives outside the codebase, instead of relying on the code to tell the story of how the system works? If you use AI to maintain an AI-written system, what confidence will you have that it inferred the right thing from the previously inferred implementation?

I'm with him on the first half. Documentation about how a system should behave is becoming load-bearing in agentic development. I pushed back gently on "outside the codebase" because I want it discoverable and usable from inside the repo. The core idea is right, though: if the code is increasingly written by agents, then the human-readable record of what the system is supposed to do is what carries continuity over time.

Mike also said he's been keeping long-running changelogs of conversations and decisions so he can always refer back. That mirrors what I've been doing in the Han skills—logging decisions, open issues, and resolutions through the planning processes so the trail back is always there.

Tech debt as a deliberate tool

Senior Software Consultant Robert Komaromi pointed me at the book Untrapping Product Teams and shared a few quotes on using tech debt to accelerate learning:

Tech debt is a handy tool to accelerate value creation when used prudently. [...] It's unlikely you'll get everything right from the beginning. [...] When users benefit from a solution, that drives business value. At that moment, it's time to pay the tech debt off instead of jumping to another solution.

The reframe in his note is that tech debt taken on deliberately is not the same as writing bad code. It's prioritizing learning over scalability. That distinction matters to me, because most of the tech debt I've worked under in my career wasn't deliberate. It was inherited, accidental, and never paid down. That history is a big part of why my reflex has always been to over-engineer up front.

Balancing code quality against user experience

Staff Software Consultant Jason Karns offered a perspective I needed to hear:

I haven't yet seen an application where code quality was held to a higher standard than the end user experience.
As individuals we may be overly focused on the code/system cleanliness to the detriment of shipping. But as teams and organizations, we are in such the tiny minority that I don't think it's possible to go too far. We would always be swimming upstream.

Later, when I shrugged about Claude Code being internally messy but working consistently for me, Jason asked:

But are you concerned that if the team had higher standards of quality that you'd have a worse experience? I can't imagine that ever being the case. If anything, as a user, I'm screaming for dev teams to ship slower and better.

That's a fair check on the direction I'm leaning. The pendulum can swing the other way. My very first reply in the thread named exactly that fear:

One of my fears in all of this, is swinging the pendulum too far in the other direction: ignoring software quality for the sake of delivering solutions, and causing further issues later on because the software design is insufficient.

I don't want to trade an over-engineering reflex for an under-engineering one.

Quality predicts behavior

Staff Software Consultant Schwa Aresty offered a definition that re-anchored me:

Quality is a predictor of consistent behavior. When you're building, if you don't care about quality, you will likely end up with inconsistent behavior—and context has momentum so correcting that can become more difficult over time.

That is the cleanest articulation I've seen of why internal quality still matters even when the user can't see it. Quality isn't a goal in itself. It's a predictor. If you stop tending to it, behavior drifts, and the cost of pulling that behavior back keeps growing.

A spreadsheet, a custom app, and a spreadsheet (again)

Senior Software Consultant Jed Schneider told a parable on the spot that I keep going back to. The short version:

A business owner runs his company off a spreadsheet. He hires an employee, then a development team, who build him a React app. To really understand his own business now, he has to understand React hooks, async data loading, APIs, and an incantation known as TDD. He has offloaded his understanding of his own system to his developers. The developers, in turn, focus manically on the quality of the source code, because the source is the system they understand. Then Claude Code rewrites the web app into a spreadsheet, and everyone can see in one place how the money flows through the business again.

The part of the parable that hit me is the offloading of understanding. From Jed's parable,

[The business owner] relies on an extra latent and slow feedback loop between questions, understanding, and working software.

In this part of the story, developers optimized code for themselves, because they are the users of the internals. The customer was never asking for that, though. He was asking the developers to give him back an understandable system. 

This is where I find myself, now, as a developer who aspires to be a product engineer. I'm relying on the latency and slow feedback loops of the agentic tooling to free up my time. I can parallelize my work because I no longer need to understand every decision being made while the system is being built. I only need to verify that I understand the system, how it works, and the output that it produces. And to some extent, I no longer need to care if the working system is made from custom software, or formulas in a spreadsheet. 

A broad debt vocabulary

Dave Mosher came back later with three categories of debt I hadn't been using as a daily lens:

  1. design debt: architecture, UX, and visual design that has drifted from its purpose
  2. product debt: whether the product is easier to add features to, or whether everything is a bespoke one-off
  3. platform debt: whether a platform-versus-product separation is needed, or whether the impedance mismatch is making things worse

He closed with this:

All of those lenses have to be filtered through the outcome we're delivering for a user/organization as the ultimate determinant of success, because we can be drowning in all forms of debt and have delighted customers and a healthy balance sheet, and at the end of the day I will take that outcome even if it means having to live with a hard to operate codebase that may not meet a [specific] measure of quality.

I'd add the word "specific" before "measure of quality" in Dave's closing line, and I'll come back to why in a moment.

The product engineer hint

Recruitment Director Anya Iverova pulled the thread that had been pulling me, too:

There's a role—"product engineer" that has emerged at different clients this year, aligning with Dave's point above. Is thinking like a product engineer a natural evolution of a software developer who focused on craft, first?

The Product Engineer idea, and my current desire to move in that direction—whether or not it's an official title at Test Double or any client—is a big part of what prompted all of this thinking for me.

Why "quality" was the word getting in the way

Partway through the thread, Schwa said:

users care about behavior, not quality

I disagreed at the time, but the disagreement was about the specific context of the word, not the idea.

My favorite example to use when talking about "quality," is my choice in ball point pens. I buy boxes of 60 Medium Point Bic Round Stick pens because they meet my exact definition of quality. They write consistently, they're comfortable in my hand, and I don't care if I lose one because they cost almost nothing. I have a box of 60 sitting on a shelf. My dad, as a CEO of various companies, needed a different "quality" in a pen. This was shaped largely by style and cost, because the people he made deals with were other business owners and he needed them to see "success" in everything he did. Both my dad and I are picky about quality. Both of our definitions are valid. The difference is the context in which we operate.

That's the trap I think I've been falling into for years. I've been using "quality" as if it were objective, when it has always been a context-dependent judgment. The Product Engineer mindset, the Sufficient Design idea, and "outcomes over outputs" all start from the same point: define quality relative to the people the software is for, and the problem it's solving for them.

This is also why I'd want "specific" in front of "measure of quality" in Dave's closing line. The hard-to-operate codebase with delighted customers and a healthy balance sheet is meeting one specific measure of quality—the one that matters most to the business. It might also fail a different, specific measure of quality—the one the engineering team wants to feel proud of. Both are real. The Product Engineer move is to name which specific measure, and for whom, you're optimizing. Without understanding that, you'll never know whether you're meeting a quality standard that truly matters.

What this is changing in how I see myself

For most of my career, my professional identity was "software engineer who hides complexity behind good APIs." That identity served me well for a long time, and it produced work I'm still proud of. It also led me to optimize for the user I understood best—the next developer to touch the code—while treating the user paying for the software as a slightly more distant concern.

Agentic coding has knocked that arrangement loose. I no longer spend my days writing code by hand. The agent writes most of it. My day-to-day work is now closer to: name the behavior the system needs to have, plan how it should be built, review what came out, and steer the next pass. The thing that's load-bearing in my work has moved one level up from where it used to be.

From what I understand right now, this shift in perspective is almost exactly the perspective of the Product Engineer manifesto:

  1. Continuous delivery over estimates
  2. Understanding customer problems before jumping to solutions
  3. Direct customer collaboration over ticket-based communication
  4. Teamwork and communication over picking up tasks and working in isolation
  5. Personal quality assurance over delegating testing
  6. Strategic ownership over purely technical contributions

I want to be honest about which of those manifesto items is the most challenging for me: "teamwork and communication over picking up tasks and working in isolation."

I've always preferred being head-down in the code, working through tasks. That preference has shaped most of my career and most of how I think about a "good day at work". But I can't afford to lean on that preference the way I used to, because of the way agentic tooling is reshaping my role.

The hours I used to spend writing code by hand are now hours I need to spend in conversations—with the agent, with the people whose problem the software is supposed to solve, and with the rest of the team. That's the rung of the ladder I'm working on right now.

I'm not throwing away quality in software engineering, though. The craft is still in there. You don't necessarily stop writing code or writing tests because you started writing specs and finding the questions you can't yet answer. You add. You move up the stack while keeping the rungs below you still functional.

What I'm doing is re-anchoring the craft to the thing it was always supposed to be in service of: shipping software that provides solutions for the users needs. Outcomes over output.

Where I'm landing, for now

A few things I'm holding onto from this thread, with no claim that they're settled:

  1. Quality is subjective and context-dependent, and any conversation about it needs to name whose quality, for what use case
  2. The over-engineering reflex many of us carry comes from real pain, and is worth understanding instead of only unlearning
  3. Agentic coding can let us go down a wrong path longer than we used to, so the documentation and decision trail outside the code have to do more work than they used to
  4. Tech debt taken on deliberately to accelerate learning is a different thing from tech debt taken on by accident and never paid down
  5. The role I want to grow into is one where I'm responsible for the outcome the software produces for a real person, not only for the code that produces it

I don't have this figured out. I'm fairly sure nobody does yet. The conversation in that Slack thread, and the writing I keep returning to about Sufficient Design, the Product Engineer manifesto, and other articles and conversations, all point in the same direction: the plot of software engineering was never the code. The plot was the working software, and the people it works for.

AI tooling is, at minimum, forcing me to remember that.

River Bailey is a Senior Software Consultant (and aspiring Product Engineer) at Test Double, and has experience in and has experience in building agentic workflows and plugins for solo and small team environments.

‍

Looking for the plot?

Join the Test Double Dispatch mailing list for software tips and tricks every month.

Subscribe

Related Insights

🔗
AI amplifies everything (including what's broken). Start there.
🔗
Anyone can code: Software Is having its Ratatouille moment
🔗
Before deploying AI tools to your engineering team: A leadership readiness assessment

Explore our insights

See all insights
Developers
Developers
Developers
Why quality software is expensive (to build)

Quality software is expensive because the parts users notice least often require the most work: usability, reliability, security, compliance, testing, and long-term maintenance.

by
Shawn Rinehart
by
Michael Timko
Leadership
Leadership
Leadership
AI amplifies everything (including what's broken). Start there.

Is your organization clear enough to benefit from the speed AI delivers? AI doesn't create dysfunction—it amplifies whatever patterns already exist, including the broken ones.

by
Jen Tedrow
Developers
Developers
Developers
The moat is made of people

Foundation models are getting better and cheaper every quarter. Coding agents can replicate almost any app from a screenshot. So what's left to build a defensible product on?

by
Jed Schneider
Letter art spelling out NEAT

Join the conversation

Technology is a means to an end: answers to very human questions. That’s why we created a community for developers and product managers.

Explore the community
Test Double Executive Leadership Team

Learn about our team

Like what we have to say about building great software and great teams?

Get to know us
Test Double company logo
Improving the way the world builds software.
What we do
Services OverviewSoftware DeliveryProduct StrategyLegacy ModernizationPragmatic AIDevOpsUpgrade RailsTechnical RecruitmentAssessments
Who WE ARE
About UsCulture & CareersGreat CausesEDIOur TeamContact UsNews & AwardsN.E.A.T.
Resources
Case StudiesAll InsightsLeadership InsightsDeveloper InsightsProduct InsightsPairing & Office Hours
NEWSLETTER
Sign up hear about our latest innovations.
Your email has been added!
Oops! Something went wrong while submitting the form.
Standard Ruby badge
614.349.4279hello@testdouble.com
Privacy PolicyTerms & Conditions
© 2020 Test Double. All Rights Reserved.

Looking for the plot?

Join the Test Double Dispatch mailing list for software tips and tricks every month.

Subscribe