<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jacob Prall</title>
    <description>The latest articles on DEV Community by Jacob Prall (@jacob_prall_1c6bff06b0e0d).</description>
    <link>https://dev.to/jacob_prall_1c6bff06b0e0d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3412346%2Fcadd9791-8294-4feb-95ed-999f3e2a15a5.png</url>
      <title>DEV Community: Jacob Prall</title>
      <link>https://dev.to/jacob_prall_1c6bff06b0e0d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jacob_prall_1c6bff06b0e0d"/>
    <language>en</language>
    <item>
      <title>Refactor or Rot: Designing a Self-Improving Codebase</title>
      <dc:creator>Jacob Prall</dc:creator>
      <pubDate>Thu, 12 Nov 2026 20:40:07 +0000</pubDate>
      <link>https://dev.to/jacob_prall_1c6bff06b0e0d/refactor-or-rot-designing-a-self-improving-codebase-22ak</link>
      <guid>https://dev.to/jacob_prall_1c6bff06b0e0d/refactor-or-rot-designing-a-self-improving-codebase-22ak</guid>
      <description>&lt;p&gt;Coding agents have made it easier to produce software quickly. They have also made an old problem more urgent: every change leaves a codebase behind for the next change.&lt;/p&gt;

&lt;p&gt;In the inner loop, an agent receives a request, reads code, makes a plan, implements a change, and runs tests. Improving that loop helps it complete the task in front of it.&lt;/p&gt;

&lt;p&gt;There is an outer loop, too. Each agent run inherits the codebase the previous run left behind. It follows existing patterns and often treats nearby code as an example. Good structure gives the next run a starting point; bad patterns become templates for more bad patterns.&lt;/p&gt;

&lt;p&gt;Agents accelerate that loop in either direction. Can we help a codebase improve as it changes without spending more on maintenance than the improvement is worth?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better means cheaper to change&lt;/strong&gt;&lt;br&gt;
For this work, we use a definition of better code: code that is cheaper to change. A person or agent should be able to understand what matters, make a change in the right place, and verify the result without pulling half the system into context.&lt;/p&gt;

&lt;p&gt;Complexity makes behavior harder to understand. Duplication forces changes in multiple places. Coupling makes a local change reach across boundaries. Refactoring addresses these problems by changing structure without changing observable behavior. But finding an opportunity is not the same as finding a worthwhile investment.&lt;/p&gt;

&lt;p&gt;We learned that distinction. In our evaluations, reviewing every pull request for refactoring cost four to nine times as much per trajectory as doing no refactoring. The approach improved a static-analysis health score, but a better score alone did not establish that the work would pay for itself.&lt;/p&gt;

&lt;p&gt;A refactor must be identified, planned, executed, and checked. Its benefits accrue only when later work passes through the improved area. We shifted from asking, “What could be cleaner?” to asking, “Where does the cost of leaving this alone justify changing it?”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find the places where debt charges interest&lt;/strong&gt;&lt;br&gt;
We use three signals to decide where a deeper review might be worthwhile.&lt;/p&gt;

&lt;p&gt;Heat asks how often a file changes across recent merges. Coupling looks for files in different directories that repeatedly change together. Health uses static analysis, including cognitive complexity and duplication, to identify code that may be difficult to change.&lt;br&gt;
These are signals, not verdicts. Complexity does not automatically justify a refactor, and files that change together do not necessarily have a bad dependency. The signals narrow the search; judgment comes later.&lt;/p&gt;

&lt;p&gt;Hard, frequently changed code is a candidate for review: each new task may pay the same tax. Easy, frequently changed code should be kept healthy. Hard but rarely touched code is different. It may look ugly, but if little work passes through it, its difficulty incurs little recurring cost. We think of that as zero-interest technical debt. Our default is to leave it alone, unless another concern, such as security, reliability, or compliance, calls for action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separate the decision from the work&lt;/strong&gt;&lt;br&gt;
At Render, we built the workflow on top of a factory for running agents in isolated Sandboxes. A GitHub webhook reaches a gateway, which verifies the event and starts a Render Workflow. The workflow starts an agent from a repository snapshot and controls external actions; the agent itself does not hold credentials to write back to GitHub.&lt;/p&gt;

&lt;p&gt;After a merge, a deterministic gate checks the signals. If its conditions are not met, no model review runs. If they are met, the gate creates a brief identifying relevant files and evidence. A separate refactoring agent reviews the recent merges and can propose a change or decide that nothing is worth doing.&lt;/p&gt;

&lt;p&gt;The review is guided by a skill based on software design, refactoring, and testing literature. Its sixteen smell cards describe what to look for, how to confirm a finding, and what does not count. The agent must quote the code, explain the cost, and assess severity, confidence, effort, and risk. It can then draw on a catalog of thirty-five refactorings to create a proposal issue for human approval.&lt;/p&gt;

&lt;p&gt;Before an approved refactor, a separate agent writes a deterministic replay against public interfaces. The workflow runs it twice to establish a stable baseline, hides the replay and output from the refactoring agent, and runs it again afterward. Changed output rejects the refactor. A passing replay is not proof that all behavior is unchanged, but it adds an independent check before a draft pull request reaches a person.&lt;/p&gt;

&lt;p&gt;Early observations of lower marginal cost per change are promising but anecdotal. Our targets are a 15–20 percent reduction in the cost of changing refactored areas and payback within 10–20 subsequent changes. We are expanding the rollout to learn whether those targets hold under traffic.&lt;/p&gt;

&lt;p&gt;The goal is not to maximize findings or make every file look pristine. It is to leave the next run with a better starting point—and to make that improvement at a cost worth paying.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>refactoring</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
