<?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[ code review - 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[ code review - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 22 May 2026 17:39:30 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/code-review/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Unblock Your AI PR Review Bottleneck: A Tech Lead’s Guide to Building a Codebase-Aware Reviewer ]]>
                </title>
                <description>
                    <![CDATA[ A few months ago, I was reviewing a pull request that added three new API endpoints. The diff was clean. Tests passed. The agent that generated it had even written sensible authorisation checks. By ev ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-unblock-ai-pr-review-bottleneck-handbook/</link>
                <guid isPermaLink="false">69f906a346610fd60629a300</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leadership ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Qudrat Ullah ]]>
                </dc:creator>
                <pubDate>Mon, 04 May 2026 20:50:43 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/c94dff21-66d0-4256-bf3e-25c1978364d9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A few months ago, I was reviewing a pull request that added three new API endpoints. The diff was clean. Tests passed. The agent that generated it had even written sensible authorisation checks. By every signal I usually rely on, it was ready to merge.</p>
<p>The problem only showed up when I checked which authentication middleware the agent had imported.</p>
<p>Our codebase had two: a v1 middleware backed by MongoDB and a v2 middleware backed by MySQL, which we had spent the previous quarter migrating.</p>
<p>New endpoints were supposed to use v2. The agent had used v1 for all three. Tests passed because user records still existed in both databases (that was the point of the migration), and the v1 middleware happily authenticated them. The code worked. But every new endpoint we shipped was reinforcing the legacy auth path we had just spent a quarter trying to retire.</p>
<p>I caught it on the second read. Twenty minutes after the comments, the engineer fixed it and reopened the PR. The third reviewer probably wouldn't have caught it. The migration timeline lived in a Slack thread from six months earlier. The rule that "new endpoints use v2" lived in my head.</p>
<p>This kind of catch is the slow-burn version of why AI changed my job as a tech lead. Code generation got faster. My review queue got longer. The hardest reviews were the ones where everything looked right, and the only thing wrong was something that lived in the team's collective memory rather than in the diff.</p>
<p>This handbook is about what we did to fix that. It's the story of how we went from drowning in clean-looking PRs to running a custom AI PR reviewer that catches a meaningful share of these mistakes before any human is pulled in. The fix turned out to be less about buying a better tool and more about moving the team's memory into a place the AI could actually read.</p>
<p>The lessons should transfer whether your team uses Claude Code, Cursor, Cline, GitHub Copilot, or any combination. The structure matters more than the tool.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-the-old-bottleneck-and-the-one-ai-created">The Old Bottleneck, and the One AI Created</a></p>
</li>
<li><p><a href="#heading-what-the-new-review-work-actually-looks-like">What the New Review Work Actually Looks Like</a></p>
</li>
<li><p><a href="#heading-why-i-did-not-just-buy-a-tool">Why I Did Not Just Buy a Tool</a></p>
</li>
<li><p><a href="#heading-the-realisation-move-the-rules-into-the-codebase">The Realisation: Move the Rules Into the Codebase</a></p>
</li>
<li><p><a href="#heading-two-files-that-changed-everything-agentsmd-and-claudemd">Two Files That Changed Everything: AGENTS.md and CLAUDE.md</a></p>
</li>
<li><p><a href="#heading-where-per-service-memory-files-earn-their-keep">Where Per-Service Memory Files Earn Their Keep</a></p>
</li>
<li><p><a href="#heading-what-this-looks-like-on-disk">What This Looks Like on Disk</a></p>
</li>
<li><p><a href="#heading-generated-documentation-as-a-side-effect">Generated Documentation as a Side Effect</a></p>
</li>
<li><p><a href="#heading-building-the-pr-review-command">Building the PR Review Command</a></p>
</li>
<li><p><a href="#heading-guardrails-read-only-by-default">Guardrails: Read-Only by Default</a></p>
</li>
<li><p><a href="#heading-the-compounding-loop-that-made-the-real-difference">The Compounding Loop That Made the Real Difference</a></p>
</li>
<li><p><a href="#heading-starting-from-zero-on-an-existing-project">Starting From Zero on an Existing Project</a></p>
</li>
<li><p><a href="#heading-what-still-needs-human-review">What Still Needs Human Review</a></p>
</li>
<li><p><a href="#heading-a-two-week-setup-plan">A Two-Week Setup Plan</a></p>
</li>
<li><p><a href="#heading-what-is-working-what-i-am-still-improving">What Is Working, What I Am Still Improving</a></p>
</li>
<li><p><a href="#heading-sources">Sources</a></p>
</li>
</ul>
<h2 id="heading-the-old-bottleneck-and-the-one-ai-created">The Old Bottleneck, and the One AI Created</h2>
<p>To understand why this fix was needed, it helps to remember what reviewing code looked like a couple of years ago.</p>
<p>Back then, the slow part was upstream of the PR. A ticket would land, and before anyone could open a branch, there was a long preamble of context-gathering.</p>
<p>Junior engineers needed time to understand what the change was for. Senior engineers had to explain business rules and architectural decisions. Tickets sat in "ready" columns for days while someone with the right context made themselves available. Then the writing itself took time, because typing real code is slower than typing comments about it.</p>
<p>That bottleneck mostly dissolved when the team got serious about AI-assisted development. Engineers used the agent to read the codebase, ask clarifying questions, draft an implementation plan, and produce a working branch in hours instead of days. Tickets moved through the queue faster. Junior engineers shipped more without blocking on senior availability. From the outside, this looked like an unambiguous win.</p>
<p>But the bottleneck didn't disappear. It moved.</p>
<p>Within a few weeks of widespread AI adoption, my review queue had doubled. Then tripled. Engineers were opening PRs faster than I could read them.</p>
<p>The PRs themselves looked clean: well-formatted, with sensible variable names, passing tests, and AI-generated descriptions that read better than most human-written ones.</p>
<p>On the surface, this was great. In practice, it was creating a different kind of pain. I was the senior engineer who knew which patterns mattered and which paths through the codebase were the right ones, and I was the bottleneck. The team's velocity was now capped by my reading speed.</p>
<p>The CircleCI 2026 State of Software Delivery report confirmed I was not alone. Drawing on more than 28 million CI workflow runs across over 22,000 organisations, the report showed feature branch throughput had grown 59% year over year, the largest jump CircleCI had ever measured. Main branch throughput, where code actually gets promoted to production, fell by 7% for the median team in the same period. Build success rates dropped to 70.8%, the lowest in five years.</p>
<p>The pattern was consistent across the industry. AI accelerated writing. The rest of the system absorbed the cost.</p>
<p>So the question for me, as a tech lead, became concrete: how do I unblock myself without lowering the bar?</p>
<h2 id="heading-what-the-new-review-work-actually-looks-like">What the New Review Work Actually Looks Like</h2>
<p>Before I explain the fix, it helps to know what kinds of issues were actually piling up. They weren't the dramatic kind. None of them would crash production. They were small, recurring, and looked plausible at a glance.</p>
<p>Take the simplest case I kept catching. An engineer would ask the agent to add a delete button on a new screen. The button needed to call our existing backend delete endpoint. Instead of reusing the hook the team already had for that endpoint, the agent would write the fetch call inline.</p>
<p>The code worked. The tests passed. But a week later, when someone changed the backend response shape, only one of the two call sites got updated.</p>
<p>That kind of duplication doesn't show up in a code review unless the reviewer happens to remember that a hook exists.</p>
<p>Another example I saw constantly: the agent comparing a status field against the literal string <code>"completed"</code> instead of using the <code>Status.Completed</code> enum that the rest of the services used. The code ran. The tests ran. The next refactor of the enum quietly skipped the file. After a few days, someone would spend half a day debugging a state machine that was working fine until the agent's literal silently fell out of sync.</p>
<p>These were two-minute fixes once spotted, but spotting them took me a reasonable time per PR. The friction wasn't the difficulty. It was the repetition.</p>
<p>The pattern repeated across larger problems, too.</p>
<p>I once asked an agent to build an event creation wizard. The wizard needed several dropdowns and one new component.</p>
<p>We have a design system folder where shared UI components live, and the rule on the team is simple: check there first, and if you build something new, register it there.</p>
<p>The agent had no way to know that. It only loaded the wizard's own files, so it never opened the design system folder. It generated brand new dropdowns inline, with APIs that were almost identical to the ones we already had. The new component went straight into the wizard rather than into the design system. CI passed. The wizard worked. We caught the duplication in human review, but it was the kind of catch that depended entirely on a reviewer who happened to know the design system existed.</p>
<p>The same pattern hit in one of the repos I was looking at for backend architecture. Backend follows a strict four-layer pattern: route, controller, app, repo. Controllers must never call repository functions directly. That rule keeps authorisation centralised, business logic testable, and database concerns isolated.</p>
<p>One PR I reviewed had the agent calling repo functions straight from a controller, skipping the app layer entirely. The code worked. The tests passed because the agent had also written tests against the new shape. But it broke a discipline the team had spent years building. If that PR had landed, the next AI-assisted PR could have used it as a template, and the layering would have eroded one diff at a time.</p>
<p>The common thread is that all of these mistakes had something written down somewhere, in code, in a Slack thread, in a senior engineer's head, that would have prevented them. The information existed. The agent just couldn't see it.</p>
<h2 id="heading-why-i-did-not-just-buy-a-tool">Why I Did Not Just Buy a Tool</h2>
<p>The obvious next move was to install one of the AI PR reviewers that flooded the market in 2026.</p>
<p>I evaluated several. Anthropic launched Claude Code Review in March 2026, billed on token usage and averaging \(15 to \)25 per review. CodeRabbit Pro charges \(24 per developer per month on annual billing, or \)30 per developer per month on monthly billing, with seats counted against developers who actually open PRs. Greptile in March 2026 moved to a base-plus-usage model at $30 per seat per month, including 50 reviews, after which each additional review costs a dollar. GitHub announced that all Copilot plans will transition to usage-based billing on June 1, 2026, with code reviews consuming both AI Credits and GitHub Actions minutes from that date.</p>
<p>For a small team with low PR volume, none of these is a dealbreaker. For a larger team running heavy AI-assisted development, the costs compound fast. A 10-person team running five PRs each per day blows through Greptile's included reviews in a single week. CodeRabbit Pro at \(24 per seat scales linearly with developers. The premium Claude Code Review at \)15 to $25 per PR is the most expensive option per review by an order of magnitude.</p>
<p>I looked at the cost numbers, but cost wasn't actually the deciding factor. The deciding factor was that none of these tools would have caught the problems I just listed.</p>
<p>A generic reviewer wouldn't have caught the v1/v2 middleware. It had no way to know v2 was the canonical path. A generic reviewer wouldn't have caught the duplicate dropdowns. It had no way to know our design system existed. A generic reviewer wouldn't have caught the bypassed architecture. It had no way to know that controllers must not call repositories.</p>
<p>The information that lets a reviewer flag any of these is exactly the information that lives in the team's head, not in any tool's default prompt.</p>
<p>The better-rated tools support custom rules, and that's where I started to see the real shape of the problem. Once you are configuring custom rules, you've already accepted that the value is in the rules. The tool is just whatever runs them.</p>
<p>This raised a different question: if the rules are the product, why pay per seat or per review for someone else's wrapper around them?</p>
<p>This is what made me change direction.</p>
<h2 id="heading-the-realisation-move-the-rules-into-the-codebase">The Realisation: Move the Rules Into the Codebase</h2>
<p>Once I started thinking of the rules as the product, the path forward got clearer.</p>
<p>I asked myself a simple question: what was I actually doing in code review that the AI was not? The answer turned out to be the same thing, over and over. I was typing review comments that captured a piece of the team's memory.</p>
<p>"Use the Status enum, not a string literal." "There is already a hook for this in <code>/hooks/useDeleteItem</code>." "Controllers must not import from the repo layer; route this through the app layer." "Check the design system folder before creating new components."</p>
<p>Each of those comments was knowledge that lived in my head and arrived in the codebase one PR comment at a time. None of it was available to the agent the next time it generated a similar PR.</p>
<p>So the fix was not to buy a smarter reviewer. The fix was to write the rules down in a place every agent on the team would read before any review happened.</p>
<p>If I had typed "use the enum, not a literal" three times in three different PRs, that was a rule the agent should know about from now on. If I had pointed at the design system folder for the fourth time, that was a rule. If I had explained the four-layer architecture twice in PR comments, that was a rule.</p>
<p>I needed somewhere to put these rules. That turned out to be a less obvious decision than I expected.</p>
<h2 id="heading-two-files-that-changed-everything-agentsmd-and-claudemd">Two Files That Changed Everything: AGENTS.md and CLAUDE.md</h2>
<p>If you start looking into how to give an AI agent a persistent project context, you run into two competing conventions almost immediately.</p>
<p>The first is <strong>AGENTS.md</strong>, an open standard that has gathered real momentum. According to InfoQ, by mid-2025, the format had already been adopted by more than 20,000 GitHub repositories and was being positioned as a complement to traditional documentation: machine-readable context that lives alongside human-facing files like README.md.</p>
<p>The standard's own site reports it is now used by more than 60,000 open-source projects and has moved to stewardship under the Agentic AI Foundation, which sits inside the Linux Foundation. The format is supported by OpenAI Codex, GitHub Copilot, Google Gemini, Cursor, and Windsurf, among others.</p>
<p>The second is <strong>CLAUDE.md</strong>, which is Anthropic's convention for Claude Code. The Claude Code documentation describes two complementary memory systems: CLAUDE.md, where you write the persistent context yourself, and an auto-memory mechanism that lets Claude save its own notes from corrections and observed patterns. By default, Claude Code reads CLAUDE.md, not AGENTS.md.</p>
<p>This split mattered for us because half the team uses Claude Code and the other half uses Cursor. We had two practical options: maintain both files with the same content (and accept the duplication), or symlink one filename to the other so both ecosystems read the same source of truth. We went with the symlink. It's one less thing to drift.</p>
<p>The next question was what to actually put in the file. After a few iterations, here's the shape that worked. Think of it as a briefing document for a new engineer who has read no code and seen no Slack threads. The minimum content was:</p>
<ul>
<li><p>The tech stack (languages, frameworks, package manager)</p>
</li>
<li><p>The project structure, especially important for our monorepo</p>
</li>
<li><p>Where shared utilities, components, and helpers live, and the rule that new code should reuse them before creating new versions</p>
</li>
<li><p>Architectural patterns the project follows, with file path examples</p>
</li>
<li><p>Anti-patterns and what to do instead</p>
</li>
<li><p>Test conventions and where good examples live</p>
</li>
<li><p>Pointers to deeper documentation when more detail is needed</p>
</li>
</ul>
<p>Two practical rules emerged from the first month of using these files.</p>
<p><strong>Keep them lean:</strong> There is a counterintuitive failure mode with long instruction lists: the agent doesn't just skip the new ones at the bottom. The average compliance across all of them drops. A bloated memory file becomes a memory file that the agent skims. If a section runs more than a paragraph or two, move it to a separate document and link to it.</p>
<p><strong>Phrase rules as imperatives, not aspirations:</strong> "Controllers must not call repositories. Route through the app layer." beats "Try to keep controllers thin." The first is testable. The second is decorative.</p>
<p>That was the entry point. But a single root-level file was not enough for a monorepo with multiple services and frontends, which led to the next decision.</p>
<h2 id="heading-where-per-service-memory-files-earn-their-keep">Where Per-Service Memory Files Earn Their Keep</h2>
<p>A single <code>AGENTS.md</code> at the root of a monorepo collapses under its own weight pretty quickly. Each service in our codebase has its own architecture, conventions, and business rules. Trying to fit all of that into one file produced a long document that the agent treated as background noise, and we were back to the bloat problem from the previous section.</p>
<p>The pattern that worked: every service or app gets its own <code>AGENTS.md</code> at its root, and the project-level <code>AGENTS.md</code> becomes an index that points to them.</p>
<p>A per-service <code>AGENTS.md</code> covers things like:</p>
<ul>
<li><p>The architecture for this service (the four-layer pattern, the directory layout)</p>
</li>
<li><p>Naming conventions specific to this service</p>
</li>
<li><p>Test patterns and where good examples live</p>
</li>
<li><p>Business rules that this service is responsible for</p>
</li>
<li><p>Inter-service contracts and what other services consume from this one</p>
</li>
<li><p>Pointers to deeper docs in <code>docs/</code></p>
</li>
<li><p>A "Lessons learned" section, which I'll come back to in the section on the compounding loop</p>
</li>
</ul>
<p>The same lean rule applies. Keep it short, point at examples, and phrase guidance as imperatives.</p>
<p>The reason this works mechanically is that the agent loads the right files for the work at hand. When an engineer asks the agent to change something in <code>backend/</code>, the agent reads the project-level <code>AGENTS.md</code>, sees that work in <code>backend/</code> should be guided by <code>backend/AGENTS.md</code>, and loads that file. It doesn't load the frontend's <code>AGENTS.md</code>, because that work is somewhere else. The context window stays focused on what's relevant.</p>
<p>Without this split, you have two bad options. Either you put everything in the root file, where the agent ignores most of it, or you put nothing in the root file, where the agent has no team context at all. The per-service split gives you both depth and signal.</p>
<p>But these files only work if the deeper docs they point to actually exist, which is where the next piece of the system came in.</p>
<h2 id="heading-what-this-looks-like-on-disk">What This Looks Like on Disk</h2>
<p>Before going further, it helps to see the whole structure laid out. Here's the shape we settled on for our monorepo. The exact folder names follow Claude Code's conventions. If you use Cursor, it would be <code>.cursor/</code>, and if you use Cline, it would be <code>.clinerules</code> – but the shape transfers directly.</p>
<pre><code class="language-plaintext">project-root/
├── AGENTS.md                       # symlink to CLAUDE.md
├── CLAUDE.md                       # root memory file
├── README.md                       # human-facing project readme
│
├── .claude/                        # tool-specific config folder
│   ├── README.md                   # explains the .claude/ layout
│   ├── settings.json               # permissions and guardrails
│   ├── agents/                     # specialised subagents (optional)
│   ├── commands/                   # slash commands engineers run
│   │   ├── review-pr.md            # the PR review command
│   │   └── plan-feature.md         # implementation plan command
│   ├── hooks/                      # lifecycle hooks (optional)
│   ├── pr-rules/                   # rule files for PR review
│   │   ├── common.md               # rules that apply to every PR
│   │   ├── frontend.md             # rules for frontend changes
│   │   ├── backend.md              # rules for backend changes
│   │   ├── service-a.md            # rules for service-a
│   │   └── service-b.md            # rules for service-b
│   └── skills/                     # reusable workflows
│
├── frontend/
│   ├── AGENTS.md                   # frontend conventions
│   ├── docs/
│   │   ├── overview.md
│   │   ├── architecture.md         # routing, state, data layer
│   │   ├── design-system.md        # design system reference
│   │   └── testing.md              # test conventions
│   └── src/
│
├── backend/
│   ├── AGENTS.md                   # the four-layer pattern
│   ├── docs/
│   │   ├── overview.md
│   │   ├── architecture.md         # route -&gt; controller -&gt; app -&gt; repo
│   │   ├── auth.md                 # v1 vs v2 middleware
│   │   ├── business-rules.md
│   │   └── integrations.md
│   └── src/
│
├── service-a/
│   ├── AGENTS.md
│   ├── docs/
│   │   ├── overview.md
│   │   ├── business-rules.md
│   │   └── integrations.md
│   └── src/
│
└── service-b/
    ├── AGENTS.md
    ├── docs/
    │   ├── overview.md
    │   ├── business-rules.md
    │   └── integrations.md
    └── src/
</code></pre>
<p>A few things worth pointing out:</p>
<p>The <code>.claude/</code> folder uses standard subfolder names: <code>commands</code>, <code>agents</code>, <code>hooks</code>, <code>skills</code>. These follow Claude Code's plugin model, but most modern AI coding tools have similar slots. Following the conventions makes the structure recognisable to anyone on the team and lowers the cost of switching tools later.</p>
<p>The <code>pr-rules/</code> folder isn't a standard convention. It's a folder we created to hold per-area review rules that the PR review command loads selectively. You don't have to call it <code>pr-rules</code> – the name matters less than having one place where review rules live.</p>
<p>Each service has its own <code>AGENTS.md</code> plus a <code>docs/</code> folder. The root <code>AGENTS.md</code> is short and acts as an index. It tells the agent things like "if you touch files in <code>backend/</code>, also read <code>backend/AGENTS.md</code> first." The per-service file then points at the deeper docs as needed.</p>
<h2 id="heading-generated-documentation-as-a-side-effect">Generated Documentation as a Side Effect</h2>
<p>Setting up per-service <code>AGENTS.md</code> files surfaced a problem I had been quietly avoiding. Most of our services didn't have decent documentation. Not API reference material, which lives in code, but the higher-level "what does this service do, what business rules does it enforce, what does it consume and produce" information that lives in nobody's head except the original author's.</p>
<p>The honest reason was that writing this kind of documentation by hand had never paid back the time it took. By the time the doc was finished, half of it was already stale.</p>
<p>So I tried something I wouldn't have considered earlier. I used the AI itself to generate a first draft for each service. I pointed the agent at each service's code and asked it to produce a <code>docs/</code> folder with a specific structure: an overview, a list of business rules, an integrations document, a domain model, and any quirks worth knowing. The agent read the code, traced the call paths, and wrote a draft.</p>
<p>I then reviewed the output by hand, corrected the things it got wrong, and committed the result. The first drafts were 70-80% correct. The remaining 20-30% was where the agent had made plausible but wrong inferences, and those were exactly the cases where human review mattered.</p>
<p>The generated docs ended up serving two audiences. The agent uses them when reasoning about changes, which means it has real context for the service it's touching rather than guessing from local files. And new engineers use them on their first day, which has cut our onboarding time noticeably.</p>
<p>We used to write onboarding documents that drifted out of date within months. These docs stay closer to current because the agent reads them on every PR, and any drift gets surfaced when the agent gives wrong advice based on stale information.</p>
<p>The pattern that works is to keep the per-service <code>AGENTS.md</code> short and pointing at the docs, rather than duplicating their content. <code>AGENTS.md</code> is the always-loaded index. <code>docs/</code> holds the details. The agent loads the relevant doc on demand when the task calls for it.</p>
<p>With the rules in place and the docs in place, I had everything I needed to build the actual reviewer.</p>
<h2 id="heading-building-the-pr-review-command">Building the PR Review Command</h2>
<p>This is the piece that most directly unblocked my queue.</p>
<p>This command didn't appear out of nowhere. It started as the checklist I was running through in my head every time I opened a PR. I was reviewing every change manually, leaving the same comments, flagging the same patterns. So I wrote that checklist down, expanded it with references to the per-service docs for the harder rules, and turned it into a command anyone on the team could run.</p>
<p>Then I handed it to the engineers and changed the rule: run this on your own branch before marking the PR ready for review. That single shift moved the work from after the PR was opened to before. Engineers now catch 90-95% of the blockers, improvements, and nice-to-haves on their own machine, fix them locally, and only then push the change.</p>
<p>The PR description includes the AI's summary, so when anyone opens the PR, they can see the reviewer's green signal at the top before even reading the diff.</p>
<p>GitHub stays clean. The conversation on the PR becomes about the things that actually need a human, not the recurring stuff the team already knows how to fix.</p>
<p>The command lives in <code>.claude/commands/review-pr.md</code>. Here's a generalised version. Your tool's command structure may differ, but the shape is what matters.</p>
<pre><code class="language-markdown"># Review PR

Review the current branch's PR. Be direct. Cite `file:line`. Surface real issues,
no padding.

## 1. Scope the diff

Run, in order:

    gh pr view --json number,title,body,headRefName 2&gt;/dev/null || true
    git fetch origin main
    git log --no-merges origin/main..HEAD --oneline
    git diff origin/main...HEAD --stat
    git diff origin/main...HEAD

Read the PR body. Note the stated intent. Every change should trace to it. Flag
anything that does not.

Use `...` (three dots) for the diff. It compares against the merge base and
excludes commits brought in by merging main.

## 2. Load rules

Always read `.claude/pr-rules/common.md`.

Then read the per-area file for each workspace touched in the diff:

| Workspace path | Rules file                      |
| -------------- | ------------------------------- |
| `frontend/**`  | `.claude/pr-rules/frontend.md`  |
| `backend/**`   | `.claude/pr-rules/backend.md`   |
| `service-a/**` | `.claude/pr-rules/service-a.md` |
| `service-b/**` | `.claude/pr-rules/service-b.md` |

For non-trivial changes, follow doc pointers inside the rules files (for
example, `backend/AGENTS.md`, `backend/docs/architecture.md`).

Apply every entry under each file's "Lessons learned" section as a check.

## 3. Output

Use exactly this format.

    ## Summary
    &lt;one paragraph: what the PR does, whether it matches the stated intent&gt;

    ## Blocking
    - [file:line] issue, why it blocks

    ## Should fix
    - [file:line] issue

    ## Nice to have
    - issue

    ## Verified
    - what was checked and looks good

If nothing blocks, say so. Do not manufacture concerns.

If you find an issue worth remembering for future PRs, suggest the bullet to
add to the relevant rules file's "Lessons learned" section. Do not edit the
rules file yourself, leave that to the human.
</code></pre>
<p>A few of the design choices in this command turned out to matter more than I expected.</p>
<p>The structured output format (Summary, Blocking, Should fix, Nice to have, Verified) keeps the review easy to scan and easy to paste into a PR description. The "Verified" section is the most underrated of the five: it tells the human reviewer what the AI already checked, so they can spend their attention elsewhere. Without it, the human reviewer ends up doing the same checks twice.</p>
<p>The instruction to be direct and stop padding does real work. Without it, AI reviewers tend to manufacture concerns to look thorough, which trains engineers to skim past the bot. Telling it explicitly to say "nothing blocks" when nothing blocks made the signal-to-noise ratio of the output much better.</p>
<p>The "suggest a bullet for the rules file" instruction at the end is the heart of the whole system, and I'll explain why in the section on the compounding loop. The key constraint here is that the agent suggests the bullet but doesn't commit to it. A human evaluates whether it's general enough to be a rule, and only then adds it to the file. That manual step is what keeps the rules sharp instead of bloated.</p>
<p>With each PR, if humans fix something or the AI suggests something, you keep adding those to your MD files and keep improving your agents for the future. The result compounds quickly.</p>
<p>One more thing here: the diff-scoping commands are all read-only. The command shouldn't be able to push, edit PRs, or close anything. Which is the next piece of the system.</p>
<h2 id="heading-guardrails-read-only-by-default">Guardrails: Read-Only by Default</h2>
<p>Giving an AI agent broad permissions on your codebase is a security incident waiting to happen. Even if you trust the model to behave, an LLM occasionally does unexpected things, and a fast-moving agent on an unrestricted shell can cause damage in seconds.</p>
<p>The fix is a <code>settings.json</code> (in Claude Code – other tools have their own equivalents) at the root of <code>.claude/</code> that explicitly declares what the agent can and can't do. The deny list matters more than the allow list, and a good one is organised around four categories of risk.</p>
<p>The first is <strong>secrets and configuration</strong>. Any read against anything that appears to be a credential is blocked. That covers <code>.env</code> files of every variant (<code>.env</code>, <code>.env.local</code>, <code>.env.production</code>, <code>.env.test</code>, and so on), <code>.npmrc</code>, <code>.netrc</code>, <code>.pgpass</code>, <code>id_rsa</code>, <code>id_ed25519</code>, <code>*.pem</code>, <code>*.key</code>, <code>*.p12</code>, <code>**/credentials.json</code>, <code>**/secrets.json</code>, <code>**/.aws/**</code>, <code>**/.ssh/**</code>, <code>**/.gcloud/**</code>, and <code>**/.kube/**</code>. Environment dumps are blocked too: <code>env</code>, <code>printenv</code>, <code>set</code>, <code>export</code>. The agent has no legitimate reason to read or echo any of these, ever.</p>
<p>The second is <strong>destructive Git operations</strong>. The agent can read Git history but can't rewrite or push it. Blocked: <code>git push</code>, <code>git commit</code>, <code>git revert</code>, <code>git cherry-pick</code>, <code>git merge</code>, <code>git rebase</code>, <code>git reset --hard</code>, <code>git tag</code>. Allowed: <code>git fetch</code>, <code>git status</code>, <code>git log</code>, <code>git diff</code>, <code>git show</code>, <code>git branch</code>, <code>git rev-parse</code>, <code>git merge-base</code>, <code>git config --get</code>.</p>
<p>The third is <strong>write operations on PRs and issues</strong>. The agent can read your GitHub state but can't act on it. Blocked: <code>gh pr create</code>, <code>gh pr edit</code>, <code>gh pr merge</code>, <code>gh pr close</code>, <code>gh pr comment</code>, <code>gh pr review</code>, <code>gh issue create</code>, <code>gh issue edit</code>, <code>gh issue close</code>, <code>gh issue comment</code>, <code>gh release create</code>, <code>gh repo create</code>, <code>gh repo edit</code>, <code>gh repo delete</code>. Allowed: <code>gh pr view</code>, <code>gh pr list</code>, <code>gh pr diff</code>, <code>gh pr checks</code>, <code>gh issue view</code>, <code>gh issue list</code>, <code>gh release view</code>.</p>
<p>The fourth is <strong>workflow and automation control</strong>. These are the surfaces where a compromised or misled agent could do the most damage. Blocked: <code>gh workflow run</code>, <code>gh run rerun</code>, <code>gh run cancel</code>, <code>gh secret</code>, <code>gh variable</code>, <code>gh auth</code>, <code>gh ssh-key</code>, <code>gh gpg-key</code>, and the unrestricted <code>gh api</code>.</p>
<p>For shell commands the agent legitimately needs to run, like build and test commands, allowlist specific patterns: <code>pnpm test</code>, <code>pnpm lint</code>, <code>pnpm format:check</code>, <code>pnpm build</code>, <code>pnpm vitest</code>. Anything outside the allowed list requires human confirmation. These are your own settings&nbsp;– I've just mentioned what I prefer.</p>
<p>The pattern is simple: read-only by default, write-allowed only for the specific commands you have explicitly approved. The agent can investigate, plan, and recommend. It can't ship.</p>
<p>With the structure in place and the guardrails set, the system started doing its job. What I didn't expect was how much better it would get over the months that followed.</p>
<h2 id="heading-the-compounding-loop-that-made-the-real-difference">The Compounding Loop That Made the Real Difference</h2>
<p>When we started, the AI reviewer was useful but not transformative. It caught some obvious issues, missed plenty of subtle ones, and produced a fair amount of noise.</p>
<p>The first month, my review burden dropped by 35%. The time I was spending on PR checking was reduced to 1/3, almost. Decent, not life-changing.</p>
<p>What changed over time wasn't the tool. It was the rules.</p>
<p>Every time a PR creator and reviewer caught something the AI had missed, we were adding bullets to the relevant rules file. Every time the AI flagged something useful that turned out to be a recurring pattern, the agent's own suggestion at the end of the review went into the file.</p>
<p>After a few days, the rules files had grown into something that captured a meaningful fraction of the team's collective review knowledge, written down in a place every agent on the team would read.</p>
<p>The catch rate went up. The noise went down because the rules also said what was acceptable and what we already considered solved. New engineers stopped getting the same comments on their first three PRs because the AI caught the comments first. Engineers joining the team didn't have to absorb the conventions through six months of review feedback. They installed the project, opened it in their editor, and the agent already knew.</p>
<p>This is the part most teams miss when they evaluate AI PR review tools. They look at the catch rate today and decide whether the tool is worth the price. The catch rate today isn't the right number. The right number is what the catch rate looks like in six months, after the rules file has absorbed every recurring mistake your team has made.</p>
<p>A single rule written down today saves a small amount of review time. Over a hundred PRs, it saves more. After a year, the rules file is a written-down version of a tech lead's accumulated taste. We've switched between Claude Code, the GitHub Copilot CLI, and Cursor for various tasks during this period. The AI tool changes, but the rules file in the repo stays the same.</p>
<p>The discipline that makes this work is treating the rules file as living documentation. Every recurring review comment is a candidate for promotion into the file. If you catch yourself typing the same feedback in two different PRs, that's a rule that belongs in <code>pr-rules/</code>. The "suggest a bullet" instruction in the review command is what makes this practical: the AI does the typing, the human does the deciding.</p>
<p>This is also what made me realise the system was worth the time it took to set up. The PR review command, on its own, is useful but unremarkable. The compounding loop is what turns it into infrastructure.</p>
<h2 id="heading-starting-from-zero-on-an-existing-project">Starting From Zero on an Existing Project</h2>
<p>If you've read this far and feel like the gap between your project and what I just described is a sprint of work, that's the most common reaction. It's also not correct.</p>
<p>The blank <code>AGENTS.md</code> is intimidating, especially on an existing codebase. You know your team has a thousand conventions, and writing a thousand rules sounds like a project that takes weeks before it produces any value.</p>
<p>The honest answer is that you can't write all the rules up front, and you shouldn't try. The first version of any of these files should take an afternoon, not a sprint.</p>
<p>Here's how I would actually start.</p>
<p>Run <code>/init</code> (or your tool's equivalent). In Claude Code, <code>/init</code> scans the project, infers the obvious shape (language, framework, entry points, build commands), and writes an initial <code>CLAUDE.md</code>. The output is a starting point, not a finished file. Read it, delete most of what it generates, and keep the bones.</p>
<p>Then add three things, each one bullet long.</p>
<p>First, an architecture rule. Pick the single most important convention your team enforces. For us, that was the four-layer pattern. The bullet was: "Controllers must not call repository functions directly. They must go through the app layer."</p>
<p>Second, a discoverability rule. Pick the single most important shared resource the team has, the one new code is most likely to duplicate. For us, that was the design system. The bullet was: "Before creating a new UI component, check <code>/src/design-system/</code> first."</p>
<p>Third, a "do not touch" rule. Pick the single most dangerous file or area in the codebase. Auth, billing, or migrations whichever has the most production risk. The bullet was: "Do not modify files in <code>/auth/</code> without human approval."</p>
<p>That's enough to start. Three rules, ten minutes of writing, and most of your team's recurring AI mistakes start to drop.</p>
<p>If even three rules feels like too much, start with one. Pick a single line that matters in your codebase and write it down.</p>
<p>"No <code>any</code> types in TypeScript." "Always use the enum, never compare against the string literal." "Run the linter before opening a PR." It doesn't have to be sophisticated. It doesn't have to cover edge cases. It just has to capture one piece of judgement that lives in your head today and would otherwise stay there.</p>
<p>Tomorrow, add another. The first week, you might catch 5% of the recurring mistakes. By 20 or 30 PRs in, you might catch 20-30%. The rules file doesn't need to be impressive on day one. It needs to exist and keep growing.</p>
<p>This is the compounding effect I'll come back to soon, and it's the reason this approach works on real projects rather than just in theory.</p>
<p>From there, the file grows the same way it would grow for any team. Every review catch becomes a candidate rule. After a few weeks, you have ten or fifteen rules. After a few months, you have a real review system.</p>
<p>The mistake is trying to write the perfect file on day one. The right file is the one you start with and keep editing.</p>
<h2 id="heading-what-still-needs-human-review">What Still Needs Human Review</h2>
<p>This system doesn't replace human review, and it shouldn't be allowed to.</p>
<p>The AI reviewer catches what the rules describe, plus a fair number of obvious things it would have spotted anyway. It doesn't catch problems that depend on context the rules don't capture. It doesn't catch product judgement. It doesn't catch the question of whether the change should have been built at all.</p>
<p>It also has an important blind spot when reviewing AI-authored code. The reviewer shares the same training data and reasoning patterns as the agent that wrote the code. If the original agent missed the v1/v2 distinction because it had no way to see the migration timeline, an AI reviewer reading the same diff has the same problem. Two AIs in a review loop are not two independent reviewers. They share blind spots.</p>
<p>That is why the AI reviewer in this setup never approves a PR. It produces a structured review that goes into the PR description. A human still reads the change and approves it. The AI is the first pass, not the gate.</p>
<p>Accountability also has to live with a human. When something the AI approved breaks production, someone has to own the post-mortem and decide what changes are needed for next time. The AI can't be that person. What it can do, well, is reduce the stack of small mistakes a human reviewer has to find before they get to the harder questions.</p>
<h2 id="heading-a-two-week-setup-plan">A Two-Week Setup Plan</h2>
<p>If you want to set this up for your own team, here's a concrete plan that fits in a couple of weeks. None of this needs to happen in a single push.</p>
<h3 id="heading-day-1-bootstrap-the-memory-file">Day 1: Bootstrap the memory file.</h3>
<p>Run <code>/init</code> (or your tool's equivalent) at the root of the project. Read the generated <code>CLAUDE.md</code> (or <code>AGENTS.md</code>). Delete most of it. Keep the tech stack and project structure sections.</p>
<p>Add the three rules from the previous section: one architecture rule, one discoverability rule, and one "do not touch" rule. Decide whether you want both files or a symlink.</p>
<h3 id="heading-day-2-add-per-service-files-for-your-highest-risk-areas">Day 2: Add per-service files for your highest-risk areas</h3>
<p>Pick the two or three areas of the codebase that change most often or carry the most risk. Add an <code>AGENTS.md</code> to each, following the same lean pattern. Include the architectural pattern for that area, the naming conventions, where to find good test examples, and pointers to any existing docs. Skip anything that doesn't need to be there yet.</p>
<h3 id="heading-day-3-set-up-the-directory-structure-and-guardrails">Day 3: Set up the directory structure and guardrails</h3>
<p>Create a <code>.claude/</code> folder (or your tool's equivalent) at the root, with <code>commands/</code> and <code>pr-rules/</code> subfolders. Add a <code>settings.json</code> with the deny list categories from the guardrails section. Test that the agent can't read a <code>.env</code> file, run <code>git push</code>, or create a PR. If any of those work, fix the settings before doing anything else.</p>
<h3 id="heading-day-4-write-the-pr-review-command">Day 4: Write the PR review command</h3>
<p>Adapt the command in this article to your structure. Include the diff scoping, the rule loading, the output format, and the "suggest a new rule" instruction at the end. Run it on a branch you've already merged, and tune the output until it's useful.</p>
<h3 id="heading-day-5-run-it-on-real-prs">Day 5: Run it on real PRs</h3>
<p>Have one or two engineers run the command on their next PRs before opening them. Read the output. Note what it caught, what it missed, and what was noise. Add the missing catches to the rules files. The first week is mostly tuning.</p>
<h3 id="heading-week-2-roll-out-and-document">Week 2: Roll out and document</h3>
<p>Once the command produces useful output reliably, ask the whole team to run it before opening PRs and paste the output into the PR description. Add a short section to your contributing guide explaining the workflow. Set a recurring item in your team's rituals to review the rules files monthly and trim anything that has gone stale.</p>
<p>That gets you to a working system. From there, the maintenance is incremental. Every recurring review comment becomes a candidate rule. Every architectural decision becomes a candidate update to the relevant <code>AGENTS.md</code>. The system improves as a side effect of the work the team is already doing.</p>
<h2 id="heading-what-is-working-what-i-am-still-improving">What Is Working, What I Am Still Improving</h2>
<p>Here's my honest assessment after a few months of running this:</p>
<h3 id="heading-whats-working">What's Working</h3>
<p>My review burden is meaningfully smaller. Engineers fix most of the easy mistakes before I see the PR. The "Verified" section of the AI's output tells me what to skip past. New engineers ramp faster because the conventions live in a place their tooling reads. The rules files have grown into something I would actually use to onboard someone new.</p>
<h3 id="heading-what-isnt-finished">What Isn't Finished</h3>
<p>The AI still misses problems that depend on context, and the rules don't capture them. The rules files grow, but they also need pruning, and we haven't been disciplined about that.</p>
<p>We're still figuring out how to handle rules that apply only conditionally. Docs are helping in that case, but we need to keep those up to date. And no system survives a determined engineer who skips the workflow or docs when they're in a rush.</p>
<p>There's no shortcut here. The work is real, ongoing, and mostly about discipline. The discipline is treating your codebase as something the AI needs to learn, and treating every recurring review comment as something that should be written down once instead of typed thirty times. If you're willing to do that, the tools take care of the rest.</p>
<p>If you take three things from this article, take these.</p>
<ol>
<li><p>First, don't pay for a generic reviewer to do a job your codebase needs to inform. Generic reviewers catch generic problems. Most of your real review work is specific to your team.</p>
</li>
<li><p>Second, put the rules in a file the AI reads, not in your head. <code>AGENTS.md</code>, <code>CLAUDE.md</code>, per-service files, per-area rules files. Pick a structure and stick to it.</p>
</li>
<li><p>Third, treat every human review catch as a chance to update the rules. The compounding effect over months is the entire point. A review system that improves itself is worth more than any single tool.</p>
</li>
</ol>
<p>That's the system. It took a couple of weeks to build the foundation and a few months for the rules to mature. It costs very little to run, and it has done more for our PR throughput than any tool I evaluated.</p>
<h2 id="heading-sources">Sources</h2>
<ul>
<li><p>CircleCI's 2026 State of Software Delivery report, analysing more than 28 million CI workflows from over 22,000 organisations: <a href="https://circleci.com/resources/2026-state-of-software-delivery/">https://circleci.com/resources/2026-state-of-software-delivery/</a></p>
</li>
<li><p>CircleCI's blog post detailing the year-over-year throughput numbers, including the 59% feature branch growth and the main branch decline: <a href="https://circleci.com/blog/five-takeaways-2026-software-delivery-report/">https://circleci.com/blog/five-takeaways-2026-software-delivery-report/</a></p>
</li>
<li><p>GitHub announcement of Copilot's transition to usage-based billing on June 1, 2026: <a href="https://github.blog/news-insights/company-news/github-copilot-is-moving-to-usage-based-billing/">https://github.blog/news-insights/company-news/github-copilot-is-moving-to-usage-based-billing/</a></p>
</li>
<li><p>GitHub changelog confirming Copilot code review will start consuming GitHub Actions minutes on June 1, 2026: <a href="https://github.blog/changelog/2026-04-27-github-copilot-code-review-will-start-consuming-github-actions-minutes-on-june-1-2026/">https://github.blog/changelog/2026-04-27-github-copilot-code-review-will-start-consuming-github-actions-minutes-on-june-1-2026/</a></p>
</li>
<li><p>AGENTS.md, the open standard's official site, including its stewardship under the Agentic AI Foundation and the Linux Foundation: <a href="https://agents.md/">https://agents.md/</a></p>
</li>
<li><p>Anthropic's Claude Code documentation on the memory system, including CLAUDE.md, auto memory, and the /init command: <a href="https://code.claude.com/docs/en/memory">https://code.claude.com/docs/en/memory</a></p>
</li>
<li><p>Anthropic's Claude Code GitHub Actions documentation, including notes on token-based billing and recommended cost controls: <a href="https://code.claude.com/docs/en/github-actions">https://code.claude.com/docs/en/github-actions</a></p>
</li>
<li><p>CodeRabbit's pricing documentation, confirming the per-developer-per-month seat model: <a href="https://docs.coderabbit.ai/management/plans">https://docs.coderabbit.ai/management/plans</a></p>
</li>
<li><p>Greptile's March 2026 pricing announcement, introducing the base-plus-usage model at $30 per seat per month with 50 included reviews: <a href="https://www.greptile.com/blog/greptile-v4">https://www.greptile.com/blog/greptile-v4</a></p>
</li>
<li><p>HumanLayer's write-up on writing a good CLAUDE.md, including data on instruction-following degradation: <a href="https://www.humanlayer.dev/blog/writing-a-good-claude-md">https://www.humanlayer.dev/blog/writing-a-good-claude-md</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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 Perform Code Reviews in Tech – The Painless Way ]]>
                </title>
                <description>
                    <![CDATA[ Okay, I know you may be skeptical: other guides have promised painless code reviews only to reveal that their solution requires some hyper-specific tech stack or a paid developer tool. I won’t do that to you. This guide provides a straightforward and... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-perform-code-reviews-in-tech-the-painless-way/</link>
                <guid isPermaLink="false">674f6a16678426d72d800cd5</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ankur Tyagi ]]>
                </dc:creator>
                <pubDate>Tue, 03 Dec 2024 20:29:10 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733242289474/def1a314-fe64-448b-9236-f66a529e3f13.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Okay, I know you may be skeptical: other guides have promised painless <code>code reviews</code> only to reveal that their solution requires some hyper-specific tech stack or a paid developer tool. I won’t do that to you.</p>
<p>This guide provides a straightforward and flexible template for <code>code reviews</code> that you can apply to your engineering team. The <strong>only</strong> requirement is that your app code is <code>open source</code>.</p>
<p>You can test a TypeScript workflow, Java workflow, Python workflow, PHP, Ruby or even some wacky web stack you invented. And it doesn’t matter if you’re developing on Windows, Linux, or Mac. Best of all, you don’t have to perform convoluted configuration or install software beyond a <code>yaml</code>.</p>
<p>I’ve been in engineering for the last 15 years, and <code>code reviews</code> have a bad reputation. We’ve all witnessed or lived through horror stories where sometimes it feels like every previous line gets torn to shreds.</p>
<p>So, what <em>can</em> you do differently? How can you make reviewing your code painless so that even the biggest nitpick on your team has nothing but praise?</p>
<p>After participating in code reviews for a decade, taking code reviews less personally is <strong>the single biggest thing you can do to improve your code.</strong> Why? Because all software is iterative. Even “perfect” code will eventually become outdated. Instead of thinking of it like a graded assignment, think of it as a part of the process.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents:</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-code-review">What is a Code Review?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-purpose-of-a-code-review">What is the Purpose of a Code Review?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-is-doing-code-reviews-hard">Why is Doing Code Reviews Hard?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-can-ai-replace-code-reviews">Can AI Replace Code Reviews?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-to-focus-on-during-a-code-review">What to Focus on During a Code Review</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-code-review-best-practices-and-process">Code Review Best Practices And Process</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-coderabbit">What is CodeRabbit?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-does-coderabbit-help">How Does CodeRabbit Help?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-github-repo-to-test">A GitHub Repo to Test</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-additional-examples">Additional Examples</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>This tutorial uses free, open-source tools. You’ll need to have a <a target="_blank" href="https://github.com/tyaga001">GitHub account</a> to help you make your code reviews more pleasant and valuable.</p>
<h2 id="heading-what-is-a-code-review"><strong>What is a Code Review?</strong></h2>
<p>The term “<a target="_blank" href="https://en.wikipedia.org/wiki/Code_review">code review</a>” can refer to various activities, from simply reading code over your teammate’s shoulder to a 10-person meeting where you dissect code line by line. I use the term to refer to a formal and written process, but not so heavyweight as a series of in-person code inspection meetings.</p>
<p>In a project where you work on a repository with other developers, after you complete your work, you commit, push, and create a pull request on the VCS, most likely using Git commands. Then, everyone reviews the pull request to determine whether it’s okay to use. If so, they approve it, and that code gets used in the project.</p>
<h2 id="heading-what-is-the-purpose-of-a-code-review"><strong>What is the Purpose of a Code Review?</strong></h2>
<p>Code Reviews are a tool for <em>knowledge transfer</em>. They help make devs more efficient when doing maintenance on a part of the system they didn't write.</p>
<p>When you review a pull request, it’s an opportunity to iron out issues before they become technical debt.</p>
<p>Code reviews can also be a good setting for mentoring junior developers.</p>
<p>Now, let’s discuss what is <strong>not</strong> the purpose of a code review:</p>
<ul>
<li>Finding bugs. That's what tests (unit, integration, e2e, api, and so on…)are for.</li>
</ul>
<p>Nitpicking on style issues – settle for one style and use formatters or AI tools to enforce it. Just keep in mind that there are many things that an AI tool cannot check. Code reviews are an excellent place to ensure the code is sufficiently documented or self-documenting.</p>
<p>Do you want to know how you can check this? Return to the code you wrote 6-12 months ago and try to understand what it was written to do.</p>
<p>If you understand it quickly, that means it's readable, and the code review was done properly and in a helpful manner.</p>
<h2 id="heading-why-is-doing-code-reviews-hard">Why is Doing <strong>Code Reviews</strong> Hard?</h2>
<p>Despite their importance, many devs don’t like doing code reviews – in part because they can be challenging, especially if you’re not following best practices.</p>
<p>Here are some pain points I’ve observed during my years of participating in code reviews:</p>
<ul>
<li><p>When people talk about code reviews, they focus on the reviewer. But the developer who writes the code is just as crucial to the review as the person who reads it.</p>
</li>
<li><p>Doing a code review is not an automatic routine for a developer.</p>
</li>
<li><p>The reviewer may sometimes just do a partial review and add new comments at every pass, even on code in the previous review(s) that remained untouched.</p>
</li>
<li><p>Sometimes, the code reviewer may not clearly express their expectations.</p>
</li>
<li><p>Multiple code reviewers can often have diverging opinions, leading to (too) long discussions.</p>
</li>
<li><p>The developer does not understand the comments from reviewers and requires back-and-forth discussions.</p>
</li>
<li><p>The developer addresses code review comments differently than agreed upon during the review process.</p>
</li>
</ul>
<p>These pain points often bottleneck our development velocity. But recent advances in AI-assisted code review tools have started addressing these common friction points in our PR workflows.</p>
<p>Let's explore how AI-powered tools, along with some best practices, can address these review challenges and optimize your development workflow.</p>
<h2 id="heading-can-ai-replace-code-reviews"><strong>Can AI Replace Code Reviews?</strong></h2>
<p>While AI hasn’t replaced human code reviews, it is a powerful force multiplier in the review process.</p>
<p>Here's how: AI code reviews excel as a preliminary screening tool, catching common issues before human reviewers see the code. This becomes especially valuable in open-source projects where maintainer bandwidth is limited.</p>
<p>I recently started using AI code reviews on a case-by-case basis for my projects.</p>
<p>AI tools improve my existing workflows, reduce failure rates by detecting logic errors early on, and boost productivity. So I’ve added it to my CI/CD pipelines. It doesn't have to be perfect at detecting logic errors, as long as its false positive rate is very low (ideally as close to 0 as possible).</p>
<p>Most importantly, AI reviews respect the golden rule of 'value your reviewer's time' by handling routine checks. This allows human reviewers to focus on architecture, business logic, and complex edge cases.</p>
<p>This approach positions AI as a complementary tool that augments rather than replaces human expertise in the code review process.</p>
<h2 id="heading-what-to-focus-on-during-a-code-review">What to Focus on During a Code Review</h2>
<p>When reviewing code, try to prioritise what matters most using the Code Review Pyramid. This is a framework that helps you focus your attention where it creates the most value.</p>
<p>Think of it like building a house — start with the foundation before worrying about paint colours.</p>
<p>The pyramid has five layers, from most critical (bottom) to least critical (top):</p>
<ol>
<li><p><strong>API Semantics</strong>: Core design decisions that affect users</p>
</li>
<li><p><strong>Implementation Semantics</strong>: The code's functionality, security, and performance</p>
</li>
<li><p><strong>Documentation</strong>: Clear explanation of how to use the code</p>
</li>
<li><p><strong>Tests</strong>: Verification that everything works as intended</p>
</li>
<li><p><strong>Code Style</strong>: Formatting and naming conventions</p>
</li>
</ol>
<p>Source: <a target="_blank" href="https://www.morling.dev/blog/the-code-review-pyramid/">The Code Review Pyramid by Gunnar Morling</a></p>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/gunnarmorling/status/1501645187407388679"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<p> </p>
<p>Remember: if you want to catch issues/bugs, there are more appropriate processes for that. That is why we have automated testing, canary releases, testing environments, and so on.</p>
<p>In my personal opinion, using code reviews as a bug catching tool is somewhat of an anti-pattern where you're compensating for a development process that may be lacking some key steps/processes.</p>
<p>To me, a <code>code review</code> is much more about managing technical <code>debt</code> and ensuring that quality is produced, while shipping more features.</p>
<p>In doing a code review, you should make sure that:</p>
<ul>
<li><p>The code is readable</p>
</li>
<li><p>It has appropriate unit tests</p>
</li>
<li><p>The developer used clear names for everything</p>
</li>
<li><p>The code is well-designed and isn’t more complex than it needs to be</p>
</li>
<li><p>Test cases make sense and have comprehensive coverage</p>
</li>
<li><p>It’s something the team can maintain in the long run</p>
</li>
<li><p>There are no architectural issues that will block the team</p>
</li>
<li><p>The code fits the team's idea of quality</p>
</li>
<li><p>You’re thinking about what you can learn from the PR</p>
</li>
<li><p>You’re sharing any knowledge the developer might use in their PR</p>
</li>
<li><p>You’re thinking about how you can empower the dev through your positive feedback</p>
</li>
<li><p>The PR has a clear changelist description</p>
</li>
</ul>
<h2 id="heading-code-review-best-practices-and-process"><strong>Code Review Best Practices And Process</strong></h2>
<p>There is no general rule in engineering for code reviews, as what you’ll need to focus on depends on many factors. You can and should set up the process according to your company standards and way of working as a team.</p>
<p>Here are some factors you’ll need to think about before setting up a code review process:</p>
<ul>
<li><p>The size and type of company you’re in (for example a startup vs a large corporation)</p>
</li>
<li><p>The number of developers on your team</p>
</li>
<li><p>Your budget</p>
</li>
<li><p>The timeframe you’re working with</p>
</li>
<li><p>Your and your team’s workloads</p>
</li>
<li><p>The complexity of the code</p>
</li>
<li><p>The abilities and skills of the reviewer(s)</p>
</li>
<li><p>The availability of the reviewer(s)</p>
</li>
</ul>
<p>As an example, at my work we have a very simple rule: <strong>all</strong> <strong>code</strong> <strong>changes must be reviewed by at least one developer</strong> before a merge or a commit to the trunk.</p>
<p>Code reviews need a systematic approach, but maintaining consistency across every PR is challenging. It’s useful to let computers handle repetitive checks (style, formatting) while humans focus on what matters most: architecture and logic. This balanced approach makes reviews both thorough and sustainable.</p>
<p><strong>Take a look at this example</strong>. It shows how we can optimize our <code>code review</code> process by intelligently delegating tasks between humans and automated tools. The diagram below illustrates a typical code style review workflow, comparing manual human review steps against automated tooling.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731490662335/8b0e9e27-c31b-409f-9c9e-fd1a33195d9b.png" alt="Human vs Automated Code Style Review Process - showing why formatting checks should be automated" class="image--center mx-auto" width="1287" height="2074" loading="lazy"></p>
<p>The diagram shows a real problem we all face in code reviews. See the left side? That's we humans doing manual formatting checks: finding weird spaces, fixing indents, writing comments about it... pretty tedious stuff. But check out the right side: that's where tools like <code>Prettier</code> just fix these formatting issues automatically.</p>
<p>No meetings, no back-and-forth – just done. That's why I started using <code>CodeRabbit</code>, which is a dev tool that caught my attention recently.</p>
<h2 id="heading-what-is-coderabbit"><strong>What is CodeRabbit?</strong></h2>
<p>The CodeRabbit docs describe the tool pretty effectively, so I’ll just leave this here:</p>
<blockquote>
<p><a target="_blank" href="https://www.coderabbit.ai/"><strong>CodeRabbit</strong></a> is an AI-powered code reviewer that delivers context-aware feedback on pull requests within minutes, reducing the time and effort needed for manual code reviews. It provides a fresh perspective and catches issues that are often missed, enhancing the overall review quality. – from the CodeRabbit docs</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731326629130/933c46f2-a24c-4e08-a470-8449e96387aa.png" alt="what is CodeRabbit - home page" class="image--center mx-auto" width="3084" height="1850" loading="lazy"></p>
<h3 id="heading-how-does-coderabbit-help">How Does CodeRabbit Help?</h3>
<p>Let me walk you through a real example. When you submit a PR, CodeRabbit:</p>
<ol>
<li>Performs a PR summary on the fly:</li>
</ol>
<ul>
<li><p>First, it gives you a quick overview of what changed.</p>
</li>
<li><p>It also explains the impact in plain English (great for non-tech folks in your team).</p>
</li>
<li><p>Then it includes a detailed walkthrough of file changes.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732879970322/c671b932-25b1-474c-8cae-c393cb1706b8.png" alt="Pull Request Summary" class="image--center mx-auto" width="2462" height="1356" loading="lazy"></p>
<ol start="2">
<li>Does a “Smart Code Review”:</li>
</ol>
<ul>
<li><p>It drops comments right on the specific lines that need attention.</p>
</li>
<li><p>It also suggests fixes in diff format that you can apply them with one click.</p>
</li>
<li><p>And it shows what commits and files it checked (which is helpful for tracking review coverage).</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732880687958/8d0e1ce5-cb23-4c62-b9ba-823f3a59845e.png" alt="Smart Code Reviews" class="image--center mx-auto" width="1952" height="1614" loading="lazy"></p>
<ol start="3">
<li>Give you interactive feedback:</li>
</ol>
<ul>
<li><p>You can chat with it right in the PR comments.</p>
</li>
<li><p>You can ask it questions about specific code changes to get more details.</p>
</li>
<li><p>And it remembers your team's patterns and preferences which is super helpful for consistency’s sake (which I discussed above).</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732880617364/9e246445-1d43-45f1-b4af-62d9f013d76a.png" alt="chat with coderabbit" class="image--center mx-auto" width="1930" height="1672" loading="lazy"></p>
<ol start="4">
<li>Extra Helpful Features:</li>
</ol>
<ul>
<li><p>CodeRabbit validates changes against linked GitHub/GitLab issues.</p>
</li>
<li><p>It creates sequence diagrams to visualize changes.</p>
</li>
<li><p>And it can perform one-click fixes on applications for simple issues.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732880539024/412d6c15-d691-4b65-b335-2e04b04a55e1.png" alt="sequence diagrams by coderabbit" class="image--center mx-auto" width="1966" height="1458" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731322941721/9e7c5e9a-ac02-458b-9de3-4cf92232786d.png" alt="Code reviews done by CodeRabbit" class="image--center mx-auto" width="2834" height="1842" loading="lazy"></p>
<p>I first discovered <code>CodeRabbit</code> last month while I was searching for something else on GitHub. I accidentally came across it and I was surprised by how many people are already using it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731323088015/12db3391-bad0-45a7-908d-2c34391a7803.png" alt="how many projects are already using coderabbit" width="3142" height="1842" loading="lazy"></p>
<p>I instantly signed up because I was looking for exactly such a solution which could help me and my team out with our reviews.</p>
<p>I read through <a target="_blank" href="https://docs.coderabbit.ai/">the CodeRabbit docs</a> and was very impressed.</p>
<p>Getting started using it is pretty much a plug and play process.</p>
<p>In the next section, we’ll go through the quick steps you can follow to enable CodeRabbit using an example repo.</p>
<ul>
<li><p>Sign up at <a target="_blank" href="http://coderabbit.ai">coderabbit.ai</a> using your GitHub account.</p>
</li>
<li><p>Go to Add Your Repository.</p>
</li>
<li><p>And that's it. CodeRabbit starts reviewing your PRs automatically.</p>
</li>
</ul>
<h3 id="heading-a-github-repo-to-test"><strong>A GitHub Repo to Test</strong></h3>
<p>As an example <strong>GitHub</strong> <strong>repo</strong> to test, we’ll use <a target="_blank" href="https://www.devtoolsacademy.com/">devtoolsacademy</a>: my blog on everything about awesome developer tools.</p>
<p>First, visit the <a target="_blank" href="https://app.coderabbit.ai/login">CodeRabbit login page</a> and login via GitHub.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732880133507/959c0521-eddf-4026-bf33-64b415f4d9b3.png" alt="login - coderabbit" class="image--center mx-auto" width="1462" height="1172" loading="lazy"></p>
<p>Next, add CodeRabbit to some of your public GitHub repositories.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731327118318/7329afd5-af9c-4e54-9aba-6720cd00b8ca.png" alt="how-to-add-a-public-repo-to-use-coderabbit" class="image--center mx-auto" width="3126" height="1804" loading="lazy"></p>
<p>Now, CodeRabbit is fully integrated and ready to do code reviews on your selected repo.</p>
<p>Yes: it’s that simple and fast. And in my opinion, it’s one of the main reasons the tool is so useful.</p>
<p>Here are some sample PRs for you to check out:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/tyaga001/devtoolsacademy/pull/10">https://github.com/tyaga001/devtoolsacademy/pull/10</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/tyaga001/devtoolsacademy/pull/13">https://github.com/tyaga001/devtoolsacademy/pull/13</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/sartography/spiff-arena/pull/1233#discussion_r1529013218">sartography/spiff-arena#1233 (comment)</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/sartography/spiff-arena/pull/1233#discussion_r1529013218">kmesiab/equilibria#1 (comment</a><a target="_blank" href="https://github.com/kmesiab/equilibria/pull/1#discussion_r1505474270">)</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/kmesiab/equilibria/pull/1#discussion_r1505474270">kamiazya/web-csv-toolbox#60</a> <a target="_blank" href="https://github.com/kamiazya/web-csv-toolbox/pull/60#discussion_r1453463448">(comment)</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/kamiazya/web-csv-toolbox/pull/60#discussion_r1453463448">openreplay/openreplay#1858 (comme</a><a target="_blank" href="https://github.com/openreplay/openreplay/pull/1858#discussion_r1467629285">nt)</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/openreplay/openreplay/pull/1858#discussion_r1467629285">ls1intum/Artemis#8037 (comm</a><a target="_blank" href="https://github.com/ls1intum/Artemis/pull/8037#discussion_r1494109998">ent)</a></p>
</li>
</ul>
<h3 id="heading-additional-examples"><strong>Additional Examples</strong></h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">check all the open source examples of code reviews done by <a target="_self" href="https://github.com/search?q=coderabbitai&amp;type=pullrequests">CodeRabbit</a>.</div>
</div>

<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Everyone’s code needs reviewing. Just because someone is the most senior person on the team does not mean that their code doesn’t need to be reviewed.</p>
<p>In this article, I talked about code reviews along with some common pain points. I then showed you how you can leverage CodeRabbit to iterate quickly through your code reviews and focus more on business.</p>
<h3 id="heading-further-reading"><strong>Further reading</strong></h3>
<p>In this article I talked about basic intro to CodeRabbit, because that was my use case with my <a target="_blank" href="https://www.devtoolsacademy.com/">blog</a>.</p>
<p>For more advanced functionality, check out the official CodeRabbit <a target="_blank" href="https://docs.coderabbit.ai/">docs</a> or read their <a target="_blank" href="https://www.coderabbit.ai/blog">blog</a>.</p>
<h3 id="heading-before-i-end"><strong>Before I End</strong></h3>
<p>I hope you found it helpful learning how to use AI tools for code reviews.</p>
<p>If you like my writing, these are some of my other most recent articles.</p>
<ul>
<li><p><a target="_blank" href="https://www.devtoolsacademy.com/blog/neon-vs-supabase"><strong>Neon Postgres vs Supabase</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.devtoolsacademy.com/blog/mongoDB-vs-postgreSQL"><strong>MongoDB vs. PostgreSQL</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.devtoolsacademy.com/blog/supabase-vs-clerk">Supabase vs Clerk</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/#heading-next-steps">How I Built a Video Conferencing App with Stream and Next.js</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/fine-grained-authorization-in-java-and-springboot/">How to Implement Fine-Grained Authorization in Java</a></p>
</li>
</ul>
<p>Follow me on <a target="_blank" href="https://x.com/theankurtyagi">Twitter</a> to stay updated on my open source projects.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Give Good Feedback for Effective Code Reviews ]]>
                </title>
                <description>
                    <![CDATA[ Hey, open sourcer! 😊 I’ve heard through the digital webs that you’ve become quite the wordsmith when it comes to giving feedback on pull requests and want to learn something new.  No worries, I’ve been there myself when I started getting more comfor... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/code-review-tips/</link>
                <guid isPermaLink="false">66b904f807654d99f7424c45</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Feedback ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ open source ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Christine Belzie ]]>
                </dc:creator>
                <pubDate>Mon, 03 Apr 2023 16:49:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/Cover-for-first-FCC-article.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hey, open sourcer! 😊 I’ve heard through the digital webs that you’ve become quite the wordsmith when it comes to giving feedback on pull requests and want to learn something new. </p>
<p>No worries, I’ve been there myself when I started getting more comfortable in the open source world. So, grab a chair, your favorite snack or beverage (I highly recommend water. It’s fresh and good for you! 😉), and your notebook (or in this case, your laptop). Because I’m about to share five techniques that will have you reviewing pull requests like a boss.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/neil-encouragement.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Neil deGrasse Tyson says "Let's Do This!" to give you confidence!</em></p>
<h2 id="heading-feedback-technique-1-the-show-and-tell-review">Feedback Technique 1: The “Show and Tell” Review</h2>
<p>For this technique, you provide screenshots or links to other sources that help explain the benefit of the new approach that you’re suggesting to your fellow contributor. Here's how it's done:</p>
<p>First, take a screenshot of the thing you want to convey in your feedback. I highly recommend using <a target="_blank" href="https://getfireshot.com/using.php">Fireshot</a>. It's an easy way to take screenshots on your computer.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/screenshot-Gif.gif" alt="Image" width="600" height="400" loading="lazy">
<em>This is a GIF of someone taking a screenshot of an image via a Mac</em></p>
<p>Then, go to the repository of your choosing and click on <strong>Pull Requests</strong> </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/repo-tabs.png" alt="Image" width="600" height="400" loading="lazy">
<em>A yellow circle surrounds the third tab called "Pull Requests". Click there to pick the PR you want to review.</em></p>
<p>Once you pick the pull request you want to review, click on <strong>Files Changed</strong>: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Suggestion-Step-1-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Add your comments, then drag and drop your image in the textbox. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/chameleon-example.png" alt="Image" width="600" height="400" loading="lazy">
<em>In a textbox,</em></p>
<p>Click <strong>Submit review</strong> and volià you're done! 😊  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Submit.png" alt="Image" width="600" height="400" loading="lazy">
<em>There's a green button saying "Submit Review". Click on it after you finish your review.</em></p>
<p>In my experience, this type of review is helpful when giving feedback on pull requests that require adding a feature to an open source project's website (for example a logo) or an image on one of its Markdown files. It can help the person see how their contribution impacts the overall project. </p>
<p>It's like if you were watching a commercial for a facial soap and you see the scenes where they show close ups of how the product makes your skin healthier. Showing someone an image of what needs fixing can help convey what's going on more clearly.</p>
<p>Speaking of skin, here's another strategy where your shifting powers, I mean adaptability skills, can be helpful.   </p>
<h2 id="heading-feedback-technique-2-the-chameleon-review">Feedback Technique 2: The “Chameleon” Review</h2>
<p>The “Chameleon” is a feedback giving technique where you adapt your PR review based on the type of contribution that your peer is making. It's like how a chameleon changes their skin color to fit in with their surroundings (minus the hiding from predators part of course 😉). </p>
<p>For example, if you’re reviewing a pull request that's text-based like the one in the image below, I highly recommend giving feedback via dialogic questions (for example, how does this resource stand out from other courses that teach JavaScript?). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Chameleon-example.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This technique is helpful because it encourages the recipient of your review to think deeply about their contribution. It also teaches you how to tailor your feedback based on the type of pull request that you are reviewing.  </p>
<p>Now that you know the Chameleon, the next technique you'll learn is one that can help you swipe through fields, I mean, long lines of code.   </p>
<h2 id="heading-feedback-technique-3-two-peas-in-a-pod">Feedback Technique 3: Two Peas in a Pod</h2>
<p>The “Two Peas in a pod” is a PR review technique where you comment on one line of code in the conversation while another contributor gives feedback on another line code in the same pull request.  </p>
<p>Here's an example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/two-peas-in-a-pod-one.png" alt="Image" width="600" height="400" loading="lazy">
<em>Two contributors comment on one line of code</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/two-peas-in-a-pod.png" alt="Image" width="600" height="400" loading="lazy">
<em>My comment on a different line of code on the same pull request</em></p>
<p>As shown in the first picture, it's helpful to point out why certain methods won't work and discuss some alternatives the pull requester can use. Additionally, consider commenting on a different way to improve the PR once you picked the line of code you want to improve. </p>
<p>When using this method, I highly recommend encouraging you and your fellow reviewer to pick a line of code that suits your strengths because it'll make giving feedback easier. </p>
<p>Since my background is in writing and education, I decided to comment on the text-based line that you see in the second picture whereas the other contributors focused on improving the image element due to being more experienced in coding. </p>
<p>This method helps you develop your written communication skills and ultimately makes reviewing pull requests less stressful. That's two benefits for the price of one! 😊 Cool right? 😉 </p>
<p>Speaking of lessening  your stress, I have another strategy that will have you reviewing pull requests like <a target="_blank" href="https://dcau.fandom.com/wiki/Flash">the Flash from <em>The Justice League</em></a>!</p>
<h2 id="heading-feedback-technique-4-teachem-review">Feedback Technique 4: Teach’em Review</h2>
<p>This “Teach’em” review is a PR review technique where you pretty much instruct your peer on how to improve their PR instead of just pointing out the issues in the PR. </p>
<p>Here are some examples:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Teach-em-example-2-jpg.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>My suggestion: turning the &lt;div&gt; element into a more semantic HTML element.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Teach-em-example-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>I give tips to the contributor how to make their code-based contributions more accessible</em></p>
<p>When using this technique, I highly recommend pointing out an area of improvement.  Then, you can briefly teach a strategy they could use in the future. </p>
<p>This approach can help improve your coding skills and develop your written communication skills, which is very useful in the world of tech.  </p>
<p>Now, there’s just one more technique that will help you upgrade your PR reviewing skills. </p>
<h2 id="heading-feedback-technique-5-the-suggestion-review">Feedback Technique 5: The “Suggestion” Review</h2>
<p>If you're focusing on other open source projects, have a deadline for an assignment, or you're just tired from a long day at work but want to review pull requests, this feedback giving technique will be the ultimate tool in your open sourcer kit. It focuses on giving constructive feedback through your review.</p>
<p>Here's how it's done: </p>
<ol>
<li>Click on the <strong>Files Changed</strong> tab of a person’s pull request:</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Suggestion-Step-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>There are four tabs underneath a person's pull request. The final one "Files changed" is circled in yellow. That's the tab you pick in the first step</em></p>
<ol start="2">
<li>Hover over the line of code you want to review and click on the blue plus sign:</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Suggestion-Step-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>There is a blue plus sign over the line code that has a yellow covering. This indicates that you have picked a line of code you want to review.</em></p>
<ol start="3">
<li>Click on the file icon that has a plus on top and a minus sign on the bottom:</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Suggestion-Step-3-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ol start="4">
<li>Rewrite the line of code, improving it as you think is necessary:</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Suggestion-Step-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>There's a yellow arrow point to an area that says ```suggestion. This where you rewrite the line of code that you choose to review.</em></p>
<ol start="5">
<li>Click on <strong>Add Single Comment</strong></li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Suggestion-Step-5-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>There is a yellow arrow pointing at the "Add single comment" button. This is what you click on to insert your suggestion into the person's line of code.</em></p>
<ol start="6">
<li>Write your comment in the textbox, click on <strong>Request Changes</strong>, and <strong>Submit Review</strong>.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Final-Suggestion-Step-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>The first arrow points to a textbox, the place where type your comment. The second arrow points the last radio button labeled "Request Changes". The final arrow points at a green button labeled "Submit review".</em></p>
<p>I highly recommend using this feedback technique for pull requests that are text-based because it will show your suggestion to the person who made the pull request, which is especially helpful if you are too tired or don't have time to give a brief grammar lesson (trust me, I've been there). </p>
<p>Like the other feedback techniques I previously mentioned, the suggestion review can also help you improve your detail-oriented skills as it encourages you to think of the best way to convey your feedback. It's pretty awesome! 😊</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congratulations, you now have five feedback giving techniques in your Open Sourcer toolkit!  </p>
<p>Before I let you go, I want you to remember this. Open source contributions begin and end with you, so use your powers wisely. Now, go out there and be the best pull request reviewer in open source! </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/deadpool.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Deadpool and his crew is walking slowly towards their next challenge. Be like Deadpool with your pull request reviews! :)</em></p>
<h2 id="heading-credits">Credits</h2>
<p>Let's Do This GIF by <a target="_blank" href="https://giphy.com/gifs/natgeochannel-startalk-JykvbWfXtAHSM">National Geographic</a></p>
<p>Super Hero Walking GIF by <a target="_blank" href="https://media.giphy.com/media/l0Iy6hheGg52GcJt6/giphy.gif">20th Century Fox Home Entertainment</a></p>
<p>Screenshot GIF from "How to Take a Screenshot on a MacBook" by <a target="_blank" href="https://smallpdf.com/blog/how-to-screenshot-on-mac">Hung Nguyen</a> </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Git Best Practices – How to Write Meaningful Commits, Effective Pull Requests, and Code Reviews ]]>
                </title>
                <description>
                    <![CDATA[ As developers we push regular code commits – and after a while, it's almost second nature to us.  But does this mean we're doing things right? Familiarity often leads to sloppiness and overlooking the basics. In this article, we will explore How to ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/git-best-practices-commits-and-code-reviews/</link>
                <guid isPermaLink="false">66bb888dc32849d18c5cdca5</guid>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ version control ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Grant Riordan ]]>
                </dc:creator>
                <pubDate>Fri, 05 Aug 2022 15:45:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/resized-image-Promo--2-.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As developers we push regular code commits – and after a while, it's almost second nature to us. </p>
<p>But does this mean we're doing things right? Familiarity often leads to sloppiness and overlooking the basics.</p>
<p>In this article, we will explore</p>
<ul>
<li>How to write meaningful Git commit messages</li>
<li>How to create efficient pull requests (PR)</li>
<li>How to get really good at the code review process and some best practices to follow</li>
</ul>
<h3 id="heading-pre-requisites">Pre-Requisites:</h3>
<p>I prefer to use VS Code as my code editor. I use this for my Git editor too. I find it easier to write commit messages within the same place as I code. It also gives me more space to write commit messages and descriptions.</p>
<p>If you haven't already done this, follow these steps to make VS Code your default git editor.</p>
<ol>
<li>Open VS Code and in the command palette search for </li>
</ol>
<blockquote>
<p>Shell Command: Install 'code' command to PATH</p>
</blockquote>
<ol start="2">
<li>Then run the following command in your terminal:</li>
</ol>
<p><code>git config --global core.editor "code --wait"</code></p>
<p>Now when you run <code>git commit</code> or <code>git -config --global -e</code> it will open the Git editor within a file in VS Code.</p>
<p><strong>Note:</strong> All given commands are to be run within the terminal (whether that be your terminal of choice, or the integrated terminal within VS Code).</p>
<h2 id="heading-how-to-write-meaningful-commit-messages">How to Write Meaningful Commit Messages</h2>
<p>When committing your code, it's helpful to write useful commit messages. Here are some tips and best practices to help you do so.</p>
<h3 id="heading-use-imperative-commands">Use Imperative Commands</h3>
<p>Prefix your commit messages with <a target="_blank" href="https://www.grammar-monster.com/glossary/imperative_mood.htm">imperative commands</a> such as: <code>fix</code>, <code>refactor</code>, <code>add</code>, and <code>remove</code></p>
<p>This is because you should be able to suffix a commit message to the phrase </p>
<blockquote>
<p>"If applied, this code will..." </p>
</blockquote>
<p>and inform other developers what it will do, for example:‌</p>
<blockquote>
<p>If applied, this code will fix issue with login button not showing</p>
</blockquote>
<h3 id="heading-keep-it-brief">Keep It Brief</h3>
<p>You're not writing a monologue, so keep it brief. As a general rule, a commit message should not exceed 50 characters.</p>
<p>Put yourself in the developer's or reviewer's shoes. Try and think about what you would want to know if you were looking at the Git log on this repo.</p>
<ul>
<li>What work did you complete?</li>
<li>Why did you do it?</li>
<li>What effect does it have on the code base?</li>
</ul>
<p>Here's an example of a concise yet informative commit message:</p>
<pre><code>fix issue <span class="hljs-keyword">with</span> login button not showing
</code></pre><h3 id="heading-how-to-keep-commit-messages-short-but-helpful">How to Keep Commit Messages Short but Helpful</h3>
<p>Within your commits, you can include a commit description, allowing us to add even more detail / context as to what you did.</p>
<p>Add an empty line underneath the commit message, and begin writing a description on line 3. It looks like this:</p>
<pre><code>fix issue <span class="hljs-keyword">with</span> login buttton not showing

- update login form validation
- update login styling <span class="hljs-keyword">for</span> showing the button
</code></pre><p>Now when other devs are reviewing Git logs, commits, or needing to revert code they have a better indication of what effect will take place, and whether it will cause any breaking changes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-29.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-examples-of-unhelpful-commit-messages">Examples of Unhelpful Commit Messages</h3>
<p>On the other hand, here are some examples of ineffective commit messages:</p>
<ul>
<li><code>fixed bug</code> – There is no reference to what bug has been fixed exactly, so it adds no value to the git history / logs. It will make reviewing previous commits extremely difficult, and painstaking. As a developer you would have to open each commit like this to understand what it's actually doing.</li>
<li><code>refactored due to PR comments</code> – This message gives us no information about what was changed. We would have to hunt down the pull request to gather any context around the changes made, or again open up the commit.</li>
<li><code>fixing previous commit</code> – Lack of context again</li>
<li><code>made tests pass</code> – Which test file was updated? You should at least give the name or area of tests that have been fixed.</li>
</ul>
<p>All of these are poor examples of commit messages due to their ambiguity,  lack of information, and lack of context. They force team members to do more work in order to understand what's going on, which is not acceptable in any team.</p>
<h2 id="heading-how-to-develop-a-commit-strategy">How to Develop a Commit Strategy</h2>
<p>You may think committing code is as straightforward as just committing and pushing the code. But there's a little more to it than that.</p>
<p>Let's talk about how you can develop a useful commit strategy to stay consistent and make useful commits.</p>
<h3 id="heading-make-small-specific-commits">Make small, specific commits</h3>
<p>Smaller commits make it easier to revert code to a previous state if there's a problem. If your commit affects too many areas, reverting back could mean losing a lot of code. </p>
<p>It's also far easier for reviewers to understand what the code is doing if it's related to one purpose. </p>
<p>Let's see a real life example of how this would work. Firstly we need to add our related file changes. We can view which files have been changed within our branch by running <code>git status</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Screenshot-2022-08-01-at-23.28.59.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of output from git status</em></p>
<p>As you can see there are various files that have been changed / added to the project. However, they're all for different areas of the project. Following the golden rule of keeping commits small and relatable, let's take a look at how we can put that into practice.</p>
<p>Using the <code>git add</code> followed by the file names we can commit only the files which are related. We do this by using the <code>git add</code> command , plus the names of the files we wish to add one after another like so:</p>
<pre><code>git add login.test.ts login.ts
</code></pre><p>If we check <code>git status</code> now, we'll see the two staged files:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Screenshot-2022-08-01-at-23.34.35.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of Git status output after staging files</em></p>
<p>We have the files, now to create our commit. As always, we'll utilise <code>git commit</code> which will open the git editor within VS Code (as we set it up like this earlier). If you skipped this step, the commit will open in your preferred editor.</p>
<p>We'll add a commit message of the changes:</p>
<pre><code>Fix issue <span class="hljs-keyword">with</span> login buttton not showing
</code></pre><p>There you have it, a small related file commit. The commit message tells us exactly what we've done, where the issue resided, along with some small context of what the issue was.</p>
<h3 id="heading-bad-example-of-a-commit">Bad Example of a Commit</h3>
<p>Since we've done it successfully, lets take a look at a bad example:</p>
<p>So imagine we've done all this work, and the developer has staged all the files at once, using the <code>git add -A</code> command which stages <strong>all</strong> changed/added files.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Screenshot-2022-08-01-at-23.45.26.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of multiple unrelated files staged for commit</em></p>
<p>They now create a commit message utilising the one liner Git command:</p>
<pre><code>git commit -m <span class="hljs-string">'Updated various areas such as validation, registration and products pages'</span>
</code></pre><h4 id="heading-why-is-this-so-bad">Why is this so bad?</h4>
<ol>
<li>Firstly there's too much happening within this commit. Too many files mean that if we need to revert the validation changes, only we can't. We'd have to revert the whole commit losing the products and registration changes.</li>
<li>The commit message is lengthy. We can remove unnecessary words like 'various areas such as'.  It adds no value to the commit message, and takes up characters that could be used for more context.</li>
<li>We're not using the imperative voice as mentioned earlier. We should change "Updated" to  'Update'. </li>
</ol>
<blockquote>
<p>If applied, this code will fix the submit button not showing on the login </p>
</blockquote>
<h3 id="heading-midway-recap">Midway Recap</h3>
<p>So at this point, we've learnt:</p>
<ul>
<li>How to formulate a useful commit message</li>
<li>How to formulate an effective commit strategy to allow us to easily keep track of related changes, and a more maintainable code base.</li>
<li>What makes a bad commit</li>
</ul>
<h2 id="heading-how-to-create-efficient-pull-requests">How to Create Efficient Pull Requests</h2>
<h3 id="heading-decide-when-to-push">Decide when to push</h3>
<p>Pushing is the act of getting your commits up to the server / remote origin ready to create a Pull Request (PR). I recommend pushing as soon as the current feature or bug is done. </p>
<p>Also, it's a good idea to keep your PR's small, containing only related commits. As an example if you had the following commits:</p>
<ul>
<li><code>Add new product search component</code></li>
<li><code>Add unit tests for product search component</code></li>
<li><code>Add documentation for product search component</code></li>
</ul>
<p>Because all these commits are related to the same component, it's recommended to pull them together into one PR.  </p>
<p>Whereas, something like:</p>
<ul>
<li><code>Fix bug within login screen</code></li>
<li><code>Refactor registration page for performance</code></li>
<li><code>Update validation tests for login form</code></li>
<li><code>Update login tests for forgotten password</code></li>
<li><code>Update unit tests for product search component</code></li>
</ul>
<p><strong>Should not</strong> go in the same PR, as there's far too much going on. These commits should have been grouped into several PR's containing relevant commits at the time.  </p>
<p>If this was the Git log for a branch, you would be unable to create a pull request with solely relatable files, due to the order in which the commits have been created, as you can't simply inform Git that you want commits 1,3 and 4 to go into this PR.</p>
<h3 id="heading-keep-it-small">Keep it small</h3>
<p>Remember – like your commits, keep your PR's small. Nobody wants to wade their way through a 50+ file pull request. All that'll happen then is that your review will suffer from the common "Looks good to me". </p>
<p>When you create a large PR, it translates to "<em>I</em> c<em>ouldn't be bothered to look through all these files, but skimming through them it looks ok</em>". With a smaller PR, on the other hand, it means exactly what it says.</p>
<p>Sometimes large pull requests are unavoidable, like when updating base functions and such. However, you should try to be aware of how you can limit the impact on other developers.</p>
<h2 id="heading-how-to-get-your-branch-ready-for-code-review">How to Get Your Branch Ready For Code Review</h2>
<p>The exact process of creating a Pull Request will differ depending on which version control hosting platform you are using, but the concepts are the same.</p>
<p>First, you should check out the <code>main</code> branch from your repo. Then run a <code>git pull</code>, which will get all the latest code from <code>main</code> onto your local dev system.</p>
<p>Once you've done that, you can go back to your own branch using <code>git checkout</code> and the name of your branch , for example <code>git checkout login-fixes</code>.</p>
<p>Now we need to get the <code>main</code> branch code into ours. We can do this utilising the <code>git merge</code> command.</p>
<pre><code>git merge main
</code></pre><p>If there were changes, that is there were files in the pull from main, you will need to create a "merge commit". That's just another commit to your own branch containing the merged changes. </p>
<p>Simply create another commit, with a message explaining you've merged from main like so:</p>
<p><code>git commit -m 'Merge main into login-fixes'</code></p>
<p>Push your changes back to the remote server using <code>git</code> </p>
<h2 id="heading-how-to-create-the-pull-request">How to Create the Pull Request</h2>
<p>The easiest way to do this is via the web interface on your preferred version control platform. In this example we'll be utilising GitHub.</p>
<p>Simply navigate to your repo, and then click the Pull Requests tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-21.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pull Requests Tab - GitHub</em></p>
<p>Select "New pull request"</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-22.png" alt="Image" width="600" height="400" loading="lazy">
<em>New Pull Request - Github</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-24.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>When you're creating a pull request, use a title which describes the PR like you did with your commit. </p>
<p> <code>PR - Fix login button not showing</code>.</p>
<p>It can be useful to provide the reviewers with some context as to why this PR was necessary, or any additional info within the PR description. </p>
<p>As you can see above, I've chosen to include what the fix was, potentially making the review smoother. I've also included some important information regarding that this PR should not be merged until another PR is merged.</p>
<p>When working for some companies, they may require you to add a ticket reference to the PR title too, but I've already discussed why I think this is not needed.</p>
<h3 id="heading-pr-labels">PR Labels</h3>
<p>If you want to make it even clearer, you can utilise PR Labels. These are labels which can be applied to the PR to illustrate either the state of the PR, or simple information to others. You can find them on the right of the pull request page:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-26.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can select from pre-defined labels, or add your own. </p>
<ul>
<li>Click on Labels </li>
<li>Enter the label you wish to use. In our scenario we're going to add a label called <code>Do Not Merge</code>.</li>
<li>Press enter once you have typed in the value, and you can configure the label's colour and name. Once saved you can now type it in again and it will show within the list.</li>
<li>Select your new label and voilà!</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-27.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click Create pull request</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-28.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>There you have it, you have created your first pull request.</p>
<h2 id="heading-how-to-review-a-pr-best-practices">How to Review a PR – Best practices</h2>
<h3 id="heading-what-to-look-for-when-reviewing-a-pr">What to look for when reviewing a PR</h3>
<p>Always take a step back and think about the key elements of a good code review. Here are some points to consider:</p>
<ul>
<li>Does the code follow your team's coding guidelines?</li>
<li>Does the code meet its objective / acceptance criteria?</li>
<li>Is the code legible and is it easy to understand what it's doing without the need for heavy comments / documentation? (This one for me is one of the most important, as I'm a huge fan of descriptive function and variable names.)</li>
<li>Does the code need any refactoring, considering security, performance or simply ease of reading?</li>
<li>Does the code follow simple design patterns / principles, like the single responsibility, abstraction, encapsulation, and so on? If not, you can make suggestions on how this can be achieved or perhaps teach those not familiar with it what it means and the benefits.</li>
<li>Are there any "magic numbers / strings" that would be better served as a constant or named variable?</li>
</ul>
<h3 id="heading-review-prs-in-a-timely-manner">Review PRs in a timely manner</h3>
<p>While you shouldn't necessarily feel obligated to look at a PR immediately, don't leave the author hanging, either. This PR could be blocking future work, or it could be important (if this is the case, the author should make this clear).</p>
<p>Try and keep discussions and PR comments flowing. If it makes it easier, you can jump on a call (if remote) or pull up a chair in the office and go through the PR together. This might speed up the process, and reduce the back and forth waiting around.</p>
<p>All this being said, don't rush the code review. Be meticulous, and read each file and change carefully. I advise you to pull down the branch the changes are made on, allowing yourself to look over the entire project, and not just the lines changed.</p>
<p>Many times, if you're looking at just one or two line code changes, you won't know exactly what the code is supposed to be doing. But if you look at the whole file you can follow the flow.</p>
<p>If you're using VS Code and GitHub, you can utilise their own <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github">extension</a> for viewing pull requests and viewing comments whilst checking out the PR branch all within VS Code itself.</p>
<h3 id="heading-were-all-human-here">We're all human here</h3>
<p>Remember that we're all human, and people often make mistakes when coding and can simply overlook things. </p>
<p>Not everyone codes the same way you do either, so don't simply request changes just because they've done it differently to how you would have. It doesn't mean that they've done it wrong, nor does it mean your way is the best.</p>
<h3 id="heading-describe-changes-clearly-and-word-your-comments-carefully">Describe changes clearly and word your comments carefully</h3>
<p>A pull request is not an exam, it is also not an opportunity for you to harshly criticise someone's work. It's a learning opportunity, and a chance to ensure the best code makes it into the main branch. It's about code quality and whether the code meets the acceptance criteria.</p>
<p>Think about the language you use when making suggestions. A PR comment is the opposite to a git commit message. No longer do we use the imperative voice. Do not command them to make changes, but instead make softer suggestions using the <a target="_blank" href="https://www.grammar-monster.com/glossary/subjunctive_mood.htm">subjunctive</a> mood instead. </p>
<p>As you're critiquing work that someone has most likely put a lot of effort into, use phrases like:</p>
<blockquote>
<p>It it were me, I'd change this if statement to a switch case statement as it's more readable.</p>
</blockquote>
<p>or </p>
<blockquote>
<p>Perhaps consider renaming this variable to a more intuitive name, such as {alternative} to make it more understandable from initial read what it's doing.</p>
</blockquote>
<p>As above, try and add your reasoning as to why you're making the change request. It will make the request more impactful, and allow the author to reflect on whether it would be best to make the change, or perhaps spark a discussion to come to a compromise.</p>
<h3 id="heading-offer-suggestions-for-improvement">Offer suggestions for improvement</h3>
<p>Most Git systems allow you to click on the line you wish to be changed and add a comment so it's much simpler to specify the exact line of code you want changed.</p>
<p>Hosting providers such as GitHub have a "suggestion" feature which allows you to add a code suggestion directly into the comment, which can instantly be accepted and committed from within the PR.</p>
<p>If this isn't available, be sure to make sure what you're requesting is clear and concise. Perhaps even rewrite, or write out your suggestion within the comment such as:</p>
<blockquote>
<p>Perhaps look at changing this if / else statement to a ternary statement like so:</p>
</blockquote>
<p><code>var backgroundColor = isError ? 'red' : 'blue'</code></p>
<p>This makes the suggestion clear, and even speeds up the process of re-writing (using copy and paste).</p>
<h3 id="heading-dont-be-afraid-to-defend-your-code">Don't be afraid to defend your code</h3>
<p>Remember a PR is a discussion. It's a two way process, giving you the opportunity to defend your code and explain with more context what you were thinking. </p>
<p>Just because the code may not look perfect, there may be a reason. There may have been matters out of your control which you had to contend with, forcing your hand to writing it in a certain way.</p>
<p>Don't be afraid to offer counter arguments, but be ready with valid reasoning, if you truly believe in your solution.</p>
<h3 id="heading-communicate-that-the-pr-is-approved">Communicate that the PR is approved</h3>
<p>Many people nowadays filter their GitHub or version control email notifications to a folder which rarely gets looked at due to the volume of updates on repos, commits, branches and such.</p>
<p>To speed up the process, and make it more fun for the author, simply drop them a message. Many companies now offer some form of instant messaging service, so why not use it?</p>
<p>Setup a specific channel on your IM platform for PR's. Post in the channel / chat room your PR link, and allow reviewers to update you on their progress by replying within threads. Add an emoji to make it more light hearted (as we all know PR's can be boring, so why not spruce them up a bit).</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article we've learned:</p>
<ul>
<li>How to setup VS Code with Git integration</li>
<li>How to write useful Git commit messages</li>
<li>When to commit to make it easier for the team</li>
<li>How to effectively code review a PR</li>
<li>How to handle PRs in a manner that helps all your team.</li>
</ul>
<p>I hope you've learned something new, thanks for reading my article</p>
<p>Feel free to connect with me on Twitter <a target="_blank" href="https://twitter.com/gweaths">@gWeaths</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Google Does Code Reviews – Quality Assurance Tips from Google's Documentation ]]>
                </title>
                <description>
                    <![CDATA[ A code review, sometimes called code Quality Assurance, is the practice of having other people check your code after you write it.  Code reviews bring many benefits to the process of writing and delivering software: Ensures consistency through your ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-google-taught-me-about-code-reviews/</link>
                <guid isPermaLink="false">66bc55edda80a491ea5a5f5f</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Google ]]>
                    </category>
                
                    <category>
                        <![CDATA[ QA ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Quality Assurance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kealan Parr ]]>
                </dc:creator>
                <pubDate>Thu, 14 Jan 2021 18:09:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/01/Google.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A code review, sometimes called code Quality Assurance, is the practice of having other people check your code after you write it. </p>
<p>Code reviews bring many benefits to the process of writing and delivering software:</p>
<ul>
<li>Ensures consistency through your codebase.</li>
<li>Teaches all members of the review (helps knowledge transfer).</li>
<li>Builds contextual awareness regarding what might affect other parts of the team</li>
<li>Helps avoid breaking builds</li>
<li>Casts fresh eyes over a code change to search for optimisations and simplifications in the change.</li>
<li>Promotes quality and helps make sure no one forgot or missed anything.</li>
</ul>
<p>Google has 1,918 repositories on <a target="_blank" href="https://github.com/google">their GitHub</a> across multiple languages, and even more that aren't open source.</p>
<p>One of their codebases is shared by over 25,000 Googlers, and typically has <a target="_blank" href="https://cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions-of-lines-of-code-in-a-single-repository/fulltext">40,000 commits</a> daily (16,000 human changes, and 24,000 by automated systems). Each day it has to serve around 800,000 queries per second during peak times.</p>
<p>Google has published their engineering practices, so let's see how they review code at their scale, with so many commits a day.</p>
<p>Google refers to changes in their codebases as <strong>CLs</strong> standing for change lists. It's just a unit of work / piece of code going through review. </p>
<h1 id="heading-how-to-prepare-for-code-reviews">How to Prepare for Code Reviews</h1>
<p>Firstly, before you even think about the code review process, try and focus on <strong>who</strong> will do the review. Try to pick a subject matter expert. Pick someone who is familiar with this codebase or area of the codebase. </p>
<p>Sometimes this may even mean having different people review different parts of the code. But less <a target="_blank" href="https://sback.it/publications/icse2018seip.pdf">than 25% of code review's at Google have more than one reviewer.</a></p>
<p>Getting someone to respond in a timely manner is also important. To avoid bottle necks and overloading individuals, just CC reviewers onto the change to review it at their convenience if they want to.</p>
<h1 id="heading-how-to-run-fast-code-reviews">How to Run Fast Code Reviews</h1>
<p>Code reviews should be completed quickly. The <strong>maximum</strong> length of time for a review should be one business day.</p>
<p>Why the urgency? I've personally had QA's sometimes take weeks or longer.</p>
<ul>
<li><strong>It becomes a blocker.</strong> Although the author of the code moves onto new work, new changes start to form a back log, and the delays can build up to weeks or months.</li>
<li><strong>Developers feel frustrated.</strong> If the reviewer asks for major changes but only responds every 3 days, it is frustrating for the developer working on that change. But with quick responses, whenever you require explanation of exactly what you need to do, the frustration fades away.</li>
<li><strong>Code quality can degrade.</strong> If your reviews are always slow, developers are less likely to do code clean ups, refactoring work or general code improvement ("If my reviewer won't reply for 4 days what's even the point?"), and the code quality submitted in the reviews is more likely to go down.</li>
</ul>
<p>The main reason code reviews can be fast is because they're small. Rather than sending a 1,000 line CL, they're separated into multiple CL's – pushing 10 smaller changes of 100 lines for example.</p>
<p>Google also has emergencies where code changes have to be made quickly to resolve major problems in production. In these cases, code quality is relaxed. This review should immediately become the reviewers first priority. There are some examples of emergencies Google has faced <a target="_blank" href="https://www.freecodecamp.org/news/what-is-a-software-post-mortem/">here</a> if you're curious.</p>
<h2 id="heading-googles-code-review-standards">Google's Code Review Standards</h2>
<p>The key rule Google emphasizes is:</p>
<p><strong>Reviewers should generally approve a change once it definitely improves the overall code health, even if it isn't perfect.</strong></p>
<p>The key point Google seem to be making is that perfect code doesn't exist. If it makes it <strong>better</strong>, that is enough. </p>
<p>It's definitely a balancing act between something being better, and <strong>how</strong> much better it could be. If you could add more feedback to make significant improvements, there may need to be more work done on the code.</p>
<h2 id="heading-what-googlers-look-for-in-code-reviews">What Googlers Look for in Code Reviews</h2>
<p>When doing code reviews, Google focuses on these elements according to their <a target="_blank" href="https://google.github.io/eng-practices/review/reviewer/looking-for.html">engineering practices documentation</a>:</p>
<blockquote>
<p><strong>Design</strong>: Is the code well-designed and appropriate for your system? Does this change belong in your codebase, or in a library? Does it integrate well with the rest of your system?  </p>
<p><strong>Functionality</strong>: Does the code behave as the author likely intended? Is the way the code behaves good for its users? Mostly, we expect developers to test CLs well-enough that they work correctly by the time they get to code review.   </p>
<p><strong>Complexity</strong>: Could the code be made simpler? Would another developer be able to easily understand and use this code when they come across it in the future? Is it over-engineered for its current use case?  </p>
<p><strong>Tests</strong>: Does the code have correct and well-designed automated tests? Will the tests actually fail when the code is broken? Will they start producing false positives? Does each test make simple and useful assertions?  </p>
<p><strong>Naming</strong>: Did the developer choose clear names for variables, classes, methods, etc.?  </p>
<p><strong>Comments</strong>: Are the comments clear and useful? Ensure where sensible comments explain <strong>why</strong> something is being done, rather than how.  </p>
<p><strong>Style &amp; Consistency</strong>: Does the code follow our <a target="_blank" href="http://google.github.io/styleguide/">style guides</a>?  </p>
<p><strong>Documentation</strong>: Did the developer also update relevant documentation?</p>
</blockquote>
<p>Google has style guides for multiple languages like <a target="_blank" href="https://google.github.io/styleguide/cppguide.html">C++</a>, <a target="_blank" href="https://google.github.io/swift/">Swift</a>, <a target="_blank" href="https://google.github.io/styleguide/htmlcssguide.html">HTML/CSS</a>, <a target="_blank" href="https://google.github.io/styleguide/lispguide.xml">Lisp</a>, <a target="_blank" href="https://google.github.io/styleguide/jsguide.html">JavaScript</a> and <a target="_blank" href="https://google.github.io/styleguide/">more.</a></p>
<p>Having a document that everyone can refer to helps standardise the code. It also helps clarify what the expectations are in the review process.</p>
<h2 id="heading-how-googlers-review-code">How Googlers Review Code</h2>
<p>There is a three-stage process for code review in Google's engineering practices. Here's a list of things you'd need to cover if you were to review:</p>
<ol>
<li>Get a high level overview of the change</li>
<li>Examine the main parts of the change</li>
<li>Look through the rest of the code, in a sensible order</li>
</ol>
<p>Let's go over each step in more detail.</p>
<h2 id="heading-1-get-a-high-level-overview-of-the-code-change">1. Get a High Level Overview of the Code Change</h2>
<p>Look at the code change's description/summary. Does it all make sense? For example, if someone is changing a codebase that is being deleted next week, push back on the change <em>courteously,</em> and explain why the change doesn't look needed anymore. </p>
<p>It's inefficient if people are spending time on work that isn't actually needed, so have a look at your development life cycle and see why this might be happening. The earlier you can catch these issues the better.</p>
<p>In order to get a high level overview of the code, you may want to briefly scan the code components to see how it all works together. </p>
<p>If you see a serious architectural problem or something majorly wrong, you should share your observations immediately at this stage. Even if you don't have time to review every single other element of the review. Reviewing the rest may well even end up being a waste of time if the architectural problems are severe enough. </p>
<p>Aside from this, there are 2 major reasons why you should send your review comments immediately: </p>
<ul>
<li>Googlers will often email a change, and then immediately start new work based on that change. If the change in review need serious adjustments, they may be building on something that needs to be significantly changed.</li>
<li>Big changes to the CL may take a while to finish. Developers all have deadlines and it's courteous to try and help them meet them by letting them start rework as soon as possible.</li>
</ul>
<h2 id="heading-2-examine-the-main-parts-of-the-code-change">2. Examine the Main Parts of the Code Change</h2>
<p>Once you have had an overview, review the "main" parts of the change.</p>
<p>Find the file or files that are central to the CL. Often, there is one file that has the largest number of changes, and it’s the major piece of the CL.</p>
<p>Spend most of your focus reviewing these pieces. This provides context to all the smaller pieces, and generally makes it faster to review. </p>
<p>If the CL is too large for you to get a good overview and understand the flow, it's a good sign the developer should be splitting up their CL into smaller changes.</p>
<h2 id="heading-3-look-through-the-rest-of-the-code-in-a-sensible-order">3. Look Through the Rest of the Code, in a Sensible Order</h2>
<p>Once you have a good overview of the change, it's time to drill down into the details and go file by file. </p>
<p>Each reviewer generally does this differently. Some go in the order that the version control presents to them and some pick a particular order. Choose what makes sense to you. It's important to just review <strong>everything</strong>, and miss nothing.</p>
<h3 id="heading-review-every-line-of-code">Review Every Line of Code</h3>
<p>Don't miss or skim important details. Sometimes there might be config files, or generated code you can scan briefly looking for irregularities. But your job here is to be very thorough and carefully scrutinise the code. </p>
<p>Make sure you think about bugs, race conditions, alternate approaches, conciseness, readability, and so on.</p>
<p>If you can't understand the code, it's highly likely other developers won't be able to either, and should ask the developer to clarify it.</p>
<h3 id="heading-understand-the-context">Understand the Context</h3>
<p>Often times the version control software will only show the changed lines. But it's important to read the lines before and after, or the whole file, to ensure you understand exactly what the change is doing.  </p>
<p>You may only see someone adding 2 more <code>if</code> blocks in a change. But if you look at the context you might see that the <code>if</code> <code>else</code> block now has 15 different <code>if</code>'s inside it. Then you can reject the code change and properly improve the code quality in this area, rather than making it worse.</p>
<p>Remember code degradation happens slowly, with every change that goes in. Our main aim is to ensure the quality trends consistently up, and we never go backwards.</p>
<h2 id="heading-how-googlers-write-code-feedback"><strong>How Googlers Write Code Feedback</strong></h2>
<p>Google has some specific sections covering how to do <a target="_blank" href="https://chromium.googlesource.com/chromium/src/+/master/docs/cr_respect.md">code reviews courteously, and respectfully</a>. This isn't in opposition to being clear and as helpful as you can to the developer. The golden rule here is to make comments about the <em>code</em> and not the developer. </p>
<h2 id="heading-what-to-do">What to Do:</h2>
<p>#### </p>
<blockquote>
<p><strong>Ask for the why:</strong> If it is unclear why the author is doing things a certain way, feel free to ask why they made a particular change. Not knowing is OK, and asking “Why” leaves a written record that will help answer this question in the future. (And sometimes, “I'm curious, why did you decide to do it that way?” can help the author to rethink their decision.)  </p>
<p><strong>Find an end:</strong> If you like things neat, it’s tempting to go over a code review over and over until it’s perfect, dragging it out for longer than necessary. It’s soul-deadening for the recipient, though. Keep in mind that “LGTM” does not mean “I vouch my immortal soul this will never fail”, but “looks good to me”. If it looks good, move on. (That doesn’t mean you shouldn’t be thorough. It’s a judgment call.) And if there are bigger refactorings to be done, move them to a new CL. (<a target="_blank" href="https://chromium.googlesource.com/chromium/src/+/HEAD/docs/cr_respect.md">Source</a>)</p>
</blockquote>
<h2 id="heading-what-not-to-do">What Not to Do</h2>
<blockquote>
<p><strong>Don't use extreme or very negative language:</strong> Please don't say things like “no sane person would ever do this” or “this algorithm is terrible”, whether it’s about the change you're reviewing or about the surrounding code. While it might intimidate the reviewee into doing what you want, it’s not helpful in the long run - they will feel incapable, and there is not much info in there to help them improve. “This is a good start, but it could use some work” or “This needs some cleanup” are nicer ways of saying it. Discuss the code, not the person.  </p>
<p><strong>Don't bikeshed:</strong> Always ask yourself if this decision <em>really</em> matters in the long run, or if you're enforcing a subjective preference. It feels good to be right, but only one of the two participants can win that game. If it’s not important, agree to disagree, and move on. (<a target="_blank" href="https://chromium.googlesource.com/chromium/src/+/HEAD/docs/cr_respect.md">Source</a>)</p>
</blockquote>
<p>Remember code reviews can sometimes trend towards finding issues or discussions with code and not praise.</p>
<p>If your reviewer has addressed your comments, or they have done some optimisation or smart code you like, thank them. Say you like the approach / how they have solved an issue. </p>
<p>Conversely, thank the reviewer if they thoroughly explain what they want and promptly answer your questions.</p>
<p>I have had some reviews where reviewers have put huge comments explaining something I misunderstood and I can still remember who it was and what they said.</p>
<h2 id="heading-how-to-handle-pushback-in-code-reviews">How to Handle Pushback in Code Reviews</h2>
<p>Sometimes the developer who is receiving the review might disagree with the changes that you're proposing. Here's how to handle that.</p>
<h3 id="heading-consider-that-they-might-be-right">Consider That They Might Be Right</h3>
<p>Sometimes the developer is closer to the code and how it works, and they may be right. If they are, move on from that discussion point and leave that code as it is.</p>
<p>But if they're not, or they've misunderstood something, you should insist on the change. Respond to what the developer initially challenged you on, and explain your reasoning courteously. </p>
<p>Code quality improvements tend to happen in small incremental steps, and review is one way it happens. Insist on the code improvement, even if it means extra work for the developer.</p>
<h3 id="heading-try-to-avoid-ill-fix-this-later">Try to Avoid "I'll fix this later..."</h3>
<p>One of the most common issues in reviews is not that people disagree whether the code change is necessary, but rather that they want to do it under a different ticket or do it later. So if you pass this review, they assure you that they will follow up later and fix the issues.</p>
<p>Generally speaking, <em>following up later</em> rarely happens. This doesn't mean there's something wrong with the developer or their work ethic. But it's easy to forget, have priorities change, or even just get lost in their queue of work. </p>
<p>Insist that the work gets done now. There is no real fantastic gain to merging changes in the codebase you have to immediately fix. You are just adding technical debt that <em>might</em> be followed up on later, or might be forgotten<em>.</em> Fixing lots of tickets later is an easy way for quality to drop.</p>
<p>The only exception to this is <a target="_blank" href="https://google.github.io/eng-practices/review/emergencies.html">emergencies</a>, which involve the highest priority bugs Google deals with where there is something seriously wrong. This could be services going down, or errors crashing people's pages in production.</p>
<p>There is naturally an eagerness to merge changes ASAP, and the review might accept slightly lower quality, with a follow up fix immediately being written. The main point is that the first change removes the emergency, and the second change fixes it <em>properly.</em></p>
<h1 id="heading-conclusion"><strong>Conclusion</strong></h1>
<p>I hope this has explained some helpful concepts Google makes use of in their code review process. I wrote this to better cement it into my own mind, and was curious about how other companies handle the QA process. </p>
<p>I found that there are quite a few points that I can take away and apply to the reviews I conduct.</p>
<p>The document I referred to throughout this article can be found <a target="_blank" href="https://google.github.io/eng-practices/review/reviewer/">here</a>.</p>
<p>I share my writing on <a target="_blank" href="https://twitter.com/kealanparr">Twitter</a> if you enjoyed this article and want to see more.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Validate Pull Requests in AWS and Make Code Reviews Easier ]]>
                </title>
                <description>
                    <![CDATA[ By Aagam Vadecha When a project grows, and developers are pushing code frequently, there is always a chance that working pull requests might break somewhere.  It could be because one PR was merged before another, or the destination branch moved a few... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/validate-pull-requests-in-aws/</link>
                <guid isPermaLink="false">66d45d5bb3016bf139028d01</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 23 Sep 2020 15:59:03 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9893740569d1a4ca1ad3.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Aagam Vadecha</p>
<p>When a project grows, and developers are pushing code frequently, there is always a chance that working pull requests might break somewhere. </p>
<p>It could be because one PR was merged before another, or the destination branch moved a few commits ahead, causing conflicts. </p>
<p>Or maybe because a developer didn’t run tests before pushing and unknowingly introduced a bug in some other part of the product. And the list goes on.</p>
<p>But this shouldn't be a problem. Every organization has a workflow for Code Reviews, right? But it still takes up a lot of time. Especially for those PR's that break and are not even ready for review. </p>
<p>We can manually build and test our code every time before a proper code review, no doubt. But after a certain point, it seems better to automate it. </p>
<p>Imagine a medium size organization with 100–150 PR’s every week. The time spent repetitively validating those might give that firm a whole set of new features. Well then, let’s go get those features!</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You should have some familiarity with AWS Services. </p>
<p>I assume you know how to create and manage Lambda Functions, Codebuild Projects, Cloudwatch Events, IAM Roles, and that you’re using CodeCommit to version your codebase.</p>
<h2 id="heading-architecture">Architecture</h2>
<p>Let’s understand, at a high level, how we are going to tackle this project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/ValidatePR-Architecture-Flowchart.png" alt="Image" width="600" height="400" loading="lazy">
<em>Uh huh, What?</em></p>
<p>Step by step, let’s understand our workflow better.</p>
<ol>
<li>Let’s say a new PR is created / an existing PR is updated.</li>
<li>A Cloudwatch event that is watching our repository will be activated and will send relevant data to a lambda function.</li>
<li>This function will do two things<br>→ Trigger CodeBuild Project to build our latest commit and run tests.<br>→ Comment any custom message that we want on our PR.</li>
<li>After CodeBuild finishes running the build, another Cloudwatch event will send those build results to a lambda function.</li>
<li>This function will comment the build results on our PR.</li>
</ol>
<p>Alright then, let’s get started!</p>
<h2 id="heading-setting-up-our-app">Setting up our App</h2>
<p>For the sake of simplicity, I’ve created a simple Node.js application. It’s written in TypeScript and all the build phase does is compile the ‘app.ts’ to ‘app.js’.</p>
<p><a target="_blank" href="https://github.com/aagam29/ValidatePR">Here’s</a> the link to the repo – clone and use it if you want to follow along.<br>All the relevant code used in this article can be found there.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/simple-express-app-screenshots.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>A simple Express app</em></p>
<p>The <code>build</code> command here is a simple <code>tsc app.ts</code> , but you can change it to your project’s build command.</p>
<p>Also to keep it simple, I’ve not included test cases. You can link them to <code>test</code> in the script section of <code>package.json</code> and follow along.</p>
<h2 id="heading-codebuild-project">Codebuild Project</h2>
<p>First, you'll want to set up a basic CodeBuild project for your repository. </p>
<p><strong>To do this, do the following:</strong></p>
<ul>
<li>Set up source as your Codecommit repository</li>
<li>Reference type should be branch</li>
<li>Environment should be per the project's requirements</li>
<li>You should use a buildspec file</li>
<li>The rest should just be defaults.</li>
</ul>
<p>Make sure you have a <code>buildspec.yml</code> file in your repo’s root folder.</p>
<p>Note: this might differ if you’re dealing with a MonoRepo. In that case, you might have separate buildspec.yml files for each App and will have to selectively pass the buildspec file path as an environment variable depending on the files changed inside the commit. </p>
<p>We have a similar setup at our organization, and we're loving the results at present!</p>
<pre><code class="lang-yml"><span class="hljs-attr">version:</span> <span class="hljs-number">0.2</span>
<span class="hljs-attr">phases:</span>
  <span class="hljs-attr">install:</span>
    <span class="hljs-attr">commands:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">n</span> <span class="hljs-number">12.12</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">curl</span> <span class="hljs-string">-sS</span> <span class="hljs-string">https://dl.yarnpkg.com/debian/pubkey.gpg</span> <span class="hljs-string">|</span> <span class="hljs-string">apt-key</span> <span class="hljs-string">add</span> <span class="hljs-bullet">-</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">echo</span> <span class="hljs-string">"deb https://dl.yarnpkg.com/debian/ stable main"</span> <span class="hljs-string">|</span> <span class="hljs-string">tee</span> <span class="hljs-string">/etc/apt/sources.list.d/yarn.list</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">apt</span> <span class="hljs-string">update</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">apt</span> <span class="hljs-string">install</span> <span class="hljs-string">yarn</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">yarn</span> <span class="hljs-string">install</span>
<span class="hljs-comment">#   pre_build:</span>
<span class="hljs-comment">#     commands:</span>
<span class="hljs-comment">#     - yarn test</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">commands:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">yarn</span> <span class="hljs-string">build</span>
</code></pre>
<p>What does this buildspec.yml do? Well, it passes runtime commands for each build to our CodeBuild project.</p>
<p>And then does what? ?</p>
<ul>
<li>Installs node 12.12.0</li>
<li>Installs yarn</li>
<li>Installs our project’s dependencies.</li>
<li>yarn test (It runs our test cases. There are none here, but you can uncomment that section if you need it.)</li>
<li>yarn build (Builds our project.)</li>
</ul>
<h2 id="heading-lambda-functions">Lambda Functions</h2>
<p>Let’s set up two functions as discussed in the architecture section above.</p>
<p>The function <strong>TriggerCodebuildStart</strong> will receive a Cloudwatch Event (which we will set up in a bit) and it will trigger our CodeBuild project to start a fresh build.</p>
<p>It will also post a Build Started comment with the timestamp and a neat link to the build logs in our PR’s comment section.</p>
<p>The function <strong>TriggerCodebuildResult</strong> will receive a Cloudwatch Event from our CodeBuild project which will have the build results. </p>
<p>It will also post the Codebuild Results comment with the timestamp and a neat link to the build logs in our PR’s comment section.</p>
<p>Here’s the code. That’s what you were waiting for, weren’t you! ? </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> AWS = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-sdk'</span>);
<span class="hljs-keyword">const</span> codecommit = <span class="hljs-keyword">new</span> AWS.CodeCommit();
<span class="hljs-keyword">const</span> codebuild = <span class="hljs-keyword">new</span> AWS.CodeBuild();

<span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> (event) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Received Event: '</span>, event);
        <span class="hljs-keyword">const</span> { destinationCommit } = event.detail;
        <span class="hljs-keyword">const</span> { sourceCommit } = event.detail;
        <span class="hljs-keyword">const</span> { pullRequestId } = event.detail;
        <span class="hljs-keyword">const</span> pullRequestName = event.detail.title;
        <span class="hljs-keyword">const</span> sourceBranch = event.detail.sourceReference.split(<span class="hljs-string">'/'</span>).pop();
        <span class="hljs-keyword">const</span> triggerCodeBuildParameters = {
            sourceBranch, sourceCommit, destinationCommit, pullRequestId, pullRequestName
        };
        <span class="hljs-keyword">const</span> codeBuildResult = <span class="hljs-keyword">await</span> triggerCodebuild(triggerCodeBuildParameters);

        <span class="hljs-keyword">const</span> buildId = codeBuildResult.build.id;
        <span class="hljs-keyword">const</span> postBuildStartedCommentOnPRParameters = {
            sourceCommit, destinationCommit, pullRequestId, buildId
        }

        <span class="hljs-keyword">await</span> postBuildStartedCommentOnPR(postBuildStartedCommentOnPRParameters);

        <span class="hljs-keyword">return</span> {
            <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>
        };
    }
    <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'An Error Occured'</span>, error);
        <span class="hljs-keyword">return</span> { 
            error
        };
    }
};

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">postBuildStartedCommentOnPR</span>(<span class="hljs-params">postBuildStartedCommentOnPRParameters</span>) </span>{
    <span class="hljs-keyword">const</span> { sourceCommit, destinationCommit, pullRequestId, buildId } = postBuildStartedCommentOnPRParameters;
    <span class="hljs-keyword">const</span> logLink = <span class="hljs-string">`https://<span class="hljs-subst">${process.env.REGION}</span>.console.aws.amazon.com/codesuite/codebuild/projects/ValidatePullRequest/build/<span class="hljs-subst">${buildId}</span>`</span>;
    <span class="hljs-keyword">const</span> parameters = {
        <span class="hljs-attr">afterCommitId</span>: sourceCommit,
        <span class="hljs-attr">beforeCommitId</span>: destinationCommit,
        <span class="hljs-attr">content</span>: <span class="hljs-string">`Build For Validating The Pull Request has been started.   
        Timestamp: **<span class="hljs-subst">${<span class="hljs-built_in">Date</span>.now()}</span>**   
        Check [CodeBuild Logs](<span class="hljs-subst">${logLink}</span>)`</span>,
        pullRequestId,
        <span class="hljs-attr">repositoryName</span>: process.env.REPOSITORY_NAME
    };

    <span class="hljs-keyword">const</span> request = <span class="hljs-keyword">await</span> codecommit.postCommentForPullRequest(parameters);
    <span class="hljs-keyword">const</span> promise = request.promise();
    <span class="hljs-keyword">return</span> promise.then(
        <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> data,
        <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Error In Commenting To Pull Request'</span>, error);
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(error);
        }
    );
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">triggerCodebuild</span>(<span class="hljs-params">triggerCodeBuildParameters</span>) </span>{
    <span class="hljs-keyword">const</span> { sourceBranch, sourceCommit, destinationCommit, pullRequestId, pullRequestName } = triggerCodeBuildParameters;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Triggering Codebuild, Branch: <span class="hljs-subst">${sourceBranch}</span>`</span>);
    <span class="hljs-keyword">const</span> parameters = {
        <span class="hljs-attr">projectName</span>: process.env.CODEBUILD_PROJECT,
        <span class="hljs-attr">sourceVersion</span>: <span class="hljs-string">`refs/heads/<span class="hljs-subst">${sourceBranch}</span>^{<span class="hljs-subst">${sourceCommit}</span>}`</span>,
        <span class="hljs-attr">environmentVariablesOverride</span>: [
            {
                <span class="hljs-attr">name</span>: <span class="hljs-string">'pullRequestId'</span>,
                <span class="hljs-attr">value</span>: pullRequestId,
                <span class="hljs-attr">type</span>: <span class="hljs-string">'PLAINTEXT'</span>
            },
            {
                <span class="hljs-attr">name</span>: <span class="hljs-string">'sourceCommit'</span>,
                <span class="hljs-attr">value</span>: sourceCommit,
                <span class="hljs-attr">type</span>: <span class="hljs-string">'PLAINTEXT'</span>
            },
            {
                <span class="hljs-attr">name</span>: <span class="hljs-string">'destinationCommit'</span>,
                <span class="hljs-attr">value</span>: destinationCommit,
                <span class="hljs-attr">type</span>: <span class="hljs-string">'PLAINTEXT'</span>
            },
            {
                <span class="hljs-attr">name</span>: <span class="hljs-string">'pullRequestName'</span>,
                <span class="hljs-attr">value</span>: pullRequestName,
                <span class="hljs-attr">type</span>: <span class="hljs-string">'PLAINTEXT'</span>
            }
        ]
    };
    <span class="hljs-keyword">const</span> request = <span class="hljs-keyword">await</span> codebuild.startBuild(parameters);
    <span class="hljs-keyword">const</span> promise = request.promise();
    <span class="hljs-keyword">return</span> promise.then(
        <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> data,
        <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Error In Starting Codebuild'</span>, error);
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(error);
        }
    );
}
</code></pre>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> AWS = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-sdk'</span>);
<span class="hljs-keyword">const</span> codecommit = <span class="hljs-keyword">new</span> AWS.CodeCommit();
<span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> (event) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event'</span>, event);
        <span class="hljs-keyword">const</span> parameters = <span class="hljs-keyword">await</span> getParameters(event);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Parameters For Comment:'</span>, parameters);
        <span class="hljs-keyword">await</span> commentCodeBuildResultOnPR(parameters);
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span> };
    }
    <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'An Error Occured'</span>, error);
        <span class="hljs-keyword">return</span> { error };
    }
};

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getParameters</span>(<span class="hljs-params">event</span>) </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> buildId = event.detail[<span class="hljs-string">'build-id'</span>].split(<span class="hljs-string">'/'</span>)[<span class="hljs-number">1</span>];
        <span class="hljs-keyword">const</span> buildStatus = event.detail[<span class="hljs-string">'build-status'</span>];
        <span class="hljs-keyword">const</span> environmentVariableList = event.detail[<span class="hljs-string">'additional-information'</span>].environment[<span class="hljs-string">'environment-variables'</span>];
        <span class="hljs-keyword">let</span> afterCommitId, beforeCommitId, content, pullRequestId;
        <span class="hljs-keyword">for</span> (element <span class="hljs-keyword">of</span> environmentVariableList) {
            <span class="hljs-keyword">if</span> (element.name === <span class="hljs-string">'pullRequestId'</span>) pullRequestId = element.value;
            <span class="hljs-keyword">if</span> (element.name === <span class="hljs-string">'sourceCommit'</span>) afterCommitId = element.value;
            <span class="hljs-keyword">if</span> (element.name === <span class="hljs-string">'destinationCommit'</span>) beforeCommitId = element.value;
            <span class="hljs-keyword">if</span> (element.name === <span class="hljs-string">'pullRequestName'</span>) pullRequestName = element.value;
        }

        <span class="hljs-keyword">const</span> logLink = <span class="hljs-string">`https://<span class="hljs-subst">${process.env.REGION}</span>.console.aws.amazon.com/codesuite/codebuild/projects/ValidatePullRequest/build/<span class="hljs-subst">${buildId}</span>`</span>;
        content = <span class="hljs-string">`Build Result: **<span class="hljs-subst">${buildStatus}</span>**   
        Timestamp: **<span class="hljs-subst">${<span class="hljs-built_in">Date</span>.now()}</span>**   
        Check [CodeBuild Logs](<span class="hljs-subst">${logLink}</span>)`</span>;

        <span class="hljs-keyword">return</span> {
            afterCommitId,
            beforeCommitId,
            content,
            pullRequestId,
            <span class="hljs-attr">repositoryName</span>: process.env.REPOSITORY_NAME
        };
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-keyword">throw</span> error;
    }
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commentCodeBuildResultOnPR</span>(<span class="hljs-params">parameters</span>) </span>{
    <span class="hljs-keyword">const</span> request = <span class="hljs-keyword">await</span> codecommit.postCommentForPullRequest(parameters);
    <span class="hljs-keyword">const</span> promise = request.promise();
    <span class="hljs-keyword">return</span> promise.then(
        <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> data,
        <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Error In Commenting To Pull Request'</span>, error);
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(error);
        }
    );
}
</code></pre>
<p>You'll need to fill in the appropriate environment variables before using these functions. Read the code once and you’ll know what to do.</p>
<p>In case you need to refer to the docs, just go <a target="_blank" href="https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CodeBuild.html#startBuild-property">here</a> and <a target="_blank" href="https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CodeCommit.html#postCommentForPullRequest-property">there</a>. ? </p>
<h2 id="heading-configure-cloudwatch-events">Configure Cloudwatch Events</h2>
<p>Okay, now to hook it all up, let’s configure our Cloudwatch events.</p>
<p>We’ll create two events: One will receive new commit data from our repository, and the other will receive the Codebuild Results. The targets for these events will be our lambda functions.  </p>
<p>I'm attaching full-page screenshots here. This will make it easier for you to understand the references.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/CloudWatch-Events.png" alt="Image" width="600" height="400" loading="lazy">
<em>Focus on the Green Ones</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/Start--CloudWatch-Event-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Replace with your CodeBuild project’s ARN.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/Result---Cloudwatch-Event.png" alt="Image" width="600" height="400" loading="lazy">
<em>Almost there!</em></p>
<p>I’ve chosen to trigger the lambda function on FAILED and SUCCEEDED events. But you can select All Events too and tailor it to your needs.</p>
<h2 id="heading-and-action">And, Action!</h2>
<p>Okay, you’re super cool if you made it to this point. ? After so much work, Let’s see what we’ve achieved. </p>
<p>Let’s make two pull requests, one which is works well and the other which has an intentional build error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/New-Working-PR.png" alt="Image" width="600" height="400" loading="lazy">
<em>Error Free PR</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/Successfull-build.png" alt="Image" width="600" height="400" loading="lazy">
<em>Great!</em></p>
<p>Now, let's create a PR with bugs. See here, instead of <strong>app.get</strong> there’s <strong>ap.get.</strong> It’s intentional and silly. But it will do the job for now.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/Faulty-PR.png" alt="Image" width="600" height="400" loading="lazy">
<em>Faulty PR</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/Failed-build.png" alt="Image" width="600" height="400" loading="lazy">
<em>Failed Build Message, Happy reviewers. Didn’t have to checkout the branch and test!</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/Failed-Logs.png" alt="Image" width="600" height="400" loading="lazy">
<em>Devs, as usual, we’ve got logs for you!</em></p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>To take this a step further, you could trigger an API call to your Slack webhook URL to immediately notify in a channel in case of build failures. Awesome, right?</p>
<p>Also, this is a very simple set up and real-world projects might be more complex.<br>For example, MonoRepos might have multiple apps and builds, and tests for each of those apps are different. </p>
<p>Triggering all those tests every time will be of no use, and it'll be costlier and create confusion. You might need to selectively trigger those builds depending on which files were committed and which apps were affected.</p>
<p>However, this article should build up a decent base for you. And you can definitely expand on it. After all, you’re awesome too. :)</p>
<p><strong>Thanks for reading!</strong> If you need some help regarding this, feel free to reach out to me on <a target="_blank" href="https://www.linkedin.com/in/aagamvadecha/">LinkedIn</a>. Looking forward to helping however I can.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write a Good Pull Request Description – And Why It's Important ]]>
                </title>
                <description>
                    <![CDATA[ By Sajal Sharma Writing a good Pull Request description is one of the most tedious jobs a developer has to do. And it can feel counter-productive at times.  But developing this skill goes a long way and really helps your stakeholders and your organiz... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-a-pull-request-description/</link>
                <guid isPermaLink="false">66d460c747a8245f78752ab3</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ version control ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 31 Aug 2020 22:01:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/wp3082255.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sajal Sharma</p>
<p>Writing a good Pull Request description is one of the most tedious jobs a developer has to do. And it can feel counter-productive at times. </p>
<p>But developing this skill goes a long way and really helps your stakeholders and your organization in the long run. </p>
<p>So it's always better to put in those 10 extra minutes today rather than having to break your head 6 months down the road trying to explain why you did what you did.</p>
<p>The following article explains the different parts of a Pull Request Description, and why you should include them.</p>
<h2 id="heading-what-is-a-pr-description">What is a PR description?</h2>
<p>A pull request description describes what constitutes the Pull Request and what changes you have made to the code.</p>
<p>It explains what you've done, including any code changes, configuration changes, migrations included, new APIs introduced, changes made to old APIs, any new workers/crons introduced in the system, copy changes, and so on. You get the gist.</p>
<p>You should include this section because it gives a glimpse to different stakeholders into what the PR is doing. </p>
<p>For a non-technical person, the description should explain what the impact will be on the system when these code changes are deployed to production. </p>
<p>It will also help the reviewer in understanding what they will be reviewing (kind of a prologue/trailer). </p>
<p>And finally it helps QA/SDET in understanding the scope of the PR as well. </p>
<p>So the "what" of the PR should give a glimpse into what constitutes the changes in the PR.</p>
<h2 id="heading-the-why-section">The "Why" section</h2>
<p>This section explains why the above changes explained were done.</p>
<p>Sometimes a developer feels that it's okay to write "Business/Product requirement" in the description. That's fine, but doing so defeats the purpose of this section. </p>
<p>If there is a better explanation as to why the changes were suggested, it's always good to attach a document reference link for that information. A good "Why" section should explain the reasoning behind any changes.</p>
<p>You should include this section because it gives an explanation of why you suggested your changes. It might not sound reasonable to include this section in the shorter term, but it plays a vital role as the product matures and spans years. </p>
<p>Developers/Product folks comes and goes, but the code remains. And when a new developer works on a piece of code and finds a discrepancy there, they can dig deeper and get to the pull request from 2 years ago which made those changes. </p>
<p>A good "why" gives them the explanation and assumptions made at that time.</p>
<p><strong>GoJek's CTO</strong> once explained that they don't challenge their legacy code and don't question why there seems to be some absurd looking feature in the product. </p>
<p>They just go back and check the documentation. </p>
<p>The assumptions and circumstances might have changed, and hence the code evolves. What seems to be quite absurd today might have been relevant 2 years ago. So it's better to explain today why you are making a particular change.</p>
<h2 id="heading-testing-scope">Testing Scope</h2>
<p>This section should comprise a list of scenarios you need to keep an eye on when testing this particular PR. (This will include flows, APIs, crons, workers, and so on.)</p>
<p>A good testing scope gives visibility to the QA/SDET team about the scenarios and flows that they need to test.</p>
<p>It can also help you while you're writing this section. I have come across issues myself, which prompted me to go back to the development phase and test them again. </p>
<p>A thoroughly written Testing Scope helps developers test the PR more efficiently, and gives a thorough picture of the PR to the person testing it.</p>
<h2 id="heading-relevant-documents">Relevant Document(s)</h2>
<p>This section includes any relevant document that needs to be attached with the PR description.</p>
<p>That might include product requirement documents, architectural diagrams, database system diagrams, design patterns used, class diagrams, external library documentation, and so on.</p>
<p>This section helps explain any assumptions and references you made while working on this feature request. And it plays a major role in the long run. </p>
<p>When someone comes back and sees why such a change was suggested, the relevant documents section will take them to the specific documentation so they can understand the issue clearly. Or it can take them to the technical implementation details of the scenario at the time of development.</p>
<h2 id="heading-dependent-prs-if-any">Dependent PR(s) (if any)</h2>
<p>There are times when a particular feature spans across multiple GitHub repositories and it's important to release them in a certain order. </p>
<p>For example, you might need to deploy one repo prior to another, or you might need to deploy them side by side.</p>
<p>Whatever the case may be, this section explains any dependent code that this PR relies upon.</p>
<p>You should include this section because it really helps the deployer understand the order of deployment. If another repo's code needs to go first, then the deployer will contact the person responsible for deployment of the other repo to make sure that their deployment happens first. Overall it helps smooth out the deployment process.</p>
<h2 id="heading-configuration-changes-if-any">Configuration Changes (if any)</h2>
<p>This section should include all the config changes that need to be added to the secrets before the PR is deployed into production.</p>
<p>There will be times when the deployer will merge 10-20 PRs at a time and it becomes hard for them to keep track of all the config changes. </p>
<p>Because of this, it's always better to include them in the config changes section. (Don't put the secret keys there, just include the key names and how to get the secrets.)</p>
<h2 id="heading-tagslabels">Tags/Labels</h2>
<p>These are very important in a pull request description and convey a lot of meaning when the team grows. </p>
<p>Following are some tags that I use, but you can add different tags according to your needs.</p>
<ul>
<li><strong>Dev Completed -</strong> When the development is completed from the dev's side.</li>
<li><strong>Self Reviewed -</strong> When the developer(s) of the Pull Request has reviewed the Pull Request from their side, and can now give it to their peers for a Peer Review.</li>
<li><strong>Self Tested -</strong> When the developer(s) of the Pull Request has tested the changes themself according to the description they have given in the Testing Scope section.</li>
<li><strong>Config Changes -</strong> This tag indicates that there are some configuration changes that need to be done before deploying the PR to production. (This includes secret keys that needs to be put into the system.)</li>
<li><strong>Contains Migration(s) -</strong> This indicates that the PR contains a Migration. If it is a long running migration, it should be specified beforehand.</li>
<li><strong>Release Ready -</strong> This indicates to the Deployer that the PR is ready for deployment and will be picked up by the deployer in the next deployment cycle.</li>
<li><strong>Peer Reviewed -</strong> When the Peer has reviewed the PR and the suggested changes are made by the developer(s). This is put up by the Peer who has reviewed the PR.</li>
<li><strong>QA Tested -</strong> This indicates that the QA/SDET has tested the PR and it is good to be deployed to production.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we went through the different parts of a PR description. Most of the PRs you make will not need all these sections and tags, but you should try to include as many of them as you can. </p>
<p>Writing this description might not seem productive at the time when you create a PR, but it can definitely prove helpful in the future.</p>
<p>A final note: The above are my views and might differ from your perspective. But I've developed this strategy over the years, and it contains the input and experience of a lot of people I have worked with in the Industry. So you can feel good knowing that it's been battle tested to a high degree.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Your Future Self Up for Success with Good Coding Habits ]]>
                </title>
                <description>
                    <![CDATA[ Think before you code. You have the power to make your future self's life Heaven on Earth or a living hell. In this article we'll explore what kinds of things you can do to make it a little easier on your future self. Revisiting "prior art" We've all... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/set-future-you-up-for-success-with-good-coding-habits/</link>
                <guid isPermaLink="false">66bee9536769d2581da6f951</guid>
                
                    <category>
                        <![CDATA[ Self-awareness ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 100Days100Projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ fundamentals ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Self Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 16 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/set-up-for-success.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Think before you code. You have the power to make your future self's life Heaven on Earth or a living hell.</p>
<p>In this article we'll explore what kinds of things you can do to make it a little easier on your future self.</p>
<h2 id="heading-revisiting-prior-art">Revisiting "prior art"</h2>
<p>We've all been there. Six months into a project, you're trying to squash a bug, and what you find is shocking. You might be asking yourself, "who would write this kind of code?"</p>
<p>So you dig through your <a target="_blank" href="https://git-scm.com/">git</a> commit history using <code>git log -p filename.js</code> showing changes for a specific file, trying to see who would come up with something like that. And then your heart drops – you're the one who wrote it!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/tituss-burgess-shocked.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Tituss Burgess shocked</em></p>
<p>This is a common scenario for any developer, experienced or new. If you haven't hit that scenario, I promise if you stick with coding long enough, you will.</p>
<h2 id="heading-becoming-more-conscious-about-our-coding-habits">Becoming more conscious about our coding habits</h2>
<p>That six month reflection point is inevitable. That's a lot of time which you've most likely been using to work on other parts of the project or another project completely. Chances are, you've leveled up which has changed the way you write code.</p>
<p>On the other hand, sometimes it takes stepping outside of the code to see the bigger picture and get a better look at how all the pieces fit together. We can naturally dig ourselves too deep into a solution and can become a little narrowly focused as we work to solve those challenges.</p>
<p>But either way, while part of the code journey will simply be gaining more experience and learning more about your craft, there are other small habits you can get used to early on that will help you down the road.</p>
<p>So let's jump in.</p>
<h2 id="heading-improving-the-readability-of-your-code">Improving the readability of your code</h2>
<h3 id="heading-what-is-the-challenge">What is the challenge?</h3>
<p>Part of the fun about our craft is there are a ton of ways you can do the same thing. Think an <code>if</code> statement is too many lines? Well we can write it <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">ternary</a> style!</p>
<pre><code class="lang-js"><span class="hljs-comment">// Example ternary statement</span>
<span class="hljs-keyword">const</span> isFreezing = temperature &lt;= <span class="hljs-number">32</span> ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;
</code></pre>
<p>But sometimes this takes a toll on the readability of your code. While it might seem like it looks nice and super clean on one line, imagine that as that ternary gets more complex, someone will have to spend more time understanding what it means.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> minutes = <span class="hljs-number">30</span>;
<span class="hljs-keyword">const</span> cookie = {
  <span class="hljs-attr">color</span>: <span class="hljs-string">'black'</span>
};

<span class="hljs-keyword">const</span> cookieStatus = minutes &gt; <span class="hljs-number">20</span> ? cookie.color === <span class="hljs-string">'black'</span> ? <span class="hljs-string">'burned'</span> : <span class="hljs-string">'done'</span> : <span class="hljs-string">'not done'</span>;
</code></pre>
<h3 id="heading-what-can-we-do-better">What can we do better?</h3>
<p>Now I would imagine most of us can figure out what <code>cookieStatus</code> is in this example (spoilers: <code>burned</code>). But think about the time you spent figuring it out. Whether an extra 1s or 2s, it forces you to spend additional cognitive energy to read through the code.</p>
<p>On the other hand:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> minutes = <span class="hljs-number">30</span>;
<span class="hljs-keyword">const</span> cookie = {
  <span class="hljs-attr">color</span>: <span class="hljs-string">'black'</span>
};
<span class="hljs-keyword">let</span> cookieStatus;

<span class="hljs-keyword">if</span> ( minutes &lt;= <span class="hljs-number">20</span> ) {
  cookieStatus = <span class="hljs-string">'not done'</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( cookie.color === <span class="hljs-string">'black'</span> ) {
  cookieStatus = <span class="hljs-string">'burned'</span>;
} <span class="hljs-keyword">else</span> {
  cookieStatus = <span class="hljs-string">'done'</span>;
}
</code></pre>
<p>No, it may not be as clean or clever as the 1-line ternary statement, but the next time you visit it, the less you'll have to think about what the answer is. </p>
<p>It's also going to make it that much easier for bugs to creep up and get past your code reviewers when all of your code changes are in a 1-line git diff.</p>
<p>And yes, this is a simple example. But imagine this in a real world scenario with important business logic where you could run into these situations frequently.  </p>
<p>Say you need to add another condition – that ternary is just going to keep getting more complex! You're just making it more difficult to debug or extend, where the <code>if</code> statements can continue on in an easily readable way.</p>
<p>For what it's worth, ternaries and other shortcuts can be simple and effective in code, but don't abuse that effectiveness and end up making things more difficult.</p>
<h2 id="heading-keeping-things-consistent">Keeping things consistent</h2>
<h3 id="heading-what-is-the-challenge-1">What is the challenge?</h3>
<p>We all have our favorite way to code. Though I'd argue not including a semicolon at the end of your JavaScript is just completely wrong, you might prefer to write your code the wrong way without them.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Jim's code style</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleOnClick</span>(<span class="hljs-params"></span>) </span>{
    alert(<span class="hljs-string">'Click!'</span>)
  }
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleOnClick}</span>&gt;</span>My Button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  )
}

<span class="hljs-comment">// Creed's code style</span>

<span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> alert('Click!')}&gt;My Button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
</code></pre>
<p>But it's not always about what <em>you</em> prefer. When working with a team, chances are, everyone's opinion on how code should look is slightly different. You might agree about the semi-colon, but disagree about whitespace.</p>
<p>And no one is wrong (except for the non-semi-coloners)! There are valid arguments to most code styles, whether for or against, but the solution isn't for everyone to write their code their own way.</p>
<h3 id="heading-what-can-we-do-better-1">What can we do better?</h3>
<p>Keeping code consistent is important to maintain code health. A typical goal is to "make the codebase look like one person wrote it."</p>
<p>The point isn't that one person gets their way, it's that the team came to a conclusion about a set of rules they would use that everyone would follow. Having this consistency provides less cognitive overhead as people work through the code. It gives everyone the ability to know what to expect when reading the code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/linting-code.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Errors from linting code</em></p>
<p>And achieving this doesn't need to be hard. There are tools that can simply <a target="_blank" href="https://www.colbyfayock.com/2019/10/what-is-linting-and-how-can-it-save-you-time">check for these inconsistencies</a> like <a target="_blank" href="https://eslint.org/">Eslint</a> for Javascript. And even better, there is another level of tools like <a target="_blank" href="https://prettier.io/">Prettier</a> that <a target="_blank" href="https://www.colbyfayock.com/2019/11/dont-just-lint-your-code-fix-it-with-prettier">will fix it for you</a>!</p>
<h2 id="heading-commenting-your-code">Commenting your code</h2>
<h3 id="heading-what-is-the-challenge-2">What is the challenge?</h3>
<p>Keeping up with commenting your code is an important way to put context to complex logic. As much as we all want our code to be self-documenting, that's rarely the case.</p>
<p>Too often we find ourselves dealing with a block of code that just doesn't make sense. And even if it makes sense on its own, we might not be able to figure out how it fits in to the rest of the application.</p>
<h3 id="heading-what-can-we-do-better-2">What can we do better?</h3>
<p>By providing a good set of comments, you're setting up the next person who touches that code to have a better understanding of what the code is doing before they make a change.</p>
<pre><code class="lang-js"><span class="hljs-comment">// DONT CHANGE - WILL STOP MAKING MONEY</span>

<span class="hljs-keyword">const</span> shouldMakeMoney = <span class="hljs-literal">true</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">makeMoney</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> ( shouldMakeMoney ) {
    <span class="hljs-keyword">return</span> noMoney;
  }
  <span class="hljs-keyword">return</span> moreMoney;
}
</code></pre>
<p>While this is a silly example, it brings up a real world case. Businesses are increasingly dependent on being able to maintain a reliable website to make money. Whether this is as an ecommerce business or an ad giant, these websites rely on business logic that determine things like cost, taxes, discounts, and other math related things we tend to not want to think about, but could make or break a business on the internet.</p>
<p>But it's not all about the company you work for. Touching old code can be scary. It's even scarier when no one on your team was around when it was written, so no one knows what it does!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/patton-oswalt-hands-over-mouth.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Patton Oswalt hands over mouth</em></p>
<p>While you might not be the next person who touches that code, try to help out your future friend who's tackling the next ticket involving that code. Because there's also a good chance you will be that person and you'll wish you remembered how it worked.</p>
<h2 id="heading-documenting-your-solutions">Documenting your solutions</h2>
<h3 id="heading-what-is-the-challenge-3">What is the challenge?</h3>
<p>Documentation is similar to commenting your code, but from a different perspective. Documentation and commenting are both about finding ways to describe a solution in a human-readable way that will ultimately give more context. But documentation is more about the overall solution rather than the implementation details.</p>
<p>Having a high performing application is everyone's goal. But how did we get there? There's a realistic chance that someone will have to be working on the same project you are like onboarding a new team member. How will they be able to maintain that high performance if they don't know how it works?</p>
<h3 id="heading-what-can-we-do-better-3">What can we do better?</h3>
<p>Whether it's introducing that new team member to the project or trying to share knowledge with another project team, documentation is an important part of maintaining a project. It helps keep everyone on the same page so we all confidently know what we're working towards.</p>
<p>For example, if we're still working with our ecommerce project with our business logic, there will be rules that the code needs to implement. While commenting might give details inline about how the rules were implemented, the documentation would define those rules.</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * DOCUMENTATION
 * Order Total &gt;= 25: Discount %10
 * Order Total &gt;= 50: Discount %15
 * Order Total &gt;= 100: Discount %20
 * Order Total &gt;= 75: Free Shipping
 */</span>

<span class="hljs-keyword">const</span> orderSubTotal = <span class="hljs-number">84.00</span>;
<span class="hljs-keyword">let</span> orderTotal = orderSubTotal;

<span class="hljs-comment">// If the order total is under 75, apply shipping discount</span>

<span class="hljs-keyword">if</span> ( orderTotal &lt; <span class="hljs-number">75</span> ) {
  orderTotal = addShipping(orderTotal);
}

<span class="hljs-comment">// If the order total reaches a threshold, apply given discount</span>

<span class="hljs-keyword">if</span> ( orderTotal &gt;= <span class="hljs-number">100</span>) {
  orderTotal = applyDiscount(orderTotal, <span class="hljs-number">.2</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( orderTotal &gt;= <span class="hljs-number">50</span> ) {
  orderTotal = applyDiscount(orderTotal, <span class="hljs-number">.15</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( orderTotal &gt;= <span class="hljs-number">25</span> ) {
  orderTotal = applyDiscount(orderTotal, <span class="hljs-number">.1</span>);
}
</code></pre>
<p>This is a minimal example, but we can see the difference between the rules at the top and how we apply them. The documentation should clearly explain what the rules are, but it shouldn't care about how those rules were implemented.</p>
<p>On the other hand, the comments might not care about what the rules are, but need to implement them in an efficient and logical way. We should be able to update the code with the business rules, such as changing the top level discount tier from $100 to $80, without having to rework the code.</p>
<p>But documentation is much more than business rules – it's providing a way for anyone to understand your work from a higher level. This could include anything from architectural diagrams to the theory behind your core algorithm.</p>
<p>While maybe code isn't the best place for details like this to live, it's really important information that can help instill confidence in your project and give others an opportunity to understand more about the work.</p>
<h2 id="heading-creating-effective-pull-requests">Creating effective Pull Requests</h2>
<h3 id="heading-what-is-the-challenge-4">What is the challenge?</h3>
<p>Pull requests (or merge requests) are a core part of any development team's project lifecycle. It provides a way to package and present your code in a consumable way for your peers to review and understand your work.</p>
<p>There's a lot that can go into a pull request from a single commit to the entirety of the next version of your website. That's a lot of context to expect someone to understand by reading through the commits alone.</p>
<h3 id="heading-what-can-we-do-better-4">What can we do better?</h3>
<p>Pull requests don't need to be an art. There should be one primary goal of the preparation you put into it – providing context into your changes. At a minimum, it should answer the questions of "what" and "why".</p>
<p>We can even use tools like pull request templates to push us in the right direction. <a target="_blank" href="https://www.freecodecamp.org/news/why-you-should-write-merge-requests-like-youre-posting-to-instagram-765e32a3ec9c/">Define an outline</a> of what you want explained and chances are, people will follow that outline. This helps avoid the 1-line "closes [ticket]" description or even worse, an empty description.</p>
<p>With my projects, I hope to have a few questions answered before I dive into a code review:</p>
<ul>
<li>What is the change?</li>
<li>What does it impact?</li>
<li>How do I reproduce or test the change?</li>
</ul>
<p>Just a few details around the change set can provide much needed context for those reviewing your code. It's easy to look at code, but it's harder to understand it without knowing how it fits into the bigger picture.</p>
<h2 id="heading-hardening-your-code-with-tests">Hardening your code with tests</h2>
<h3 id="heading-what-is-the-challenge-5">What is the challenge?</h3>
<p>Tests are a way to ensure your code runs the same way each time. Being able to prove that the same input will always have the same output will help provide you and your team with a higher level of confidence that your application won't come crashing down with the next small change.</p>
<p>Without them, we're left with human error, where no matter how good your QA Engineer is (shoutout to my testers out there), something will always slip through. And that's not to say your tests will always catch every problem, but we can use the tools available to help prevent it.</p>
<h3 id="heading-what-can-we-do-better-5">What can we do better?</h3>
<p>Where comments are a way of providing the context of how something works, test are a way to ensure they work. Providing test cases that are repeatable helps enforce that.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">applyDiscount</span>(<span class="hljs-params">value, discount</span>) </span>{
  <span class="hljs-keyword">const</span> discountAmount = value * discount;
  <span class="hljs-keyword">return</span> value - discountAmount;
}

expect(applyDiscount(<span class="hljs-number">10</span>, <span class="hljs-number">.1</span>)).toEqual(<span class="hljs-number">.9</span>);
expect(applyDiscount(<span class="hljs-number">532151235</span>, <span class="hljs-number">.1054</span>)).toEqual(<span class="hljs-number">476062494.831</span>);
</code></pre>
<p>If I fudge the math on our <code>applyDiscount</code> function above, there's a high probability that the test would fail (never say never).</p>
<p>But testing doesn't need to be hard. There are many tools out there that help from different perspectives. For example, you might use <a target="_blank" href="https://jestjs.io/">Jest</a> to run your unit tests or add <a target="_blank" href="https://enzymejs.github.io/enzyme/">Enzyme</a> on top to test your React components. But you can also bring in <a target="_blank" href="https://www.cypress.io/">Cypress</a> as an integration test solution that will work like a robot clicking through your application to make sure all the components actually work together.</p>
<p>There's also different methodologies of testing. While you probably see most teams write their tests after they have a working solution, some people swear by <a target="_blank" href="https://en.wikipedia.org/wiki/Test-driven_development">test-driven development</a>. They might write their tests first where the code has to pass the tests rather than the other way around. This is a great way to define the requirements of the code before diving right in.</p>
<p>Whatever the method, capture the points that are most likely to break or the functions that add the most business value. You'll be helping to prevent a potential business loss or even simpler, a headache.</p>
<h2 id="heading-what-can-we-learn-from-this">What can we learn from this?</h2>
<p>That might be a lot to digest, but they're important points to consider as you grow as a developer. Starting these habits early in your career will help you naturally build these skills and work that way by default.</p>
<p>And if you're late in your career, it's never too late to start. We should all want to strive to be the best developer we can be and do our best to help make our teammate's lives easier, as we're all in this together.</p>
<h2 id="heading-looking-for-more-to-learn">Looking for more to learn?</h2>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/08/put-down-the-javascript-learn-html-css">Put Down the Javascript - Learn HTML &amp; CSS</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/02/how-to-become-a-full-stack-web-developer-in-2020">How to Become a Full Stack Web Developer in 2020</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/02/what-is-the-jamstack-and-how-do-i-get-started">What is the JAMstack and how do I get started?</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/10/what-is-linting-and-how-can-it-save-you-time">What is linting and how can it save you time?</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/why-you-should-write-merge-requests-like-youre-posting-to-instagram-765e32a3ec9c/">Why you should write merge requests like you’re posting to Instagram</a></li>
</ul>
<h2 id="heading-whats-your-advice-for-growing-as-a-developer">What’s your advice for growing as a developer?</h2>
<p><a target="_blank" href="https://twitter.com/colbyfayock">Share with me on Twitter!</a></p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Don’t just lint your code - fix it with Prettier ]]>
                </title>
                <description>
                    <![CDATA[ Linting makes our lives easier because it tells us what’s wrong with our code. But how can we avoid doing the actual work that goes into fixing it? Previously I wrote about linting, what it is, and how it makes your life easier. At the end, I actuall... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/dont-just-lint-your-code-fix-it-with-prettier/</link>
                <guid isPermaLink="false">66b8e322682e4a25eed26199</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ eslint ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Prettier ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 06 Nov 2019 15:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/11/formatting-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Linting makes our lives easier because it tells us what’s wrong with our code. But how can we avoid doing the actual work that goes into fixing it?</p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/what-is-linting-and-how-can-it-save-you-time/">Previously I wrote about linting</a>, what it is, and how it makes your life easier. At the end, I actually included a way that you could automatically fix your code. So why am I writing this?</p>
<h2 id="heading-what-do-you-mean-fix-it"><strong>What do you mean fix it?</strong></h2>
<p>Before we roll into it, let’s hit this quick. Linters are powerful and provide an easy way to scan your code for syntax errors that could lead to bugs. Or they can simply help keep a codebase clean, healthy, and consistent. When run, it will show all the issues and let you go through each one individually to fix them.</p>
<p>Taking that to the next level, some linters will actually allow you to pass in an argument to the command running the linter that allows it to fix it for you automagically. This means you don’t have to manually go through and make all of those little whitespace and semicolon (add them! ?) tweaks yourself!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/ron-swanson-happy.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Ron Swanson happy</em></p>
<h2 id="heading-so-what-more-can-i-do-to-fix-things"><strong>So what more can I do to fix things?</strong></h2>
<p>If you already use the fix option, thats a good start. But there are tools out there that have been developed specifically to tackle this problem beyond just a flag into your command. The one I’m going to cover is Prettier.</p>
<h2 id="heading-what-is-prettier"><strong>What is Prettier?</strong></h2>
<p><a target="_blank" href="https://prettier.io/">Prettier</a> pegs itself as “an opinionated code formatter." It takes an input of your code and outputs it in a consistent format stripping any of the original code style. It actually converts your code to a <a target="_blank" href="https://github.com/benjamn/recast">syntax tree</a>, then rewrites it using the styles and rules you and Prettier provide together via your ESLint config and Prettier’s default rules.</p>
<p>You can easily use Prettier alone just to format your code, which works just fine. But if you combine this with an underlying ESLint process, you get both a powerful linter and a powerful fixer. I’m going to show you how to make those work together.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/voltron.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Voltron</em></p>
<h2 id="heading-getting-started-with-prettier"><strong>Getting started with Prettier</strong></h2>
<p>For this walkthrough, I’m going to assume that you have ESLint set up and configured in an application. Particularly, I’m going to pick up where I left off in my previous walkthrough where <a target="_blank" href="https://www.freecodecamp.org/news/what-is-linting-and-how-can-it-save-you-time/">we installed ESLint to a React application</a>.</p>
<p>Additionally of note, Prettier tells us right from the start that it's an opinionated code formatter. You should expect that it will format your code in a consistent way, but maybe a different way than you currently have it configured. But don’t fret! You can tweak this configuration.</p>
<p>So what are we starting off with? We already:</p>
<ul>
<li>Have installed <a target="_blank" href="https://github.com/eslint/eslint">ESLint</a></li>
<li>Have added <a target="_blank" href="https://github.com/babel/babel-eslint">Babel</a> as our parser</li>
<li>Have added a <a target="_blank" href="https://github.com/yannickcr/eslint-plugin-react">plugin</a> that includes React configurations</li>
</ul>
<p>Next, let’s get started by installing a few packages:</p>
<pre><code class="lang-shell">yarn add prettier prettier-eslint prettier-eslint-cli -D
</code></pre>
<p><em>Note: the command above is similar to using <code>npm</code>. If your project doesn't use <code>yarn</code>, swap out to <code>npm</code> as appropriate.</em></p>
<p>Above, we’re installing:</p>
<ul>
<li><a target="_blank" href="https://github.com/prettier/prettier">prettier</a>: core Prettier package and engine</li>
<li><a target="_blank" href="https://github.com/prettier/prettier-eslint">prettier-lint</a>: passes the Prettier result to ESLint to fix using your ESLint config</li>
<li><a target="_blank" href="https://github.com/prettier/prettier-eslint-cli">prettier-eslint-cli</a>: helps Prettier and ESLint work together on various files across your project</li>
</ul>
<p>And we’re installing them as a dev dependency, as we don’t need it outside development.</p>
<h2 id="heading-configuring-your-new-formatter"><strong>Configuring your new formatter</strong></h2>
<p>Now that our packages are installed, we can set up <code>yarn</code> to run this command for us.</p>
<p>Previously, we set up a <code>lint</code> script to look like this in our <code>package.json</code>:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
  ...
  <span class="hljs-attr">"lint"</span>: <span class="hljs-string">"eslint . --ext .js"</span>
  ...
}
</code></pre>
<p>We’re going to leave that as it is, but we’ll do something similar and create a new script right next to it called <code>format</code> for our formatter Prettier:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
  ...
  <span class="hljs-attr">"format"</span>: <span class="hljs-string">"prettier-eslint --eslint-config-path ./.eslintrc.js --write '**/*.js'"</span>,
  <span class="hljs-attr">"lint"</span>: <span class="hljs-string">"eslint . --ext .js"</span>
  ...
}
</code></pre>
<p>So what’s going on there? We’re:</p>
<ul>
<li>Adding a new script called <code>format</code>, that we can run as <code>yarn format</code></li>
<li>We’re utilizing our <code>prettier-eslint-cli</code> package to run the formatting for us</li>
<li>We’re passing in our ESLint config located next to our <code>package.json</code> in the root of the project (change this if it’s in a different location)</li>
<li>And finally, we’re telling prettier to write all files matching <code>**/*.js</code>, or any JS files it finds recursively through our project</li>
</ul>
<p>The beauty here is that we're passing in our ESLint config to Prettier. This means we only have to maintain 1 config for both tools, but we still leverage the linting power of ESLint along with the formatting power of Prettier.</p>
<h2 id="heading-run-your-formatter"><strong>Run your formatter!</strong></h2>
<p>Now that we’re all set up, let’s run it! Run this following:</p>
<pre><code>yarn format
</code></pre><p>and immediately, we see that it works:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/prettier-command-line-success.png" alt="Image" width="600" height="400" loading="lazy">
<em>Successfully running Prettier</em></p>
<h2 id="heading-hey-my-code-looks-different"><strong>Hey, my code looks different!</strong></h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/spongebob-pitchforks.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Angry mob with pitchforks</em></p>
<p>As I mentioned earlier, Prettier tells us straight up, it’s an opinionated formatter. It ships with its own rules, sort of like its own ESLint config, so it will go through and make those changes as well.</p>
<p>Don’t abandon your code! Instead, you can review the changes, see if maybe it makes sense to keep it that way (it will be very consistent) or you can update your ESLint config (<code>.eslintrc.js</code>) to overwrite the rules you don’t like. This is also a good way to maybe learn some new things that you might not have expected to get caught before.</p>
<h2 id="heading-so-where-does-this-leave-us"><strong>So where does this leave us?</strong></h2>
<p>If you’ve followed along so far, we now have two commands:</p>
<ul>
<li><code>lint</code>: which will check your code for you and tell you what's wrong</li>
<li><code>format</code>: will automatically try to fix the problems for you</li>
</ul>
<p>When using these in practice, your best bet is to always run <code>format</code> first to let it try to automatically fix anything it can. Then immediately run <code>lint</code> to catch anything Prettier wasn’t able to fix automatically.</p>
<h2 id="heading-whats-next"><strong>What’s next?</strong></h2>
<p>Now that we can format our code automatically, we should be able to fix our code automatically!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/fresh-off-the-boat-mind-blown.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Eddie from Fresh Off the Boat's mind blown</em></p>
<p>Next time we’ll take this a step further and set up a <code>git</code> hook that will allow this to run before you commit. This means you won't ever have to worry about forgetting to run this again!</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>

<p><em>Originally published at <a target="_blank" href="https://www.colbyfayock.com/2019/11/dont-just-lint-your-code-fix-it-with-prettier/">https://www.colbyfayock.com/2019/11/dont-just-lint-your-code-fix-it-with-prettier/</a></em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is linting and how can it save you time? ]]>
                </title>
                <description>
                    <![CDATA[ One of the biggest challenges in software development is time. It’s something we can’t easily get more of, but linting can help us make the most out of the time we have. So what is linting? lint, or a linter, is a tool that analyzes source code to fl... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-linting-and-how-can-it-save-you-time/</link>
                <guid isPermaLink="false">66b8e39893a17625e9eef113</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ eslint ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 09 Oct 2019 14:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/10/linting.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>One of the biggest challenges in software development is time. It’s something we can’t easily get more of, but linting can help us make the most out of the time we have.</p>
<h2 id="heading-so-what-is-linting">So what is linting?</h2>
<p><strong>lint</strong>, or a <strong>linter</strong>, is a tool that analyzes source code to flag programming errors, bugs, stylistic errors, and suspicious constructs. <a target="_blank" href="https://en.wikipedia.org/wiki/Lint(software)">https://en.wikipedia.org/wiki/Lint(software)</a></p>
<p>Simply put, a linter is a tool that programmatically scans your code with the goal of finding issues that can lead to bugs or inconsistencies with code health and style. Some can even help fix them for you!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/miachel-scott-tell-me-more.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Michael Scott - Tell me more</em></p>
<p>Take for instance, the following example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> test = <span class="hljs-string">'I am a test'</span>;
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Test: <span class="hljs-subst">${test}</span>`</span>);
<span class="hljs-keyword">const</span> test = <span class="hljs-string">'Another one.'</span>;
</code></pre>
<p>We’re declaring the constant <code>test</code> twice, which our javascript engine won’t be happy about. With the proper linter settings and watch configuration, instead of getting caught later as an error when the code runs, you’ll immediately get an error through your linter running in the background:</p>
<pre><code>  <span class="hljs-number">10</span>:<span class="hljs-number">9</span>  error  Parsing error: Identifier <span class="hljs-string">'test'</span> has already been declared

   <span class="hljs-number">8</span> |   <span class="hljs-keyword">const</span> test = <span class="hljs-string">'I am a test'</span>;
   <span class="hljs-number">9</span> |   <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Test: <span class="hljs-subst">${<span class="hljs-number">2</span>}</span>`</span>);
&gt; <span class="hljs-number">10</span> |   <span class="hljs-keyword">const</span> test = <span class="hljs-string">'Another one.'</span>;
     |         ^
</code></pre><p>It might be pretty obvious that you have 2 of the same <code>const</code> declarations given this is only 3 lines, but in a more complex application, this can save tons of time having to hunt down a pesky bug that’s not always obvious.</p>
<h2 id="heading-what-all-can-linting-help-with"><strong>What all can linting help with?</strong></h2>
<p><a target="_blank" href="https://eslint.org/docs/rules/">Lots of things</a>, including but not limited to:</p>
<ul>
<li>Flagging bugs in your code from syntax errors</li>
<li>Giving you warnings when code may not be intuitive</li>
<li>Providing suggestions for common best practices</li>
<li>Keeping track of TODO’s and FIXME’s</li>
<li>Keeping a consistent code style</li>
</ul>
<p>Most things you can think of probably already <a target="_blank" href="https://github.com/dustinspecker/awesome-eslint">exist in one form or another</a>, and if not, you can even <a target="_blank" href="https://gist.github.com/sindresorhus/1656c46f23545deff8cc713649dcff26">create custom rules</a> that fit your needs!</p>
<h2 id="heading-how-is-this-actually-helping-or-why-should-i-care"><strong>How is this actually helping or why should I care?</strong></h2>
<p>Probably the biggest overlying theme of the list above is the fact that these issues will be called out immediately. No longer will these issues creep up on you in the middle of running your app or give someone anxiety during a code review. No longer will you and your reviewer endlessly fight passive aggressively through the comments about whether or not to include a semicolon at the end of JS statements (<a target="_blank" href="https://stackoverflow.com/a/444082">you should</a> ?).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/looking-for-semicolon.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Grandma looking for a semicolon</em></p>
<p>All of those moments that stop you from being productive because of a silly syntax error or the micro-interactions you and your teammates have during a review take time. They add up and end up taking away the time you can spend fixing another bug or developing the next great feature of your product.</p>
<h2 id="heading-so-how-do-i-actually-get-started"><strong>So how do I actually get started?</strong></h2>
<p>Even though there are linters for most, if not all, other mainstream languages, for the purpose of this post, I’m going to focus on Javascript. The same principles apply, but the tooling may be a bit different.</p>
<p>I’m going to run through how you can get set up for basic linting in a React app. You can easily follow along by spinning up your own React app or using my <a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a> starter: <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-sass#starting-from-scratch">https://github.com/colbyfayock/gatsby-starter-sass#starting-from-scratch</a></p>
<h3 id="heading-your-linter"><strong>Your Linter</strong></h3>
<p>To get started, we first need a linter. <a target="_blank" href="https://trends.google.com/trends/explore?geo=US&amp;q=eslint,jshint,jslint">Probably the most popular</a> in the Javascript world is <a target="_blank" href="https://eslint.org/">ESLint</a>. Your linter will actually be the engine for defining rules and parsing your files to test against. ESLint is available as an <a target="_blank" href="https://www.npmjs.com/package/eslint">npm package</a> by itself and <a target="_blank" href="https://eslint.org/docs/user-guide/getting-started">once installed</a>, out of the box it allows you to set up a basic configuration file and hit the ground running with some command line tools.</p>
<p>Let’s first add our ESLint dependency:</p>
<pre><code>yarn add eslint -D
</code></pre><p>We’re installing this as a <code>devDependency</code> (hence the <code>-D</code> flag), because this isn’t something our application needs to run. After it’s successfully installed, let’s add it to our <code>package.json</code> as a script:</p>
<pre><code class="lang-json">...
<span class="hljs-string">"scripts"</span>: {
  ...
  <span class="hljs-attr">"lint"</span>: <span class="hljs-string">"eslint .  --ext .js"</span>
  ...
},
...
</code></pre>
<p>In the above, we’re running our linter on the entire project directory on any file that has an extension of <code>.js</code>. If you're working with a large project with many file types, maybe even some you don't want linted, you can <a target="_blank" href="https://eslint.org/docs/user-guide/command-line-interface">change that flag or be more specific</a> with other options.</p>
<p>To support ESLint, we’ll need to do one more thing. Let’s add a file at the root of our project (probably where your <code>package.json</code> is) called <code>.eslintrc.js</code> and make the contents of the file simply:</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = {};
</code></pre>
<p>Once you’re ready, you can run <code>yarn lint</code> and… get an error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/lint-with-import-errors.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Lint results - Import errors</em></p>
<p>This is okay, and expected in our project, so let’s move on.</p>
<h3 id="heading-your-parser"><strong>Your Parser</strong></h3>
<p>A common tool in the chain for Javascript developers is <a target="_blank" href="https://babeljs.io/">Babel</a>, which allows you to write code with features that may not be supported in all browsers, such as using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">arrow functions</a>, that are available in <a target="_blank" href="http://es6-features.org/#Constants">ES6</a>, and other conventions like importing files via <code>import</code>.</p>
<p>The code you write may already run through Babel to work in a browser, but that doesn’t apply to ESLint by default, so ESLint allows you to specify a parser that allows the linting processing to look at the same code as your browser sees. In this case we’ll want to use <a target="_blank" href="https://github.com/babel/babel-eslint">Babel’s ESLint</a> parser that’s made available to us.</p>
<p>To set that up, we’ll want to first install our dependency:</p>
<pre><code>yarn add babel-eslint -D
</code></pre><p>Typically if you're using <code>babel-eslint</code> you'll want to make sure <code>babel</code> is installed next to it, but in our case, Gatsby already uses <code>babel</code>, so we don’t necessarily need to add it. After that’s set up, we’ll want to update our <code>.eslintrc.js</code> config file with some new options:</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = {
    <span class="hljs-string">"env"</span>: {
        <span class="hljs-string">"browser"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-string">"node"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-string">"es6"</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-string">"parser"</span>: <span class="hljs-string">"babel-eslint"</span>
};
</code></pre>
<p>Here, we’re letting ESLint know that our environment will be run in node (Gatsby’s precompiling), inside the browser (the app), and it will use ES6. This helps ESLint know how to run your code. Additionally, we want to set up our parser to be <code>babel-eslint</code>.</p>
<p>Once we’re ready to go, run <code>yarn lint</code> again and… well nothing really happened.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/lint-with-nothing-happening.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Lint results - Nothing happened</em></p>
<p>This is still expected, as we don’t have any rules set up!</p>
<h3 id="heading-plugins-for-your-code"><strong>Plugins for your code</strong></h3>
<p>Writing a <a target="_blank" href="https://reactjs.org/">React</a> app? The Babel parser may help you transform your code, but you might have a hard time being productive, as ESLint needs to understand how it should work to lint your React files.</p>
<p>Part of the beauty of ESLint is that it allows you to <a target="_blank" href="https://eslint.org/docs/developer-guide/working-with-plugins">configure plugins</a> that have the opportunity to create and set rules for you. Luckily, along with our Babel parser above that does some of the heavy lifting, we have a <a target="_blank" href="https://github.com/yannickcr/eslint-plugin-react">React plugin</a> available that does just that and takes care of linting the JSX for us.</p>
<p>Let’s first install our dependency:</p>
<pre><code>yarn add eslint-plugin-react -D
</code></pre><p>Further, let’s update our <code>.eslintrc.js</code> file again:</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = {
    <span class="hljs-string">"settings"</span>: {
        <span class="hljs-string">"react"</span>: {
            <span class="hljs-string">"version"</span>: <span class="hljs-string">"detect"</span>
        }
    },
    <span class="hljs-string">"env"</span>: {
        <span class="hljs-string">"browser"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-string">"node"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-string">"es6"</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-string">"plugins"</span>: [
        <span class="hljs-string">"react"</span>
    ],
    <span class="hljs-string">"parser"</span>: <span class="hljs-string">"babel-eslint"</span>
};
</code></pre>
<p>What we’re adding here is a setting that automatically detects what React version you’re using, which is helpful to let your linting get parsed properly, and then set up our react plugin that we installed above.</p>
<p>For one last final time, we will run our <code>lint</code> script and get nothing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/lint-with-nothing-happening-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Lint results - Nothing happened</em></p>
<h3 id="heading-rules-defined-by-otherss-opinions"><strong>Rules defined by others’s opinions</strong></h3>
<p>If you’re not really sure where to get started or just want to quickly get up and running, it’s recommend that you enable <a target="_blank" href="https://eslint.org/docs/rules/">ESLint’s own recommended rules</a>. Let’s add this to our <code>.eslintrc.js</code> config file:</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = {
    <span class="hljs-string">"settings"</span>: {
        <span class="hljs-string">"react"</span>: {
            <span class="hljs-string">"version"</span>: <span class="hljs-string">"detect"</span>
        }
    },
    <span class="hljs-string">"env"</span>: {
        <span class="hljs-string">"browser"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-string">"node"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-string">"es6"</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-string">"plugins"</span>: [
        <span class="hljs-string">"react"</span>
    ],
    <span class="hljs-string">"extends"</span>: [
        <span class="hljs-string">"eslint:recommended"</span>
    ],
    <span class="hljs-string">"parser"</span>: <span class="hljs-string">"babel-eslint"</span>
};
</code></pre>
<p>And let’s run our <code>yarn lint</code>.</p>
<p>Woah! This will immediately give you a lot errors, it seems like something’s wrong.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/lint-with-react-errors.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Lint results - React errors</em></p>
<p>Since we’re running a React app, we also want to make sure our linter understands the rules it should follow, so let’s also add our React plugin to the <code>.eslintrc.js</code> config setup:</p>
<pre><code class="lang-json">    <span class="hljs-string">"extends"</span>: [
        <span class="hljs-string">"eslint:recommended"</span>,
        <span class="hljs-string">"plugin:react/recommended"</span>
    ],
</code></pre>
<p>Now if you run <code>yarn lint</code>, you get something a little more logical.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/lint-with-errors.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Lint results - Normal errors</em></p>
<p>If you’re following along, it looks like our starter app had a misplaced semicolon and a missing prop in our <code>propTypes</code> validation for <code>Layout.js</code>. Writing this helped me fix my own repo! ?</p>
<p>Going further, if those don’t seem to fit your needs, lots of developers and teams have published their own configurations that ESLint allows you to easily tap into.</p>
<p>Some popular ones include:</p>
<ul>
<li><a target="_blank" href="https://www.npmjs.com/package/eslint-config-airbnb">Airbnb’s config</a></li>
<li><a target="_blank" href="https://github.com/standard/eslint-config-semistandard">Semistandard</a></li>
<li><a target="_blank" href="https://github.com/google/eslint-config-google">Google’s JS Style Guide</a></li>
</ul>
<p>Not happy with the options available? You can even <a target="_blank" href="https://eslint.org/docs/6.0.0/developer-guide/shareable-configs">create and publish your own</a> to either layer on top of others as a starting point or give it a go from scratch.</p>
<h3 id="heading-let-it-do-the-work-most-of-it"><strong>Let it do the work (most of it)</strong></h3>
<p>You don’t think I’m going to make you fix all of those thing yourself do you? Well, you may have to fix some, but let’s try to get ESLint to fix some of it for us.</p>
<p>If you noticed after we ran the command above, ESLint gave us an extra message:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/lint-fix-option.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Lint results - Option to fix</em></p>
<p>So let’s give it a try! Let’s run:</p>
<pre><code>yarn lint --fix
</code></pre><p>And what do you know, it now only gives us 1 linting error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/lint-with-one-error.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Lint results - 1 error</em></p>
<p>Turns out ESLint was able to fix our semicolon issue automatically, but we’ll still have to add <code>pageName</code> to our <code>Layout</code>’s <code>propTypes</code> manually, not too much of a lift.</p>
<p>Running one more time and finally nothing again! But this time because everything's looking good.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/lint-with-nothing-happening-2.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Lint results - No errors</em></p>
<h2 id="heading-go-forth-and-write-messy-code"><strong>Go forth and write messy code!</strong></h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/bruce-almighty-typing.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Bruce Almighty - Typing</em></p>
<p>Kidding ? The good news here, is now you can easily take a look at the general health of your codebase as well as hopefully fix most of it automatically. This is going to save a lot of headaches as you work with others on your team, and generally, it’s nice to have all of your code neat and tidy.</p>
<p>This post is just getting started. ESLint is a wide open book with tons of plugins and rules, and it’s not the only linting tool in the game. Play around and find what fits best for you and your team. The little time spent configuring it to your app will save you lots more time in the long run.</p>
<h2 id="heading-other-linting-tools-to-check-out"><strong>Other linting tools to check out</strong></h2>
<ul>
<li><a target="_blank" href="https://jshint.com/">JSHint</a>: an alternative to ESLint</li>
<li><a target="_blank" href="https://github.com/stylelint/stylelint">Stylelint</a>: a linting tool for CSS and CSS-like syntaxes like <a target="_blank" href="https://sass-lang.com/">Sass</a></li>
<li><a target="_blank" href="https://github.com/dustinspecker/awesome-eslint">Awesome ESLint</a>: a simple list of awesome configs, parsers, plugins, and other tools to boost your ESLint game</li>
<li><a target="_blank" href="https://webhint.io/">Webhint</a>: linting tool for accessibility, speed, and more website best practices</li>
<li><a target="_blank" href="https://github.com/evcohen/eslint-plugin-jsx-a11y">A11y JSX Plugin</a>: ESLint plugin for checking accessibility rules on JSX elements</li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>

<p><em>Originally published</em> at <a target="_blank" href="https://www.colbyfayock.com/2019/10/what-is-linting-and-how-can-it-save-you-time">https://www.colbyfayock.com/2019/10/what-is-linting-and-how-can-it-save-you-time</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Proven Code Review Best Practices ]]>
                </title>
                <description>
                    <![CDATA[ By Michaela Greiler What are the code review best practices companies such as Microsoft follow to  ensure great code review feedback? How do you stay productive while doing code reviews? Learn proven code review best practices from Microsoft in this ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/proven-code-review-best-practices/</link>
                <guid isPermaLink="false">66d460447df3a1f32ee7f871</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 24 Jun 2019 07:39:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/Code-Review-Best-Practice-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Michaela Greiler</p>
<p>What are the code review best practices companies such as Microsoft follow to  ensure <a target="_blank" href="https://www.michaelagreiler.com/great-code-review-feedback/">great code review feedback</a>? How do you <a target="_blank" href="https://www.michaelagreiler.com/developer-productivity/">stay productive</a> while doing code reviews? Learn proven code review best practices from Microsoft in this article.</p>
<p>The benefits of code reviews rise and fall with the value of the code review feedback. If done correctly, code reviews can help to ensure a high-quality code base. However, if teams are not aware of and do not follow code review best practices, developers may experience several <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">code review pitfalls</a>. In the worst case, <a target="_blank" href="https://www.michaelagreiler.com/wp-content/uploads/2019/02/Code-Reviews-Do-Not-Find-Bugs.-How-the-Current-Code-Review-Best-Practice-Slows-Us-Down.pdf">reviewing code can slow your team down</a>.</p>
<p>I have been researching and working with teams at Microsoft for several years. Through <a target="_blank" href="https://www.michaelagreiler.com/publications/">several large scale-studies</a>, we discovered a number of code review best practices that help teams stay productive and <a target="_blank" href="https://www.michaelagreiler.com/great-code-review-feedback/">boost their code review value</a>. But first, let’s start at the beginning. What does code review look like?</p>
<h3 id="heading-a-typical-code-review-process">A typical code review process</h3>
<p>A <a target="_blank" href="https://www.michaelagreiler.com/code-reviews-at-microsoft-how-to-code-review-at-a-large-software-company/">typical tool-based code review process</a> starts when the engineer prepares the code for review. Then, she selects relevant reviewers for the code change. The reviewers are notified and give feedback on the code. The code review author works on the feedback until all parties are satisfied. Then, the code is checked into the common code base.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*ZOAaTZc1Z6XEK3Ri" alt="Image" width="414" height="656" loading="lazy"></p>
<p><em>A typical tool-based code review</em></p>
<p>To ensure that this process is smooth and does not become a nightmare, it is important to <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">understand code review pitfalls</a> and which code review best practices you can follow to overcome those.</p>
<p>The main code review pitfalls are:</p>
<ul>
<li>not getting useful feedback,</li>
<li>not having enough time to do code reviews,</li>
<li>code reviews taking too long causing long waiting times.</li>
</ul>
<p>The code review best practices I present below help counteract those pitfalls, by making the job of the reviewers as easy as possible. They also help the reviewer to focus on providing valuable feedback.</p>
<h3 id="heading-code-review-best-practices-for-code-authors">Code review best practices for code authors</h3>
<p>In a code review, there are two different stakeholders: the code author who asks for feedback and the code reviewers, who look through the code change and provide the feedback. As a code review starts with the author, I explain the code review best practices for code authors first.</p>
<p>For my e-mail subscribers, I prepared an <strong>exclusive code review e-book</strong> including a checklist with all code review best practices. I also added additional bonus insights. You can request the <a target="_blank" href="https://www.michaelagreiler.com/code-review-e-book/">Code Review e-Book here</a>.</p>
<h3 id="heading-read-through-the-change-carefully">Read through the change carefully</h3>
<p>The first code review best practice is to read carefully through the code change before submitting the code for review. There is nothing worse than asking several developers to look through the code and give feedback on issues you could have fixed yourself.</p>
<p>This wastes everyone’s time and it might make you look bad. For future code reviews, developers may also be reluctant to review your code.</p>
<p>So, ensure you use a code review tool or a diff tool that can highlight what changed between this and the previous version. Because the code is presented in a different way and changed code passages are highlighted, it makes it easier for you to review your code yourself before sending it out.</p>
<p>Often you will see changes that you actually forgot you made or missing issues highlighted you should fix before asking somebody to review.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-pitfalls-slow-down/&amp;text=The%20best%20time%20to%20fix%20issues%20is%20before%20the%20code%20is%20sent%20out%20for%20review.%20&amp;via=mgreiler&amp;related=mgreiler">The best time to fix issues is before the code is sent out for review. (Click to tweet).</a></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*dvvMg-MkjhWYFzbM-Rpekw.jpeg" alt="Image" width="922" height="615" loading="lazy"></p>
<p>_Thoroughly look through your code before submitting for review (Photo by <a target="_blank" href="https://unsplash.com/photos/uAFjFsMS3YY?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Marten Newhall</a> on <a target="_blank" href="https://unsplash.com/search/photos/magnifier?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>)_</p>
<h3 id="heading-aim-for-small-incremental-changes">Aim for small, incremental changes</h3>
<p>As a developer, you should always strive for small, incremental and coherent changes. This best practice helps when working with code revision tools, such as git or SVN.</p>
<p>Small, incremental code changes are also a crucial code review best practice as other developers must be able to understand your code change in a small amount of time.</p>
<p><em>10 lines of code = 10 issues.</em></p>
<p><em>500 lines of code = “looks fine.”</em></p>
<p><em>Code reviews.</em></p>
<p><em>- I Am Devloper (@iamdevloper)</em> <a target="_blank" href="https://twitter.com/iamdevloper/status/397664295875805184?ref_src=twsrc%5Etfw"><em>November 5, 2013</em></a></p>
<p>If several changes with different purpose happen within one code review <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">the task of code reviewing becomes more difficult</a>. This also decreases the ability of code reviewers to spot problems with the code. In several studies, we see that the value of the code review feedback decreases with the size of the change under review.</p>
<p>On the other hand, you also want to make sure the changes are coherent. Rarely code changes are too small to be sent out. It happens, but, not that often.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=The%20quality%20and%20value%20of%20code%20review%20feedback%20decrease%20with%20the%20size%20of%20the%20change.%20&amp;via=mgreiler&amp;related=mgreiler">The quality and value of code review feedback decrease with the size of the change. (Click to tweet).</a></p>
<h3 id="heading-cluster-related-changes">Cluster related changes</h3>
<p>Another code review best practice is to cluster related code changed. Imagine you plan to add some new functionality, fix a bug in another function, and refactor a class. Then, each of those changes should be a separate code review. This way, you ensure the purpose of the code change is clear to the reviewers. A clear purpose makes the reviewing job much easier and increases the feedback value.</p>
<h3 id="heading-describe-the-purpose-and-motivation-of-the-change">Describe the purpose and motivation of the change</h3>
<p>One way to make sure you invest your time right during code review preparation is to write a description of what this code change is all about. With a small note, you help the code reviewers to understand the purpose of the code change and also why you changed it. This code review best practice speeds up code review time, increases the quality and value of the feedback, and improves code review participation rates.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*f-R3JWukTtkMA20T" alt="Image" width="800" height="534" loading="lazy"></p>
<p>_Code reviewing isn’t a puzzle. Help reviewers focus on key issues by describing the code change. (Photo by <a target="_blank" href="https://unsplash.com/photos/3y1zF4hIPCg?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Hans-Peter Gauster</a> on <a target="_blank" href="https://unsplash.com/search/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>)_</p>
<p>Code reviewing isn’t a puzzle. Help reviewers focus on key issues by describing the code change. (Click to tweet).</p>
<p>Interestingly, in our studies, we observed that developers really appreciate code change description. They actually wish that more people would write descriptions. On the other hand, we saw that the same developers did not always include descriptions themselves.</p>
<p>One reason for this is that when you write the code yourself, you are so involved with the code that you think it is self-explanatory. Fact is, it is not.</p>
<p>And if you do not help the reviewers to understand the code, <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">they will not be able to provide valuable feedback</a>.</p>
<p>So, write the note, even if it just says: “Updated the API endpoint to be compliant with security regulations”.</p>
<p>How much easier did the job of reviewing the code just get with this note? Remember, code reviewing isn’t a puzzle!</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=Even%20if%20the%20code%20change%20seems%20trivial%20to%20you%2C%20add%20a%20description%2C%20so%20reviewers%20know%20what%20to%20expect.&amp;via=mgreiler&amp;related=mgreiler">Even if the code change seems trivial to you, add a description, so reviewers know what to expect (Click to tweet).</a></p>
<h3 id="heading-run-tests-before-submitting-a-code-review">Run tests before submitting a code review</h3>
<p>Yes, take the time to run the tests for your code change. Testing isn’t only a best engineering practice, but it’s also a code review best practice. Because testing your code ensures that the code actually works before you ask for feedback.</p>
<p>In addition, it shows that you respect the time of the code reviewers. It is not only embarrassing to send out code that obviously (as the tests show) is not working as expected, it also kills everyone’s productivity. So, run the tests first!</p>
<h3 id="heading-automate-what-can-be-automated">Automate what can be automated</h3>
<p>As one of the main pitfalls for code reviews is taking too long, you better follow the code review practices of automating what can be automated.</p>
<p>Use style checkers, syntax checkers and other automated tools like static analysis tools to help improve the code. This way, you make sure that code reviewers can really concentrate on giving valuable feedback and do not need to use their time to comment on issues that can be found automatically.</p>
<h3 id="heading-skip-unnecessary-reviews">Skip unnecessary reviews</h3>
<p>You read that right. Some reviews can be skipped. Obviously, it depends on your organizational policies, but if they permit it, you might consider skipping code reviews.</p>
<p>But stop before heading out and telling your team you need no code reviews anymore. Skipping code reviews is only advisable for trivial changes that do not change the logic such as commenting, formatting issues, renaming of local variable or stylistic fixes.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=Skipping%20unnecessary%20code%20reviews%20boosts%20your%20productivity.&amp;via=mgreiler&amp;related=mgreiler">Skipping unnecessary code reviews boosts your productivity. Click to tweet.</a></p>
<h3 id="heading-do-not-select-too-many-reviewers">Do not select too many reviewers</h3>
<p>You should select the right number of reviewers for your code change. If now numbers above 4 people come to your mind, I’d like you to stop right there. Because adding too many developers on code reviews does more harm than good.</p>
<p>One problem is that if you add too many developers, each one of them feels less responsible to give feedback. Another issue is that adding more people than necessary decreases your team’s productivity.</p>
<p>Some studies suggest the code review best practice of adding only two active reviewers.</p>
<p>For some code changes, you want additional experts like security experts or developers from other teams to look through the code. But, more often than not, two active reviewers are just fine.</p>
<p>Many code review tools allow notifying developers without making them mandatory reviewers. This ensures that they stay in the loop and are aware of what is happening, but removes the obligation for them to comment on your code.</p>
<h3 id="heading-add-experienced-reviewers-to-get-insightful-feedback">Add experienced reviewers to get insightful feedback</h3>
<p>Studies have shown that the most insightful feedback comes from reviewers that have worked on the code you are going to change before. They are the ones that give the most insightful feedback.</p>
<p>How often a reviewer has already reviewed code influences the ability to give useful feedback. Similar, experienced and senior developers tend to give better code review feedback.</p>
<p>But, be mindful about the workload of senior engineers, as they tend to be added as reviewers a lot.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=Developers%20that%20changed%20or%20reviewed%20pieces%20of%20the%20code%20before%2C%20give%20the%20most%20valuable%20code%20review%20feedback.&amp;via=mgreiler&amp;related=mgreiler">Developers that changed or reviewed pieces of the code before, give the most valuable code review feedback. (Click to tweet).</a></p>
<h3 id="heading-add-junior-developers-to-let-them-learn">Add junior developers to let them learn</h3>
<p>One of the code review goals is training and learning, so do not forget to include junior developers. Consider adding reviewers that are not familiar with the code base, but that would benefit from the knowledge to allow knowledge dissemination.</p>
<h3 id="heading-notify-people-that-benefit-from-this-review">Notify people that benefit from this review</h3>
<p>For some people, like project managers or team leads, receiving notification about code reviews (without being actually required to do the code review) is beneficial. But, you have to take a conscious decision on whom you gonna notify. Not everybody really cares or should care about your code review.</p>
<h3 id="heading-dont-notify-too-many-people">Don’t notify too many people</h3>
<p>Do not add everybody on the notification list. Only add people who actually benefit from the information that a code review is in the process.</p>
<p>I have seen teams, where each team member was added to each of the code review of the extended team by default (+70 people). This practice is like adding nobody to the list. Or in the worst case, you have several of your engineers spending their time looking through hundreds of code reviews to figure out if it’s relevant for them.</p>
<h3 id="heading-give-reviewers-a-heads-up-before-the-review">Give reviewers a heads-up before the review</h3>
<p>A really effective code review best practice is to let your co-workers know ahead of time that they will receive a code review soon. This code review best practice reduces turn-around times substantially.</p>
<p>So, let them know a code review is coming their way as soon as possible.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=Giving%20people%20a%20heads-up%20that%20a%20code%20review%20is%20on%20its%20way%20can%20speed%20up%20review%20time.%20&amp;via=mgreiler&amp;related=mgreiler">Giving people a heads-up that a code review is on its way can speed up review time. (Click to tweet).</a></p>
<h3 id="heading-be-open-to-suggested-changes">Be open to suggested changes</h3>
<p>Receiving unexpected comments or feedback might make you tense and defensive. Try to prepare yourself mentally and work on your ability to be open to suggestions and different viewpoints. Always start with the assumption that the reviewer had the best intention.</p>
<p>If some feedback made you uncomfortable try to sort things out as soon as possible. Sometimes it is a good idea to have more personal face-to-face conversations to resolve some issues.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*oWg1z_ShPb7yfPB1G7VzSg.jpeg" alt="Image" width="1054" height="703" loading="lazy"></p>
<p>_Don’t be defensive if confronted with unexpected feedback. (Photo by <a target="_blank" href="https://unsplash.com/photos/2VwP6rUzZQ0?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Sweet Ice Cream Photography</a> on <a target="_blank" href="https://unsplash.com/search/photos/danger?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>)_</p>
<h3 id="heading-show-respect-and-gratitude-to-the-reviewers">Show respect and gratitude to the reviewers</h3>
<p>Code reviews rise and fall with the team’s feedback culture. As a code author, show gratitude and value the received feedback. Make sure to carefully consider the reviewers’ feedback and communicate throughout the feedback cycle.</p>
<p>Tell the reviewers which actions you took and which decisions you made because of the received feedback in a respectful manner.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=Code%20review%20rises%20and%20falls%20with%20the%20quality%20of%20the%20team%27s%20feedback%20culture.&amp;via=mgreiler&amp;related=mgreiler">Code review rises and falls with the quality of the team’s feedback culture. (Click to tweet).</a></p>
<p>But, creating a great feedback culture is a two-way street. Naturally, code reviewers influence the culture a lot. So let us look closely at the code review best practices for code reviewers.</p>
<h3 id="heading-code-review-best-practices-for-code-reviewers">Code Review Best Practices for Code Reviewers</h3>
<p>Being asked to give feedback on a code review is an honor, so you want to make sure you know <a target="_blank" href="https://www.michaelagreiler.com/great-code-review-feedback/">how to give valuable code review feedback</a>.</p>
<p>During code reviews, you can not only demonstrate your skills and knowledge but also mentor other developers and contribute to the team’s success. Nothing worth than investing time in <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">code reviews and not getting valuable feedback</a>.</p>
<h3 id="heading-give-respectful-and-constructive-feedback">Give respectful and constructive feedback</h3>
<p>Even though it reads like a no-brainer, code reviews do put the code author in a vulnerable position, so you must be considerate of that.<br>Your job is it to give constructive and valuable feedback but also to do so in a respectful manner.</p>
<p>Especially using code review tooling, please reflect on how and what kind of feedback you give. It is just so easy to hurt someone feelings — especially in written form. Too often time pressure might make you give a sloppy answer that can be misinterpreted.</p>
<h3 id="heading-go-and-talk-in-person-if-necessary">Go and talk in person if necessary</h3>
<p>Code review tools and chat-tools allow us to communicate with our peers in an asynchronous and effortless way. But, there are quite a few situations where a proper human interaction, either face to face or via voice/video cannot be bet.</p>
<p>Complex issues, for example, can be much more efficient and positively resolved once you hop over to your colleague or call her and discuss it personally. The same holds true for contentious issues or sensitive matters.</p>
<p>Maybe it is a better strategy to write a private email or seek a personal discussion with the code author if you think you might hurt some feelings are make the engineer lose the face. So, whenever you face a complex issue or might hurt some feelings, rethink your communication channels and act accordingly.</p>
<h3 id="heading-ensure-traceability-for-decisions">Ensure traceability for decisions</h3>
<p>Even though less traceable conversations, such as face to face or video calls can make a big difference for team dynamics, it is important to document the discussion. Especially the code review outcome should be tracked for future reference by using traceable tools such as the code review tool.</p>
<p>The code review tool is the right communication channel for all simple matters, as it allows the whole team to follow along, and enables to look-up decisions and understand code development after the fact.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*b9Y7gwaQTuwuJHHn0WnitQ.jpeg" alt="Image" width="1152" height="768" loading="lazy"></p>
<p>_Leaving traces about your decisions and changes helps to understand code evolvement (Photo by <a target="_blank" href="https://unsplash.com/photos/GM9Xpgb0g98?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Marten Bjork</a> on <a target="_blank" href="https://unsplash.com/search/photos/trace?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>)_</p>
<h3 id="heading-always-explain-why-you-rejected-a-change">Always explain why you rejected a change</h3>
<p>Let’s be honest. Having a code change rejected isn’t something the code author will enjoy. So, it is important that you are thoughtful and explain your rejection in a polite, constructive and friendly way.</p>
<p>Explaining the reasons behind your decision does not only help the code author to learn and grow but also helps the author to understand your viewpoint. It also promotes an ongoing dialog with the author.</p>
<p>Tell the code author exactly what she has to do to get the change accepted.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=If%20you%20have%20to%20reject%20a%20code%20change%2C%20explain%20exactly%20what%20has%20to%20happen%20that%20the%20change%20can%20be%20approved.&amp;via=mgreiler&amp;related=mgreiler">If you have to reject a code change, explain exactly what has to happen that the change can be approved. (Click to tweet).</a></p>
<h3 id="heading-code-review-best-practices-for-boosting-productivity">Code review best practices for boosting productivity</h3>
<p>Some of the biggest challenges during code reviews, for both the code author and the code reviewer are time constraints.</p>
<p>As a reviewer, you might find it challenging to take time out of your daily tasks to review the code of your peers. But, code reviews can be very beneficial to you and the team if done in the right way.</p>
<h3 id="heading-integrate-code-review-into-your-daily-routine">Integrate code review into your daily routine</h3>
<p>Structure your day-to-day business in a way that you set dedicated time aside just for doing code reviews. For example, plan to work on code reviews every day from 11 to 12 AM.</p>
<p>This way you make sure you can account the time for code reviews, and also make it an anticipated activity for you and your team. This schedule will come in handy every time you have a reflection on your work progress or an evaluation of your work.</p>
<h3 id="heading-reduce-task-switching-as-it-kills-productivity">Reduce task switching as it kills productivity</h3>
<p><a target="_blank" href="https://www.michaelagreiler.com/developer-productivity/">Switching from one task to another is costly</a>. Knowing you do not stop whatever you do every time a code review comes along your way ensures you can work more focused.</p>
<p>Which time slots work depends on your workload, the number of code reviews you have to perform as well as on the time those reviews normally come in. In some settings, your team benefits from two (shorter) scheduled reviewing times, such as in the morning and before you leave the office. This way, your peers do not have to wait for your feedback too long.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*WQJJWck316aARPb0jFk97w.png" alt="Image" width="1024" height="512" loading="lazy"></p>
<p>_Task switching kills productivity (Photo by <a target="_blank" href="https://unsplash.com/photos/1K9T5YiZ2WU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Tim Gouw</a> on <a target="_blank" href="https://unsplash.com/search/photos/problem?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>)_</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=%20Task%20switching%20kills%20productivity.%20So%20have%20dedicated%20code%20review%20times.%20%23codereview%20&amp;via=mgreiler&amp;related=mgreiler">Task switching kills productivity. So have dedicated code review times.</a> <a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=%20Task%20switching%20kills%20productivity.%20So%20have%20dedicated%20code%20review%20times.%20%23codereview%20&amp;via=mgreiler&amp;related=mgreiler">#codereview</a> <a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=%20Task%20switching%20kills%20productivity.%20So%20have%20dedicated%20code%20review%20times.%20%23codereview%20&amp;via=mgreiler&amp;related=mgreiler">(Click to tweet)</a></p>
<h3 id="heading-give-feedback-in-a-timely-manner">Give feedback in a timely manner</h3>
<p>It is not advisable to jump right into a code review, whenever the notifications pop up, because of context switching costs. Still, it has several advantages for you and the code author to review the code in a timely matter.</p>
<p>Giving feedback as soon as possible ensures that the code author is not blocked by waiting for feedback. Also, if the author has to wait too long, it becomes harder for her or him to remember the changes and incorporate the feedback. Remember long waiting times are a number one <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">code review pitfall</a>.</p>
<p>Being one of the first reviewers (especially if there are quite a few) also ensures your effort looking through the code <a target="_blank" href="https://www.michaelagreiler.com/great-code-review-feedback/">actually adds value</a>. If you are the fifth person inspecting the code, chances are you are not going to add new insights anymore. If that happens frequently, you should implement the code review best practice for selecting fewer reviewers.</p>
<h3 id="heading-review-frequently-not-in-a-big-bang-fashion">Review frequently not in a big bang fashion</h3>
<p>Research shows that you can give better quality feedback if you review frequently and therefore less changes at a time. That means that you do not wait until several code reviews pile up to look through them in one go. Instead, you stick to your schedule and review one code review (or even parts of one if it is a larger code review) at a time.</p>
<p>If code reviews are generally too large and take too long, you can suggest the code review best practices for small, incremental and coherent changes to the code review authors.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-best-practices/&amp;text=Give%20better%20quality%20feedback%20to%20code%20reviews%20by%20not%20letting%20them%20pile%20up.&amp;via=mgreiler&amp;related=mgreiler">Give better quality feedback to code reviews by not letting them pile up. (Click to tweet).</a></p>
<h3 id="heading-focus-on-core-issues-less-nit-picking">Focus on core issues, less nit-picking</h3>
<p>Your goal as a reviewer should be to help with core issues, such as bugs, architectural problems, structural problems or problems that will lead to maintainability issues.</p>
<p>Obviously, if you see typos, badly named variables or styling issues, you might also point that out. Still, this is not your main tasks and, understandably, over <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">discussing minor issues isn’t valuable to code authors.</a></p>
<h3 id="heading-use-a-review-checklists">Use a review checklists</h3>
<p>Another code review best practice is to use a systematic approach for code reviews. A code review checklist can speed-up and improve your code review performance. Instead of making one from scratch, download a ready-made list and customize it to fit your team’s practices and your needs. Be sure to look for a checklist that is tailored towards your technology stack. </p>
<h3 id="heading-code-review-best-practices-checklist">Code review best practices checklist</h3>
<p>Now you know all the code review best practices to make the most out of code reviews. If you enjoyed this post, consider subscribing to my email list.</p>
<p>I prepared an exclusive <a target="_blank" href="https://www.michaelagreiler.com/code-review-e-book/">Code Review e-Book</a> for my e-mail subscribers to help you remember the code review best practices. I also added other great insights and summaries about code reviews. Get the 12 page insights to code reviews now. Not a subscriber yet? Just sign-up.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*HBwTGSldWHSf2u7yZ-8X1A.jpeg" alt="Image" width="860" height="561" loading="lazy"></p>
<h2 id="heading-want-more-on-code-reviews">Want more on Code Reviews?</h2>
<p>Check out <a target="_blank" href="https://www.michaelagreiler.com/code-review-best-practices/">proven code review best practices</a>, learn about which <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">code review pitfalls</a> you should avoid, and also how to <a target="_blank" href="https://www.michaelagreiler.com/great-code-review-feedback/">boost your code review value with great feedback</a>.</p>
<p>To <strong>stay in the loop</strong> and never miss a blog post, <strong>sign-up</strong> to my email list and get the <strong>exclusive code review e-book.</strong> You can request the <a target="_blank" href="https://www.michaelagreiler.com/code-review-e-book/">Code Review e-Book here</a>.</p>
<h3 id="heading-you-find-me-on-twitter">You find me on Twitter</h3>
<p><a target="_blank" href="https://twitter.com/mgreiler">Let's connect on Twitter</a> to discuss software engineering topics and code reviews there.</p>
<hr>
<p><em>Originally published at</em> <a target="_blank" href="https://www.michaelagreiler.com/code-review-best-practices/"><em>https://www.michaelagreiler.com</em></a> <em>on May 2, 2019.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A zen manifesto for effective code reviews ]]>
                </title>
                <description>
                    <![CDATA[ By Jean-Charles Fabre When you are coding, interruptions really suck. You are in the zone, flying high, killing it. And BAM… meeting, standup, insert interruption… Great! In that context, code reviews can be perceived as another hurdle to productivit... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-zen-manifesto-for-effective-code-reviews-e30b5c95204a/</link>
                <guid isPermaLink="false">66c3437452e2abc555bfcbf7</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ teamwork ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 02 May 2019 20:30:34 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*Pt73-k3YNsgjnOP8" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jean-Charles Fabre</p>
<p>When you are coding, interruptions <strong>really</strong> suck.</p>
<p>You are in the zone, flying high, killing it. And BAM… meeting, standup, <em>insert interruption</em>… Great!</p>
<p>In that context, code reviews can be perceived as another hurdle to productivity.</p>
<p>And frankly I can relate to that.</p>
<h4 id="heading-code-reviews-are-hard">Code reviews are hard.</h4>
<p>Not only do you need to stop what you are currently doing, you also need to immerse yourself into somebody else’s code. It takes <em>a lot</em> of energy just to switch your focus.</p>
<h4 id="heading-code-reviews-are-time-consuming">Code reviews are time consuming.</h4>
<p>According to <a target="_blank" href="https://insights.stackoverflow.com/survey/2019#development-practices">Slack Overflow’s 2019 survey</a>, 56.4% of developers spend 4 hours or more per week performing code reviews. And it can represent up to 20% of a developer’s week!</p>
<h4 id="heading-code-reviews-are-frustrating">Code reviews are frustrating.</h4>
<p>As a submitter, it can be frustrating to get your pull request rejected, to wait hours if not days for a review. As a reviewer, code reviews can feel like an obstacle to a good productive day.</p>
<p>Yes, code reviews can sometimes be hard, time consuming and frustrating.</p>
<p>But they’re also a good way to <strong>share knowledge, prevent bugs, and reinforce your company’s culture</strong> among other things.</p>
<p>What follows is a manifesto for submitters and reviewers to bring back peace of mind into code reviews. ?</p>
<h3 id="heading-a-submitters-manifesto">A Submitter’s Manifesto</h3>
<p>As a submitter, here’s what you can do to increase your chances of getting your pull requests approved in a timely manner.</p>
<h4 id="heading-submit-when-youre-done">Submit when you’re done.</h4>
<p>It sounds obvious, I know. But the thing is — most of the time if the machine doesn’t work, it’s not because it’s broken… it’s because it’s not plugged in!</p>
<p>Very small details can make a big difference on how your work is perceived. And you don’t want your colleagues to feel they are investing time and effort into reviewing work in progress code.</p>
<blockquote>
<p>Me: “It was just a missing !”</p>
<p>You: “Yeah I know, but the whole thing didn’t work and it took me 20 minutes to spot it.”</p>
</blockquote>
<p>So here’s what you can do:</p>
<ul>
<li><strong>Self-test your code.</strong> Include WIP in title or label if you’re not done yet.</li>
<li><strong>Self-review your code.</strong> Use the diff report of your code editor or versioning tool to catch mistakes.</li>
<li><strong>Make sure the tests of your CI are green</strong> before assigning a reviewer, this will save them time.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/5O1kil0Dxt4qNqUrwFEx6sfPRoyjWHqdD7df" alt="Image" width="400" height="300" loading="lazy">
_Don’t be this guy, obviously ? (G[iphy)](https://giphy.com/" rel="noopener" target="<em>blank" title=")</em></p>
<h4 id="heading-make-smaller-pull-requests">Make smaller pull requests</h4>
<p>I get it, it’s a big, important and complex feature and you might be tempted to submit a long pull request. Yet, most of the time, you are better off submitting smaller pull requests.</p>
<p>Code reviews take energy. Big code reviews even more. Don’t impose on your team a <strong>developer vs food</strong> challenge every time they review your code.</p>
<p>Be nice, cut it in smaller chunks. You are also doing yourself a favor:</p>
<ul>
<li><strong>You’ll get more qualitative feedback.</strong> The longer a pull requests the fewer qualitative feedback per line of code you’ll receive. Keep your pull request small (not too small either) and you’ll increase your chances of getting great feedback on it.</li>
<li><strong>You’ll get them approved faster.</strong> It’s a win-win, by breaking down your work into smaller pull requests, you increase your chances of getting them approved faster.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/irUe6ZKsZwrWHJwrIqGsymee1oo2cq0mMEBs" alt="Image" width="622" height="340" loading="lazy">
<em>LGTM ?</em></p>
<p><em>For the nerds out there, here’s a <a target="_blank" href="https://smartbear.com/learn/code-review/best-practices-for-peer-code-review/">study</a> conducted on a Cisco programming team. It shows that after 400 LoC the ability to find defects diminishes pretty dramatically.</em> ?</p>
<p>The next principle helps with keeping pull requests size under control.</p>
<h4 id="heading-narrow-the-scope">Narrow the scope</h4>
<p>The scope of your pull request should be <strong>simple, unique and well-defined.</strong> That might be a feature, a user-story or a bug fix.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hVle2Ce9EvgyfDMvplMuSbg3FpXTF9CN55-j" alt="Image" width="800" height="253" loading="lazy">
<em>Making the world a better place, one LoC at a time ?</em></p>
<p>One way to think about it is that reviewers have a <strong>limited number of “attention credits”</strong> (like everybody). Every time they focus on something, they use 1 credit. What happens when they have 0 left?</p>
<blockquote>
<p>LGTM ?</p>
</blockquote>
<p>Do what you can to reduce the noise around your work. Be mindful of the reviewer’s attention span.</p>
<p>For instance, <strong>avoid void changes</strong> (like skipping lines). They don’t add any value and complicate the code review.</p>
<p>Similarly, if your pull request changes the <em>behavior</em>, don’t include changes to <em>formatting</em>. Conversely, if your pull request changes <em>formatting</em>, don’t include changes that affect the <em>behavior</em>. They might be overlooked by the reviewer.</p>
<h4 id="heading-give-context">Give context</h4>
<p>Think about your pull request as documentation for new comers. Guide the reader with context.</p>
<p>Start with a <strong>self-explanatory title.</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-rZMLs8GynJOJMIB2C1ZTf1sa22RdiccZaw2" alt="Image" width="800" height="203" loading="lazy">
<em>Good title taken from the xg2xg repo ?</em></p>
<p>Then<strong>, write a clear description</strong> to explain what you are doing and why are you doing it. What is the purpose of this pull request? Why is this change necessary? How did you approach this problem?</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/QfB-BL9MLi1SnpFMByRDtEoGcLsnhYqAbtUZ" alt="Image" width="800" height="250" loading="lazy">
<em>Good example of explaining why the change is necessary taken from react repo</em></p>
<p>The description is also is great place to <strong>point out unresolved issues and open questions.</strong> Reviewers might have suggestions to unblock you.</p>
<p>Are you working on a visible part of the product? <strong>Screenshots</strong> can help get your point across faster.</p>
<ul>
<li>Show before/after differences.</li>
<li>Use colored arrows.</li>
<li>Add screen recordings if you feel like it :)</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/BMOl9N0I3lUy6RFHW6koF-AHvUaS3zj8ZJzz" alt="Image" width="800" height="772" loading="lazy">
<em>From react repository</em></p>
<p>Finally, write <strong>information signs</strong> along the way to guide the reviewer through your reasoning.</p>
<p>Keep a clean commit history to make it easier for the reviewer to follow your step. Use comments to point out alternatives you explored.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/parB1wMVMrNCIoUjqixRqCHHJ08HMuE2FEb8" alt="Image" width="442" height="185" loading="lazy">
<em>Good comment example from Lodash</em></p>
<h4 id="heading-welcome-feedback">Welcome feedback ?</h4>
<p>Rejection hurts.</p>
<p>Truth be told, <strong>code rejection hurts even more.</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Hw2grLkrNu8rHBcUJxqHt9v71eUAPRVwiBnn" alt="Image" width="776" height="167" loading="lazy">
<em>I’m seeing this a lot!</em></p>
<p>It’s alright. Don’t take it personally.</p>
<p>Comments and suggestions are an opportunity to learn and become a better software engineer ?</p>
<h3 id="heading-a-reviewers-manifesto">A Reviewer’s Manifesto</h3>
<p>Congrats on making it this far! Now let’s look at a few principles that might help you become a better reviewer ?</p>
<h4 id="heading-adopt-the-right-mindset">Adopt the right mindset</h4>
<p>There is no scenario where a team can benefit from a reviewer being mean or patronising. <strong>Be</strong> <strong>kind</strong>. Period.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xLy0yeaSYmd9HAUIDvcN892VA7ehvPvD4b5p" alt="Image" width="544" height="291" loading="lazy">
_What are you trying to say my friend? ([Giphy](https://giphy.com/" rel="noopener" target="<em>blank" title="))</em></p>
<p>Want to make code reviews more exciting?</p>
<p>Look for something you can <strong>learn</strong> from this review. A new library, a new method, a new concept, a simpler way to do things. What piece of knowledge will you extract from it?</p>
<p>If you are the more experienced developer, is there something you can <strong>share</strong>? How can you use this review to transfer knowledge to the submitter? How can you help them become a better software engineer?</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/CA98J-KCq3p77rFiVmv4W5ojoQnUnBEvgNOn" alt="Image" width="669" height="425" loading="lazy">
<em>Thanks for the tip mate! ?</em></p>
<h3 id="heading-how-to-actually-do-a-code-review">How to actually do a code review</h3>
<h4 id="heading-what-to-review"><strong>What to review</strong></h4>
<p>What am I even supposed to look for? Without clear guidance on what and how to review, it’s easy to get lost. Here is what you can do.</p>
<p>First off, <strong>check the purpose</strong>. Is this code accomplishing what it is meant to do? Are there parts of the new code that are not clear to you? Ask clarifying questions. The code is easily testable? Test it. There’s no need to go beyond if this square is not checked.</p>
<p>Ok now that the code works, time to focus on the <strong>implementation</strong>.</p>
<p>Think about how you would have approached this problem. Would you have done it differently? Is there potential for refactoring or abstraction? Is this re-inventing the wheel? Is this using standard code patterns?</p>
<h4 id="heading-what-to-not-review"><strong>What to not review</strong></h4>
<p>Because a piece of code has room for improvement, it doesn’t always mean it needs to be improved.</p>
<p>At the end of the day, code reviews are a tradeoff between <strong>quality</strong> and <strong>velocity</strong> and depending on the scope and stage of the project it might make sense to let a few things behind.</p>
<p>Similarly, you shouldn’t be doing things that can be automated. Let your favorite linter hunt for the missing semicolons and extra indentation. No need for an endless debate on tabs vs spaces.</p>
<p>Finally, don’t increase the scope of the pull request. If you think of new things that need to be done, create a new pull request /task for that matter.</p>
<h4 id="heading-review-in-a-timely-manner">Review in a timely manner</h4>
<p>There are at least 3 good reasons to review pull requests in <strong>hours rather than days.</strong></p>
<ul>
<li>The submitter can move to the next task quicker</li>
<li>It reduces context switching cost</li>
<li>It reduces the risk of merge conflicts between branches.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/XVktldbIDiDVoWG2GCGSIo4ppuEMv49qFU5m" alt="Image" width="800" height="53" loading="lazy">
<em>Opened 6 years ago. Be right back ?</em></p>
<p><strong>Disclaimer:</strong> I just released <a target="_blank" href="https://www.gitrise.com/">GitRise</a>, a tool that helps teams using GitHub &amp; Slack review pull requests faster. I do think it can help with this one :)</p>
<h3 id="heading-how-to-give-feedback-in-a-code-review">How to give feedback in a code review?</h3>
<p>When giving a feedback, the form matters as much as the substance.</p>
<p>Did you know that in written communication, <strong>neutral content looks more negative than it actually is?</strong> Beware of this bias and include emojis when needed to get the tone right in your comments.</p>
<p>Also, most of the time, even if you are pretty sure that there is a better way to do something, you are better off <strong>asking a question rather than requesting a change</strong>. Plus, questions sound less aggressive.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/YDgB2aLyBwOvo21kVLfvYdlKdlTioV1UUP4a" alt="Image" width="799" height="517" loading="lazy">
<em>Example from ember.js repo</em></p>
<p><strong>Finally, reward when things are done right.</strong> Code reviews are also a great place to give kudos to colleagues for doing a good job. Be creative and fun :)</p>
<p>? Congrats on reaching the end of this blog post!</p>
<p>? Thanks a lot for reading and let me know if you have any comments!</p>
<p>? I <strong>just released G<a target="_blank" href="https://www.gitrise.com/">itRise,</a> a tool that creates pull requests reminders for teams using Slack &amp; GitHub. G</strong>ive it a try if you want. Looking forward to your feedback.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to avoid code review pitfalls that slow your productivity down ]]>
                </title>
                <description>
                    <![CDATA[ By Michaela Greiler Code reviewing is an engineering practice used by many high performing teams. And even though this software practice has many advantages, teams doing code reviews also encounter quite a few code review pitfalls. In this article, I... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-avoid-code-review-pitfalls-that-slow-your-productivity-down-b7a8536c4d3b/</link>
                <guid isPermaLink="false">66d46042d7a4e35e38434995</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 06 Apr 2019 18:36:01 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*_9ClYv6zGLGlJJpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Michaela Greiler</p>
<p>Code reviewing is an engineering practice used by many high performing teams. And even though this software practice has many advantages, teams doing code reviews also encounter quite a few code review pitfalls.</p>
<p>In this article, I explain the main code review pitfalls you should be aware of to ensure code reviewing does not slow your team down. Knowing which pitfalls and problems arise can help you to ensure a productive and effective code review experience. Those findings are based on a <a target="_blank" href="https://www.michaelagreiler.com/wp-content/uploads/2019/03/Code-Reviewing-in-the-Trenches-Understanding-Challenges-Best-Practices-and-Tool-Needs.pdf">survey we conducted at Microsoft with over 900 participants</a>.</p>
<h3 id="heading-a-typical-code-review-process">A typical code review process</h3>
<p>A typical tool-based code review process looks roughly like this: Once the developer has finished a piece of code, they prepare the code for being submitted for review. Then, they select reviewers who are notified about the review. The reviewers then review the code and give comments. The author of the code works on those comments and improves and changes the code accordingly. Once everybody is satisfied, or an agreement is reached, the code can be checked into the code base.</p>
<p>In another post, I described how <a target="_blank" href="https://www.michaelagreiler.com/code-reviews-at-microsoft-how-to-code-review-at-a-large-software-company/">a typical code review process looks like at Microsoft.</a></p>
<h3 id="heading-code-reviewing-isnt-always-a-smooth-process">Code reviewing isn’t always a smooth process</h3>
<p>These steps read like a smooth process. But, like everything, in practice, things tend to be more complicated than anticipated. During the code review process there a quite a few pitfalls that can reduce the positive experience with code reviews for the whole team. If not done correctly, code reviewing can also take its tolls on the whole team’s productivity. So, let’s have a look at the difficulties and pitfalls of code reviews.</p>
<p>The two main types of code review pitfalls are about the time spent on code reviews, and the value code reviews provide.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-pitfalls-slow-down/&amp;text=Be%20aware%20of%20code%20review%20pitfalls.%20Otherwise%2C%20code%20reviews%20can%20slow%20your%20team%20down.%20&amp;via=mgreiler&amp;related=mgreiler">Be aware of code review pitfalls. Otherwise, code reviews can slow your team down. Click To Tweet</a></p>
<h3 id="heading-waiting-for-code-review-feedback-is-a-pain">Waiting for code review feedback is a pain</h3>
<p>One of the main pitfalls code authors face is to receive feedback in a timely manner. Waiting for the comments to come in and not being able to work on the code in the meanwhile can be a huge problem. Even though developers can pick up other tasks to work on, if the code review takes too long, it impacts the developer’s productivity and also the developer’s satisfaction.</p>
<p>But, why does the code review feedback take so long?</p>
<h3 id="heading-developers-have-to-juggle-several-responsibilities">Developers have to juggle several responsibilities</h3>
<p>Well, code reviewing is not the only task the code reviewer has to perform. On the contrary, code reviewing — even though it can take a significant amount of time of a developer’s day-to-day work — is only one part of the responsibilities and tasks of a developer. So, it is very likely that the code reviewer is engaged in other activities and has to stop or finish those first before looking at the code review.</p>
<p>If the timing is not ideal, and especially if the code reviewer hasn’t anticipated this change coming along, chances are, it takes a while before they look at the review. Remote teams also have to be aware of time differences. Otherwise, code reviews might even take longer.</p>
<h3 id="heading-developers-face-problems-if-code-reviews-are-not-counted-as-actual-work">Developers face problems if code reviews are not counted as actual work</h3>
<p>Time constraints are real, and they affect both, the code reviewer and the author of the code. Doing a proper code review takes time. If teams want developers to do code reviews but do not value or count the time developers spend on code reviews, this becomes a real problem.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/iO9crhcrMsfcZYZnlcTayHSfN647zOBnmRQs" alt="Image" width="800" height="400" loading="lazy">
_You have to value and plan for the time spent doing code reviews.<br>Photo by [Unsplash](https://unsplash.com/photos/vcPtHBqHnKk?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="_blank" title=""&gt;freestocks.org on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="<em>blank" title=")</em></p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-pitfalls-slow-down/&amp;text=You%20can%27t%20expect%20quality%20code%20reviews%2C%20if%20you%20don%27t%20value%20the%20time%20a%20developer%20spends%20on%20them.&amp;via=mgreiler&amp;related=mgreiler">You can’t expect quality code reviews if you don’t value the time a developer spends on them. Click To Tweet</a></p>
<h3 id="heading-not-rewarding-code-reviewing-efforts-and-performance">Not rewarding code reviewing efforts and performance</h3>
<p>It does not help to claim to value code reviews if you do not reward the effort developers spend on this task. Many companies focus on rewarding developers for the amount of code they write or the features they develop. This decreases the motivation and the ability of developers to do a good job helping each other (which includes code reviewing). Code review effort and performance should be a cornerstone for performance evaluation or promotion decisions.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-pitfalls-slow-down/&amp;text=If%20you%20want%20your%20team%20to%20do%20code%20reviews%20well%2C%20reward%20them%20for%20their%20work.%20&amp;via=mgreiler&amp;related=mgreiler">If you want your team to do code reviews well, reward them for their work. Click To Tweet</a></p>
<h3 id="heading-social-factors-and-team-dynamics">Social factors and team dynamics</h3>
<p>But waiting on a code review had not always to do with the lack of time or missing reward system. Due to its social character, delayed reviews can be due to insecurities or team dynamics. Especially if the code review is overwhelming, or if the reviewer is new to the code, doing a code review can be overwhelming:</p>
<blockquote>
<p><em>I’m expected to participate, but I’m not quite sure how. I’ll wait until someone else starts. — study participant</em></p>
</blockquote>
<h3 id="heading-large-reviews-are-hard-to-review">Large reviews are hard to review</h3>
<p>Another significant code review pitfall is large reviews. Imagine you are the reviewer, and you just got this review. You think, well, I am quickly going to look at that, but once you open the review, you see this large code change. Several files have been changed, and all changes tangle throughout the code base. What’s your first reaction?</p>
<p>Probably: holy cow!</p>
<p>That’s right. That is exactly what we saw when analyzing thousands of code reviews. Not only does review time increase with the size of the code change, but also feedback quality decreases. Well, that’s probably understandable.</p>
<blockquote>
<p><em>10 lines of code = 10 issues.</em></p>
<p><em>500 lines of code = “looks fine.”</em></p>
<p><em>Code reviews.</em></p>
<p>_— I Am Devloper (@iamdevloper) <a target="_blank" href="https://twitter.com/iamdevloper/status/397664295875805184?ref_src=twsrc%5Etfw">November 5, 2013</a>_</p>
</blockquote>
<p>Large code changes are just incredibly difficult to review. If, in addition, the code reviewer is not that familiar with the part of the code base the change took place in, reviewing can quickly become a nightmare.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-pitfalls-slow-down/&amp;text=Large%20code%20reviews%20are%20hard%20to%20review.%20The%20quality%20of%20the%20review%20decreases%20with%20the%20size%20of%20the%20change%2C%20thus%20limiting%20the%20value%20teams%20get%20out%20of%20from%20code%20reviews.%20&amp;via=mgreiler&amp;related=mgreiler">Large code reviews are hard to review. The quality of the review decreases with the size of the change, thus limiting the value teams get out of from code reviews. Click To Tweet</a></p>
<h3 id="heading-understanding-code-changes-needs-some-guidance">Understanding code changes needs some guidance</h3>
<p>Understanding code changes, and especially the motivation for a code change, is another code review pitfall many reviewers face. If there is no description explaining the purpose of the change, code reviewing becomes much harder. We saw in the study that if the code reviewer does not understand the code change, or if she is overwhelmed by the amount of change, she cannot give insightful feedback.</p>
<blockquote>
<p><em>It’s just this big incomprehensible mess. Then you can’t add any value because they are just going to explain it to you and you’re going to parrot back what they say.</em></p>
<p><em>— interviewed developer13</em></p>
</blockquote>
<h3 id="heading-not-getting-valuable-feedback-decreases-the-developers-benefit-from-and-motivation-for-code-reviews">Not getting valuable feedback decreases the developers’ benefit from and motivation for code reviews</h3>
<p>Without doubt, spending the time on code reviews and not getting useful feedback back is a problem. Even though the team might still benefit from the knowledge transfer, the developer’s motivation to do code reviews and the benefits from code reviews decrease when they do not get valuable feedback.</p>
<p>There are several reasons why reviewers do not or can’t give insightful feedback. It can be that the code reviewer did not have the right expertise. Another common reason is that the reviewer did not have enough time to look thoroughly through the change.</p>
<p>Maybe the code reviewer does not understand the code. It can also be that the code reviewer does not know what issues to look for. <a target="_blank" href="https://docs.microsoft.com/en-us/azure/devops/learn/devops-at-microsoft/boosting-code-reviews-useful-comments">Understanding what makes for valuable code review feedback</a> and implementing best practices mitigates this pitfall.</p>
<h3 id="heading-once-the-main-discussion-is-about-styling-you-need-to-act">Once the main discussion is about styling, you need to act</h3>
<p>Another problem that can happen during a code review is called bikeshedding. Bikeshedding means that developers focus on smaller issues and start disputing minor issues and overlook the serious ones.</p>
<p>The reasons for that are manifold. Common behind the scenes challenges that lead to bikeshedding is that developers do not understand the code change or that they do not have enough time for the code reviews. Sometimes bikeshedding can be a sign that there are issues with the team dynamics.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-review-pitfalls-slow-down/&amp;text=If%20people%20dispute%20about%20minor%20issues%20during%20code%20reviews%2C%20you%20have%20to%20take%20a%20look%20at%20the%20underlying%20issue.%20Time%20pressure%2C%20too%20large%20reviews%2C%20rivalry%3F%20&amp;via=mgreiler&amp;related=mgreiler">If people dispute about minor issues during code reviews, you have to take a look at the underlying issue. Time pressure, too large reviews, rivalry? Click To Tweet</a></p>
<h3 id="heading-reaching-consensus-might-need-a-face-to-face-discussion">Reaching consensus might need a face-to-face discussion</h3>
<p>Sometimes it can happen that it is hard to reach a consensus. This can occur between code reviewer and code author, or also between several code reviewers directly. Such situations must be handled carefully as team dynamics are closely connected to these happenings. Communication via tools and in written form can aggravate this problem. If there seems to be any tension, or contentious issues to discuss, switching to face-to-face (either in person or via a video call) might be a good idea.</p>
<h3 id="heading-the-benefits-of-code-review-outweigh-the-effort">The benefits of code review outweigh the effort</h3>
<p>I hope this list of code review pitfalls did not change your mind about code reviews. Because, the good news is that if you are aware of the code review pitfalls and counteract them, code reviews are a very beneficial engineering technique. And, there are even more proven ways to work effectively with code reviews.</p>
<h3 id="heading-code-review-best-practices">Code review best practices</h3>
<p>In the next blog post in <a target="_blank" href="https://www.michaelagreiler.com/code-review-blog-post-series/">this code review series</a>, I show best practices to help to minimize the code review pitfalls and challenges and ensure your team gets the best out of the code review practice. So keep on reading. To be notified when I publish the next post, follow me on <a target="_blank" href="https://twitter.com/mgreiler">twitter</a>.</p>
<p>I prepared an exclusive Code Review e-Book for my newsletter subscribers. So make sure <a target="_blank" href="https://www.michaelagreiler.com/code-review-e-book/">you subscribe to my email list</a> and secure your Code Review e-Book including a handy cheat sheet of code review best practices.</p>
<p><em>Originally published at <a target="_blank" href="https://www.michaelagreiler.com/code-review-pitfalls-slow-down/">https://www.michaelagreiler.com</a> on April 6, 2019.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How code reviews work at Microsoft ]]>
                </title>
                <description>
                    <![CDATA[ By Michaela Greiler Have you ever wondered how one of the largest software companies world wide ensures high quality code through code reviewing? So did I. That’s why together with my colleagues at Microsoft, we investigated how code reviews are done... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-code-reviews-work-at-microsoft-4ebdea0cd0c0/</link>
                <guid isPermaLink="false">66d46040787a2a3b05af43e4</guid>
                
                    <category>
                        <![CDATA[ code review ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 27 Mar 2019 08:00:57 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*GWGY5OFKBHznk598" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Michaela Greiler</p>
<p>Have you ever wondered how one of the largest software companies world wide ensures high quality code through code reviewing?</p>
<p>So did I. That’s why together with <a target="_blank" href="https://www.michaelagreiler.com/category/code-reviews/#ms-peers">my colleagues</a> at Microsoft, we investigated how code reviews are done at our company. Is it a common practice? Are developers required to do code reviews? And which tools do they use?</p>
<p>Let’s find out in this post, which is part of a <a target="_blank" href="https://www.michaelagreiler.com/code-review-blog-post-series/"><strong>larger blog post series about code reviewing</strong></a>.</p>
<p>To begin with, let me give you some key information about Microsoft. <a target="_blank" href="https://news.microsoft.com/facts-about-microsoft/#EmploymentInfo">Microsoft has around 140,000 employees</a>. Approximately 44% of them, that means over 60,000 employees, are engineers. Several products such as Office, Visual Studio or Windows are developed by thousands of engineers that work on the same code base simultaneously.</p>
<p>I say all this to give you some context and perspective of what it means to coordinate and manage the software development process. As you can imagine, it is a non trivial task to ensure code developed by different sub teams actually works perfectly together. And code reviews play a big role at Microsoft to allow smooth collaboration at such a large scale.</p>
<h3 id="heading-code-reviews-at-microsoft-are-an-integral-part-of-the-development-process">Code reviews at Microsoft are an integral part of the development process</h3>
<p>One of the important facts when it comes to code reviews at Microsoft is that it is a highly adopted engineering practice. Thousands of engineers perceive it as a great best practice. And most high-performing teams spend a lot of time doing code reviews.</p>
<p><a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-reviews-at-microsoft-how-to-code-review-at-a-large-software-company/&amp;text=%20At%20Microsoft%2C%20code%20reviewing%20is%20an%20highly%20adopted%20engineering%20practice%20and%20perceived%20as%20a%20great%20best%20practice.%20%20&amp;via=mgreiler&amp;related=mgreiler">At Microsoft, code reviewing is a highly adopted engineering practice and perceived as a great best practice. Click To Tweet</a>.</p>
<h3 id="heading-investigating-code-reviews-at-microsoft">Investigating code reviews at Microsoft</h3>
<p>Because code reviews play such an important role in the Microsoft development process, it was an ideal target for us to dig deeper and really understand the benefits and drawbacks of this practice. <a target="_blank" href="https://www.michaelagreiler.com/wp-content/uploads/2019/03/Code-Reviewing-in-the-Trenches-Understanding-Challenges-Best-Practices-and-Tool-Needs.pdf">In a large scale study on code reviews at Microsoft,</a> we interviewed, observed and surveyed more than 900 developers about their code review practices.</p>
<p>Our aim was to understand how exactly code reviews are done at Microsoft, which challenges developers face while doing code reviews, and to distill which best practices they develop to overcome those challenges.</p>
<h3 id="heading-what-can-you-learn-from-code-review-practices-at-microsoft">What can you learn from code review practices at Microsoft?</h3>
<p>Most of the lessons learned are as valuable to smaller teams and organizations as they are for large teams and large organizations. In case your team does not do code reviews yet, I distilled our findings in a way that shows you the benefits of the practice. I also explain how the code review life cycle looks like so you can incorporate that practice in your own development process.</p>
<p>If your team already does code reviews, you can compare your practice with the code review practice at Microsoft. Does your code review lifecycle look different? In later posts, you learn from the challenges that arise doing code reviews and the best practices. With this information you can set out to see if your team already implements all the best practices I present and overcome challenges. But, let’s get started:</p>
<h3 id="heading-how-often-do-microsoft-engineers-perform-code-reviews">How often do Microsoft engineers perform code reviews?</h3>
<p>In this study, 36% of the developers said they perform code reviews multiple times a day. Another 39% of the developers said they do code reviews at least once per day. 12% do code reviews multiple times a week, and only 13% said they did not do a code review in the past week.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/K3jMFIgEEHEn8kADlr7CUZnBrg-4rFnFYtIj" alt="Image" width="595" height="373" loading="lazy"></p>
<p>This means that developers at Microsoft spend a significant amount of their time on code reviews. So it is important to make sure that this time spent is worthwhile. But, which benefits does code reviewing provide?</p>
<h3 id="heading-which-benefits-does-code-reviewing-provide">Which benefits does code reviewing provide?</h3>
<p>The most important reasons developers mentioned as benefits of code reviews are to improve the code quality and to find defects in the code. Another important benefit of code reviews is knowledge transfer.</p>
<p>Knowledge transfer means that team members that review each others code, become familiar with a larger part of the code base. But, it also means that best practices are developed within the team. Another advantage is that new team members and junior developers can learn and improve their coding skills while reviewing or getting feedback.</p>
<p>If developers discuss alternative solutions during code reviews, it not only improves the code base, but has also a learning effect for all involved. Learning, mentoring and self-improvement are therefore all reasons code reviewing is perceived as such a beneficial practice at Microsoft.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/J4xPSMk926cmcD0tTDWcePiZ4aGfxMDDUQfn" alt="Image" width="793" height="421" loading="lazy"></p>
<p>Developers do code reviews to improve the code, to find defects, but mostly to increase the knowledge transfer amongst team members and for the learning effects. <a target="_blank" href="https://twitter.com/intent/tweet?url=https://www.michaelagreiler.com/code-reviews-at-microsoft-how-to-code-review-at-a-large-software-company/&amp;text=Developers%20do%20code%20reviews%20to%20improve%20the%20code%2C%20to%20find%20defects%2C%20but%20mostly%20to%20increase%20the%20knowledge%20transfer%20amongst%20team%20members%20and%20for%20the%20learning%20effects.&amp;via=mgreiler&amp;related=mgreiler">Click To Tweet</a>.</p>
<h3 id="heading-but-how-does-a-developer-typically-do-code-reviews">But how does a developer typically do code reviews?</h3>
<p>Code reviews can be performed in many ways. Sometimes, it is as informal as one developer walking over to another developer’s desk to look at some code together. Other times, teams review code together in groups. But the most likely scenario you will encounter for code reviews at Microsoft is that code reviews are done with the help of tools.</p>
<h4 id="heading-code-reviews-at-microsoft-are-most-often-done-via-an-internal-tool">Code reviews at Microsoft are most often done via an internal tool</h4>
<p>There is a wide variety of code review tools available, and at Microsoft teams are free to choose their tooling. In 2016, 89% of the developers indicate to use the CodeFlow code review tool. I will explain more about this <a target="_blank" href="https://www.michaelagreiler.com/code-reviews-at-microsoft-how-to-code-review-at-a-large-software-company/#ms-tool">code review tool at Microsoft</a> later. Since then, and with the rise of Git, the tooling landscape has changed. I’ll add updated numbers as soon as they become available. But, let us consider a typical review situation:</p>
<p>Let’s imagine a developer at Microsoft, and let us call her Rose. Rose just finished a part of a feature and now wants feedback from her peers.</p>
<h4 id="heading-how-does-rose-start-a-code-review-at-microsoft">How does Rose start a code review at Microsoft?</h4>
<p>Well, as said, Rose is ready to get some feedback. Therefore she first prepares the code for review. This step includes that she opens the code review tool, that allows her to preview the code change. The code review tool performs some diffing tasks that help Rose to see exactly which changes she has done.</p>
<p>After carefully reviewing those changes, she prepares a small note that tells the reviewers what she did and why she did that. This note helps the reviewers to understand the purpose of the code change and its motivation. Now the code is ready to be sent to the reviewers.</p>
<h4 id="heading-how-does-rose-select-the-right-code-reviewers">How does Rose select the right code reviewers?</h4>
<p>Many experienced developers know who should be on the code review. Nevertheless, for people new on the team, or for new areas of work the selection can be a bit more tricky. If Rose does not know whom she should add, she would either look at the team policies or ask her colleagues. She can also use a recommendation feature of the code review tool that helps select reviewers based on experience and knowledge with the code base.</p>
<h4 id="heading-who-are-relevant-reviewers">Who are relevant reviewers?</h4>
<p>Rose selects reviewers that she thinks can contribute their knowledge to this piece of code. The reviewers are often other developers, but can also include other stakeholders, such as dev-ops engineers, UI experts, or also managers. Some reviewers are selected for their expertise, others are selected in order to stay informed about a coming change.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Siud62YVmYXQ1xe6xFrPMeFcZR-nkz7zrh26" alt="Image" width="414" height="656" loading="lazy"></p>
<h4 id="heading-rose-requests-feedback-from-her-peers">Rose requests feedback from her peers</h4>
<p>Once everybody is selected, Rose sends out the code review (by pressing the send button ?). The code review tool sends notification automatically to inform everybody that a code review has been created. Notifications are sent to all reviewers. But, often additional parties, such as managers or product managers of other teams, are also added to the notification list, and are automatically informed for each review. Those notifications allow them to stay in the loop. They are not required to perform the review.</p>
<h4 id="heading-receiving-feedback-is-an-iterative-process">Receiving feedback is an iterative process</h4>
<p>Once Rose’s colleagues have time, they will look at the code review. Each reviewer can annotate the code and add comments. Once finished commenting, the reviewer sends the annotated code back to Rose. Rose can now work on the comments and prepare a new improved version of the code.</p>
<p>Reviewers normally look for things like: does the code look bug free? Is there an architectural problem? Are there minor issues such as missing comments, spelling mistakes? Not all comments are equally valuable. But, there are <a target="_blank" href="https://docs.microsoft.com/en-us/azure/devops/learn/devops-at-microsoft/boosting-code-reviews-useful-comments">several best practices to boost the value of code review comments.</a></p>
<h4 id="heading-rose-prepares-a-new-improved-version-of-the-code">Rose prepares a new improved version of the code</h4>
<p>Rose works on the feedback by fixing and addressing the suggestions. If Rose sees that there are some misconceptions or other contentious issues, she might walk over to a colleague to discuss this in person. That’s sometimes easier and more personal than through the tooling.</p>
<p>Anyway, once she finished working on all the feedback, she sends a new version of the code to the reviewers. That new improved version is called a revision.</p>
<p>If needed, she will receive further feedback. Whether or not this cycle continues for a few times depends on the type of change and its quality. For simple and small code changes, often only one code review revision is needed. For other more complex changes or changes in problematic code, several iterations might be necessary.</p>
<p>It is totally normal, and partly desirable, that this code review feedback cycle sparks some discussions between the author and the code reviewers.</p>
<h4 id="heading-all-reviewers-approve-and-rose-checks-in-the-code">All reviewers approve and Rose checks-in the code</h4>
<p>After this review cycle, reviewers mark the code as okay, and Rose can finally check-in the code into the common code base.</p>
<p>Some teams have policies that allow the developer to check-in the code before an actual review is completed. This is normally restricted to small and trivial changes, in order to allow asynchronous reviews and to speed-up development.</p>
<p>All steps I describe are part of a typical code review life cycle at Microsoft and are performed by all teams. Depending on the team’s policies, teams are more strict or rigorous for each of the steps.</p>
<h3 id="heading-not-all-teams-are-the-same">Not all teams are the same</h3>
<p>As you can imagine, not all 60,000 engineers, and not all of the thousands of teams do the same. Some teams at Microsoft have additional steps or tools they require during the code review life cycle. I want to give you a short overview of some additional steps that teams add to the code review process.</p>
<h3 id="heading-code-reviews-including-test-results">Code reviews including test results</h3>
<p>The least what you want is to waste time by reviewing “automatic detectable” buggy code. I mean, if you could run automated tests and realize that the code does not work as expected, then, that’s what you should do: Run the tests before the review.</p>
<p>That’s why some teams require test results to be submitted with each code review. This way nobody can forget about running the tests. And it assures that the tests have actually run and passed for the given code change.</p>
<p>Other teams went even a step further and configured the code review tool in such a way that for each code review a developer submits, a build is triggered. That build contains that exact change, and also starts a series of automated tests. The results of this build and these tests are attached to the code review. Configuring it this way, ensures that the code changes have been tested with the latest code changes from the common code base.</p>
<h3 id="heading-code-reviews-including-user-interface">Code reviews including user interface</h3>
<p>If changes affect the user interface, it is also a smart idea to require the developer to submit a screenshot. That way the code reviewer can see the effects of the code change without running the code. Second, the code reviewer can spot discrepancies when running the code on her own machine.</p>
<h3 id="heading-code-reviews-including-static-analysis">Code reviews including static analysis</h3>
<p>Static analysis tools are only as good as their configuration, but, in terms of styling issues they can save a lot of time for code reviewers. Some teams at Microsoft use automated static and dynamic analysis tools as dedicated bot-reviewers. Those bots comment on code styling and other static issues. Thus, freeing up time for human code reviewers to perform more interesting tasks.</p>
<h3 id="heading-microsofts-code-review-tool">Microsoft’s code review tool</h3>
<p>For many years, one of the de facto standards for code review at Microsoft was an internal tool called CodeFlow. This is a sophisticated code review tool that supports developers and guides them through all steps of a code review. CodeFlow helps during preparation of the code, automatically notifies reviewers, and has a rich commenting and discussion functionality.</p>
<p>CodeFlow is an UI heavy tooling, much like Word or PowerPoint, as you can see in the screenshot below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/CnMpM1uqn911onDKhvrJ2AVuXg0lz035cMg8" alt="Image" width="451" height="339" loading="lazy"></p>
<h4 id="heading-codeflows-interface-explained">CodeFlow’s interface explained</h4>
<p>You can skip this if you want, but for all interested, I am walking you through the interface of CodeFlow. Looking at the screenshot, on the left (A) you see all affected documents.</p>
<p>Also on the left, you see (B) the list of reviewers assigned to the review as well as their status (e.g., signed-off or pending). The active document is shown in the editor (C ). At the bottom, you see (D) a list of comments for all documents.</p>
<p>On the other hand, in the active document (F) is one single comment. This comment is connected to the concrete part of the code (i.e., one word in a line). Finally, at the top you see the overall status of the code review. In this case, completed. The numbers before signal the different revisions. In this review, there have been five revisions.</p>
<h4 id="heading-commenting-functionality">Commenting functionality</h4>
<p>One of the nicest features of CodeFlow is its commenting functionality.</p>
<p>A code reviewer can select very precisely the parts of the code she wants to comment on. For example, a reviewer can even highlight just one or two characters in a line, instead of highlighting a whole row. Then, the reviewer can attach a comment to that selection.</p>
<p>The code author or other reviewers are notified of this comment and can start a conversation in form of a thread around this comment.</p>
<h4 id="heading-discussion-functionality">Discussion functionality</h4>
<p>This commenting functionality feels like commenting on social media platforms, such as Twitter or Facebook. Therefore, the commenting experience in CodeFlow feels very natural and allows rich conversations and discussions. Another nice perk is the possibility to assign a status to each of these comment threads. The status can, for example, be “won’t fix”, “resolved” or “open”.</p>
<h3 id="heading-comparison-between-code-review-revisions">Comparison between code review revisions</h3>
<p>A helpful feature is the possibility to select two different revisions of the code review and compare the differences between that. This means that you can see exactly which changes the code review author has performed between one code review revision and another one. That’s super handy to track the progress of the review.</p>
<h3 id="heading-code-review-analytics-tool">Code review analytics tool</h3>
<p>Developers spend a substantial amount of their time performing code reviews at Microsoft. To ensure this time is well spent, Microsoft has its own code review analytics platform.</p>
<p>This platform stores all code review data starting from the code under review, the developers involved in code reviews, to all comments of the developers. Even the code changes for each of the revisions can be traced back.</p>
<p>This <a target="_blank" href="https://queue.acm.org/detail.cfm?id=3292420">code review data is the base for several empirical studies</a> on code reviews at Microsoft. It is also used by many product teams for tracking their productivity and to understand their own code review practices. Also, many of the insights I share in <a target="_blank" href="https://www.michaelagreiler.com/code-review-blog-post-series/">this blog post series about code reviews at Microsoft</a> stem from studies and analyses that involved this code review data.</p>
<h3 id="heading-the-future-of-code-review-at-microsoft">The future of code review at Microsoft</h3>
<p>With Micorosft’s engagement and acquisition of GitHub change was inevitable. The change is visible by the vast adoption of Git as a source control tooling within Microsoft for example. But, this also means that at Microsoft code reviewing in form of pull requests is on the rise.</p>
<p>I’ll definitely plan to address code reviewing using pull requests at a later time.</p>
<h3 id="heading-coming-up-next-code-review-challenges">Coming up next: Code review challenges</h3>
<p>I will write about code review challenges in the next blog post. To <strong>stay in the loop</strong> and <strong>follow me</strong> on medium.</p>
<p><strong>Credit where credit is due:</strong></p>
<p>I would like to mention my wonderful colleagues at Microsoft and the University of Victoria that have been part of this study: <a target="_blank" href="https://www.microsoft.com/en-us/research/people/cbird/">Chris Bird</a>, <a target="_blank" href="https://www.microsoft.com/en-us/research/people/jacekcz/">Jacek Czerwonka</a> and <a target="_blank" href="http://lmacleod.com/">Laura Macleod</a> and <a target="_blank" href="http://margaretstorey.com/">Margaret-Anne Storey</a>. I loved to work with you on this ♥</p>
<p><em>Originally published at <a target="_blank" href="https://www.michaelagreiler.com/code-reviews-at-microsoft-how-to-code-review-at-a-large-software-company/">www.michaelagreiler.com</a> on March 27, 2019.</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
