<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ refactoring - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ refactoring - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 30 May 2026 14:17:50 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/refactoring/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Refactor Complex Codebases – A Practical Guide for Devs ]]>
                </title>
                <description>
                    <![CDATA[ Developers often see refactoring as a secondary concern that they can delay indefinitely because it doesn’t immediately contribute to revenue or feature development. And managers frequently view refactoring as "not a business need" until it boils ove... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-refactor-complex-codebases/</link>
                <guid isPermaLink="false">682df5a0f2057ab279952dbe</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webdev ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ refactoring ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ankur Tyagi ]]>
                </dc:creator>
                <pubDate>Wed, 21 May 2025 15:47:44 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747835131515/f6ea465a-9b14-4918-8943-87ec225b19b3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Developers often see refactoring as a secondary concern that they can delay indefinitely because it doesn’t immediately contribute to revenue or feature development.</p>
<p>And managers frequently view refactoring as "not a business need" until it boils over and becomes the most significant business need possible.</p>
<blockquote>
<p><em>"Oh, our software somehow works. We can't implement any new changes. And oh, everyone is quitting because work is miserable."</em></p>
</blockquote>
<p>In this article, I’ll walk you through the steps I use to refactor a complex codebase. We’ll talk about setting goals, writing tests, breaking up monoliths into smaller modules, verifying changes, making sure existing features still work, and keeping tabs on performance. I’ll also show you how to speed up reviews using AI tools.</p>
<p>By following these steps, you can turn complex, fragile code into a clean, reliable codebase your team can own.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXccvZ3sehF8oGifjnapnY9AUcPde9aKy9t_YEUeL8M2s3dcwxFq_bJLCSp_S02fIvfbwzpZfkz7e-2JQpXpzcdqELqs80EjkLLRpz0Uat6q9_RcRM5VQbjLoUxA2GlaqyeolsKGeA?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="code-refactoring" width="800" height="450" loading="lazy"></p>
<h2 id="heading-the-issue-of-technical-debt">The Issue of Technical Debt</h2>
<p>As projects grow and evolve, <a target="_blank" href="https://en.wikipedia.org/wiki/Technical_debt">technical debt</a> increases. Code that was once functional and manageable turns into an unmaintainable mess, where even small changes become risky and time-consuming.</p>
<p>Despite the obvious need for cleanup, refactoring rarely gets prioritized because there's always something more urgent, new features, bug fixes, and client demands.</p>
<p>I’ve had conversations with engineers, many of whom are working on enterprise software and are fully aware of their codebase's code smells and inconsistencies. They dislike the situation but feel powerless to change it.</p>
<p>So how do we shift from a culture of writing for pure functionality to a culture that values maintainability, especially for complex codebases?</p>
<p>It’s usually a mistake to completely halt new feature development for a long refactoring period (except perhaps in emergencies). Business needs still exist, and putting everything on hold can create tension and lost opportunities. It’s better to find a balance so you’re still delivering value to users even as you clean under the hood.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeZx-XKCA2DC6kQQe2-4NU07wKEm0_VZ4kqEjbF6u2vy2paRigdNRUGjr-_AoE6ueNjCxNjnB-mI7uroXFhJ0nFfvWzwYq2VUMsdsPhXu4KvGYSZcUN0nFmKg8U8WzgGJQAgKtUaw?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="Uncle-bob-take-on-refactoring" width="1600" height="518" loading="lazy"></p>
<p>While there is no one-size-fits-all solution, a structured approach can help teams introduce sustainable refactoring practices, even in environments where management is resistant. Let’s explore how this works.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents:</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-refactoring">What is Refactoring?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-preparing-for-refactoring">Preparing for Refactoring</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-secure-management-buy-in">Secure Management Buy-in</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-ensure-a-safety-net-with-automated-testing">Ensure a Safety Net with Automated Testing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-identify-high-risk-areas">Identify High-Risk Areas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-set-clear-refactoring-goals">Set Clear Refactoring Goals</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-techniques-for-refactoring-complex-codebases">Techniques for Refactoring Complex Codebases</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-identifying-and-isolating-problem-areas">1. Identifying and Isolating Problem Areas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-incremental-vs-big-bang-refactoring">2. Incremental vs. Big Bang Refactoring</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-breaking-down-monolithic-code">3. Breaking Down Monolithic Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-ensuring-backward-compatibility">4. Ensuring Backward Compatibility</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-handling-dependencies-and-tight-coupling">5. Handling Dependencies and Tight Coupling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-testing-strategiessafely-refactoring-with-confidence">6. Testing Strategies (Safely Refactoring with Confidence)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-7-refactoring-without-breaking-performance">7. Refactoring Without Breaking Performance</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-8-automate-code-reviews-with-ai-tools">8. Automate Code Reviews with AI Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-what-is-refactoring"><strong>What is Refactoring?</strong></h2>
<p>Many people all too often use the word "refactor" when they mean a targeted rewrite.</p>
<p>As Martin Fowler famously said,</p>
<blockquote>
<p><em>“Refactoring is a controlled technique for improving the design of an existing code base. Its essence is applying a series of small behavior-preserving transformations... However, the cumulative effect... is quite significant.”</em>​</p>
</blockquote>
<p>In practice, this means continuously polishing code to reduce complexity and technical debt.</p>
<p>While traditional software development follows a linear approach of designing first and coding second, real-world projects often evolve in ways that lead to structural decay. Refactoring counteracts this by continuously refining the codebase, transforming disorganized or inefficient implementations into well-structured, maintainable solutions.</p>
<p>A targeted rewrite is a focused overhaul of a specific aspect of an application, often affecting multiple parts of the codebase. It carries more risk than refactoring but is still controlled and contained.</p>
<h2 id="heading-preparing-for-refactoring">Preparing for Refactoring</h2>
<p>Even the most skilled refactoring effort can stall without proper preparation. Before you start moving code around, laying a foundation that will keep your work organized and your team on the same page is crucial.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcr3hNpzC9XPUVnG6d7uHuC977aYrG2VVOH-8E4WhzM5Rfz3vzPDUPTwJChrK0l7WUK8BLTzYr5-295_27ARWQvcmjufXOk68Bg8szUjEq3IFVCDO0XfTSRFy1LaxqyjvjVDNddsw?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="martin-fowler-on-refactoring" width="1600" height="364" loading="lazy"></p>
<p>Here are some steps you can take to ensure your refactoring efforts are successful.</p>
<h3 id="heading-secure-management-buy-in">Secure Management Buy-in</h3>
<p>As I’ve already discussed, getting time for refactoring can be difficult in feature-driven organizations. Often, management will accept refactoring investment if you can tie it to business outcomes, faster time to market, fewer outages (which translates to happier customers), and the ability to take on new initiatives.</p>
<p>Make those connections explicit. For example, you could say:</p>
<blockquote>
<p><em>“If we refactor our reporting engine now, it will make it feasible to add the analytics module next quarter, which unlocks a new revenue stream.”</em></p>
</blockquote>
<p>Or use data:</p>
<blockquote>
<p><em>“We spent 30% of our last sprint fixing bugs in module Y. After refactoring Y, we expect that to drop significantly, freeing time for new features.”</em></p>
</blockquote>
<p>Business-minded arguments help justify the balance.</p>
<h3 id="heading-ensure-a-safety-net-with-automated-testing">Ensure a Safety Net with Automated Testing</h3>
<p>As you refactor, tests are your safety net. Before modifying a component, write characterization tests around it if they don’t exist.</p>
<pre><code class="lang-python"><span class="hljs-comment"># example: characterization test for a legacy function</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">legacy_calculate_discount</span>(<span class="hljs-params">price, rate</span>):</span>
    <span class="hljs-comment"># ... complex logic you don't fully understand yet ...</span>
    <span class="hljs-keyword">return</span> price * (<span class="hljs-number">1</span> - rate/<span class="hljs-number">100</span>) <span class="hljs-keyword">if</span> rate &lt; <span class="hljs-number">100</span> <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_legacy_calculate_discount</span>():</span>
    <span class="hljs-comment"># capture existing behavior</span>
    <span class="hljs-keyword">assert</span> legacy_calculate_discount(<span class="hljs-number">100</span>, <span class="hljs-number">10</span>) == <span class="hljs-number">90</span>
    <span class="hljs-keyword">assert</span> legacy_calculate_discount(<span class="hljs-number">50</span>, <span class="hljs-number">200</span>) == <span class="hljs-number">0</span>
</code></pre>
<p>These tests capture the current behavior, so you’ll know if you accidentally change it. Unit tests, integration tests, and e2e tests all validate that refactoring hasn’t broken anything.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfWfke-9FxoQIPFwRWVoIWrYN7L40mEmhpdAUkcBm34mwzXJ0R8jXKH8rZ0HjAghAtQ-v6dTUYYvK0T8_QBgyfeab-7R50pnB6BgdDm9L4PkFwvwGlUYTHNo21f37fxMZYt3xeY?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="automated-testing-is-imp-for-refactoring" width="1600" height="432" loading="lazy"></p>
<p>It’s often worth investing time in setting up a continuous integration pipeline so that every change triggers automated tests. This gives rapid feedback and confidence that you’re not introducing regressions. Robust testing and CI/CD enable you to move faster and refactor with peace of mind.</p>
<pre><code class="lang-powershell"><span class="hljs-comment"># .github/workflows/ci.yml</span>
name: CI
on: [<span class="hljs-type">push</span>, <span class="hljs-type">pull_request</span>]
jobs:
  test:
    runs<span class="hljs-literal">-on</span>: ubuntu<span class="hljs-literal">-latest</span>
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup<span class="hljs-literal">-python</span>@v4
        with: python<span class="hljs-literal">-version</span>: <span class="hljs-string">'3.10'</span>
      - run: pip install <span class="hljs-literal">-r</span> requirements.txt
      - run: pytest -<span class="hljs-literal">-maxfail</span>=<span class="hljs-number">1</span> -<span class="hljs-literal">-disable</span><span class="hljs-literal">-warnings</span> <span class="hljs-literal">-q</span>
</code></pre>
<h3 id="heading-identify-high-risk-areas">Identify High-Risk Areas</h3>
<p>The first step is to figure out what to refactor. High-risk areas are parts of the code likely to cause bugs or slow development. Common signs include long methods, large classes, duplicate code, and complex conditional logic​.</p>
<p>Such code “smells” often hint at deeper design problems. Tools like static analysis can automatically flag these issues.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfS4aFy2hyRSq3UmgB2gQ8NN_-yUksNXcSavTtpnL8KIiWpGGidCSCstLKANZGOjJLqEF69wp-xjMGH6jrjurSaFtUIMS09vUaDgJ6vGtyabP-4QC5ISmT_cMvaaw6c2KlyVa1CKQ?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="SonarQube-dashboard" width="1600" height="743" loading="lazy"></p>
<p>For example, SonarQube will mark code smells (like high complexity or long methods) that increase technical debt​. Using SonarQube or similar tools, you can generate reports on code complexity (for example, cyclomatic complexity metrics​) and find hotspots in the codebase that need more attention.</p>
<h3 id="heading-set-clear-refactoring-goals">Set Clear Refactoring Goals</h3>
<p>Before refactoring code, define the goal.</p>
<p>Goals must be specific and measurable. For example, you might aim to reduce a class’s size or a function’s <a target="_blank" href="https://www.ibm.com/docs/en/raa/6.1.0?topic=metrics-cyclomatic-complexity">cyclomatic complexity</a> by a certain amount or to increase unit test coverage from 60% to 90%.</p>
<p>Each goal is tied to a measurable outcome: shorter methods, fewer if statements or classes with a single responsibility, faster execution for processing orders, higher test coverage, and no unused code. These targets will guide our refactoring plan and let us verify when we’ve succeeded.</p>
<p><strong>Tip:</strong> Write down your refactoring goals and share them with your team. This sets expectations that you’re not adding new features in this effort, just making the code cleaner and more robust. It also helps justify the time spent by showing the benefits (like more straightforward future additions and fewer bugs).</p>
<h2 id="heading-techniques-for-refactoring-complex-codebases">Techniques for Refactoring Complex Codebases</h2>
<h3 id="heading-1-identifying-and-isolating-problem-areas">1. Identifying and Isolating Problem Areas</h3>
<p>It can be overwhelming to decide where to start refactoring a large codebase. Not every part of the code needs refactoring – some areas are delicate or rarely touched.</p>
<p>The most impactful refactoring efforts typically target the “problem areas”: parts of the codebase that are overly complex, error-prone, or act as bottlenecks for development and performance. Identifying these areas is a crucial first step.</p>
<h3 id="heading-techniques-for-finding-hotspots">Techniques for Finding Hotspots</h3>
<h4 id="heading-team-knowledge-amp-developer-frustration">Team knowledge &amp; developer frustration</h4>
<p>Don’t underestimate the value of anecdotal information from the team. Which parts of the code do developers dread working in? Often, the team’s instincts point to areas that are hard to understand or modify (for example, “the accounting module is a black box, we hate touching it”). These could be areas to improve.</p>
<p>In my experience, simply asking, “If you had a magic wand, which part of the code would you rewrite?” yields very insightful answers.</p>
<h4 id="heading-code-complexity-metrics">Code complexity metrics</h4>
<p>Use static analysis tools to measure cyclomatic complexity, code duplication, large functions/classes, and so on. Files or modules with extremely high complexity numbers or thousands of lines are good candidates for scrutiny. But static complexity alone doesn’t tell the whole story – a file might be ugly but rarely touched.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc07SWwlu4GxU6AwoXQEHyyEcQY-6YMOEPr7b7Quhk5UvLD7qx9XyZla2SzP32eGFoYY_Xy-SYZQ9mOMX7Mxeq1YCnFXQxudsMNbvak9CLZfSOeRIvdll_pLW56sAmvRcPZMk36Rg?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="SonarQube" width="1600" height="1030" loading="lazy"></p>
<h4 id="heading-change-frequency-churn">Change frequency (Churn)</h4>
<p>Look at version control history to see which files are often changed, especially those associated with bug fixes or incidents.</p>
<h4 id="heading-hotspot-analysis">Hotspot analysis</h4>
<p>A robust approach combines complexity and change frequency to find “hotspots.” For example, a tool or technique plotting modules by their complexity and how often they change can highlight the problematic areas. CodeScene (a code analysis tool) popularized this: <em>hotspots</em> are parts of the code that are highly complex and frequently modified, indicating areas where “paying down debt has a real impact”​.</p>
<p>If a module is a mess and developers are in it every week, improving that module will likely yield outsized benefits (fewer bugs, faster adds).</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdJkGfbDK6UFDN9hqzeyCMBWmajADhAMJwzSouyMNz_63o9SRNfOly9AP_XiY2jqfi02fHSIFkMBCfstkjJfkxVB-NaHCSit0xssTYfztZ2BRQZmqYr_lTc3R750-1-lrJi7eeViQ?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="code-health-dashboard" width="1542" height="1600" loading="lazy"></p>
<h4 id="heading-performance-bottlenecks-and-crashes">Performance bottlenecks and crashes</h4>
<p>Some parts of the codebase become targets for refactoring because they cause frequent performance problems or outages. For instance, if a specific service or job crashes often or can’t keep up with the load, you might need to refactor it for stability.</p>
<h3 id="heading-how-to-isolate-problem-areas">How to Isolate Problem Areas</h3>
<p>Once you’ve identified a hotspot or problem area, the next challenge is isolating it so you can refactor safely. In a complex system, nothing lives in complete isolation. That problematic module likely interacts with many others.</p>
<p>Here are strategies to isolate and tackle it:</p>
<h4 id="heading-break-dependencies-create-seams">Break dependencies (Create seams)</h4>
<p>Michael Feathers (in <em>Working Effectively with Legacy Code</em>) introduced the concept of “seams” – places where you can cut into a codebase to isolate a part for testing or refactoring. This might mean introducing an interface or abstraction between components so you can work on one side independently.  </p>
<p>For example, suppose PaymentService is tightly coupled to StripeGateway, with direct calls scattered throughout the code.</p>
<pre><code class="lang-python"><span class="hljs-comment"># payment_service.py</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">charge_customer</span>(<span class="hljs-params">order_id, amount</span>):</span>
    <span class="hljs-comment"># Hardcoded dependency to Stripe</span>
    stripe = StripeGateway()
    stripe.charge(order_id, amount)
</code></pre>
<p>To isolate and refactor the payment logic safely, you can introduce a <code>PaymentProcessor</code> interface and have <code>PaymentService</code> depend on that interface instead. Then, create an adapter like StripeAdapter that implements PaymentProcessor and delegates to the existing Stripe logic.</p>
<p>This way, you can safely refactor or even replace the Stripe integration behind the StripeAdapter without impacting <code>PaymentService</code> or any other module that uses it. As long as the <code>PaymentProcessor</code> interface is honored, the rest of the system remains unaffected.</p>
<pre><code class="lang-python"><span class="hljs-comment"># interfaces.py</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentProcessor</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">charge</span>(<span class="hljs-params">self, order_id, amount</span>):</span>
        <span class="hljs-keyword">raise</span> NotImplementedError


<span class="hljs-comment"># stripe_adapter.py</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StripeAdapter</span>(<span class="hljs-params">PaymentProcessor</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">charge</span>(<span class="hljs-params">self, order_id, amount</span>):</span>
        <span class="hljs-comment"># Internally still uses Stripe</span>
        stripe = StripeGateway()
        stripe.charge(order_id, amount)


<span class="hljs-comment"># payment_service.py (Refactored)</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentService</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, processor: PaymentProcessor</span>):</span>
        self.processor = processor

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">charge_customer</span>(<span class="hljs-params">self, order_id, amount</span>):</span>
        self.processor.charge(order_id, amount)
</code></pre>
<h4 id="heading-branch-by-abstraction">“Branch-by-abstraction”</h4>
<p>This technique is related to the above and is often used in continuous delivery. The idea is to add a layer of abstraction (like an interface or proxy) in front of the old code, have both old and new code implementations behind it, and then gradually shift usage from the old to the new implementation. For a while, you might have a temporary state where both versions exist (perhaps toggled by a config or feature flag).</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcaFoXSHVYTBz_1DOsucPkvwGQwfo9qrvhPYvvjYOXQsLIh2MCTfseB1g9SOfijpdKMwcwmK4lfPWcyhn4vf5gaFwdliKUZUGDOcQVJ0qupRLjvnhFrSm5LZfe8OoqZtZkHkj9IXw?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="Branch-by-abstraction" width="1194" height="726" loading="lazy"></p>
<p>This is similar to how the strangler fig pattern works at an architectural level. It’s a bit of extra work (since you maintain two paths for a while), but it allows you to migrate functionality and fall back if needed incrementally.</p>
<p>Aim to identify the 20% of the code causing 80% of the problems. Focus your refactoring energy there for maximum impact. When you do, create a plan to isolate that area via abstractions, interfaces, modules, or other means so that you can work on it with minimal risk of side effects. The more you can contain the blast radius of a refactoring, the more confidently you can move forward.</p>
<h3 id="heading-2-incremental-vs-big-bang-refactoring">2. Incremental vs. Big Bang Refactoring</h3>
<p>One of the first strategic decisions is approaching the refactor <strong>incrementally</strong> or going for a <strong>“big bang”</strong> overhaul. In most cases, an incremental approach is preferable, but there are scenarios where more significant coordinated refactoring steps are considered.</p>
<p><strong>Let’s break down what these mean:</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># before: one large function with multiple responsibilities</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_order</span>(<span class="hljs-params">order</span>):</span>
    validate(order)
    apply_discount(order)
    save_to_db(order)
    send_confirmation(order)
    log_metrics(order)
    update_loyalty_points(order)
    <span class="hljs-comment"># potentially more steps </span>

<span class="hljs-comment"># after: refactored incrementally into clearer, smaller units</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_order</span>(<span class="hljs-params">order</span>):</span>
    validate(order)
    apply_discount(order)
    persist_and_notify(order)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">persist_and_notify</span>(<span class="hljs-params">order</span>):</span>
    save_to_db(order)
    send_confirmation(order)
    log_metrics(order)
    update_loyalty_points(order)
</code></pre>
<h4 id="heading-incremental-refactoring">Incremental refactoring</h4>
<p>This means making small, manageable changes over time rather than attempting a massive overhaul in one shot. The system should remain functional at each step (even internally in transition). The advantage is risk mitigation: each small change is less likely to go wrong, and it’s easier to pinpoint and fix if it does.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdaSmnIWRE9FKNmmABBzc6Tk6KFwsj29FQ2YwyQ_kWqryheb0yUdpec51lQHg5XahoxKgCm4vv9twD849H3Yo5dn0678tuGih9Z-HfBBCfhBngs4YhpH6x2pjzqnAeDVYGohXHvDQ?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="Incremental refactoring" width="640" height="379" loading="lazy"></p>
<p>Incremental delivery lets you confirm changes in production and makes diagnosing issues easier since you’re only changing one small thing at a time​. It also means the system keeps running during the refactor, so there’s less pressure to rush to “get the system back to working condition”​. If priorities shift, you can pause after some increments and still have a working product.</p>
<h4 id="heading-big-bang-refactoring-rewrite">Big bang refactoring (Rewrite)</h4>
<p>This is the “tear it down and rebuild” approach. You stop adding new features, possibly freeze the code for a period, and devote a considerable effort to redesigning or rewriting a significant portion (or the entirety) of the system. The idea is to emerge on the other side with a <em>brand new, clean</em> system.</p>
<p>So when (if ever) is a big bang justified? Perhaps when the existing system is truly untenable – for example, an outdated technology that <strong>must</strong> be replaced (such as a platform that can’t meet new performance or security requirements or code written in a language no longer supported). Even then, wise teams often simulate a big bang by breaking it into stages or developing the new system in parallel.</p>
<p>Whenever possible, favor an incremental refactoring strategy. Teams successfully pull off massive transformations by treating the big refactor as a series of mini-refactors under a shared vision.</p>
<h3 id="heading-3-breaking-down-monolithic-code">3. Breaking Down Monolithic Code</h3>
<p>Many complex codebases start life as a single monolithic application, one deployable, a single code project, or a tightly coupled set of modules all maintained and released together.</p>
<p>Over time, monoliths can become unwieldy, builds take forever, a change in one area can unintentionally affect another, and teams can be complex to scale because everyone is stepping on each other’s toes in the same code. A common refactoring challenge for senior engineers is modularising or splitting a monolith into more manageable pieces.</p>
<pre><code class="lang-python"><span class="hljs-comment"># define the interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentProcessor</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">charge</span>(<span class="hljs-params">self, amount</span>):</span> ...

<span class="hljs-comment"># old implementation</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LegacyProcessor</span>(<span class="hljs-params">PaymentProcessor</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">charge</span>(<span class="hljs-params">self, amount</span>):</span>
        <span class="hljs-comment"># original code</span>

<span class="hljs-comment"># new implementation behind a feature flag</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewProcessor</span>(<span class="hljs-params">PaymentProcessor</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">charge</span>(<span class="hljs-params">self, amount</span>):</span>
        <span class="hljs-comment"># cleaner code</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_processor</span>():</span>
    <span class="hljs-keyword">if</span> config.feature_new_payment:
        <span class="hljs-keyword">return</span> NewProcessor()
    <span class="hljs-keyword">return</span> LegacyProcessor()

<span class="hljs-comment"># usage remains the same</span>
processor = get_processor()
processor.charge(<span class="hljs-number">100</span>)
</code></pre>
<h4 id="heading-strategies-for-modularization">Strategies for modularization.</h4>
<ul>
<li><p><strong>Layer separation:</strong> Start by enforcing logical layer boundaries. For example, separate the user interface code from business logic and separate business logic from data access. In a messy monolith, these concerns often get mixed together. By organizing the code into layers (even within the same repository), you can limit the ripple effect of changes.</p>
</li>
<li><p><strong>Domain-based modularization:</strong> If your system spans multiple business domains or functional areas, consider splitting along those lines. For example, an e-commerce monolith might be separated into modules like Accounts, Orders, Products, Shipping, and so on.<br>  Each could become a subsystem or a package. The goal is to minimize the information these modules need to know about each other’s internals (high cohesion within modules and clear APIs between them).</p>
</li>
<li><p><strong>Microservices or services extraction:</strong> In recent years, the trend has been to break monoliths into microservices, independent services that communicate over APIs. This form of architectural refactoring can significantly improve independent deployability and scalability. But it’s a significant undertaking with complexities (distributed systems, network calls, and so on). If you decide to go this route, do it gradually.<br>  A proven method is the <strong>strangler fig pattern</strong> mentioned earlier: you pick one piece of functionality and rewrite or extract it as a separate service, redirect traffic or calls to the new service. At the same time, the rest of the monolith remains intact and iteratively does this for other pieces​.</p>
</li>
<li><p><strong>Modular monolith:</strong> Not every system needs to go full microservices. There’s an approach called a modular monolith, essentially structuring your single application into well-defined modules that communicate via explicit interfaces (almost like internal microservices but without the overhead of separate deployments).</p>
</li>
</ul>
<p>This can give you many microservices' advantages (clear boundaries, separate development responsibility) while avoiding operational complexity.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfLiNAEDyOsR4G_q1oQS3jpSenci3XDJRm10Gy3picTpaO9uHwme2H3YkbJF-Jrvqq3Q-QMxGjJJwy04mqUf1a7D8IRsCDER5pHBT6GTMPRkao5EXXIFGtj4Iki15mOHmRKRLTiWw?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="microservices' advantages" width="1087" height="744" loading="lazy"></p>
<ul>
<li><strong>Identify shared utilities vs. truly independent components:</strong> In breaking down a monolith, some code is widely shared (like utility functions or cross-cutting concerns such as authentication). It might make sense to factor those into libraries or services <em>first</em>, as they will be needed by whatever other pieces you split out.</li>
</ul>
<p>While breaking down a monolith, maintaining functionality during the transition is essential. Techniques like backward compatibility (discussed next) and thorough testing will be your safety net.</p>
<p>Finally, be prepared for the team workflow to change. If you move to microservices, teams might take ownership of different services, requiring more DevOps and communication across teams. If you keep a modular monolith, enforce code ownership or review rules to keep the modules from tangling up again (for example, you might restrict direct database access from one module to another’s tables, and so on).</p>
<h3 id="heading-4-ensuring-backward-compatibility">4. Ensuring Backward Compatibility</h3>
<p>A critical concern during large refactoring is: <em>Will our changes break existing contracts</em>?</p>
<p>In other words, can other systems, modules, or clients that rely on our code work as expected after we refactor? Backward compatibility is especially important if your codebase provides public APIs (to external customers or other teams), data persisted in a certain format, configuration files that users have written, etc.</p>
<p>Here are some strategies and considerations to maintain backward compatibility:</p>
<p>Suppose you have a widely-used function like <code>send_email(to, subject, body)</code>. You want to refactor the internal logic to support additional features like HTML formatting, but you don’t want to break existing callers.</p>
<p>Instead of changing the function signature, you keep the public API unchanged and delegate to a new internal function:</p>
<pre><code class="lang-python"><span class="hljs-comment"># original API</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_email</span>(<span class="hljs-params">to, subject, body</span>):</span>
    <span class="hljs-comment"># send mail...</span>

<span class="hljs-comment"># refactored internals, keep signature</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_email</span>(<span class="hljs-params">to, subject, body</span>):</span>
    sendv2(to=to, subject=subject, body=body)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sendv2</span>(<span class="hljs-params">to, subject, body, html=True</span>):</span>
    <span class="hljs-comment"># new implementation with HTML support</span>
</code></pre>
<p>The internal <code>send_email_v2()</code> function adds new capabilities like HTML formatting, but older code using <code>send_email()</code> still works without any modifications.</p>
<p>If you're introducing a new, improved version like <code>send_email_v2(to, subject, body, html=True)</code>, it's good practice to:</p>
<ul>
<li><p>Mark the old version (send_email) as deprecated in documentation.</p>
</li>
<li><p>Ensure the old version internally calls the new one.</p>
</li>
<li><p>Give other teams time to migrate at their own pace.</p>
</li>
</ul>
<h4 id="heading-use-versioning-for-external-apis">Use versioning for external APIs</h4>
<p>If your system provides an HTTP API or similar to external clients, the safest route for major changes is to version the API. Introduce a v2 API endpoint for the refactored logic, keep v1 running (maybe internally calling v2 or using a translation layer). Clients can move to v2 at their own pace.</p>
<p>It’s extra work to maintain two APIs temporarily, but it prevents a breaking change from angering users or causing outages. Always communicate changes clearly and provide migration guides if applicable.</p>
<h4 id="heading-have-a-clear-deprecation-policy">Have a clear deprecation policy</h4>
<p>Make sure there’s a policy (and communication) around how long deprecated features will be supported. For internal APIs, maybe it’s one release cycle. For external ones, maybe multiple cycles or never removal without a major version bump. A good practice is to announce deprecation early.</p>
<p>If you’re exposing an HTTP API, consider introducing a new versioned endpoint (for example, <strong>/api/v2/send_email</strong>) and maintain the older <strong>/api/v1/send_email temporarily</strong>. Internally, v1 might call v2 with default parameters, ensuring behavior stays consistent for existing clients.</p>
<p>In summary, maintain backward compatibility whenever possible, and implement a clear deprecation policy for anything you do change​.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe3xM4som_GQrtHXI3NNR0G-4KJ-1D2YO-JbNdT75IxZ5_upcBRDnOVp7krEESiqwwtXg18pDypLq3VxDr44Hof76cs8HajOZy2w0FZ50kWmPk6Y7EwNByNLNrqAokmhmmL5sP3AA?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="Clear deprecation policy" width="768" height="493" loading="lazy"></p>
<h4 id="heading-write-adapter-or-compatibility-layers">Write adapter or compatibility layers</h4>
<p>In some cases, you can write an adapter to bridge old and new systems. For instance, suppose you refactor the underlying data model of your application, but you still have old configuration files in the old format. Rather than forcing all those files to be rewritten immediately, you could write a small adapter that translates the old format to the new one at runtime (or during startup). This way, old data continues to work. </p>
<h4 id="heading-test-for-compatibility">Test for compatibility</h4>
<p>Include tests that specifically ensure backward compatibility. For instance, if you have a public API, keep a suite of tests using the old API contracts and run them against the refactored code, they should still pass. </p>
<p>In summary, ensure that as you refactor, the external behavior and contracts remain consistent. This careful approach protects your users and downstream systems, allowing you to reap the internal benefits of refactoring without causing external chaos.</p>
<h3 id="heading-5-handling-dependencies-and-tight-coupling">5. Handling dependencies and tight coupling</h3>
<p>One of the hairiest aspects of refactoring a large codebase is dealing with deeply interdependent code. Complex systems often suffer from tight coupling. Module A assumes details about Module B and vice versa, global variables or singletons are used all over, or a change in one place ripples through half the codebase.</p>
<p>Reducing coupling is a significant aim of refactoring because it makes the code more modular, meaning each piece can be understood, tested, and changed independently. So, how do we gradually loosen the coupling in a legacy system?</p>
<p>Let’s go over some strategies to reduce coupling.</p>
<h4 id="heading-introduce-interfaces-or-abstraction-layers">Introduce interfaces or abstraction layers</h4>
<p>A very effective way to decouple is to put an interface between components. For example, if you have a class that directly queries a database, introduce an interface and have the class use that instead. The underlying database code implements the interface.</p>
<pre><code class="lang-python"><span class="hljs-comment"># before: direct instantiation</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.repo = OrderRepository()

<span class="hljs-comment"># after: inject dependency</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, repo</span>):</span>
        self.repo = repo

<span class="hljs-comment"># wiring up in application startup</span>
repo = OrderRepository(db_conn)
service = OrderService(repo)
</code></pre>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfuMNvzC4x3X0EOgoRXzflfOv4C-Dxzc2Tm16KA0NdZcOH0nK300LUwcNzXCL6iqu0rhknHiVhnQN4csDCYUupQLc4Kt6Q4c7d1Pi47NfrXKoF9rhXCUMAhtozsDpFMVT2lo2OX5Q?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="Introduce interfaces or abstraction layers" width="1600" height="441" loading="lazy"></p>
<p>Now, that class no longer depends on how the data is fetched. Applying the dependency inversion principle depends on abstractions, not concretions.</p>
<h4 id="heading-use-dependency-injection">Use dependency injection</h4>
<p>Once you have interfaces, use dependency injection to supply concrete implementations. Many frameworks support DI containers, or you can do it manually (passing in dependencies via constructors). Dependency injection means code A doesn’t instantiate code B itself – instead, B is passed into A.  </p>
<p>This approach also makes unit testing easier (you can inject mock dependencies).</p>
<h4 id="heading-facades-or-wrapper-services">Facades or wrapper services</h4>
<p>If a particular subsystem is heavily entangled with others, consider creating a Facade, an object that provides a simplified interface to a larger body of code. Other parts of the system are then called the Facade, not the many internal methods of the subsystem. Internally, the subsystem can be refactored (even split into smaller pieces) as long as the Facade’s outward interface remains consistent.</p>
<p>This is similar to how microservices work (other services don’t care how one service is implemented internally – they just call its API), but you can do it in-process, too.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe_X2G_VNTR-I2EIp86SgPD3Zlks70Q4iG3BsqIs94PMgh-_qNfRk7ogT4mqONP7qXzg8PpN92k342-2nH6ertfy32Ga6SFH3PdSLwxP4US9PPjMi6Rqc9hy-gHbSKVzvTvYmTzOQ?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="Facades or wrapper services" width="1600" height="1549" loading="lazy"></p>
<h4 id="heading-gradual-replacement-parallel-run">Gradual replacement (Parallel Run)</h4>
<p>If a specific component is to be replaced with a new implementation, it can help to run them in parallel for a while. For instance, if you have a spaghetti module that you want to redo correctly, you could leave the spaghetti code in place for legacy calls but start routing new calls to the new module.</p>
<p>The result is a codebase where changes in one area (hopefully) won’t unpredictably break another, a key property of a maintainable system.</p>
<h3 id="heading-6-testing-strategies-safely-refactoring-with-confidence">6. Testing Strategies (Safely Refactoring with Confidence)</h3>
<p>A robust testing strategy will give you the confidence to make sweeping changes because you’ll know quickly if something important breaks. Here’s how to approach testing in the context of a large refactoring:</p>
<h4 id="heading-establish-a-baseline-with-regression-tests">Establish a baseline with regression tests</h4>
<p>Before you even begin refactoring a particular component, make sure you have tests that cover its current behavior. You're lucky if the codebase already has a good test suite, but many legacy systems have inadequate tests.</p>
<p>One of the first tasks in those cases is often writing <strong>characterization tests</strong>. A characterization test is a test that documents what the system <em>currently does</em>, not what we think it should do​.</p>
<p>As Feathers says, “a characterization test is a test that characterizes the actual behavior of a piece of code.” This allows you to take a snapshot of what it does and ensure that it doesn’t change​.</p>
<p>This gives you a safety net so you can refactor with confidence that you’re not introducing regressions​. Use automated test suites to help things run smoothly (unit, integration, end-to-end).</p>
<h4 id="heading-continuous-integration-ci">Continuous integration (CI)</h4>
<p>It is highly recommended that testing be integrated into a CI pipeline that runs on every commit or merge. This way, you catch a bug during refactoring as soon as you introduce it, tightening the feedback loop.</p>
<h4 id="heading-canary-releases-and-feature-flags">Canary releases and feature flags</h4>
<p>Beyond pre-release testing, consider strategies for safely deploying refactored code. A canary release involves rolling out the change to a small subset of users or servers first, observing it, and then gradually expanding​.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfAif0ftiqEhiRPDygrmhtzSsfrctq6ZPfJnMg04GwKmxKk-NFiP9GjEGE9rfz7U_WKhRcBYSBYlirjKwzr-PvfZz2FJpEWS6U0UqNh-WayiVM5BGIyz3sabSX-zdKKA0j_ojvhIA?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="Canary releases and feature flags" width="593" height="210" loading="lazy"></p>
<p>This is great for catching issues that tests might miss (for example, performance issues or edge cases in production data). If the canary looks good (no errors, metrics are healthy), you proceed to full rollout. If not, you rollback quickly—with only a small impact scope.</p>
<h4 id="heading-performance-and-load-testing">Performance and load testing</h4>
<p>If performance is a concern, incorporate performance tests into your strategy. This can be done in a staging environment. You might reconsider your approach or optimize the new code if you see a significant regression.</p>
<h4 id="heading-testing-legacy-code-lacking-tests">Testing legacy code lacking tests</h4>
<p>If you’re dealing with a part of the system with zero tests (not uncommon in older code), prioritize getting at least some coverage there. There are also techniques like <strong>approval testing</strong> (where you generate output and have a human approve it as correct, then use that as a baseline for future tests). The key is not to refactor entirely in the dark; give yourself at least a flashlight in the form of tests!</p>
<p>In sum, a strong testing strategy is non-negotiable for refactoring complex systems. It’s your safety net, early warning system, and guide to know that your “cleanup” hasn’t broken anything vital.</p>
<h3 id="heading-7-refactoring-without-breaking-performance">7. Refactoring Without Breaking Performance</h3>
<p>A common concern when refactoring is whether these cleaner code changes will make my system slower or more resource-hungry. Ideally, refactoring is about the internal structure and shouldn’t change external behavior, and performance is part of the behavior.</p>
<p>In theory, performance should remain the same if you don’t change algorithms or data structures in a way that affects complexity.</p>
<p>In practice, though, performance can be inadvertently affected by refactoring. The new code may be more readable but uses more memory, or perhaps a critical caching mechanism was removed in the spirit of simplicity.</p>
<p><strong>Senior engineers need to be mindful of performance-sensitive parts of the system when refactoring and take steps to avoid regressions (or even improve performance where possible).</strong></p>
<p>Here’s how to refactor with performance in mind:</p>
<h4 id="heading-identify-performance-critical-code-paths">Identify performance-critical code paths</h4>
<p>Not all codes are equal regarding performance impact. If you refactor them, treat it almost like a functional change: you must re-measure performance afterwards. You have more leeway for parts of the code that run rarely or are not bottlenecks.</p>
<h4 id="heading-use-profiling-before-and-after">Use profiling before and after</h4>
<p>A profiler is a tool that measures where time is spent in your code or how memory is allocated. It’s beneficial to run a profiler on the code before refactoring a module to see how it behaves, and then run it after to compare. If you see, for example, that after refactoring, a function now shows up as taking 30% of execution time (when it was negligible before), that’s a red flag. Maybe the new code calls it more times than before.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> cProfile, pstats
<span class="hljs-keyword">from</span> mymodule <span class="hljs-keyword">import</span> slow_function

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">profile</span>(<span class="hljs-params">fn</span>):</span>
    profiler = cProfile.Profile()
    profiler.enable()
    fn()
    profiler.disable()
    stats = pstats.Stats(profiler).strip_dirs().sort_stats(<span class="hljs-string">'cumtime'</span>)
    stats.print_stats(<span class="hljs-number">10</span>)

<span class="hljs-comment"># run before refactor</span>
profile(<span class="hljs-keyword">lambda</span>: slow_function())

<span class="hljs-comment"># after you refactor slow_function(), re-run and compare stats</span>
</code></pre>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd1xNcjypguN9JbN7JtBhAtBkfDrtCV6IwOORRUVT5rOAha_I2GQx3vgKRAjlxpeeUIGLTETRR6J3EnS2y95DY6ypiH95DQJT0vRfcyxv2KIz99hPXa0O8JjTzxpi5eSsk3spN6EQ?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="profiler-dashboard" width="1464" height="1136" loading="lazy"></p>
<h4 id="heading-when-possible-improve-performance-through-refactoring">When possible, improve performance through refactoring</h4>
<p>On the flip side, refactoring can help performance.</p>
<p>For example, by refactoring duplicated code into one place, you can use better caching in that one place. So, watch for performance improvement opportunities that arise naturally as you refactor.</p>
<p>Performance should be treated as part of the “external behavior” that needs to be preserved in a good mindset. Refactoring should ideally not make things slower for users. To ensure that, incorporate performance checks into your plan, especially for critical sections. Measure, don’t guess. The end goal is a codebase that is both clean <strong>and</strong> fast enough.</p>
<h3 id="heading-8-automate-code-reviews-with-ai-tools">8. Automate Code Reviews with AI tools</h3>
<p>Refactoring code is an ongoing process, not a one-time event – AI code review tools help enforce clean-code standards, catch smells early, and reduce the repetitive tasks that can bog down human reviewers. This frees your engineers to focus on deeper architectural or domain-specific issues.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfWs-ZM80TK_JcjwyPEnywdJl6Tf4G6gYFa1cN_J2ugTlniaGr4a397JuUj721m7kUw0EKMnzYHykpHJdG_aW7w3_B2J91bLL1UoaabdNsmH1uckMJHcFVpAhqZM2r855AsVYwDJg?key=nBTgfzmVkL2-N7DBMJ6e6gyk" alt="CodeRabbit-ai-code-reviewer-tool" width="1600" height="779" loading="lazy"></p>
<p>One powerful option is <a target="_blank" href="https://www.coderabbit.ai/">CodeRabbit</a>, an AI-driven review platform designed to cut review time and bugs in half.</p>
<p>Here’s how it works and why it can boost your refactoring workflow:</p>
<h4 id="heading-ai-powered-contextual-feedback">AI-powered contextual feedback</h4>
<p>CodeRabbit analyzes pull requests line by line, applying both advanced language models and static analysis under the hood. It flags potential bugs, best-practice deviations, and style issues before a human opens the PR.</p>
<p>Some other features include:</p>
<ul>
<li><p><strong>Auto-generated summaries and 1-click fixes</strong> – Summarize large PRs and apply straightforward fixes instantly.</p>
</li>
<li><p><strong>Real-time collaboration and AI chat</strong> – Chat with the AI for clarifications, alternate code snippets, and instant feedback.</p>
</li>
<li><p><strong>Integrates with popular dev platforms</strong> – Supports GitHub, GitLab, and Azure DevOps for seamless PR scanning.</p>
</li>
</ul>
<p>CodeRabbit even has a free AI code reviews in VS Code and with this <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=CodeRabbit.coderabbit-vscode">VS Code extension</a>, you can get the most advanced AI code reviews directly in your code editor, saving review time, catching more bugs, and helping you in refactoring.</p>
<h2 id="heading-summary">Summary</h2>
<p>Refactoring a complex enterprise codebase is like renovating a large building while people still live in it without collapsing the structure.</p>
<p>Refactoring should be an ongoing process. You prevent the codebase from decaying by incorporating these practices into your regular development (perhaps allocating some time each sprint for refactoring or doing it opportunistically when touching your code). Each minor refactoring should not be too complex, and the cumulative effect is significant.</p>
<p>As <a target="_blank" href="https://martinfowler.com/">Martin Fowler</a> puts it, a series of small changes can lead to a significant improvement in design.</p>
<p>That's it for this blog. I hope you learned something new today.</p>
<p>If you want to read more interesting articles about developer tools, React, Next.js, AI and more, then I'll encourage you to checkout my <a target="_blank" href="https://www.devtoolsacademy.com/">blog</a>.</p>
<p>Some of the new and interesting articles I've written in the last 24 months.</p>
<ul>
<li><p><a target="_blank" href="https://www.devtoolsacademy.com/blog/cursor-vs-windsurf/">Cursor vs Windsurf</a></p>
</li>
<li><p><a target="_blank" href="https://clerk.com/blog/nextjs-role-based-access-control">How to Implement Role-Based Access Control in Next.js</a></p>
</li>
<li><p><a target="_blank" href="https://www.devtoolsacademy.com/blog/ai-code-reviewers-vs-human-code-reviewers/">AI Code Reviewers vs Human Code Reviewers</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/how-i-built-a-custom-video-conferencing-app-with-stream-and-nextjs/">How to Build a Custom Video Conferencing App with Stream and Next.js</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/how-to-perform-code-reviews-in-tech-the-painless-way/">How to Perform Code Reviews in Tech – The Painless Way</a></p>
</li>
</ul>
<p>You can get in touch if you have any questions or corrections. I’m expecting them.</p>
<p>And if you found this blog useful, please share it with your friends and colleagues who might benefit from it as well. Your support enables me to continue producing useful content for the tech community.</p>
<p>Now it’s time to take the next step by subscribing to my <a target="_blank" href="https://bytesizedbets.com/"><strong>newsletter</strong></a> and following me on <a target="_blank" href="https://twitter.com/theankurtyagi"><strong>Twitter</strong></a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Refactor to Configurable Dependency in 5 Steps ]]>
                </title>
                <description>
                    <![CDATA[ By Bertil Muth Configurable Dependency, also known as Dependency Injection, is a pattern that enables you to switch dependencies of your application. The term was coined by Alistair Cockburn. Say your application has a GUI. But your administrator wan... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/refactoring-to-configurable-dependency-in-5-steps/</link>
                <guid isPermaLink="false">66d45dea4a7504b7409c335b</guid>
                
                    <category>
                        <![CDATA[ dependency injection ]]>
                    </category>
                
                    <category>
                        <![CDATA[ refactoring ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 19 Aug 2022 20:42:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/diana-polekhina-ONuLIzB0UtA-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Bertil Muth</p>
<p>Configurable Dependency, also known as Dependency Injection, is a pattern that enables you to switch dependencies of your application. The <a target="_blank" href="https://web.archive.org/web/20170624023207/http://alistair.cockburn.us/Configurable+Dependency">term</a> was coined by Alistair Cockburn.</p>
<p>Say your application has a GUI. But your administrator wants to use certain functions via the console. Or your production code calls an external service. But your tests shouldn’t call the service, since it doesn’t provide reliable results. Or the service isn’t always available.</p>
<p>Here’s where a Configurable Dependency is helpful. Depending on context, you use one dependency or the other.</p>
<p>A lot of articles attempt to explain the pattern. But they embed it in a broader context, like ports and adapters architecture. That makes understanding harder than necessary. I know, I’ve written such articles myself.</p>
<p>On top of that, many articles focus on greenfield applications. But most of us have to maintain applications that already exist.</p>
<p>Let’s start with a simple class that has a hard-wired dependency. Then we'll refactor it to a class that has a Configurable Dependency. </p>
<p>The example is trivial, but the refactoring steps are generally applicable to your own application if you’re in a similar situation.</p>
<p>I’ll refer to an example <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency">GitHub project</a> in the article. It shows the steps to perform, in its commit history. At the end of the article, there are appendices for IntelliJ IDEA and Eclipse. They show how to do the refactoring steps in your IDE.</p>
<h1 id="heading-the-calculator-example">The Calculator Example</h1>
<p>Say you have a class called <code>Calculator</code>. It’s the equivalent of “business logic”. At the end of each calculation, it prints the result to the screen. In a real world application, it might save something to a database instead.</p>
<p><a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/3d8540dd9566cb48f29902b9c9e10292cf8f7560/src/main/java/example/Calculator.java">Here</a>’s the code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Calculator</span><span class="hljs-params">()</span></span>{
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">long</span> one, <span class="hljs-keyword">long</span> two)</span> </span>{
        <span class="hljs-keyword">long</span> result = one + two;
        printResult(result);
        <span class="hljs-keyword">return</span> result;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">sub</span><span class="hljs-params">(<span class="hljs-keyword">long</span> one, <span class="hljs-keyword">long</span> two)</span> </span>{
        <span class="hljs-keyword">long</span> result = one - two;
        printResult(result);
        <span class="hljs-keyword">return</span> result;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printResult</span><span class="hljs-params">(<span class="hljs-keyword">long</span> result)</span> </span>{
        System.out.println(<span class="hljs-string">"The result is: "</span> + result);
    }
}
</code></pre>
<p>Now if you want to test that class, your <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/3d8540dd9566cb48f29902b9c9e10292cf8f7560/src/test/java/example/CalculatorTest.java">test code</a> may look like this:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> org.junit.jupiter.api.Assertions.*;
<span class="hljs-keyword">import</span> org.junit.jupiter.api.*;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CalculatorTest</span> </span>{
    <span class="hljs-keyword">private</span> Calculator calculator;

    <span class="hljs-meta">@BeforeEach</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span> </span>{
        calculator = <span class="hljs-keyword">new</span> Calculator();
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">addsToNumbers</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">long</span> result = calculator.add(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>);
        assertEquals(<span class="hljs-number">3</span>, result);
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">subtractsToNumbers</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">long</span> result = calculator.sub(<span class="hljs-number">5</span>, <span class="hljs-number">1</span>);
        assertEquals(<span class="hljs-number">4</span>, result);
    }
}
</code></pre>
<p>Every time you run your test, it prints the results to the screen. That’s unnecessary. It slows your tests down.</p>
<p>With dependency injection, you can still assert the result in the test. But you avoid printing the result to the screen (or saving the result to the database, the file system, or somewhere else).</p>
<h2 id="heading-step-1-move-dependency-creation-to-the-constructor">Step 1: Move Dependency Creation to the Constructor</h2>
<p>Find out where an instance of the dependent class is created. Move creation to the constructor by assigning the instance to a field. Use the field throughout the class, so that only the constructor creates the dependency.</p>
<p>The example code is a bit different. The dependency is a static one, <code>System.out</code>. But as described above, the refactored code assigns it to the <code>printer</code> field in the constructor.</p>
<p>So the <code>Calculator</code> class now looks like <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/43ba441138edafdbca2f7f4a100f5e5b528235a2/src/main/java/example/Calculator.java">this</a>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">import</span> java.io.PrintStream;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> PrintStream printer;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Calculator</span><span class="hljs-params">()</span></span>{
        printer = System.out;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">long</span> one, <span class="hljs-keyword">long</span> two)</span> </span>{
        <span class="hljs-keyword">long</span> result = one + two;
        printResult(result);
        <span class="hljs-keyword">return</span> result;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">sub</span><span class="hljs-params">(<span class="hljs-keyword">long</span> one, <span class="hljs-keyword">long</span> two)</span> </span>{
        <span class="hljs-keyword">long</span> result = one - two;
        printResult(result);
        <span class="hljs-keyword">return</span> result;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printResult</span><span class="hljs-params">(<span class="hljs-keyword">long</span> result)</span> </span>{
        printer.println(<span class="hljs-string">"The result is: "</span> + result);
    }
}
</code></pre>
<p>Run the test. It still needs to pass.</p>
<h2 id="heading-step-2-pass-the-dependency-as-a-constructor-argument">Step 2: Pass the Dependency as a Constructor Argument</h2>
<p>Pass the instance as a constructor argument, instead of creating it in the constructor. <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/411cb1650ddfd209b12d0ebc9007fcd1f857d280/src/main/java/example/Calculator.java">Here</a>’s the refactored example code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">import</span> java.io.PrintStream;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> PrintStream printer;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Calculator</span><span class="hljs-params">(PrintStream printer)</span></span>{
        <span class="hljs-keyword">this</span>.printer = printer;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">long</span> one, <span class="hljs-keyword">long</span> two)</span> </span>{
        <span class="hljs-keyword">long</span> result = one + two;
        printResult(result);
        <span class="hljs-keyword">return</span> result;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">long</span> <span class="hljs-title">sub</span><span class="hljs-params">(<span class="hljs-keyword">long</span> one, <span class="hljs-keyword">long</span> two)</span> </span>{
        <span class="hljs-keyword">long</span> result = one - two;
        printResult(result);
        <span class="hljs-keyword">return</span> result;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printResult</span><span class="hljs-params">(<span class="hljs-keyword">long</span> result)</span> </span>{
        printer.println(<span class="hljs-string">"The result is: "</span> + result);
    }
}
</code></pre>
<p>For this class to work, you need to adapt each line of code that creates a <code>Calculator</code> object to pass in the dependency. So the line to create the <code>Calculator</code> in <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/411cb1650ddfd209b12d0ebc9007fcd1f857d280/src/test/java/example/CalculatorTest.java">CalculatorTest</a> now looks like this:</p>
<p><code>calculator = new Calculator(System.out);</code></p>
<p>Run the test. It still needs to pass.</p>
<h2 id="heading-step-3-create-an-interface-and-implementation">Step 3: Create an Interface and Implementation</h2>
<p>Create an <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/d453d47d297eed94108f4b136e467fc66502fe84/src/main/java/example/PrintStream.java">interface</a> with the exact same name as the class name of the dependency. Place it in the same package. Put the method in it that the business logic calls.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PrintStream</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span></span>;
}
</code></pre>
<p>In the <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/d453d47d297eed94108f4b136e467fc66502fe84/src/main/java/example/Calculator.java">Calculator</a> class, remove the import statement of the dependency, <code>java.io.PrintStream</code>, to use the new interface instead.</p>
<p>Here’s one implementation of the interface. <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/d453d47d297eed94108f4b136e467fc66502fe84/src/main/java/example/ConsolePrinter.java">ConsolePrinter</a> contains the original functionality that prints to a screen.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConsolePrinter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PrintStream</span></span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span> </span>{
        System.out.println(text);
    }
}
</code></pre>
<p>In the <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/d453d47d297eed94108f4b136e467fc66502fe84/src/test/java/example/CalculatorTest.java">test class</a>, pass in the <code>ConsolePrinter</code>. Run the test. It still needs to pass, and print the results to the screen:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> org.junit.jupiter.api.Assertions.*;
<span class="hljs-keyword">import</span> org.junit.jupiter.api.*;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CalculatorTest</span> </span>{
    <span class="hljs-keyword">private</span> Calculator calculator;

    <span class="hljs-meta">@BeforeEach</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span> </span>{
        calculator = <span class="hljs-keyword">new</span> Calculator(<span class="hljs-keyword">new</span> ConsolePrinter());
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">addsToNumbers</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">long</span> result = calculator.add(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>);
        assertEquals(<span class="hljs-number">3</span>, result);
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">subtractsToNumbers</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">long</span> result = calculator.sub(<span class="hljs-number">5</span>, <span class="hljs-number">1</span>);
        assertEquals(<span class="hljs-number">4</span>, result);
    }
}
</code></pre>
<h2 id="heading-step-4-rename-and-clean-up">Step 4: Rename and Clean Up</h2>
<p>This is an optional step. You can decide to rename the interface, to give it a more meaningful name. For example, rename <code>PrintStream</code> to <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/d453d47d297eed94108f4b136e467fc66502fe84/src/test/java/example/CalculatorTest.java">Printer</a>. </p>
<p>You can also decide to move the class to a different package and rename its method(s).</p>
<p>Run the test. It still needs to pass.</p>
<h2 id="heading-step-5-configure-the-dependency">Step 5: Configure the Dependency</h2>
<p>Create <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency/blob/66a4aadbaad42616661357bc0ba9f5aaa6f5d846/src/main/java/example/IdlePrinter.java">another implementation</a> that ignores the text argument, for testing purposes:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IdlePrinter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Printer</span></span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span> </span>{
        <span class="hljs-comment">// This is empty, because we don't want to print in tests.</span>
    }
}
</code></pre>
<p>Now, you can change a single line of the CalculatorTest to turn off printing:</p>
<p><code>calculator = new Calculator(new IdlePrinter());</code></p>
<p>Since Java 8, you don’t even need <code>IdlePrinter</code>. Pass in a Lambda function instead:</p>
<p><code>calculator = new Calculator(text -&gt; {});</code></p>
<h2 id="heading-congratulations">Congratulations!</h2>
<p>You have refactored to a Configurable Dependency.</p>
<p>Have a look at the <a target="_blank" href="https://github.com/bertilmuth/configurable-dependency">GitHub project</a> commit history to see the changes in code that I performed.</p>
<p>If you have any questions, leave a comment or contact me.</p>
<p>Twitter: <a target="_blank" href="https://twitter.com/BertilMuth">https://twitter.com/BertilMuth</a></p>
<p>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/bertilmuth/">https://www.linkedin.com/in/bertilmuth/</a></p>
<p>The following appendices explain the concrete refactoring steps in IntelliJ IDEA and Eclipse.</p>
<h1 id="heading-appendix-a-how-to-refactor-in-intellij-idea">Appendix A — How to refactor in IntelliJ IDEA</h1>
<h2 id="heading-intellij-step-1-move-dependency-creation-to-the-constructor">IntelliJ Step 1: Move Dependency Creation to the Constructor</h2>
<p>Open the <code>Calculator</code> class. Locate <code>System.out</code>. Right click, select <code>Refactor &gt; Introduce Field</code>. Select <code>initialize in: constructor</code>. Name the field <code>printer</code>. Hit Return.</p>
<h2 id="heading-intellij-step-2-pass-the-dependency-as-a-constructor-argument">IntelliJ Step 2: Pass the Dependency as a Constructor Argument</h2>
<p>Set the cursor into the constructor, <code>Calculator()</code>. Mark the access to the dependency, <code>System.out</code>. Right click, select <code>Refactor &gt; Introduce Parameter</code>. Name the field <code>printer</code>. Hit Return.</p>
<h2 id="heading-intellij-step-3-create-an-interface-and-implementation">IntelliJ Step 3: Create an interface and Implementation</h2>
<p>Create the interface and implementation in the same package:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PrintStream</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span></span>;
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConsolePrinter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PrintStream</span></span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span> </span>{
        System.out.println(text);
    }
}
</code></pre>
<p>Go to the business logic class <code>Calculator</code> and remove the import statement <code>import java.io.PrintStream;</code>. Save the file.</p>
<p>In the test class <code>CalculatorTest</code>, use the new implementation class.</p>
<p>Change this:</p>
<p><code>calculator = new Calculator(System.out);</code></p>
<p>to this:</p>
<p><code>calculator = new Calculator(new ConsolePrinter());</code></p>
<p>Save the file. Run the test and check if it still passes.</p>
<h2 id="heading-intellij-step-4-rename-and-clean-up">IntelliJ Step 4: Rename and Clean Up</h2>
<p>Go to the interface <code>PrintStream</code>. Right click on <code>PrintStream</code> and select <code>Refactor &gt; Rename</code>. Enter <code>Printer</code> and press Return. Run the test and check if it still passes.</p>
<h2 id="heading-intellij-step-5-configure-the-dependency">IntelliJ Step 5: Configure the Dependency</h2>
<p>Create another implementation that ignores the text argument, for testing purposes:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IdlePrinter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Printer</span></span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span> </span>{
        <span class="hljs-comment">// This is empty, because we don't want to print in tests.</span>
    }
}
</code></pre>
<p>Go to <code>CalculatorTest</code> and change this:</p>
<p><code>calculator = new Calculator(new ConsolePrinter());</code></p>
<p>to this:</p>
<p><code>calculator = new Calculator(new IdlePrinter());</code></p>
<p>Save the file. Run the test and check if it still passes.</p>
<p>The text output should now be off. Well done.</p>
<h1 id="heading-appendix-b-how-to-refactor-in-eclipse">Appendix B — How to Refactor in Eclipse</h1>
<h2 id="heading-eclipse-step-1-move-dependency-creation-to-the-constructor">Eclipse Step 1: Move Dependency Creation to the Constructor</h2>
<p>Open the <code>Calculator</code> class. Locate <code>System.out</code>. Right click, select <code>Refactor &gt; Extract Local Variable</code>. Click <code>OK</code>. </p>
<p>Mark the newly created local variable <code>out</code>. Right click, select <code>Refactor &gt; Convert Local Variable to Field</code>. Name the variable <code>printer</code>. Choose <code>Initialize in Class Constructors</code>. Check <code>Declare field as ‘final’</code>. Hit <code>OK</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/grafik-13.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Run the test and check if it still passes.</p>
<h2 id="heading-eclipse-step-2-pass-the-dependency-as-a-constructor-argument">Eclipse Step 2: Pass the Dependency as a Constructor Argument</h2>
<p>Set the cursor into the constructor, <code>Calculator()</code>. Mark the access to the dependency, <code>System.out</code>, and copy it to the clipboard (CTRL-C).</p>
<p>Right click, select <code>Refactor &gt; Change Method Signature</code>. Click <code>Add</code>. Type <code>PrintStream</code> under <code>Type</code>, <code>printer</code> under <code>Name</code>, and paste <code>System.out</code> under <code>Default value.</code> Click <code>OK</code> and <code>Continue.</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/grafik-14.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Change the constructor to look like this:</p>
<p><code>public Calculator(PrintStream printer){</code><br> <code>this.printer = printer;</code><br> <code>}</code></p>
<p>Save the file. Run the test and check if it still passes.</p>
<h2 id="heading-eclipse-step-3-create-an-interface-and-implementation">Eclipse Step 3: Create an Interface and Implementation</h2>
<p>Create the interface and implementation in the same package:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PrintStream</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span></span>;
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConsolePrinter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PrintStream</span></span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span> </span>{
        System.out.println(text);
    }
}
</code></pre>
<p>Go to the business logic class <code>Calculator</code> and remove the import statement <code>import java.io.PrintStream;</code>. Save the file.</p>
<p>In the test class <code>CalculatorTest</code>, use the new implementation class.</p>
<p>Change this:</p>
<p><code>calculator = new Calculator(System.out);</code></p>
<p>to this:</p>
<p><code>calculator = new Calculator(new ConsolePrinter());</code></p>
<p>Save the file. Run the test and check if it still passes.</p>
<h2 id="heading-eclipse-step-4-rename-and-clean-up">Eclipse Step 4: Rename and Clean Up</h2>
<p>Go to the interface <code>PrintStream</code>. Right click on <code>PrintStream</code> and select <code>Refactor &gt; Rename</code>. Enter <code>Printer</code> and press Return. Run the test and check if it still passes.</p>
<h2 id="heading-eclipse-step-5-configure-the-dependency">Eclipse Step 5: Configure the Dependency</h2>
<p>Create another implementation that ignores the text argument, for testing purposes:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> example;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IdlePrinter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Printer</span></span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">println</span><span class="hljs-params">(String text)</span> </span>{
        <span class="hljs-comment">// This is empty, because we don't want to print in tests.</span>
    }
}
</code></pre>
<p>Go to <code>CalculatorTest</code> and change this:</p>
<p><code>calculator = new Calculator(new ConsolePrinter());</code></p>
<p>to this:</p>
<p><code>calculator = new Calculator(new IdlePrinter());</code></p>
<p>Save the file. Run the test and check if it still passes.</p>
<p>The text output should now be off. Well done.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Code Refactoring Best Practices – with Python Examples ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I will discuss what code refactoring is. We'll go over why you need to refactor your code, the advantages of code refactoring, and some best practices for code refactoring. What is Code Refactoring? Refactoring means organizing your ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/best-practices-for-refactoring-code/</link>
                <guid isPermaLink="false">66bae7cf02a6638884966f13</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ refactoring ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Fagbuyiro ]]>
                </dc:creator>
                <pubDate>Thu, 18 Aug 2022 15:15:29 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/Author-Share-ImageFREE--1-.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I will discuss what code refactoring is. We'll go over why you need to refactor your code, the advantages of code refactoring, and some best practices for code refactoring.</p>
<h2 id="heading-what-is-code-refactoring">What is Code Refactoring?</h2>
<p>Refactoring means organizing your code without modifying its original functionality. Refactoring is the process of making small changes or adjustments to your code without affecting or changing how the code functions while in use.</p>
<h2 id="heading-why-do-you-need-to-refactor-your-code">Why Do You Need to Refactor Your Code?</h2>
<h3 id="heading-it-helps-improve-your-codeprogram">It Helps Improve Your Code/Program</h3>
<p>Refactoring helps you improve the design of your software because developing applications is a difficult task. As you add additional functions, the relevance of the program may be affected. Then, abstractions are no longer as pure as they once were. </p>
<p>You can improve things by refactoring your code regularly to demonstrate a better understanding of the program or code you're working with.</p>
<h3 id="heading-it-gives-you-a-better-understanding-of-the-code">It Gives You a Better Understanding of the Code</h3>
<p>If you refactor properly, your code will be more easily understandable afterwards. You can also make the code easier to understand by improving the design. </p>
<p>It is common knowledge that developers read code far more frequently than they write it. As a result, it's in your best interest to keep things as simple as possible, which considerably improves maintainability. Also, people who read it in the future will be grateful.</p>
<h3 id="heading-refactoring-broadens-your-knowledge">Refactoring Broadens Your Knowledge</h3>
<p>Finally, refactoring is a method of active learning. Even if you didn't write the code, refactoring it gives you a better grasp of what it does.</p>
<h2 id="heading-how-refactoring-helps-your-team">How Refactoring Helps Your Team</h2>
<p>Refactoring is a common activity for software development teams. If done correctly, refactoring your code makes it easier for your team members to understand your code and the changes you've made.</p>
<p>The refactoring stage is often difficult for teams to include in their process. But refactoring, in my opinion, is an essential component of working on any process. Adding comments for me entails leaving the code in a better state than when I found it. </p>
<p>Whatever you do, avoid creating a separation between technical value and business value (creating the feature). You can do this by keeping the code understandable.</p>
<h2 id="heading-refactoring-best-practices-with-python-examples">Refactoring Best Practices – with Python Examples</h2>
<p>If you want to get the most benefit from restructuring your code, you should keep the following in mind:</p>
<ul>
<li>Refactor only tested code. Without tests, refactoring code is, to put it bluntly, gambling. If you don't have tests that verify that the before and after are equivalent, you can't be certain you didn't break the code. No matter how disciplined you are, eventually, you'll introduce bugs.</li>
<li>Minimize refactoring. The modification is riskier the more drastic it is. Divide it into several more compact portions. You get flexibility and mitigation.</li>
<li>Take little, gradual steps. Check to see if everything is working after making a small code change. </li>
<li>Observe the guidelines. Don't begin adding functionality while refactoring is still being done. Refactoring has no impact on the system's output. Before moving on to the next challenge, complete this one.</li>
</ul>
<p>Below is an example of code refactoring using the <strong>Define function</strong> in Python to find the force (F) required to move an object of mass (m) with an acceleration (a) given by the formula “F = m x a”. </p>
<p>Because we are performing a repeated task, it's a good idea to use a function instead of using only the conditional statement. So when we need to in the future, we just have to call the function out for usage.</p>
<h3 id="heading-code-before-refactoring">Code Before Refactoring:</h3>
<table><colgroup></colgroup><tbody><tr><td><p><span>#Using the Force formula F=ma</span><span><br></span><span><br></span><span>while</span><span> </span><span>True</span><span>:</span><span><br></span><span>&nbsp; mass = int(input(</span><span>"Enter the mass value: "</span><span>))</span><span><br></span><span>&nbsp; </span><span>if</span><span> mass &gt; </span><span>0</span><span>:</span><span><br></span><span>&nbsp; &nbsp; </span><span>break</span><span><br></span><span>while</span><span> </span><span>True</span><span>:</span><span><br></span><span>&nbsp; acceleration = int(input(</span><span>"Enter the acceleration: "</span><span>))</span><span><br></span><span>&nbsp; </span><span>if</span><span> acceleration &gt; </span><span>0</span><span>:</span><span><br></span><span>&nbsp; &nbsp; </span><span>break</span><span><br></span><span>print(</span><span>"The Force is"</span><span>, mass * acceleration)</span></p></td></tr></tbody></table>

<p>Notice how the two blocks look nearly identical. What if we’re calculating the “Work done” by a person or machine? Most likely, we’d copy and paste the while loop, changing the variable name and input prompt. Now let's use a function to refactor this.</p>
<h3 id="heading-code-after-refactoring">Code After Refactoring:</h3>
<table><colgroup></colgroup><tbody><tr><td><p><span>#REFACTORED code</span><span><br></span><span><br></span><span>def</span><span> </span><span>input_positive_integer</span><span>(prompt)</span><span>:</span><span><br></span><span>&nbsp; </span><span>while</span><span> </span><span>True</span><span>:</span><span><br></span><span>&nbsp; &nbsp; input_value = int(input(prompt))</span><span><br></span><span>&nbsp; &nbsp; </span><span>if</span><span> input_value &gt; </span><span>0</span><span>:</span><span><br></span><span>&nbsp; &nbsp; &nbsp; </span><span>return</span><span> input_value</span><span><br></span><span>mass = input_positive_integer(</span><span>"Enter the mass: "</span><span>)</span><span><br></span><span>acceleration = input_positive_integer(</span><span>"Enter the acceleration: "</span><span>)</span><span><br></span><span>print(</span><span>"The Force is"</span><span>, mass * acceleration)</span><span><br><br></span></p></td></tr></tbody></table>

<p>Now that our code is simpler to understand, we can start to save some lines of code. What's more, in the future, we'll be able to effortlessly insert our function into another script by just calling out the function, saving us time.</p>
<p>Here are some other tips to keep in mind while refactoring your Python code:</p>
<h3 id="heading-use-list-comprehension-instead-of-a-for-loop">Use List Comprehension Instead of a For Loop</h3>
<p>One of the most well-known Python constructs is list comprehension. Compared to several basic for loops, list comprehension provides a cleaner, quicker solution.</p>
<p>The code will run more quickly, existing data won't be altered, and list comprehensions are simpler to understand at a glance once you become used to them. </p>
<p>Below is a simple expression of using list comprehension instead of a For Loop:</p>
<p>Initial code:</p>
<table><colgroup></colgroup><tbody><tr><td><p><span>#List Comprehension instead of For Loop</span><span><br></span><span><br></span><span>numbers = [1,2,3,4,5,6,7,8]</span><span><br></span><span>odd_numbers = []</span><span><br></span><span>for</span><span> item </span><span>in</span><span> numbers:</span><span><br></span><span>&nbsp; </span><span>if</span><span> item % </span><span>2</span><span> == </span><span>1</span><span>:</span><span><br></span><span>&nbsp; &nbsp; odd_numbers.append(item)</span><span><br></span><span>print(odd_numbers)</span><span><br></span><span><br></span><span>#Outcome will be [1,3,5,7]</span></p></td></tr></tbody></table>

<p>In the above example, we loop through a list of integers (numbers) to see if we should enter each one into the odd numbers list.</p>
<p>Refactored code:</p>
<table><colgroup></colgroup><tbody><tr><td><p><span>numbers = [</span><span>1</span><span>,</span><span>2</span><span>,</span><span>3</span><span>,</span><span>4</span><span>,</span><span>5</span><span>,</span><span>6</span><span>,</span><span>7</span><span>,</span><span>8</span><span>]</span><span><br></span><span>odd_numbers = [item </span><span>for</span><span> item </span><span>in</span><span> numbers </span><span>if</span><span> item % </span><span>2</span><span> == </span><span>1</span><span>]</span><span><br></span><span>print</span><span> (odd_numbers)</span></p></td></tr></tbody></table>

<p>In the above-refactored code, the list comprehension is an assignment into the odd numbers. Then we iterate over the "numbers" and set the return (the first item). Then, we can include an if-statement to filter.</p>
<h3 id="heading-use-def-functions-for-repetitive-tasks">Use Def Functions for Repetitive Tasks</h3>
<p>Defining functions for repetitive tasks is the first and perhaps most significant refactoring we can perform. </p>
<p>Although functions provide many advantages, from the standpoint of refactoring, we will shorten our code and increase readability. In addition, you only have to update the job once, in the declaration of the function (the example given below).</p>
<p>Initial code:</p>
<table><colgroup></colgroup><tbody><tr><td><p><span>#Using the Work done expression W=f<em>d</em></span><span><br></span><span><br></span><span>while</span><span> </span><span>True</span><span>:</span><span><br></span><span>&nbsp; force = int(input(</span><span>"Enter the force value:&nbsp; "</span><span>))</span><span><br></span><span>&nbsp; </span><span>if</span><span> force &gt; </span><span>0</span><span>:</span><span><br></span><span>&nbsp; &nbsp; </span><span>break</span><span><br></span><span>while</span><span> </span><span>True</span><span>:</span><span><br></span><span>&nbsp; distance = int(input(</span><span>"Enter the distance value:&nbsp; "</span><span>))</span><span><br></span><span>&nbsp; </span><span>if</span><span> distance &gt; </span><span>0</span><span>:</span><span><br></span><span>&nbsp; &nbsp; </span><span>break</span><span><br></span><span>print(</span><span>"The Workdone is"</span><span>, force  distance)</span></p></td></tr></tbody></table>

<p>Refactored code:</p>
<table><colgroup></colgroup><tbody><tr><td><p><span>#REFACTORED code</span><span><br></span><span><br></span><span>def</span><span> </span><span>input_positive_integer</span><span>(prompt)</span><span>:</span><span><br></span><span>&nbsp; </span><span>while</span><span> </span><span>True</span><span>:</span><span><br></span><span>&nbsp; &nbsp; input_value = int(input(prompt))</span><span><br></span><span>&nbsp; &nbsp; </span><span>if</span><span> input_value &gt; </span><span>0</span><span>:</span><span><br></span><span>&nbsp; &nbsp; &nbsp; </span><span>return</span><span> input_value</span><span><br></span><span>force = input_positive_integer(</span><span>"Enter the force value:&nbsp; "</span><span>)</span><span><br></span><span>distance = input_positive_integer(</span><span>"Enter the distance:&nbsp; "</span><span>)</span><span><br></span><span>print(</span><span>"The Workdone is"</span><span>, force * distance, </span><span>"J"</span><span>)</span><span><br><br></span></p></td></tr></tbody></table>

<h3 id="heading-use-ternary-operators-instead-of-if-else-statements">Use Ternary Operators Instead of if-else Statements:</h3>
<p>You can use an easy if-statement like this to find if an input integer is an "even" or "odd" number instead of an if-else statement:</p>
<table><colgroup></colgroup><tbody><tr><td><p><span># USING TERNARY OPERATOR</span><span><br></span><span><br></span><span>to_check = int(input(</span><span>"Enter a whole number :"</span><span>))</span><span><br></span><span>msg = </span><span>"Even"</span><span> </span><span>if</span><span> to_check%</span><span>2</span><span> == </span><span>0</span><span> </span><span>else</span><span> </span><span>"Odd"</span><span><br></span><span>print(</span><span>"The number you entered is"</span><span>, msg, </span><span>"number"</span><span>)</span><span><br></span><span><br></span><span><br></span><span># USING USUAL IF-ELSE</span><span><br></span><span><br></span><span>to_check = int(input(</span><span>"Enter a whole number :"</span><span>))</span><span><br></span><span>msg = </span><span>""</span><span><br></span><span>if</span><span>(to_check%</span><span>2</span><span> == </span><span>0</span><span>):</span><span><br></span><span>&nbsp; msg = </span><span>"Even"</span><span><br></span><span>else</span><span>:</span><span><br></span><span>&nbsp; msg = </span><span>"Odd"</span><span><br></span><span>print(</span><span>"The number you entered is"</span><span>, msg, </span><span>"number"</span><span>)</span><span><br></span><span><br><br></span></p></td></tr></tbody></table>

<p>The ternary operator is used in the code above to determine if an integer is even or odd.</p>
<p><code>msg</code> will be assigned <code>Even</code> if the condition (to_check% 2 == 0) is true. <code>msg</code> will also be assign <code>Odd</code> if the condition (to check% 2 == 0) is not true.</p>
<p>Note: you can't use the ternary operator to replace any code that uses an if-else expression. For example, if-else statements involving more than two cases.</p>
<h3 id="heading-use-the-enumerate-function-instead-of-range">Use the Enumerate Function Instead of Range():</h3>
<p>Python for loops can be complicated, especially if you are coming from another programming language. </p>
<p>Initially, you might have thought to make an index variable and use it to loop through your list. As a result, people often find and utilize the range() method. But it's not a best practice to use this method. Below is an example:</p>
<p>Code Before Refactoring:</p>
<table><colgroup></colgroup><tbody><tr><td><p><span>colors = [</span><span>"white"</span><span>, </span><span>"black"</span><span>, </span><span>"brown"</span><span>]</span><span><br></span><span>for</span><span> i </span><span>in</span><span> range(len(colors)):</span><span><br></span><span>&nbsp; print(i+</span><span>1</span><span>, colors[i])</span><span><br></span><span># 1 white</span><span><br></span><span># 2 black</span><span><br></span><span># 3 brown</span></p></td></tr></tbody></table>

<p>Using the index on the initial list makes it more difficult to understand and encourages poor habits like changing original values. Particularly in complex nested data structures. </p>
<p>Additionally, we need to manually change the index's values into "counting numbers."</p>
<p>Code After Refactoring:</p>
<table><colgroup></colgroup><tbody><tr><td><p><span>colors = [</span><span>"white"</span><span>, </span><span>"black"</span><span>, </span><span>"brown"</span><span>]</span><span><br></span><span>for</span><span> i, colors </span><span>in</span><span> enumerate(colors, </span><span>1</span><span>):</span><span><br></span><span>&nbsp; print(i, colors)</span><span><br></span><span>&nbsp; </span><span><br></span><span># 1 white</span><span><br></span><span># 2 black</span><span><br></span><span># 3 brown</span><span><br><br></span></p></td></tr></tbody></table>

<p>The enumerate() method returns the current counter value and each item in the iterable and requires two arguments: the iterable and the initial count value.</p>
<p>Note: It is a typical error to order the temporary count variable first in the for loop and the initial count value second in the function call.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Hopefully, you now understand what code refactoring is along with the importance and reasons for refactoring your code.</p>
<p>Based on the simple Python code above, you should understand that refactoring does not necessarily mean your code needs to be shorter after refactoring – but just somehow simpler and more understandable.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Make Calculation Tests Simpler and More Expressive with These New Refactorings ]]>
                </title>
                <description>
                    <![CDATA[ It is a good idea to make tests as descriptive as possible – to achieve Tests as Documentation. Including the calculations in the test is a big part of this, and avoids the Hard Coded Test Data smell. For example, if a test looks like this, it is har... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-test-complicated-calculations-new-refactoring/</link>
                <guid isPermaLink="false">66bb9264fce17a7d99885305</guid>
                
                    <category>
                        <![CDATA[ refactoring ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Cedd Burge ]]>
                </dc:creator>
                <pubDate>Wed, 03 Feb 2021 17:32:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/02/unit-testing-calculations.JPG" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>It is a good idea to make tests as descriptive as possible – to achieve <a target="_blank" href="http://xunitpatterns.com/Goals%20of%20Test%20Automation.html#Tests%20as%20Documentation">Tests as Documentation</a>. Including the calculations in the test is a big part of this, and avoids the <a target="_blank" href="http://xunitpatterns.com/Obscure%20Test.html#Hard-Coded%20Test%20Data">Hard Coded Test Data</a> smell.</p>
<p>For example, if a test looks like this, it is hard to know what the problem is when it fails, as the test data is all hard coded. The test tells you very little about how the system under test (SUT) should behave, and so doesn’t act as documentation.</p>
<pre><code class="lang-python"><span class="hljs-keyword">assert</span> sut.wake_erosion_rate(<span class="hljs-number">0.03</span>) == <span class="hljs-number">0.8</span>
</code></pre>
<p>However, if you remove this code smell, and include the calculation in the test, it becomes obvious what the problem is when there is a failure, and the test does now act as documentation. </p>
<p>You might also want to replace the <code>2.5</code> and <code>0.05</code> with the names of the constants they represent.</p>
<pre><code class="lang-python">ambient_turbuluence = <span class="hljs-number">0.03</span>

<span class="hljs-keyword">assert</span> 
    sut.wake_erosion_rate(ambient_turbuluence) 
    == <span class="hljs-number">2.5</span> * ambient_turbuluence + <span class="hljs-number">0.05</span>
</code></pre>
<p>This article references the excellent <a target="_blank" href="https://www.goodreads.com/review/show/2179089513">XUnit Test Patterns book</a>, which defines the most widely accepted lexicon on unit test patterns and practices.</p>
<h2 id="heading-example-calculation">Example Calculation</h2>
<p>The rest of this article will discuss the <a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/cash_flow_calculator/construction_margin_calculator.py#L31">example ConstructionMarginCalculator class</a>, and will describe refactorings that simplify the tests and allow them to feasibly include the calculations. </p>
<p>The calculation is around 30 lines long, and is worth a quick glance now if you have the time. But if not, don’t worry, the rest of this post will still make sense.</p>
<p>There are a few if statements and a loop, and in total these lead to 2^9, or 512, paths through the code! Eek! It is clearly not feasible (or useful) to test all these, hence the need to find ways to make it easier.</p>
<p>This example code has an <a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/tests/test_construction_margin_calculator.py#L17">initial naive test</a>, which is around 30 lines long. It doesn’t include the calculations, and introducing them would make the test even longer and more complicated, so would be hard to justify.</p>
<p>Each of the following sections describes a refactoring, and includes links to the refactored example code. These build on the existing <a target="_blank" href="http://xunitpatterns.com/Test%20Refactorings.html">test refactorings</a> from <a target="_blank" href="https://www.goodreads.com/review/show/2179089513">XUnit Test Patterns</a>.</p>
<p>The refactorings reduce the number of paths through the code and simplify the test. This means that fewer tests are needed, and that the tests become small and simple enough to include the calculations.</p>
<h2 id="heading-extract-calculation-from-loop">Extract Calculation From Loop</h2>
<p>The code initially calculates values for a <em>list of</em> <code>steps</code>, which means that any test for it must take on this complication. </p>
<p>The setup of the test is harder, as we have to create a list as opposed to a single value. The assertions are harder as we have to assert on a list as opposed to a single value. Finally, we should have multiple tests (probably for 0, 1, and multiple items in the list).</p>
<p>The easy fix is simply to refactor the code so that it only calculates a single <code>step</code>. This displaces the iteration code to some other place, which might want testing. However, this can be tested using a Mock, so only the iteration needs to be tested (as opposed to the iteration <em>and</em> the calculation), which is simple, and potentially so simple that you don’t need to test it.</p>
<p>This refactoring means that instead of requiring 3 tests (for 0, 1, and multiple items in the list), there is now just one. This reduces the number of paths through the code from 2^9 to 2^7, or 128. This is already a lot better, but still too many to test!</p>
<ul>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/cash_flow_calculator/construction_margin_calculator_without_loop.py#L31">Refactored Calculation</a></li>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/tests/test_construction_margin_calculator_remove_loop.py#L11">Refactored Test</a></li>
</ul>
<h2 id="heading-introduce-mockable-abstractions">Introduce Mockable Abstractions</h2>
<p>The details of the inflation calculation aren’t shown in the example, but they are reasonably complicated.</p>
<p>To avoid this we can change the code to accept an <code>InflationCalculator</code>. The inflation calculation always uses the same <code>date_of_financial_close</code>, <code>inflation_rate</code> and <code>inflation_mode</code>, which means that it can take these in the constructor. This in turn means that the main calculation no longer requires the <code>inflation_rate</code> and <code>inflation_mode</code>.</p>
<p>Then in the tests we can create a mock <code>InflationCalculator</code>. This could for example always return a value of <code>2</code>, which makes the overall calculation a lot simpler.</p>
<p>It is also easy to imagine that inflation calculations will happen in other parts of the code, so the abstraction will be widely useful.</p>
<p>This step means that instead of 4 conditional branches in the inflation calculation, there is now just one. This reduces the number of paths through the code from 2^7 to 2^3, or just 8. It is also necessary to test the <code>InflationCalculator</code>, and this has 4 branches, so needs 4 tests, but this still only makes 12 tests in total. Yay for loosely coupled code!</p>
<p>We now have a feasible number of tests to write, but including the calculation in the test is still going to be very cumbersome. Luckily we still have some refactorings left up our sleeve.</p>
<ul>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/cash_flow_calculator/construction_margin_calculator_mockable_abstraction.py#L29">Refactored Calculation</a></li>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/tests/test_construction_margin_calculator_mockable_abstraction.py#L11">Refactored Test</a></li>
</ul>
<h2 id="heading-test-conditional-branches-in-isolation">Test Conditional Branches in Isolation</h2>
<p>The code branches based on certain conditionals. We can simply make some of these conditionals <code>False</code>, and then test each branch of the code in isolation. This way, each test only has to include the calculation for the branch that it is concerned with.</p>
<p>For example, we can set <code>in_selling_mode</code> to be <code>False</code> and <code>step.start_of_step</code> to be different to <code>date_of_financial_close</code>. This makes the test simple enough that it is feasible for it to perform the same calculation that the code does. </p>
<p>This in turn means that the test clearly communicates that the <code>turbine_cost_including_margin</code> should be the <code>turbine_costs * fraction_of_spend * inflation</code>. This helps readers understand the calculator, and achieves the goal of <a target="_blank" href="http://xunitpatterns.com/Goals%20of%20Test%20Automation.html#Tests%20as%20Documentation">Tests as Documentation</a></p>
<p>At the moment the test is still quite long. However, because we are only testing a small part of the calculation, a lot of this information is now irrelevant (the <code>any_double</code> variable). This means we can now create a <a target="_blank" href="http://natpryce.com/articles/000714.html">Test Data Builder</a>, or use helper functions to make things more concise. We will see an example of this in the next refactoring.</p>
<ul>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/cash_flow_calculator/construction_margin_calculator_mockable_abstraction.py#L29">No Change to Calculation</a></li>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/tests/test_construction_margin_calculator_isolate_branches.py#L16">Refactored Test</a></li>
</ul>
<h2 id="heading-test-values-in-isolation">Test Values in Isolation</h2>
<p>“Test Conditional Branches in Isolation” is a useful technique, but it can still leave us with some complications if a value is calculated / updated in multiple branches. </p>
<p>A good example of this is <code>balance_of_plant_cost_including_margin</code>, which is set initially, and then updated in the <code>if (in_selling_mode)</code> branch.</p>
<p>Testing <code>balance_of_plant_cost_including_margin</code> in isolation allows the test to concentrate just on this one value / calculation, which means that a lot less setup is required. The <a target="_blank" href="http://natpryce.com/articles/000714.html">Test Data Builder</a> pattern hides <a target="_blank" href="http://xunitpatterns.com/Obscure%20Test.html#Irrelevant%20Information">Irrelevant Information</a>, and the test becomes more concise and expressive.</p>
<p>Including the calculation continues to make the test clearly communicate its intent and act as documentation. Interestingly the test calculation code is no longer an exact copy of the SUT calculation code, as it already knows that it is <code>in_selling_mode</code>, so doesn’t need a conditional statement. This means that the test is simpler than the code, which helps avoid the <a target="_blank" href="http://xunitpatterns.com/Obscure%20Test.html">Obscure Test</a> smell.</p>
<ul>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/cash_flow_calculator/construction_margin_calculator_mockable_abstraction.py#L29">No Change to Calculation</a></li>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/tests/test_construction_margin_calculator_isolate_values.py#L18">Refactored Test</a></li>
</ul>
<h2 id="heading-test-partial-values-in-isolation">Test Partial Values in Isolation</h2>
<p>Sometimes the calculation of individual values is very complex, and can’t be split up by conditional branches. This can make it challenging to include the calculation in the test. <code>construction_profit</code> is a reasonable example of this, which is calculated as follows:</p>
<pre><code class="lang-python">step.turbine_cost_including_margin = 
 turbine_costs * inflation * fraction_of_spend;

step.balance_of_plant_cost_including_margin = 
 balance_of_plant_costs_at_financial_close * inflation * fraction_of_spend;

step.construction_profit = 
 <span class="hljs-number">-1</span> * 
 (step.turbine_cost_including_margin + step.balance_of_plant_cost_including_margin) *
 epc_margin
</code></pre>
<p><code>inflation</code>, <code>fraction_of_spend</code> and <code>epc_margin</code> have a multiplicative effect, so if we set them to <code>1</code>, they won’t have any effect and we can easily write a test for the rest of the logic.</p>
<p><code>step.turbine_cost_including_margin</code> and <code>step.balance_of_plant_cost_including_margin</code> have an additive effect, so if we set them to <code>0</code>, again they won’t have any effect and we can easily write a test for the rest of the logic.</p>
<p>Testing just a portion of <code>construction_profit</code> in isolation allows the test to concentrate just on this part of the calculation, which, as before, makes the test shorter and simpler, and avoids the <a target="_blank" href="https://hackmd.io/4xuiUbrAQimsWCknJiqXNw?both">Obscure Test</a> smell.</p>
<ul>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/cash_flow_calculator/construction_margin_calculator_mockable_abstraction.py#L29">No Change to Calculation</a></li>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/tests/test_construction_margin_calculator_isolate_partial_values.py#L14">Refactored Test</a></li>
</ul>
<h2 id="heading-introduce-the-blackboard-pattern">Introduce the Blackboard Pattern</h2>
<p>The Blackboard pattern is a more involved technique, and is often badly understood. But essentially it involves using a “blackboard” to break the dependencies within complicated calculations.</p>
<p>In this example the <code>construction_profit</code> depends on <code>turbine_cost_including_margin</code> and <code>balance_of_plant_cost_including_margin</code>, which are themselves calculated from the inputs. This makes testing harder. </p>
<p>In order to test the <code>construction_profit</code> you essentially also have to test <code>turbine_cost_including_margin</code> and <code>balance_of_plant_cost_including_margin</code>.</p>
<p>When we introduce the blackboard pattern, one calculator writes the <code>turbine_cost_including_margin</code> and <code>balance_of_plant_cost_including_margin</code> to the blackboard, and when calculating the <code>construction_profit</code> we read these values from the blackboard.</p>
<p>This breaks the connection between the two things, so when testing we can just add values for <code>turbine_cost_including_margin</code> and <code>balance_of_plant_cost_including_margin</code> to the blackboard.</p>
<ul>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/cash_flow_calculator/construction_margin_calculator_blackboard_pattern.py#L15">Refactored Calculation</a></li>
<li><a target="_blank" href="https://github.com/ceddlyburge/unit-testing-calculations/blob/main/tests/test_construction_margin_calculator_blackboard_pattern.py#L12">Refactored Test</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>When testing calculations, it is important to include the calculation in the tests. This avoids the <a target="_blank" href="http://xunitpatterns.com/Obscure%20Test.html#Hard-Coded%20Test%20Data">Hard Coded Test Data</a> smell, allows the tests to clearly express their intent and achieve <a target="_blank" href="http://xunitpatterns.com/Goals%20of%20Test%20Automation.html#Tests%20as%20Documentation">Tests as Documentation</a>.</p>
<p>The refactorings described in this article allow you to do this while also making sure that the tests are concise and understandable.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Why You Should Refactor Your Code ]]>
                </title>
                <description>
                    <![CDATA[ Raise your hand if any of the following sounds familiar: Think about code formatting. Get rid of unnecessary <div>'s and <span>'s. Use functional React components. Try to avoid arrow function in render. And do not repeat yourself! Before I go straigh... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/why-you-should-refactor-your-code/</link>
                <guid isPermaLink="false">66be14d94acec4a9c337d05e</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ refactoring ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oleh Romanyuk ]]>
                </dc:creator>
                <pubDate>Fri, 03 Apr 2020 20:00:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/refactor-your-react-code.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Raise your hand if any of the following sounds familiar: Think about code formatting. Get rid of unnecessary <code>&lt;div&gt;</code>'s and <code>&lt;span&gt;</code>'s. Use functional React components. Try to avoid arrow function in render. And do not repeat yourself!</p>
<p>Before I go straight to refactoring, I need you to answer one simple question: What does it mean to develop an application? Usually, this means producing a piece of software that meets requirements by implementing certain features. </p>
<p>And how do we do that? We collect customer requirements, estimate them, and develop features one by one, right? Almost.</p>
<h2 id="heading-do-not-forget-about-bugs"><strong>Do Not Forget About Bugs</strong></h2>
<p>Yes, errors do occur. Depending on the development process, software complexity, technical stack, and many other parameters, the number of bugs may vary. </p>
<p>A business cannot afford critical issues in production. To minimize problems, you should pay particular attention to the <a target="_blank" href="https://keenethics.com/blog/qa-documentation">QA process</a>. But QA theory claims that it is usually impossible to run 100% test coverage of your apps and prepare for all possible scenarios. </p>
<p>Still, to achieve optimal results, teams spend a lot of time testing software and fixing issues. This is a necessary part of the process that each customer should understand and prioritize.</p>
<h2 id="heading-mind-the-technical-debt"><strong>Mind the Technical Debt</strong></h2>
<p>Yet, this coin has a flip side. The longer the development and testing process takes, the more technical debt you incur. </p>
<p>So, what does "technical debt" mean? Technical debt refers to all the quality-related issues you have in your code. Issues which will require spending additional resources in the future. </p>
<p>You incur technical debt for a variety of reasons, such as:</p>
<ol>
<li>The business pushes to release new features faster.</li>
<li>Testing is insufficient.</li>
<li>The requirements are changing rapidly.</li>
<li>The developers are inexperienced.</li>
</ol>
<p>Technical debt should be documented. If you do not leave to-do's in the code, you will most likely forget about the issue. And even if you have time for it in the future, you will not remember to fix it.</p>
<h2 id="heading-understand-the-importance-of-refactoring"><strong>Understand the Importance of Refactoring</strong></h2>
<p>Usually, you need to spend some time refactoring the existing code in order to solve code quality issues and thus lower technical debt. </p>
<p>But what is refactoring? It is the process of restructuring the existing code without changing its external behavior. And that is actually something that might be difficult to understand for business people managing the project.</p>
<blockquote>
<p>– Will we get any new features?   </p>
<p>– No.   </p>
<p>– Will we at least fix some bugs?   </p>
<p>– Also no.    </p>
<p>– What will we get then?   </p>
<p>– …</p>
</blockquote>
<p>Working with technical debt helps to avoid bugs. And to add fixes or changes to the project, we always need to read the old code. </p>
<p>Therefore, refactoring and maintaining good code quality will help us keep development at a good pace. </p>
<p>Sometimes a business might not need it. For instance, if you're working on a prototype or <a target="_blank" href="https://keenethics.com/services-proof">Proof of Concept</a>, or if there are business priorities that cannot be adjusted, you can do without refactoring. </p>
<p>But in most cases, cutting out refactoring is not a wise thing to do. You might spend a huge amount of time on refactoring if your developers are perfectionists, but this makes no sense either. </p>
<p>Therefore, you need to strike a balance. You should not spend more time refactoring than you will save in the future.</p>
<h2 id="heading-how-to-start-refactoring-your-react-code"><strong>How to Start Refactoring Your React Code</strong></h2>
<h3 id="heading-think-about-code-formatting"><strong>Think about code formatting</strong></h3>
<p>Some people add trailing commas, and some don't. Some use single quotes, while others use double quotes for a string. </p>
<p>If you work in a team, maintaining the common code style can be really difficult. And inconsistency in code style can make your code look dirty and hard to read. </p>
<p>So if you haven’t thought about using code formatting tools before, it’s high time to do so. One of the most popular and easy-to-use React refactoring tools is <a target="_blank" href="https://prettier.io/">Prettier</a>. You can just add it to the project and it will take care of formatting for you. </p>
<p>Prettier has some default style settings, but you can change them according to your preferences by adding a <code>.prettierrc</code> file with your formatting rules. </p>
<p>A good setup of <code>.prettierrc</code> may look like this:</p>
<pre><code class="lang-js">{ <span class="hljs-string">"printWidth"</span>: <span class="hljs-number">120</span>,  <span class="hljs-string">"singleQuote"</span>: <span class="hljs-literal">true</span>, “trailingComma”: “none” }
</code></pre>
<p>You can also automatically reformat the code before committing with <a target="_blank" href="https://prettier.io/docs/en/precommit.html">pre-commit hooks</a>.</p>
<h3 id="heading-get-rid-of-unnecessary-s-and-s"><strong>Get rid of unnecessary <div>’s and <span>’s</span></div></strong></h3>
<p>When React 16.2 was released in November 2017, a lot of React developers sighed in relief. Prior to that, for a component to return a list of children, it was necessary to wrap the children in an extra element, such as <code>&lt;div&gt;</code> or <code>&lt;span&gt;</code>. </p>
<p>But with React 16.2 we received improved support for returning components’ children. Now developers can use so-called fragments. They look like empty JSX tags (<code>&lt;&gt; … &lt;/&gt;</code>). With the help of fragments, you can pass a list of children to the component without adding extra nodes to the DOM.</p>
<h3 id="heading-think-about-names"><strong>Think about names</strong></h3>
<p>Don’t be lazy when you're thinking about names for components and variables. Every name should be self-explanatory.</p>
<p>Have you ever seen code snippets like this?</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> modifyData = data.map(<span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> [x.a, x.b]))
</code></pre>
<p>What does it do? If you cannot understand the purpose of a variable from its name, it is time to rename it! </p>
<p>This will help you and your team understand the logic more easily. It will also eliminate the time spent making changes to existing components in the future.</p>
<h3 id="heading-dont-repeat-yourself"><strong>Don’t Repeat Yourself</strong></h3>
<p>The DRY principle was first formulated in the book <em>The Pragmatic Programmer</em>. It states that "every piece of knowledge must have a single, unambiguous, authoritative representation within a system". In other words, you need to put repetitive code blocks into separate reusable components. </p>
<p>Making your code DRY has a lot of benefits. It can save you a lot of time. If you need to change this code in the future, you will only do that in one place. Also, you will never have to worry that you forgot to make changes in some places. Furthermore, you will keep the components cleaner and increase the readability of code. </p>
<p>To keep your components DRY and small, you can follow two simple rules:</p>
<ol>
<li>If you use a code block more than two times, it’s time to extract it.</li>
<li>If you exceed a predefined number of lines in a component (e.g. 100 lines), there is probably logic that can be extracted. Divide it into smaller components by functionality.</li>
</ol>
<h3 id="heading-use-functional-over-class-components"><strong>Use functional over class components</strong></h3>
<p>With the introduction of Hooks in React 16.8, we received access to React class features in functional components. Hooks solve a bunch of problems frequently encountered by developers over the past few years. </p>
<p>For example, the <code>useEffect</code> hook, as the React docs suggest, allows us to group the component logic into small functions based on what pieces are related (instead of grouping the logic based on life-cycle methods). This helps us to better restructure our logic. </p>
<p>All in all, refactoring React components with the help of hooks makes the code cleaner and reduces the amount of code you need to write. </p>
<p>Here is a very basic example: fetching the data after the component has mounted and re-fetching it based on the updated props. </p>
<p>In a class component, we would write something like this:</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookList</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
  componentDidMount() {
    <span class="hljs-built_in">this</span>.props.fetchBooks(<span class="hljs-built_in">this</span>.props.bookGenre);
  }
  componentDidUpdate(prevProps) {
    <span class="hljs-keyword">if</span> (prevProps.bookGenre !== <span class="hljs-built_in">this</span>.props.booksGenre) {
      <span class="hljs-built_in">this</span>.props.fetchBooks(<span class="hljs-built_in">this</span>.props.bookGenre);
    }
  } 
<span class="hljs-comment">// ... }</span>
</code></pre>
<p>With React hooks it will look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> BookList = <span class="hljs-function">(<span class="hljs-params">{ bookGenre, fetchBooks }</span>) =&gt;</span> {
  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetchBooks(bookGenre);
  }, [bookGenre]);
<span class="hljs-comment">// ... }</span>
</code></pre>
<p>The books fetching logic is now gathered in one place. The <code>useEffect</code> hook will run after mount each time the props <code>[bookGenre]</code> in square brackets change. Much cleaner, isn’t it? </p>
<p>Also, you can extract similar stateful logic and reuse it in different components by creating your custom hooks. You can read more about custom hooks in the official <a target="_blank" href="https://reactjs.org/docs/hooks-custom.html">React documentation</a>.</p>
<h3 id="heading-try-to-avoid-arrow-functions-in-render"><strong>Try to avoid arrow functions in render</strong></h3>
<p>Have you ever seen code like this?:</p>
<pre><code class="lang-js">render() {    
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> this.setState({ flag: true })} /&gt;
      ...      
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>    
  );  
}
</code></pre>
<p>Sure you have. What is the problem with it? Every time a component is rendered, a new instance of such a function is created. </p>
<p>It is not a big deal if the component is rendered one or two times. But in other cases, it can really affect performance. So, if you care about performance, declare the function before using it in render:</p>
<pre><code class="lang-js">changeFlag = <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">flag</span>: <span class="hljs-literal">true</span> })
render() {    
  <span class="hljs-keyword">return</span> (      
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.changeFlag}</span> /&gt;</span>        
      ...      
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>    
  );  
}
</code></pre>
<h3 id="heading-make-the-bundle-smaller"><strong>Make the bundle smaller</strong></h3>
<p>If you are using a third-party library, you should not load the entire thing if it isn't necessary. Sometimes you can stumble upon an import which uses only one method from the library, such as:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> lodash form <span class="hljs-string">'lodash'</span>  
...  
const certainProps = lodash.pick(userObject, [<span class="hljs-string">'name'</span>, <span class="hljs-string">'email'</span>]);  ...
</code></pre>
<p>Instead, it is better to use the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> pick <span class="hljs-keyword">from</span> <span class="hljs-string">'lodash/pick'</span> 
... 
const certainProps = pick(userObject, [<span class="hljs-string">'name'</span>, <span class="hljs-string">'email'</span>]); ...
</code></pre>
<p>Now you do not load the whole library, just the method you need.</p>
<h2 id="heading-to-wrap-up"><strong>To Wrap Up</strong></h2>
<p>Let's review the steps you should take to refactor your React code:</p>
<ul>
<li>Think about code formatting</li>
<li>Get rid of unnecessary <code>&lt;div&gt;</code>'s and <code>&lt;span&gt;</code>'s</li>
<li>Think about names</li>
<li>Don’t Repeat Yourself</li>
<li>Use functional over class components</li>
<li>Try to avoid arrow functions in render</li>
<li>Make the bundle smaller</li>
</ul>
<p>Yet, ideal refactoring is refactoring that does not occur. As a developer and especially as a tech lead, you should think many steps ahead and try to produce high-quality code. You should also carry out regular code reviews, not only within one team but also between teams.</p>
<h2 id="heading-do-you-have-an-idea-for-a-react-project">Do you have an idea for a React project?</h2>
<p>My company KeenEthics is an experienced React <a target="_blank" href="https://keenethics.com/services-web-development">development company</a>. If you are ready to change the game with your software project, feel free to <a target="_blank" href="https://keenethics.com/services-web-development">request an estimate</a>.</p>
<p>You can read more similar articles on my Keen Blog. Allow me to suggest <a target="_blank" href="https://keenethics.com/blog/the-value-of-user-testing">The Value of User Testing</a> or <a target="_blank" href="https://keenethics.com/blog/angular-vs-react-what-to-choose-for-your-app">Angular vs React: What to Choose for Your App?</a></p>
<p>Most importantly, I would like to say "thank you" to Yaryna Korduba and Max Fedas, both outstanding React developers, for coauthoring this article as well as the readers for making it to the end!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Code Becomes A Dumping Ground (And How To Fix It!) ]]>
                </title>
                <description>
                    <![CDATA[ By James Hickey Earlier in my career, I faced a sort of career crisis. I was part of a team creating a large analytics platform in the automotive industry. This application had the typical "enterprise-y" layered architecture you would expect ("Busine... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/fixing-code-dumping-grounds/</link>
                <guid isPermaLink="false">66d45f31a3a4f04fb2dd2e57</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ refactoring ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 18 Sep 2019 20:36:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/09/ashim-d-silva-Kw_zQBAChws-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By James Hickey</p>
<p>Earlier in my career, I faced a sort of career crisis.</p>
<p>I was part of a team creating a large analytics platform in the automotive industry. This application had the typical "enterprise-y" layered architecture you would expect ("Business Layer", "Data Access Layer", "Core", etc.).</p>
<p>You would expect to find business logic - the really important business logic - embedded somewhere inside of the code from these layers. But, usually, the really important business rules were coded into stored procedures.</p>
<p><strong>Stored procedures</strong>, if you don't know, is like a function you create inside of a database that uses an SQL-like syntax to process data, store it, etc.</p>
<p>I wondered what the purpose of the layers was. They didn't have any code except for passing data to stored procedures or showing data returned by one.</p>
<p>I started to learn more about object-oriented programming, industry best-practices, SOLID, other programming paradigms, application architecture, etc.</p>
<p>From this career crisis, I discovered that these problems have already been solved! It just takes research, time and practice to learn and grow skilled in them.</p>
<h2 id="heading-object-oriented">Object-Oriented?</h2>
<p>One thing I discovered is that all the projects I've been on that were doing "Object-Oriented" programming were <em>not</em> doing true OOP. Just because you use classes doesn't mean you are doing OOP. Especially if you are using stored procedures to encode all your business rules.</p>
<h3 id="heading-a-short-aside-the-great-debate">A Short Aside: The Great Debate</h3>
<p>It needs to be brought up: is object-oriented programming or functional programming better?</p>
<p>For starters, most people don't understand what OOP was intended to be in the first place. Similar to how Agile today is usually misunderstood (e.g. just because you are having daily stand-ups, using story points, kanban, etc. it doesn't mean you are doing Agile).</p>
<p>Alan Kay is considered one of the fathers of OOP. <a target="_blank" href="http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en">In a certain email</a>, he gave some frank explanations about what OOP was supposed to be.</p>
<blockquote>
<p>"I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning -- it took a while to see how to do messaging in a programming language efficiently enough to be useful)...</p>
<p>OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things...</p>
<p>But just to show how stubbornly an idea can hang on, all through the seventies and eighties, there were many people who tried to get by with 'Remote Procedure Call' instead of thinking about objects and messages."</p>
</blockquote>
<p>For those familiar with microservices, the actor model, and other advanced programming paradigms, your Spidey sense is tingling. These are actually more closely related to true OOP.</p>
<p>So, is FP better than true OOP?</p>
<p>I don't think so. I think they both have their merits. Many languages today are embracing both paradigms and allowing developers to use the tools and methods that work best for the given problem!</p>
<p>What you'll usually find are classes that expose all their properties or internal data members. An HTTP request or database query will fill-up all the properties, and then, perhaps, something else will work on that object's data.</p>
<p>Instead of what Alan Kay intended to be as little "bundles" that pass messages to each other (see aside above), most developers are using objects as mere "data holders". Glorified variables, as it were.</p>
<p>What you'll also find in many codebases are very generic classes like <code>User</code>, <code>Customer</code> or <code>Order</code>.</p>
<p>Is that bad? Well, <strong>yes</strong>.</p>
<p>Let me ask you a question:</p>
<p>Is <code>User</code> used in many different unrelated places in your application?</p>
<p>For example, is your <code>User</code> class used in the billing part of your code, the user profile parts, the shipping parts, etc.?</p>
<p>Most systems are doing something like that.</p>
<p>What will end up happening is that, because these classes are so generic, <strong>they become dumping grounds for code which we don't know where it belongs.</strong></p>
<p>Instead of taking the time to think about the business need for this new code we've written, often we feel that it's easier to put into our generic classes. It's all shareable, right? And we're all about code-reuse, right?</p>
<h2 id="heading-coupling">Coupling</h2>
<p>So... what if I changed the <code>User</code> class to conform to some billing logic? What are the chances that I've also broken the shipping feature by changing this class? I don't know, but it's <strong>higher than 0%.</strong></p>
<p>This <code>User</code> class has coupled all your features together. This causes lots of problems.</p>
<p>Ideally, we want our code to be orthogonal (that's just a fancy word that means changing code in one place won't affect other unrelated places).</p>
<p>We want to be able to change the shipping feature, for example, and <strong>not have to test our entire application again.</strong> But, if we're sharing our <code>User</code> class everywhere then, to have confidence that we didn't break stuff, we need to re-test <strong>everything.</strong></p>
<p>This leads to a fear of changing code. The fear of making our code better. It also leads to a lot of bugs.</p>
<p>If you are building out the payment feature for your application - you shouldn't have to think about whether you are breaking the shipping feature at the same time! This causes a huge cognitive load that doesn't need to be there.</p>
<h3 id="heading-another-aside-warning-sign">Another Aside: Warning Sign</h3>
<p>Overall, I find that the idea of segmenting your business features/functions via different physical folders or even entirely different projects altogether is best. <a target="_blank" href="https://dev.to/jamesmh/the-life-changing-and-time-saving-magic-of-feature-focused-code-organization-1708">I've written about this before</a>.</p>
<p>But, when it comes to our code at a deeper level, we can still tend to design our classes and objects in a way that's still too generic and leads to much coupling.</p>
<p>Anytime I find classes that have simple names like <code>User</code> or <code>Customer</code>, a warning signal goes off. I'd much rather see classes that are created for a specific context.</p>
<p>For example, if I saw a class named <code>UserForAuthentication</code> or <code>PaymentsCustomer</code> then I would be more confident that these classes aren't being thrown around and reused in too many contexts.</p>
<p>Here's a basic way that might help get started on analyzing your classes. Take your class name and answer these questions:</p>
<p>Is there a subject? (user, client, order, etc.)</p>
<p>Is there a context for that subject? (shipping, orders, dashboard, etc.)</p>
<p>Is there even perhaps an action being performed on the subject? (as we'll see in more details soon)</p>
<p>If you cannot answer 2 of those questions then I'd say there's a good chance that your class might be doing too much by being too generic.</p>
<h2 id="heading-one-of-these-things-is-not-like-the-others">One Of These Things Is Not Like The Others</h2>
<p>There's a programming principle called the Single Responsibility Principle.</p>
<p>When looking at classes or methods that are doing too much, using the SRP as a guiding light can help us to make code that is easier to maintain, less coupled and therefore leads to fewer bugs.</p>
<p>Let's look at a generic <code>User</code> class that might be similar to code you've seen before:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> User {
    <span class="hljs-keyword">public</span> firstName: <span class="hljs-built_in">string</span>;
    <span class="hljs-keyword">public</span> lastName: <span class="hljs-built_in">string</span>;
    <span class="hljs-keyword">public</span> id: <span class="hljs-built_in">number</span>;
    <span class="hljs-keyword">public</span> jwtToken: <span class="hljs-built_in">string</span>;
    <span class="hljs-keyword">public</span> homeAddress: <span class="hljs-built_in">string</span>;
    <span class="hljs-keyword">public</span> creditCardNo: <span class="hljs-built_in">string</span>;

    <span class="hljs-keyword">public</span> getFullName(): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.firstName + <span class="hljs-string">" "</span> + <span class="hljs-built_in">this</span>.lastName;
    }

    <span class="hljs-keyword">public</span> decodeJwtToken(): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> decode(<span class="hljs-built_in">this</span>.jwtToken);
    }
}
</code></pre>
<p>Look familiar?</p>
<p>Given the name of the class, we should start to be suspicious that it's too generic of a class.</p>
<h2 id="heading-you-have-mail">You Have Mail</h2>
<p>You've been tasked with adding a new business requirement. We need users to be able to pay for their products using PayPal.</p>
<p>This <code>User</code> class is already used in multiple places like the user profile, shipping and payment features.</p>
<p>All we need to do is add the user's PayPal email address to the user. Right?</p>
<h2 id="heading-breaking-it-up">Breaking It Up</h2>
<p>Usually, you will get new business requirements that require <em>more</em> changes to your code than this. But this is a simple example.</p>
<p>If we start changing this <code>User</code> class so that it works with the payment feature then we risk affecting the user profile or the shipping feature (since they use this class too).</p>
<p>What should we do?</p>
<p>The best thing to do here is <em>create a different user class that's used within each specific context.</em></p>
<p>Out of this should come classes like <code>UserForAuthentication</code>, <code>UserProfileUser</code>, <code>ShippingUser</code> and <code>PaymentUser</code>.</p>
<p>Are those models/classes going to contain similar pieces of data that all of them will need? Sure.</p>
<p>Will they also have pieces of data that are only used in one context? Sure.</p>
<p>For example, the user's <code>id</code> is needed everywhere.</p>
<p>But, the user's home address is only ever needed by shipping. Why then, does the payment feature need access to that data? It doesn't.</p>
<p>Here's what these classes might look like:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> UserProfileUser {
    <span class="hljs-keyword">public</span> firstName: <span class="hljs-built_in">string</span>;
    <span class="hljs-keyword">public</span> lastName: <span class="hljs-built_in">string</span>;
    <span class="hljs-keyword">public</span> id: <span class="hljs-built_in">number</span>;
    <span class="hljs-keyword">public</span> homeAddress: <span class="hljs-built_in">string</span>;

    <span class="hljs-keyword">public</span> getFullName(): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.firstName + <span class="hljs-string">" "</span> + <span class="hljs-built_in">this</span>.lastName;
    }
}

<span class="hljs-keyword">class</span> ShippingUser {
    <span class="hljs-keyword">public</span> id: <span class="hljs-built_in">number</span>;
    <span class="hljs-keyword">public</span> homeAddress: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">class</span> UserForAuthentication {
    <span class="hljs-keyword">public</span> id: <span class="hljs-built_in">number</span>;
    <span class="hljs-keyword">public</span> jwtToken: <span class="hljs-built_in">string</span>;

    <span class="hljs-keyword">public</span> decodeJwtToken(): <span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> decode(<span class="hljs-built_in">this</span>.jwtToken);
    }
}

<span class="hljs-keyword">class</span> PaymentUser {
    <span class="hljs-keyword">public</span> id: <span class="hljs-built_in">number</span>;
    <span class="hljs-keyword">public</span> creditCardNo: <span class="hljs-built_in">string</span>;
}
</code></pre>
<h2 id="heading-keep-separate-things-separate">Keep Separate Things Separate</h2>
<p>Notice that the home address is needed by <code>UserProfileUser</code> and <code>ShippingUser</code>. Is that bad?</p>
<p>We've had it drilled into us so much that duplicating code is a bad thing. So much so, that it's this idea that's caused the problems we're talking about right now!</p>
<p>Sometimes, it's better to "duplicate" code and/or data - if they are within different contexts. Again, we want to avoid coupling our features and classes together.</p>
<p>Let me ask you a question:</p>
<p><em>Is it probable that the behavior for the home address within the user profile will be different than the behavior for it in the shipping feature?</em></p>
<p>The answer: <strong>yes.</strong></p>
<p>So then, we are talking about two different things. It's the same raw data but <strong>not the same business function or concept</strong><em>.</em></p>
<p>Shipping needs the home address so that it knows <strong>where to send products.</strong></p>
<p>The user profile needs the home address <strong>so the user can update its values from a UI.</strong></p>
<p><em>Not the same things.</em></p>
<p>Also, consider that it might also make sense to add an address to the <code>PaymentUser</code> class too. But, should this context share the same address as shipping?</p>
<p>Well, is it possible that your shipping address wouldn't be the same address you want to bill to? Sure! This happens all the time!</p>
<p>Using the Single Responsibility Principle, we see that these two concepts/responsibilities should be kept separate.</p>
<p>Also, notice that <em>most</em> of our pieces of data are <strong>not</strong> being shared. The JWT token, for example, is only needed for authenticating a user. Why would we ever need that piece of data inside our Shipping feature's code?</p>
<p>Now, that information is isolated.</p>
<p><strong>Also, any methods that act on that data will also be moved and not inappropriately called by another feature's code.</strong></p>
<p>This was a simple example, and in most cases, this can get a little trickier than we might want. In the end, though, keeping different business concepts separate from each other will make your code easier to understand within a specific context, easier to maintain and will become less error-prone!</p>
<p>This is an excerpt from my book  <a target="_blank" href="https://leanpub.com/refactoringtypescript">"Refactoring TypeScript: Keeping Your Code Healthy"</a>. This section of the book has <strong>more</strong> techniques for you to help deal with these kinds of dumping grounds. If you enjoyed this article then <a target="_blank" href="https://leanpub.com/refactoringtypescript">check out the book for more content like this!</a></p>
<p>You can <a target="_blank" href="https://twitter.com/jamesmh_dev">connect with me</a> on Twitter too.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ When to refactor legacy code vs. when to stay focused on your current project ]]>
                </title>
                <description>
                    <![CDATA[ By Sihui Huang When I work on projects, I often run into legacy code that can be improved — to be more readable, more testable, or more compliant with the current coding style. My urge to refactor the code is especially strong after spending a good a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/when-to-refactor-legacy-code-vs-when-to-stay-focused-on-your-current-project-fda99919cc34/</link>
                <guid isPermaLink="false">66c3665109a9333511bcdb63</guid>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ refactoring ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 08 Feb 2019 21:14:01 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*qw5zQRKKw4pNbhv3nwjIjQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sihui Huang</p>
<p>When I work on projects, I often run into legacy code that can be improved — to be more readable, more testable, or more compliant with the current coding style. My urge to refactor the code is especially strong after spending a good amount of time trying to understand a piece of obscure code. <a target="_blank" href="https://www.sihui.io/brain-friendly-code/">That code hurts my brain</a>, and I don’t want the same thing to happen to other developers. There is (the adaptation of) the famous Boy Scout Rule: <strong>Leave Code Better than You Found It</strong>.</p>
<p>But at the same time, I also want to stay focused and make progress on my current projects. I worry that I might get distracted and spend too much time refactoring.</p>
<p>This is a dilemma I often face. <strong>I want to be the good samaritan leaving code better than I found it, an engineer turning all the messy code I come across into something clean and elegant. But I also want to stay pragmatic and ship projects quickly.</strong></p>
<p>Balancing between refactoring the legacy code I come across and staying focused on my current project can be hard.</p>
<p>A recent conversation with my manager on this topic provided me guidance to find that balance. Here are a few points I find helpful.</p>
<h4 id="heading-you-dont-have-to-make-the-code-perfect-small-improvements-are-still-useful"><strong>You don’t have to make the code perfect. Small improvements are still useful.</strong></h4>
<p>After I read a piece of legacy code, my brain immediately thinks about how it should be ideally. But refactoring that code from its current state to the ideal state sometimes requires an extensive refactoring. At its best, the required refactoring can be time-consuming. At its worst, it can turn into a rabbit hole that causes a big delay on the project.</p>
<p>When I face cases like this, I used to either take a chance and do the extensive refactoring anyway or hold my nose and let the code stay stinky. Now I realize there is a happy middle point: <strong>I don’t have the make the code perfect. I can spend as much or as little time as I can afford to make the code a bit better.</strong></p>
<p>Small improvements I do can be still useful for the developers that come next. And those developers may have time to improve the code further, building upon the improvements I make.</p>
<p>(PS: There’s no perfect nor ideal code. The moment you make a change, you see more improvements you can make.)</p>
<h4 id="heading-time-box-your-refactoring"><strong>Time-box your refactoring.</strong></h4>
<p>Time-boxing is a great technique to avoid rabbit holes. Before starting to refactor, do a quick estimation about how much time you can spend on refactoring legacy code without delaying the project too much. Write that number down.</p>
<p>Time-boxing your refactoring gives you the peace of mind knowing the main project will stay on track. And that makes the refactoring experience more enjoyable.</p>
<h4 id="heading-bake-the-refactoring-time-into-the-project-estimation"><strong>Bake the refactoring time into the project estimation.</strong></h4>
<p>Things can be even easier if you bake the refactoring time into the project estimation before starting a project. While estimating how much time a project might take, take a quick look at the code you need to touch: when was it first written? How readable and extensible is it? How much test coverage does it have? Unless there’s a hard requirement about when the project needs to be shipped, you should bake some refactoring time into the project’s timeline.</p>
<p>After all, <strong>as we keep building upon a legacy codebase, refactoring it as we go is the best way to keep it healthy.</strong> And a healthy codebase, in turn, makes building new features faster and safer.</p>
<h4 id="heading-refactoring-is-educational"><strong>Refactoring is educational.</strong></h4>
<p>Refactoring a piece of code is the best way to understand it. Compared to staying aloof and just reading a piece of code, coming in and modifying it gives you a much deeper and intimate relationship with the code.</p>
<p>When you try to add your touch to the code, you will start to notice things you missed before. You may see the constraints and may even understand why the author originally wrote the code this way.</p>
<p><strong>Although refactoring a piece of code doesn’t seem to add any immediate value to the business, it’s an opportunity for you to gain a piece of domain knowledge you currently don’t have.</strong> Gaining that domain knowledge is invaluable to both you and the business.</p>
<h4 id="heading-refactoring-is-a-muscle-you-can-build"><strong>Refactoring is a muscle you can build</strong></h4>
<p><strong>The more you do it, the faster you become.</strong> One last reason to refactor legacy code is to use it as an opportunity to strengthen your “refactoring muscle”. Investing in building your “refactoring muscle” has a self-reinforcing compound effect: <strong>the more you refactor, the better you are at refactoring, making your next refactoring faster.</strong> The more you do it, the better the codebase is, making building future features faster.</p>
<p>Luckily, my next project relates to code from almost three years ago. I expect to face many cases requiring me to balance between refactoring legacy code and making progress on the project. I will share my new learning on <a target="_blank" href="https://www.sihui.io">my personal blog</a> (NOT medium). Subscribe to follow along!</p>
<p>My career plan for the year is to grow into a tech lead. I’m excited about all the learnings ahead and would love to share this journey with you in a brutally honest fashion. <strong>I will be sharing my weekly learning on my <a target="_blank" href="https://www.sihui.io">personal blog</a> (NOT medium)</strong>.</p>
<p>In the next few months, I will focus on growing in the following areas, so you can expect to see posts related to them:</p>
<ul>
<li>focusing on the big picture of the project instead of near-term implementation details;</li>
<li>balancing my efforts between leading projects and coding;</li>
<li>work-life balance for long-term productivity;</li>
<li>the human side of software development: making sure everyone riding with me enjoys the ride and feels fulfilled and inspired.</li>
</ul>
<p><em>Originally published at <a target="_blank" href="https://www.sihui.io/refactoring-vs-staying-focused/">www.sihui.io</a> on February 1, 2019.</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
