<?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: Kerrial Newham</title>
    <description>The latest articles on DEV Community by Kerrial Newham (@kerrialn).</description>
    <link>https://dev.to/kerrialn</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1429060%2Fbf5534fc-405b-45c4-a8b5-f44f9568a4a8.jpeg</url>
      <title>DEV Community: Kerrial Newham</title>
      <link>https://dev.to/kerrialn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kerrialn"/>
    <language>en</language>
    <item>
      <title>The Boardroom Argument That Kills More Migrations Than Bad Code</title>
      <dc:creator>Kerrial Newham</dc:creator>
      <pubDate>Mon, 25 May 2026 09:48:18 +0000</pubDate>
      <link>https://dev.to/kerrialn/the-boardroom-argument-that-kills-more-migrations-than-bad-code-1i3p</link>
      <guid>https://dev.to/kerrialn/the-boardroom-argument-that-kills-more-migrations-than-bad-code-1i3p</guid>
      <description>&lt;p&gt;This is an excerpt from* &lt;strong&gt;&lt;em&gt;&lt;a href="https://leanpub.com/legacy-to-symfony" rel="noopener noreferrer"&gt;Legacy to Symfony: The Enterprise Blueprint for Zero-Downtime PHP Migrations&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; *— a hands-on guide for tech leads migrating legacy PHP monoliths to Symfony without downtime, without burning the team, and without losing the business's confidence in the process.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Standard risk frameworks assume known probabilities. A legacy migration doesn't give you those. Here's how to change the conversation before you walk into the room.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You have done the audit. The codebase scores in the low thirties. The God Files are real. The test coverage is zero. You have the data, the rollout plan, and the business case. You are ready for the Go/No-Go meeting.&lt;/p&gt;

&lt;p&gt;Then someone in the room says: "We've assessed the risk. We're going to tolerate it for now."&lt;/p&gt;

&lt;p&gt;Meeting over.&lt;/p&gt;

&lt;p&gt;This is not a failure of data. It is a failure of language. The executives in that room are not blank slates — they have been trained, by consultants and MBA programmes and their own experience, to evaluate risk through a specific lens. The framework is called the Four Ts: &lt;strong&gt;Tolerate&lt;/strong&gt;, &lt;strong&gt;Treat&lt;/strong&gt;, &lt;strong&gt;Transfer&lt;/strong&gt;, &lt;strong&gt;Terminate&lt;/strong&gt;. You will encounter it in some form in every boardroom you enter.&lt;/p&gt;

&lt;p&gt;The framework works when the odds are known. Fire insurance works because actuaries have decades of claims data. The probability of a factory fire in a given year is calculable. The cost of that fire is estimable. The premium follows from the maths.&lt;/p&gt;

&lt;p&gt;A legacy migration is not that problem.&lt;/p&gt;

&lt;p&gt;You cannot tell a CFO that there is a 34% chance the system will fail in Q3. The system might degrade gradually for two more years before it collapses under a peak load event, or it might survive indefinitely on the goodwill of the one developer who understands it. The odds are not unknown because no one has done the research — they are structurally unknowable. The Four Ts assume a probability distribution that does not exist here.&lt;/p&gt;

&lt;p&gt;This is why the standard risk conversation fails. The business applies Tolerate — they assess the current pain, decide it is manageable, and close the meeting. Two years later the same business is in crisis mode, doing an emergency rewrite under pressure, and paying ten times the cost of a controlled migration.&lt;/p&gt;

&lt;p&gt;Your job in that room is not to argue against Tolerate. It is to change the frame entirely. There are three reframes that work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reframe 1: Mitigate via Architecture
&lt;/h2&gt;

&lt;p&gt;Instead of asking the business to commit to a migration, ask them to commit to a containment strategy.&lt;/p&gt;

&lt;p&gt;A Docker environment isolating the legacy system from new infrastructure is not a migration step — it is a risk mitigation step. A proxy sitting in front of both systems, routing traffic selectively, is not a commitment to replace the legacy application — it is a structural quarantine that ensures any failure in the legacy system cannot take the new system down with it.&lt;/p&gt;

&lt;p&gt;This matters in the boardroom because "we are isolating the legacy system from the new infrastructure" is a risk &lt;em&gt;treatment&lt;/em&gt;. It fits the framework they already understand. You are not asking them to abandon the known for the unknown. You are asking them to put a firebreak between the two.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reframe 2: Establish Tripwires
&lt;/h2&gt;

&lt;p&gt;If the business genuinely cannot commit to a migration timeline, do not argue. Accept that position — and then establish the conditions under which you will revisit it.&lt;/p&gt;

&lt;p&gt;A tripwire is a metric that, when crossed, triggers a mandatory re-evaluation. It converts "we are tolerating the risk" into "we are tolerating the risk &lt;em&gt;unless&lt;/em&gt;." Three have proven reliable across migrations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server load exceeding 85% for two-hour stretches, twice a week or more.&lt;/strong&gt; When headroom disappears, a single traffic spike becomes an outage. This is a performance ceiling indicator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer onboarding time exceeding four weeks.&lt;/strong&gt; When the lead developer who understands the system leaves, it becomes unmaintainable almost immediately. This is a knowledge fragility indicator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Severity-1 production bugs crossing a defined threshold per month.&lt;/strong&gt; When the rate accelerates month over month, the codebase is not aging — it is actively collapsing. This is a decay curve indicator.&lt;/p&gt;

&lt;p&gt;Write the thresholds down before the meeting, not after. Get them agreed and documented. When a tripwire is crossed, you do not need to restart the migration argument from scratch. The business already agreed to re-evaluate at that point. The conversation is already scheduled.&lt;/p&gt;

&lt;p&gt;Assign ownership of the tripwire document to the tech lead. One monthly report to the CTO — three metrics, three numbers, one line each. If a threshold is crossed, it triggers a conversation, not a crisis. That is the point.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Draft specific thresholds before the Go/No-Go meeting, not after. "We will revisit if things get bad" is not a tripwire — it is a vague intention that will be ignored. Numbers force a conversation. Vague language ends one.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Reframe 3: Pitch it as an Insurance Premium
&lt;/h2&gt;

&lt;p&gt;Stop pitching the migration as a way to prevent failure or speed things up. Neither framing lands. Failure is hypothetical. Speed is intangible.&lt;/p&gt;

&lt;p&gt;An insurance premium is not a cost — it is the price of optionality. When you pay for business interruption insurance, you are not predicting that your office will flood. You are buying the right to survive if it does. The migration is the same instrument. The business is not spending £200,000 on a rewrite. It is paying £200,000 for the right to hire any developer on the market rather than the two people who know the legacy framework, to launch a product line without a six-month archaeological dig, and to respond to a competitive threat in weeks instead of quarters.&lt;/p&gt;

&lt;p&gt;Finance teams call this Real Options Valuation — pricing a decision not by its direct return, but by the future choices it makes available. The migration does not just fix the current system. It buys agility. In a competitive market, agility has a calculable value. Help them calculate it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Counter-Argument You Will Hear
&lt;/h2&gt;

&lt;p&gt;At some point in the meeting, someone will say it: "We have already invested so much in this system. Walking away from that investment feels wasteful."&lt;/p&gt;

&lt;p&gt;This is the sunk cost fallacy. Money already spent is gone regardless of what you decide today. The only decision on the table is whether to spend &lt;em&gt;future&lt;/em&gt; money on a controlled migration or on the accumulating cost of keeping the legacy system alive.&lt;/p&gt;

&lt;p&gt;The reframe is simple: the historical investment does not change the calculation. What changes the calculation is the cost of the next year of the legacy system versus the cost of the migration. Run those numbers, not the historical ones.&lt;/p&gt;




&lt;h2&gt;
  
  
  Matching the Reframe to the Room
&lt;/h2&gt;

&lt;p&gt;Not everyone in the meeting responds to the same argument. Deliver the wrong reframe to the wrong person and you will get polite agreement and no decision.&lt;/p&gt;

&lt;p&gt;The architecture containment argument — firebreaks, quarantine, isolation — lands with a CTO or VP of Engineering. It speaks to technical risk in terms they already manage.&lt;/p&gt;

&lt;p&gt;The insurance premium argument — optionality, future agility, Real Options Valuation — lands with a CFO. It reframes a capital expenditure as a risk instrument, which is a category they already sign off on.&lt;/p&gt;

&lt;p&gt;The tripwire argument — specific thresholds, monthly reporting, mandatory re-evaluation — lands with a CEO or Managing Director. They are not interested in the technical details. They want to know when they need to pay attention and what the escalation trigger looks like.&lt;/p&gt;

&lt;p&gt;If you are presenting to all three in the same room, lead with the tripwire framing. It is the one that requires buy-in from everyone, and agreement on the thresholds gives you a basis for the other two conversations.&lt;/p&gt;




&lt;p&gt;The difference between a migration that ships and one that gets quietly abandoned is not the quality of the code. It is the quality of the conversation in that room.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How can we upgrade our Java codebase instantly with a command line tool?</title>
      <dc:creator>Kerrial Newham</dc:creator>
      <pubDate>Tue, 16 Apr 2024 14:08:48 +0000</pubDate>
      <link>https://dev.to/kerrialn/how-can-we-upgrade-our-java-codebase-instantly-with-a-command-line-tool-2fa9</link>
      <guid>https://dev.to/kerrialn/how-can-we-upgrade-our-java-codebase-instantly-with-a-command-line-tool-2fa9</guid>
      <description>&lt;p&gt;A very good friend of mine, &lt;a href="https://tomasvotruba.com/"&gt;Tomas Votruba&lt;/a&gt; created &lt;a href="https://getrector.com/"&gt;Rector&lt;/a&gt;, a command line tool for instant upgrades and automated refactoring in PHP. &lt;/p&gt;

&lt;p&gt;About three years ago, I mentioned creating the same tool for Java, hypothesizing that it would be incredibly lucrative as it seemed there were so many medium to large sized companies that used Java and had terrible legacy systems.&lt;/p&gt;

&lt;p&gt;It took me three years to put fingertips to keyboard, but I have done it. ‘How on earth does that work?’ I hear you doubting Thomas's heckle.  &lt;/p&gt;

&lt;p&gt;Well &lt;a href="http://javaupgrader.com/"&gt;JavaUpgrader&lt;/a&gt; is hugely inspired by Rector. &lt;/p&gt;

&lt;p&gt;The tool converts your code to Abstract Syntax Tree (AST) basically objects of code. &lt;br&gt;
There are a list of rules that can be applied to the AST, each rule has one very specific task, for example “ConstantNameToUpperSnakeCaseRule” This rule will only find class constants and change the name to upper snake case, which is a common convention. &lt;/p&gt;

&lt;p&gt;A group of rules are in a set, for example the “ConstantNameToUpperSnakeCaseRule” is part of the NamingSet, that way you can add many rules in one line in your config file. &lt;/p&gt;

&lt;p&gt;Let’s have a look a the config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.example.config&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.RuleList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.SetList&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.rules.RuleInterface&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.sets.SetInterface&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JavaUpgraderConfig&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;JavaUpgraderConfigInterface&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SetInterface&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;addSets&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SetList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NAMING_SET&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;


    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RuleInterface&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;addRules&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RuleList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEAD_CODE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The config file allows you to addSets or &lt;code&gt;addRules&lt;/code&gt;, in this case we have added the naming set which is comprised of 5 rules (for now) and we have also added the dead code rule, which will remove any code that isn’t being used. &lt;br&gt;
What does a rule look like I hear you ask? &lt;br&gt;
Let’s have a look at the &lt;code&gt;ConstantNameToUpperSnakeCaseRule&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.example.rules.naming&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.model.UpgraderFileModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.rules.RuleInterface&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.github.javaparser.ast.body.FieldDeclaration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConstantNameToUpperSnakeCaseRule&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;RuleInterface&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UpgraderFileModel&lt;/span&gt; &lt;span class="n"&gt;fileModel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fileModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAst&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FieldDeclaration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldDeclaration&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldDeclaration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isFinal&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;fieldDeclaration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getVariables&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;oldName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getNameAsString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;newName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;convertToUpperCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;});&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;convertToUpperCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getDescription&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Converts constant names from snake_case to upper snake case"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"ConstantNameToUpperCaseConverter"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getBeforeState&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"""
    public class Example {
        public static final int my_constant_value = 42;
    }
    """&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getAfterState&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"""
        public class Example {
            public static final int MY_CONSTANT_VALUE = 42;
        }
        """&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All rules must implement the &lt;code&gt;RuleInterface&lt;/code&gt; which requires us to have the following methods: &lt;br&gt;
getName,  getDescription, getBeforeState, getAfterState and execute.&lt;/p&gt;

&lt;p&gt;The name allows us to single out a rule by name, the description tells us what the rule does, the beforeState and afterState tells us what effect the rule will have on the code, but also is there for testing purposes, to make sure that is exactly what the rule does and finally the execute method actions the change of the rule. &lt;/p&gt;

&lt;p&gt;This is just the beginning, I’ll be creating sets to upgrade your code quality, ensure design pattern conventions and even migrate to different Java versions.&lt;/p&gt;

&lt;p&gt;If you are interested in the JavaUpgrader and want to find out more, please visit &lt;a href="http://javaupgrader.com/"&gt;JavaUpgrader&lt;/a&gt; join the waiting list or message me directly if you have a specific question. &lt;/p&gt;

</description>
      <category>java</category>
    </item>
  </channel>
</rss>
