<?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 Quality - 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 Quality - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 14 May 2026 22:43:45 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/code-quality/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How AI Changed the Economics of Writing Clean Code ]]>
                </title>
                <description>
                    <![CDATA[ If you've ever wanted to add an interface to a codebase and gotten pushback, you already know the argument: "That's twice the code for the same thing." And honestly? It was a fair point. You'd write t ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-ai-changed-the-economics-of-writing-clean-code/</link>
                <guid isPermaLink="false">69f0bce210a70b3335bf635a</guid>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Aaron Yong ]]>
                </dc:creator>
                <pubDate>Tue, 28 Apr 2026 13:57:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/ecb13bda-70dd-437a-8d9a-4ef8b18ccc05.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you've ever wanted to add an interface to a codebase and gotten pushback, you already know the argument: "That's twice the code for the same thing."</p>
<p>And honestly? It was a fair point. You'd write the contract — the interface, the abstract class, the protocol — and then write the implementation. Two files where one would do. That's more surface area, more indirection, and more to maintain.</p>
<p>The Ruby and Rails communities built an entire philosophy around this: convention over configuration, less ceremony, fewer keystrokes. If the framework could infer your intent, why spell it out?</p>
<p>Then AI happened.</p>
<p>I was recently chatting with a CEO about what current-generation software engineers get wrong, and he put it cleanly:</p>
<blockquote>
<p>"Abstract interfaces were challenging a few months ago just because it required twice as much code. But with AI, lines of code are free. The reason we still need such constructs is because at some point a human still needs to look at the code. Interfaces reduce the cognitive load."</p>
</blockquote>
<p>That framing stuck with me. The cost of writing code has collapsed. The cost of reading it hasn't moved. And that asymmetry changes everything about how you should think about abstraction.</p>
<p>Here's what I mean.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-your-brain-is-the-bottleneck">Your Brain Is the Bottleneck</a></p>
</li>
<li><p><a href="#heading-the-greats-already-knew-this">The Greats Already Knew This</a></p>
</li>
<li><p><a href="#heading-the-economics-have-flipped">The Economics Have Flipped</a></p>
</li>
<li><p><a href="#heading-the-data-backs-it-up">The Data Backs It Up</a></p>
</li>
<li><p><a href="#heading-the-contrarian-case-and-why-it-actually-agrees">The Contrarian Case (And Why It Actually Agrees)</a></p>
</li>
<li><p><a href="#heading-what-this-means-for-you">What This Means for You</a></p>
</li>
<li><p><a href="#heading-references">References</a></p>
</li>
</ul>
<h2 id="heading-your-brain-is-the-bottleneck">Your Brain Is the Bottleneck</h2>
<p>This isn't a vibes argument. There's actual neuroscience behind why interfaces help.</p>
<p>In 1988, educational psychologist John Sweller introduced Cognitive Load Theory. A <a href="https://dl.acm.org/doi/full/10.1145/3483843">2022 ACM review</a> covers how it's been applied to computing education since.</p>
<p>The short version: your brain juggles three types of load when processing information. <em>Intrinsic</em> load is the inherent difficulty of the problem itself. <em>Extraneous</em> load is the noise — poorly organized information, unnecessary details, bad naming. <em>Germane</em> load is the good stuff — the mental effort you spend building useful mental models.</p>
<p>Here's the kicker: your working memory can only hold a handful of chunks of information at a time — cognitive scientists typically estimate somewhere between 2 and 6. Not 2 to 6 files, or 2 to 6 classes — 2 to 6 <em>things</em>.</p>
<p>Felienne Hermans explores this in <em>The Programmer's Brain</em> (2021), arguing that design patterns act as chunking aids. When you recognize a Strategy pattern, your brain collapses an entire class hierarchy into a single cognitive unit. The word "Strategy" replaces five classes and their relationships. That's not hand-waving about clean code — that's how human memory actually works.</p>
<p>And we can literally see it on brain scans. In 2021, a team led by Norman Peitek and Janet Siegmund published <a href="https://dl.acm.org/doi/10.1109/ICSE43902.2021.00056">an fMRI study on program comprehension</a> that won the ACM SIGSOFT Distinguished Paper Award at ICSE.</p>
<p>They put developers in brain scanners and watched what happened when they read code. The finding: semantic-level comprehension — understanding <em>what</em> code does — required measurably less neural activation than bottom-up syntactic parsing — tracing <em>how</em> it does it.</p>
<p>An interface lets you comprehend at the semantic level. <code>UserRepository.findById(id)</code> tells you everything you need to know without opening the implementation. Your brain doesn't need to hold the SQL query, the connection pool logic, the error handling, and the result mapping in working memory simultaneously. The interface compresses all of that into one chunk.</p>
<p>That's not elegance. That's neuroscience.</p>
<h2 id="heading-the-greats-already-knew-this">The Greats Already Knew This</h2>
<p>The case for abstraction isn't new. The people who built the foundations of computer science were making this argument before most of us were born.</p>
<p>Dijkstra said it with precision:</p>
<blockquote>
<p><em>"The purpose of abstracting is not to be vague, but to create a new semantic level in which one can be absolutely precise."</em></p>
</blockquote>
<p>Abstraction isn't about hiding things from people who can't handle complexity. It's about creating a level of discourse where you can reason clearly.</p>
<p>David Parnas formalized information hiding in his <a href="https://dl.acm.org/doi/10.1145/361598.361623">1972 ACM paper</a>: <em>"Every module is characterized by its knowledge of a design decision which it hides from all others."</em> He proved that decomposing systems by design decisions (rather than processing steps) produced modules that were both more flexible <em>and</em> easier to understand. Comprehensibility wasn't a bonus — it was the design criterion.</p>
<p>Tony Hoare argued that abstraction is the most powerful tool available to the human intellect — a way to manage complexity by focusing on what matters and ignoring what doesn't. Martin Fowler brought it down to earth:</p>
<blockquote>
<p><em>"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."</em></p>
</blockquote>
<p>And then there's John Ousterhout, whose book <em>A Philosophy of Software Design</em> (2018) makes the connection to cognitive load explicit. His central argument: more lines of code can actually be <em>simpler</em> if they reduce cognitive load.</p>
<p>His concept of <em>deep modules</em> — simple interfaces hiding complex implementations — is essentially the argument that interfaces are worth their weight in code. The Unix file system API (<code>open</code>, <code>close</code>, <code>read</code>, <code>write</code>, <code>lseek</code>) is five functions hiding an enormous amount of complexity. That's a deep module. That's the goal.</p>
<p>The Gang of Four put it first in their book for a reason. Page one: <em>"Program to an interface, not an implementation."</em></p>
<p>None of this is controversial. But it's easy to forget when your AI tool just generated 200 lines of perfectly functional inline code in three seconds.</p>
<h2 id="heading-the-economics-have-flipped">The Economics Have Flipped</h2>
<p>Here's where the CEO's insight becomes an economic argument.</p>
<p>The historical case against interfaces was always about <em>writing cost</em>. Interfaces meant more code to write, more files to create, more boilerplate to maintain. The entire dynamic typing movement — Python, Ruby, JavaScript — was partly a reaction to the ceremony that languages like Java imposed. Convention over configuration. Don't Repeat Yourself. Less is more.</p>
<p>But ask yourself: what exactly is the cost of writing boilerplate now?</p>
<p>GitHub's <a href="https://arxiv.org/abs/2302.06590">2022 controlled study</a> found that developers using Copilot completed tasks 55% faster. The boilerplate that used to justify skipping interfaces — the extra file, the type definitions, the method signatures — takes seconds to generate. The writing cost of an interface has effectively collapsed to zero.</p>
<p>But again, the reading cost hasn't budged.</p>
<p>Robert C. Martin argued in <em>Clean Code</em> (2008) that developers spend far more time reading code than writing it — an observation he framed as a ratio of 10 to 1.</p>
<p>You can quibble with the exact number (it's anecdotal), but the direction is consistent across studies. A <a href="https://ieeexplore.ieee.org/document/7997917/">large-scale field study</a> tracking 78 professional developers across 3,148 working hours found they spend roughly 58% of their time on program comprehension alone. New developer onboarding averages six weeks — most of which is spent understanding existing systems, not producing new ones.</p>
<p>Addy Osmani named this asymmetry perfectly. In a <a href="https://addyosmani.com/blog/comprehension-debt/">March 2026 piece</a>, he described <em>comprehension debt</em>:</p>
<blockquote>
<p>"When a developer on your team writes code, the human review process has always been a bottleneck — but a productive and educational one. Reading their PR forces comprehension. AI-generated code breaks that feedback loop. The volume is too high."</p>
</blockquote>
<p>The output looks clean, passes linting, follows conventions — precisely the signals that historically triggered merge confidence. But comprehension debt is distinct from technical debt because it accumulates invisibly — your velocity metrics, your DORA scores, your PR counts all look fine while your team's actual understanding of the codebase quietly erodes.</p>
<p>So here's the math: AI reduced the cost of writing abstractions to near zero. The cost of <em>not</em> having them — in human reading time, onboarding friction, and comprehension debt — hasn't changed at all. The break-even point for "is this interface worth it?" just shifted massively in favor of "yes."</p>
<h2 id="heading-the-data-backs-it-up">The Data Backs It Up</h2>
<p>This isn't theoretical. We have data on what happens when AI generates code without good abstractions.</p>
<p><a href="https://www.gitclear.com/ai_assistant_code_quality_2025_research">GitClear analyzed 211 million changed lines of code</a> between 2020 and 2024. Their findings: code churn — lines reverted or updated within two weeks — doubled compared to the pre-AI baseline. Copy-pasted code blocks rose from 8.3% to 12.3%. And refactoring-associated changes dropped from 25% to under 10%.</p>
<p>AI-generated code, as they put it, "resembles an itinerant contributor, prone to violate the DRY-ness of the repos visited."</p>
<p>The <a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/">METR study</a> (2025) found something even more striking. Experienced open-source developers <em>predicted</em> AI would make them 24% faster. They <em>perceived</em> being 20% faster while using it. They were actually 19% slower. The perception gap is the story — you <em>feel</em> productive while generating code that creates more work downstream.</p>
<p>And then there's a study from Anthropic (yes, the company that makes Claude — full disclosure). They observed 52 software engineers learning a new library. The AI-assisted group completed tasks at the same speed, but scored <a href="https://arxiv.org/abs/2601.20245">17% lower on comprehension quizzes</a> afterward — 50% versus 67%. The biggest declines were in debugging ability. You can ship code you don't understand. You can't debug code you don't understand.</p>
<p>Kent Beck <a href="https://tidyfirst.substack.com/p/90-of-my-skills-are-now-worth-0">put it bluntly</a>: "The value of 90% of my skills just dropped to $0. The leverage for the remaining 10% went up 1000x." What that remaining 10% is, he leaves deliberately open — but it's hard to read that and not think about system design.</p>
<h2 id="heading-the-contrarian-case-and-why-it-actually-agrees">The Contrarian Case (And Why It Actually Agrees)</h2>
<p>I'd be dishonest if I didn't address the people who argue against abstraction. And some of them are very smart.</p>
<p>Casey Muratori's <a href="https://www.computerenhance.com/p/clean-code-horrible-performance">"Clean Code, Horrible Performance"</a> demonstrated that polymorphism and virtual dispatch can make code 10 to 15 times slower than straightforward procedural alternatives.</p>
<p>His benchmark is real. If you're writing a game engine or a high-frequency trading system, abstract interfaces on your hot path will cost you.</p>
<p>Dan Abramov wrote <a href="https://overreacted.io/goodbye-clean-code/">"Goodbye, Clean Code"</a> after watching a premature abstraction make his codebase harder to modify:</p>
<blockquote>
<p><em>"My code traded the ability to change requirements for reduced duplication, and it was not a good trade."</em></p>
</blockquote>
<p>Sandi Metz <a href="https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction">put it more sharply</a>: <em>"Duplication is far cheaper than the wrong abstraction."</em></p>
<p>And Rich Hickey, in his talk <a href="https://www.infoq.com/presentations/Simple-Made-Easy/">"Simple Made Easy"</a>, draws the critical distinction: <em>simple</em> (not intertwined) is not the same as <em>easy</em> (familiar). Wrong abstractions <em>complect</em> — they braid concerns together rather than separating them.</p>
<p>Here's the thing: none of these are arguments against abstraction. They're arguments against <em>bad</em> abstraction.</p>
<p>Muratori's performance argument applies to hot paths in performance-critical systems — not to your REST API's service layer. Abramov and Metz argue against <em>premature</em> abstraction — pulling patterns out before you understand the domain. And Hickey's entire talk is a case <em>for</em> the right abstractions, the ones that genuinely decompose rather than complect.</p>
<p>The irony is that in an AI-assisted world, these arguments are <em>easier</em> to address. You can generate the explicit, unabstracted version first. Let it stabilize. Watch the patterns emerge. Then extract the abstraction — with AI handling the mechanical refactoring. The cost of the "duplicate first, abstract later" approach just dropped to near zero.</p>
<h2 id="heading-what-this-means-for-you">What This Means for You</h2>
<p>If you're writing code with AI tools — and at this point, <a href="https://survey.stackoverflow.co/2024/ai">most of us are</a> — the temptation is to let the AI produce whatever it produces and move on. It works. It passes the tests. Ship it.</p>
<p>But "it works" is table stakes. The harder question is: can the next person who opens this code understand it in under five minutes? Can <em>you</em> understand it in six months?</p>
<p>Interfaces aren't about making code prettier or satisfying some abstract (pun intended) design principle. They're compression algorithms for human cognition. They let your brain operate at the semantic level instead of the syntactic level. And now that AI has eliminated the only real cost of creating them — the boilerplate — there's no economic argument left for skipping them.</p>
<p>The rules haven't changed. The excuse has just expired.</p>
<h2 id="heading-references">References</h2>
<h3 id="heading-academic-papers">Academic Papers</h3>
<ul>
<li><p>Duran, R., Zavgorodniaia, A., &amp; Sorva, J. (2022). <a href="https://dl.acm.org/doi/full/10.1145/3483843">"Cognitive Load Theory in Computing Education Research: A Review."</a> <em>ACM Transactions on Computing Education, 22</em>(4), Article 40.</p>
</li>
<li><p>Parnas, D.L. (1972). <a href="https://dl.acm.org/doi/10.1145/361598.361623">"On the Criteria To Be Used in Decomposing Systems into Modules."</a> <em>Communications of the ACM, 15</em>(12), 1053–1058.</p>
</li>
<li><p>Peitek, N., Apel, S., Parnin, C., Brechmann, A., &amp; Siegmund, J. (2021). <a href="https://dl.acm.org/doi/10.1109/ICSE43902.2021.00056">"Program Comprehension and Code Complexity Metrics: An fMRI Study."</a> <em>ICSE 2021</em>. ACM SIGSOFT Distinguished Paper Award.</p>
</li>
<li><p>Peng, S., Kalliamvakou, E., Cihon, P., &amp; Demirer, M. (2023). <a href="https://arxiv.org/abs/2302.06590">"The Impact of AI on Developer Productivity: Evidence from GitHub Copilot."</a> <em>arXiv:2302.06590</em>.</p>
</li>
<li><p>Shen, J.H. &amp; Tamkin, A. (2026). <a href="https://arxiv.org/abs/2601.20245">"How AI Impacts Skill Formation."</a> <em>arXiv:2601.20245</em>.</p>
</li>
<li><p>Xia, X., Bao, L., Lo, D., Xing, Z., Hassan, A.E., &amp; Li, S. (2018). <a href="https://ieeexplore.ieee.org/document/7997917/">"Measuring Program Comprehension: A Large-Scale Field Study with Professionals."</a> <em>IEEE Transactions on Software Engineering, 44</em>(10), 951–976.</p>
</li>
<li><p>METR. (2025). <a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/">"Measuring the Impact of Early 2025 AI on Experienced Open Source Developer Productivity."</a> <em>metr.org</em>.</p>
</li>
</ul>
<h3 id="heading-talks-and-blog-posts">Talks and Blog Posts</h3>
<ul>
<li><p>Hickey, R. (2011). <a href="https://www.infoq.com/presentations/Simple-Made-Easy/">"Simple Made Easy."</a> <em>Strange Loop Conference</em>.</p>
</li>
<li><p>Beck, K. (2023). <a href="https://tidyfirst.substack.com/p/90-of-my-skills-are-now-worth-0">"90% of My Skills Are Now Worth $0."</a> <em>Tidy First? Substack</em>.</p>
</li>
<li><p>Osmani, A. (2026). <a href="https://addyosmani.com/blog/comprehension-debt/">"Comprehension Debt: The Hidden Cost of AI-Generated Code."</a> <em>addyosmani.com</em>.</p>
</li>
<li><p>Muratori, C. (2023). <a href="https://www.computerenhance.com/p/clean-code-horrible-performance">"Clean Code, Horrible Performance."</a> <em>Computer Enhance</em>.</p>
</li>
<li><p>Abramov, D. (2020). <a href="https://overreacted.io/goodbye-clean-code/">"Goodbye, Clean Code."</a> <em>overreacted.io</em>.</p>
</li>
<li><p>Metz, S. (2016). <a href="https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction">"The Wrong Abstraction."</a> <em>sandimetz.com</em>.</p>
</li>
<li><p>GitClear. (2025). <a href="https://www.gitclear.com/ai_assistant_code_quality_2025_research">"AI Assistant Code Quality in 2025."</a> <em>gitclear.com</em>.</p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Apply GAN Architecture to Multi-Agent Code Generation ]]>
                </title>
                <description>
                    <![CDATA[ Ask an AI coding agent to build a feature and it will probably do a decent job. Ask it to review its own work and it will tell you everything looks great. This is the fundamental problem with single-p ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-apply-gan-architecture-to-multi-agent-code-generation/</link>
                <guid isPermaLink="false">69c4123410e664c5dac5298f</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ claude ]]>
                    </category>
                
                    <category>
                        <![CDATA[ multi-agent systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Christopher Galliart ]]>
                </dc:creator>
                <pubDate>Wed, 25 Mar 2026 16:49:56 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/3c06f375-0e26-427d-9659-b3be60716492.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Ask an AI coding agent to build a feature and it will probably do a decent job. Ask it to review its own work and it will tell you everything looks great.</p>
<p>This is the fundamental problem with single-pass AI code generation: the same context that created the code is the one evaluating it. There's no adversarial pressure. No second opinion. No fresh eyes.</p>
<p>What if you could structure the work so that separate agents generate and critique each other in iterative loops, the way a generator and discriminator improve each other in a <a href="https://www.freecodecamp.org/news/an-intuitive-introduction-to-generative-adversarial-networks-gans-7a2264a81394/">GAN</a>? The code that reaches you has already survived an argument between agents who disagreed about whether it was good enough.</p>
<p>This article walks through why that pattern works, how to build it, and when it is (and is not) worth the extra tokens. The concrete example is an open source project called <a href="https://github.com/HatmanStack/claude-forge">Claude Forge</a>, but the ideas are framework-agnostic. Anything that supports subagent spawning with fresh context windows can implement this pattern.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-the-single-pass-problem">The Single-Pass Problem</a></p>
</li>
<li><p><a href="#heading-what-the-ecosystem-is-solving">What the Ecosystem Is Solving</a></p>
</li>
<li><p><a href="#heading-the-gan-pattern-applied-to-code">The GAN Pattern Applied to Code</a></p>
</li>
<li><p><a href="#heading-why-rhetorical-questions-outperform-direct-instructions">Why Rhetorical Questions Outperform Direct Instructions</a></p>
</li>
<li><p><a href="#heading-feedback-as-filesystem">Feedback as Filesystem</a></p>
</li>
<li><p><a href="#heading-the-zero-context-engineer">The Zero-Context Engineer</a></p>
</li>
<li><p><a href="#heading-phase-0-immutable-conventions">Phase-0: Immutable Conventions</a></p>
</li>
<li><p><a href="#heading-convergence-design-knowing-when-to-stop">Convergence Design: Knowing When to Stop</a></p>
</li>
<li><p><a href="#heading-ground-truth-documents-and-the-pipeline">Ground Truth Documents and the Pipeline</a></p>
</li>
<li><p><a href="#heading-what-the-adversarial-loop-actually-catches">What the Adversarial Loop Actually Catches</a></p>
</li>
<li><p><a href="#heading-honest-trade-offs">Honest Trade-offs</a></p>
</li>
<li><p><a href="#heading-when-to-use-this-and-when-not-to">When to Use This (And When Not To)</a></p>
</li>
<li><p><a href="#heading-getting-started">Getting Started</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Familiarity with <a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code</a> or a similar AI coding agent</p>
</li>
<li><p>A working installation of Claude Code (for the hands-on sections)</p>
</li>
<li><p>Basic understanding of how LLM context windows work</p>
</li>
<li><p>Git installed and configured</p>
</li>
</ul>
<p>No machine learning background is required. The GAN concepts are explained from first principles where they appear.</p>
<h2 id="heading-the-single-pass-problem">The Single-Pass Problem</h2>
<p>The AI generates code in one pass. If it hallucinates a file path, misunderstands the architecture, or writes tests that don't actually test anything, you catch it during review. Or worse, you don't.</p>
<p>This isn't a hypothetical. Anyone who has used AI coding agents at scale has seen placeholder tests like <code>expect(true).toBe(true)</code>, phantom dependencies where Phase 2 assumes a model that Phase 1 never creates, and instructions so ambiguous that two valid interpretations exist. These aren't rare edge cases. They're the predictable failure mode of single-pass generation.</p>
<p>The problem compounds with task complexity. A simple utility function generates fine in one pass. An auth middleware with token refresh, error handling, rate limiting, and logging across multiple files? The agent starts cutting corners, because the entire generation happened inside one context window that is simultaneously tracking the plan, the code, the tests, and the growing weight of its own prior reasoning.</p>
<h2 id="heading-what-the-ecosystem-is-solving">What the Ecosystem Is Solving</h2>
<p>There is a growing ecosystem of frameworks tackling different aspects of this problem. They each bring real contributions worth understanding.</p>
<p><a href="https://github.com/obra/superpowers">Superpowers</a> focuses on development methodology. It uses subagent-driven development, TDD enforcement, and multi-stage review. The framework generates a design spec, then an implementation plan, then dispatches subagents to execute. Review subagents check the output, and if they find issues, the implementer revises and gets re-reviewed until approved.</p>
<p><a href="https://github.com/gsd-build/get-shit-done"><strong>Get Shit Done</strong></a> <strong>(GSD)</strong> focuses on context engineering. Its key insight is fighting context window degradation through fresh 200k subagent contexts, parallel wave execution, and XML-structured plans. A JavaScript CLI handles the deterministic work (tracking progress, dependency ordering, context budgets) so the LLM never wastes tokens on bookkeeping it would do unreliably anyway.</p>
<p>Both frameworks share a crucial design decision: fresh context windows. When an agent has been reasoning for 100k tokens, its attention degrades. By spawning subagents with clean 200k contexts, these frameworks sidestep the "context rot" problem that plagues long-running agent sessions.</p>
<p>Where these frameworks diverge is in how they handle quality assurance. GSD relies on mechanical verification: lint, test, type-check, and auto-fix retries if the checks fail. There is no agent reading another agent's code to assess whether it matches the spec's intent. The "review" is whether <code>npm run test</code> passes.</p>
<p>Superpowers does have agent-to-agent review with iterative loops. But the review is enforced by in-context instructions, which means the agent can (and frequently does) rationalize skipping the review step to save tokens.</p>
<p>This is a known issue in the project. When review enforcement lives inside the same prompt that the model is also using to make efficiency decisions, the model sometimes decides that review is not worth the cost.</p>
<p>The adversarial GAN pattern addresses this differently. Instead of asking an agent to review its own work or trusting in-context instructions to enforce review, it structures the pipeline so that <strong>review is architecturally mandatory</strong>. The reviewer is a separate agent that cannot be skipped, because the orchestrator will not advance the pipeline without the reviewer's signal. The reviewer cannot modify source code, only <code>feedback.md</code>. The generator cannot approve its own output. Role separation is enforced by the system, not suggested by the prompt.</p>
<h2 id="heading-the-gan-pattern-applied-to-code">The GAN Pattern Applied to Code</h2>
<p>In machine learning, GANs pit two networks against each other: a generator creates content, a discriminator evaluates it, and the feedback loop between them drives both to improve. The generator gets better at producing realistic output. The discriminator gets better at finding flaws. The adversarial tension is what produces quality.</p>
<p>Applied to software development, this creates two stacked feedback loops:</p>
<img src="https://cdn.hashnode.com/uploads/covers/698f5932352111d3f67030a2/09d2fc1a-94f7-44e8-a35e-f221f5c9563e.jpg" alt="Diagram comparing generator and discriminator roles in GAN loops. Top: Planner (Generator) vs Plan Reviewer (Discriminator). Bottom: Implementer (Generator) vs Reviewer (Discriminator). Arrows indicate iterative feedback between each pair." style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>Each role runs as a <strong>separate agent with its own fresh context window</strong>. The Plan Reviewer has never seen the Planner's reasoning process. It only sees the output. The Code Reviewer has never seen the Implementer's struggles. It only sees the code.</p>
<p>This separation fundamentally changes what the reviewer can catch. When a reviewer shares context with the generator, it inherits the generator's blind spots. When a reviewer starts fresh, it reads the plan the way an actual engineer would: with no assumptions about what the author "meant" versus what they wrote.</p>
<p>The adversarial Plan Reviewer doesn't just verify structure. It actively tries to break the plan:</p>
<ul>
<li><p><strong>Deadlock search:</strong> Is there a task ordering that would deadlock the implementer? (Task 3 needs the output of Task 5.)</p>
</li>
<li><p><strong>False positive verification:</strong> Could any verification checklist pass even with a wrong implementation?</p>
</li>
<li><p><strong>Ambiguity search:</strong> Are there instructions that could be interpreted two valid ways?</p>
</li>
<li><p><strong>Missing context:</strong> Could the implementer get stuck because a task assumes knowledge not provided?</p>
</li>
</ul>
<p>This is where the GAN analogy is most literal. The discriminator isn't checking if the plan looks good. It's trying to find failure modes.</p>
<h2 id="heading-why-rhetorical-questions-outperform-direct-instructions">Why Rhetorical Questions Outperform Direct Instructions</h2>
<p>When a reviewer finds an issue, there are two ways to communicate it.</p>
<p><strong>Direct instruction:</strong></p>
<pre><code class="language-plaintext">Fix line 45: the error handler returns 500 instead of 401 for invalid tokens.
</code></pre>
<p><strong>Rhetorical question:</strong></p>
<pre><code class="language-plaintext">Consider: The test test_invalid_token_rejection expects a 401 status code.
Are you returning the correct HTTP status in your error handling?

Think about: In src/auth/middleware.js:45, what happens when the token is
invalid? Is the error properly caught?

Reflect: Look at how other middleware handles auth errors. Are you following
the same pattern?
</code></pre>
<p>The direct instruction produces a mechanical edit. The agent changes line 45 and moves on. The rhetorical question produces a deeper investigation. The agent re-examines the surrounding code, considers the pattern used elsewhere, and is more likely to find the root cause rather than just patching the symptom.</p>
<p>This maps to how the underlying models work. When given an explicit instruction, the model follows it literally. When guided to reason about a problem, it activates a broader search through its understanding of the codebase. The fix addresses related issues that a mechanical edit would miss.</p>
<p>Reviewer prompts structured around "Consider," "Think about," and "Reflect" prefixes consistently produce better fixes than "Fix" or "Change" directives. The implementer agent receives these as feedback in <code>feedback.md</code> and addresses them in the next iteration of the GAN loop.</p>
<h2 id="heading-feedback-as-filesystem">Feedback as Filesystem</h2>
<p>Most agent orchestration systems rely on some form of message passing: API calls, databases, queue systems, in-memory state. These all work, but they introduce infrastructure dependencies and make the agent conversation opaque after the fact.</p>
<p>An alternative: use the filesystem as the message bus and git as the orchestration layer.</p>
<p>All agent communication flows through <code>feedback.md</code>, a structured markdown file with two sections:</p>
<pre><code class="language-markdown">## Active Feedback (OPEN)

### FB-001: Auth middleware missing rate limiting
- **Status:** OPEN
- **Source:** Plan Reviewer
- **Phase:** 1
- **Detail:** The plan specifies JWT validation but does not address rate
  limiting for failed auth attempts. Consider: what happens if an attacker
  brute-forces tokens?

## Resolved Feedback

### FB-000: Missing error codes in API spec
- **Status:** RESOLVED
- **Resolution:** Added error code table to Phase-0 conventions
</code></pre>
<p>This design has several properties that matter in practice:</p>
<p><strong>Full audit trail:</strong> Every piece of feedback, every resolution, every signal is committed to git alongside the code it produced. When you want to understand why the auth middleware was designed a certain way, the conversation that shaped it is right there in the commit history.</p>
<p><strong>State recovery:</strong> If a pipeline gets interrupted (token limits, network issues, you need to step away), resuming is trivial. The orchestrator re-reads <code>feedback.md</code> and <code>git log</code>, determines what stage the pipeline reached, and picks up where it left off. No cloud infrastructure, no database, no queue. Just files.</p>
<p><strong>Transparency:</strong> You can read the agent conversation in your editor. You can see exactly what the reviewer flagged, exactly how the implementer responded, and whether the resolution actually addressed the concern.</p>
<p>Agents communicate through structured signals routed by the orchestrator:</p>
<ul>
<li><p><code>PLAN_COMPLETE</code> / <code>REVISION_REQUIRED</code> / <code>PLAN_APPROVED</code> (plan GAN loop)</p>
</li>
<li><p><code>IMPLEMENTATION_COMPLETE</code> / <code>CHANGES_REQUESTED</code> / <code>PHASE_APPROVED</code> (code GAN loop)</p>
</li>
<li><p><code>GO</code> / <code>NO-GO</code> (final gate)</p>
</li>
<li><p><code>VERIFIED</code> / <code>UNVERIFIED</code> (post-remediation verification)</p>
</li>
</ul>
<p>Each signal marks a state transition. The orchestrator reads the signal, determines the next agent to invoke, and passes it the relevant context. The orchestrator itself is a Claude Code session, but the agents it spawns are fresh subagents with clean context windows.</p>
<h2 id="heading-the-zero-context-engineer">The Zero-Context Engineer</h2>
<p>One of the most effective constraints in the system is the "zero-context engineer" framing. The Planner writes every plan as if it will be executed by an engineer who:</p>
<ul>
<li><p>Is skilled but has <strong>zero context</strong> on the codebase</p>
</li>
<li><p>Is unfamiliar with the toolset and problem domain</p>
</li>
<li><p>Will follow instructions precisely</p>
</li>
<li><p>Will not infer missing details. If it's not in the plan, it won't happen.</p>
</li>
</ul>
<p>This constraint forces explicit instructions. No "add the usual auth middleware." Instead: which library, which pattern, which error codes, which files to create, which existing files to modify, and how to verify the result.</p>
<p>The Plan Reviewer then simulates this zero-context experience: "If I knew nothing about this codebase, could I follow these instructions and produce a working result?"</p>
<p>This framing catches a class of failures that are invisible to someone with context. The author of the plan knows what they meant. The zero-context reviewer only knows what is written. The gap between intention and specification is where bugs live.</p>
<h2 id="heading-phase-0-immutable-conventions">Phase-0: Immutable Conventions</h2>
<p>Every pipeline run starts with a Phase-0 document that defines immutable rules: tech stack, testing strategy, deployment approach, shared patterns, commit format. Every subsequent phase inherits from Phase-0. Every reviewer checks against it.</p>
<p>This solves a common multi-agent problem: drift. Without a shared source of truth, Agent A might decide to use Jest while Agent B sets up Vitest. Agent C might use a different error handling pattern than Agent D. Phase-0 prevents this by establishing conventions before any code is written.</p>
<p>The conventions aren't suggestions. They're constraints that every agent in the pipeline must respect, and every reviewer must verify against.</p>
<h2 id="heading-convergence-design-knowing-when-to-stop">Convergence Design: Knowing When to Stop</h2>
<p>An adversarial loop without exit conditions is just two agents arguing forever. The convergence design has three mechanisms:</p>
<p><strong>Iteration caps:</strong> Each GAN loop (plan review, code review) runs a maximum of 3 iterations. If the planner and reviewer cannot converge in 3 rounds, the issue requires human judgment, not more machine cycles.</p>
<p><strong>Signal protocol:</strong> The structured signals (<code>PLAN_APPROVED</code>, <code>GO</code>, <code>NO-GO</code>) are explicit state transitions, not suggestions. When the final reviewer issues <code>NO-GO</code>, the pipeline rolls back the phase. There is no "let's try one more time." The rollback is automatic.</p>
<p><strong>Token budget:</strong> Each phase targets roughly 50k tokens with a 75k hard ceiling. This prevents any single phase from consuming the entire context budget and ensures the orchestrator retains enough headroom to manage the pipeline.</p>
<p>These caps exist because adversarial loops have a cost curve. The first iteration catches major issues. The second iteration catches subtle issues. The third iteration catches edge cases. A fourth iteration almost never catches anything the previous three missed, but it costs just as many tokens. Three iterations hit the sweet spot between thoroughness and efficiency.</p>
<h2 id="heading-ground-truth-documents-and-the-pipeline">Ground Truth Documents and the Pipeline</h2>
<p>The adversarial pipeline doesn't start from a vague prompt. Every workflow begins with an intake skill that produces a structured ground truth document. The pipeline then runs from that document, not from the original user request.</p>
<h3 id="heading-brainstorm-turning-ideas-into-specs">Brainstorm: Turning Ideas into Specs</h3>
<p>The <code>/brainstorm</code> skill is the feature creation workflow. Given a feature idea, it first explores the codebase to understand the existing architecture, tech stack, and patterns. Then it asks 5-15 clarifying questions designed to front-load high-impact decisions:</p>
<pre><code class="language-plaintext">The codebase uses DynamoDB for storage. For this feature's data, should we:

A) Add tables to the existing DynamoDB setup
B) Use a different storage approach (e.g., S3 for documents)
C) Both - DynamoDB for metadata, S3 for content
</code></pre>
<p>These aren't generic questions. They're grounded in what the skill found during codebase exploration. The skill identifies the real decision points for this specific project and surfaces them before any planning or code generation begins.</p>
<p>The output is <code>brainstorm.md</code>, a structured design spec. Not a conversation transcript, but a distilled set of decisions that the Planner agent can consume cold. This document becomes the single source of truth for the entire pipeline run.</p>
<h3 id="heading-repository-evaluation-health-and-documentation-audits">Repository Evaluation, Health, and Documentation Audits</h3>
<p>The same ground-truth-document pattern applies to the audit workflows:</p>
<ul>
<li><p><code>/repo-eval</code> spawns three evaluator agents in parallel (the Pragmatist, the Oncall Engineer, the Team Lead), each scoring the codebase from a different lens across 12 pillars. The output is <code>eval.md</code>.</p>
</li>
<li><p><code>/repo-health</code> runs a technical debt auditor across four vectors (architectural, structural, operational, hygiene). The output is <code>health-audit.md</code>.</p>
</li>
<li><p><code>/doc-health</code> runs six detection phases comparing documentation against actual code. The output is <code>doc-audit.md</code>.</p>
</li>
<li><p><code>/audit</code> runs any combination of the above. It asks scoping questions once, then spawns up to 5 agents in parallel (3 evaluators + health auditor + doc auditor). All intake documents land in one directory.</p>
</li>
</ul>
<p>Each of these intake skills produces a read-only assessment. The agents doing the evaluation never modify the codebase. They only write their findings into the intake document.</p>
<h3 id="heading-the-pipeline-runs-from-ground-truth">The Pipeline Runs from Ground Truth</h3>
<p>The <code>/pipeline</code> skill reads whatever intake documents exist and runs the adversarial GAN loop from them. For a feature, it reads <code>brainstorm.md</code>. For an audit, it reads whichever combination of <code>eval.md</code>, <code>health-audit.md</code>, and <code>doc-audit.md</code> are present.</p>
<img src="https://cdn.hashnode.com/uploads/covers/698f5932352111d3f67030a2/ec48de80-2185-45d2-89b2-2008fbc14365.jpg" alt="Diagram of the extended pipeline agent workflow. Shows brainstorm exploring the codebase and producing a design spec, which feeds into the pipeline orchestrator. The orchestrator routes through three stages: Planning (Planner and Plan Reviewer in a GAN loop, max 3 iterations), Implementation (Implementer and Reviewer in a GAN loop, max 3 iterations), and Final Review (GO or NO-GO gate)." style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>When multiple intake documents exist (from a combined audit), the Planner reads all findings together and consolidates overlapping concerns into a single unified plan. Phases are tagged by implementer type and ordered:</p>
<ol>
<li><p><code>[HYGIENIST]</code> phases first, subtractive cleanup (deleting dead code, simplifying over-abstractions)</p>
</li>
<li><p><code>[IMPLEMENTER]</code> phases next, structural fixes on clean code</p>
</li>
<li><p><code>[FORTIFIER]</code> phases next, locking in the clean state (linting, CI checks, git hooks)</p>
</li>
<li><p><code>[DOC-ENGINEER]</code> phases last, documentation reflecting final code</p>
</li>
</ol>
<p>The ordering matters. You don't want the implementer building on top of dead code that the hygienist would have removed. You don't want the doc-engineer documenting an API that the fortifier is about to add validation to.</p>
<p>This separation between intake and pipeline is deliberate. The intake skills are exploratory and interactive. They ask questions, explore the codebase, and produce a document. The pipeline is autonomous. It reads the document and runs through the adversarial loops with minimal human intervention, stopping only at explicit decision points.</p>
<h2 id="heading-what-the-adversarial-loop-actually-catches">What the Adversarial Loop Actually Catches</h2>
<p>In practice, the adversarial loops catch issues that single-pass generation consistently misses.</p>
<p><strong>Plan Review catches:</strong></p>
<ul>
<li><p>Hallucinated file paths (the Planner says "modify" a file that doesn't exist)</p>
</li>
<li><p>Phantom dependencies (Phase 2 assumes a model that Phase 1 never creates)</p>
</li>
<li><p>Test strategies that require live cloud resources instead of mocks</p>
</li>
<li><p>Ambiguous instructions that a zero-context engineer could misinterpret</p>
</li>
<li><p>Deadlocks in task ordering (Task 3 needs the output of Task 5)</p>
</li>
</ul>
<p><strong>Code Review catches:</strong></p>
<ul>
<li><p>Placeholder tests (<code>expect(true).toBe(true)</code>)</p>
</li>
<li><p>Deviations from Phase-0 architecture conventions</p>
</li>
<li><p>Missing error path coverage (only happy paths tested)</p>
</li>
<li><p>Hardcoded secrets and input validation gaps</p>
</li>
</ul>
<p><strong>Verification catches:</strong></p>
<ul>
<li><p>Remediation targets that weren't actually addressed</p>
</li>
<li><p>Regressions introduced during fixes</p>
</li>
<li><p>Partial fixes where the symptom changed but the root cause remains</p>
</li>
</ul>
<p>An earlier design re-ran the full evaluator or auditor agents after remediation, 3-5 agents re-scanning the entire codebase. This was token-expensive and redundant since the per-phase reviewers had already verified each fix. The current design uses a single verification agent with a targeted scope: read the original intake document findings and check each specific <code>file:line</code> location. One agent, targeted scope, a fraction of the tokens. Evaluator and auditor agents run exactly once (during intake) and never again.</p>
<h2 id="heading-honest-trade-offs">Honest Trade-offs</h2>
<p>This pipeline is not free. There are some trade-offs you'll want to consider and be aware of:</p>
<h3 id="heading-token-cost">Token Cost</h3>
<p>Multiple agents reviewing each other's work uses significantly more tokens than a single-pass approach. The adversarial loops can triple the total token usage for a feature. On a subscription plan, this means hitting session limits faster. On API billing, this means real money.</p>
<h3 id="heading-time">Time</h3>
<p>A feature that takes one agent 10 minutes might take the pipeline 30-45 minutes with review loops. Multi-agent frameworks in general are slower than single-pass. The adversarial loops add time on top of the orchestration overhead that any multi-agent system carries.</p>
<h3 id="heading-orchestrator-context-pressure">Orchestrator Context Pressure</h3>
<p>The orchestrator accumulates agent result summaries across phases. Long pipelines with many phases may hit context compression, which degrades the orchestrator's ability to route effectively.</p>
<h3 id="heading-not-fire-and-forget">Not Fire-and-Forget</h3>
<p>Despite the automation, complex features benefit from human checkpoints. The pipeline stops and asks for judgment at key moments. If you skip those checkpoints, you may end up with technically correct code that misses the actual requirement.</p>
<h3 id="heading-diminishing-returns-on-simple-tasks">Diminishing Returns on Simple Tasks</h3>
<p>For a quick script, a utility function, or a prototype, the adversarial overhead is pure waste. Single-pass generation is faster, cheaper, and sufficient.</p>
<p>The trade-off is worth it for features where correctness matters more than speed: anything touching auth, payments, data integrity, or infrastructure. When the cost of a bug in production exceeds the cost of the extra tokens to prevent it, the math works. For everything else, single-pass is fine.</p>
<h2 id="heading-when-to-use-this-and-when-not-to">When to Use This (And When Not To)</h2>
<p><strong>Use adversarial multi-agent patterns when:</strong></p>
<ul>
<li><p>The feature touches authentication, authorization, or session management</p>
</li>
<li><p>The code handles payments or financial transactions</p>
</li>
<li><p>Data integrity is critical (migrations, schema changes, ETL pipelines)</p>
</li>
<li><p>Infrastructure changes could affect production (IaC, CI/CD modifications)</p>
</li>
<li><p>The codebase is unfamiliar to the agents (large legacy systems)</p>
</li>
</ul>
<p><strong>Use single-pass generation when:</strong></p>
<ul>
<li><p>Prototyping or exploring an idea</p>
</li>
<li><p>Writing utility scripts or one-off tools</p>
</li>
<li><p>Making small, well-scoped changes to familiar code</p>
</li>
<li><p>Speed matters more than thoroughness</p>
</li>
<li><p>You will review the output carefully yourself anyway</p>
</li>
</ul>
<h2 id="heading-getting-started">Getting Started</h2>
<p>Claude Forge is built entirely from Claude Code custom skills. No external tooling, no CI integration required. Install by copying the skills directory into your project:</p>
<pre><code class="language-bash">git clone https://github.com/hatmanstack/claude-forge.git
cp -r claude-forge/.claude/skills/ /path/to/your-project/.claude/skills/
</code></pre>
<p>Then in your project:</p>
<pre><code class="language-bash"># Feature development
/brainstorm I want to add webhook support for payment events
/pipeline 2026-03-12-payment-webhooks

# Full audit (health + eval + docs), one command
/audit all
/pipeline 2026-03-16-audit-remediation

# Individual audits
/repo-eval
/repo-health
/doc-health
</code></pre>
<p>The pipeline handles the orchestration. You'll see progress reports between stages, and it will stop and ask when something needs human judgment.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>The adversarial pattern (separate generator and discriminator with isolated context windows, structured feedback as the communication channel, iteration caps for convergence) can be implemented in any agent system that supports subagent spawning with fresh contexts. The specific implementation uses Claude Code skills, but the pattern is the contribution, not the tooling.</p>
<p>Sometimes the best code comes from the argument, not the agreement.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use SonarQube to Improve Your Code Quality ]]>
                </title>
                <description>
                    <![CDATA[ SonarQube is a powerful open-source tool that helps you maintain code quality and security by analyzing your codebase for bugs and vulnerabilities. And it can play a major role when integrated into your CI/CD pipeline. In this tutorial, we will cover... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-improve-your-code-quality-with-sonarqube/</link>
                <guid isPermaLink="false">6815023dec2e34790eeb71a8</guid>
                
                    <category>
                        <![CDATA[ sonarqube ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ci-cd ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Divya Valsala Saratchandran ]]>
                </dc:creator>
                <pubDate>Fri, 02 May 2025 17:34:53 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746207275407/7b0da6c9-9bd7-40ca-853e-b1f7957acf3b.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>SonarQube is a powerful open-source tool that helps you maintain code quality and security by analyzing your codebase for bugs and vulnerabilities. And it can play a major role when integrated into your CI/CD pipeline.</p>
<p>In this tutorial, we will cover:</p>
<ol>
<li><p>What is SonarQube?</p>
</li>
<li><p>How SonarQube Improves Code Quality</p>
</li>
<li><p>Step-by-step Installation and Configuration</p>
</li>
<li><p>How to Run Your First Code Analysis</p>
</li>
</ol>
<h2 id="heading-what-is-sonarqube">What is SonarQube?</h2>
<p>SonarQube is an open-source tool that checks for code quality continuously. It analyzes code to find issues like duplication, bad practices, test coverage gaps, bugs, and vulnerabilities, giving detailed reports. It works with many programming languages like Java, C#, JavaScript, Python, TypeScript, and Kotlin.</p>
<p>You can add SonarQube to your CI/CD pipelines, IDEs, and version control systems like GitHub, GitLab, or Bitbucket. It provides detailed dashboards that show metrics, trends, and issues in your code.</p>
<p>You can use custom rules to enforce coding standards and reduce technical debt. SonarQube also supports code coverage analysis to help teams improve their tests. With the Quality Gate feature, teams can ensure only clean, maintainable code goes into production.</p>
<p>SonarQube offers both free and paid versions to suit any team size. Overall, it helps improve software quality and encourages good coding practices.</p>
<h2 id="heading-how-does-sonarqube-improve-code-quality">How Does SonarQube Improve Code Quality?</h2>
<p>Here’s how SonarQube helps improve code quality:</p>
<ol>
<li><p><strong>Early bug detection:</strong> Identifies bugs before they reach production</p>
</li>
<li><p><strong>Improved maintainability:</strong> Highlights code and design issues</p>
</li>
<li><p><strong>Security insights:</strong> Identifies vulnerabilities and security risks</p>
</li>
<li><p><strong>Code coverage:</strong> Integration with testing tools to monitor unit test coverage</p>
</li>
<li><p><strong>Customizable rules:</strong> Allows teams to set coding standards and policies</p>
</li>
<li><p><strong>Team collaboration:</strong> Ensures consistent code quality across development teams</p>
</li>
</ol>
<h2 id="heading-step-by-step-installation-and-configuration">Step-by-Step Installation and Configuration</h2>
<h3 id="heading-prerequisites"><strong>Prerequisites:</strong></h3>
<p>Here are the prerequisites that you will need before installing SonarQube</p>
<ol>
<li><p><strong>Java Runtime Environment(JRE)</strong>: Java 11 or above installed in your system.</p>
</li>
<li><p><strong>System Requirements</strong>: 2GB RAM minimum (Recommended: 4GB+).</p>
</li>
<li><p><strong>MacOS</strong>: You can use HomeBrew, which is the package manager for MacOS that simplifies the installation of software.</p>
</li>
</ol>
<p>Below are the steps to install SonarQube in your local machine:</p>
<h3 id="heading-download-sonarqube"><strong>Download SonarQube</strong></h3>
<p>Download the software from <a target="_blank" href="https://www.sonarsource.com/products/sonarqube/downloads/">sonarsource downloads</a> and choose the <em>Community Edition</em> for open-source projects.</p>
<h3 id="heading-extract-and-configure"><strong>Extract and Configure</strong></h3>
<p>To install SonarQube, you need to run the below command to unzip the file:</p>
<pre><code class="lang-bash">unzip sonarqube-&lt;version&gt;.zip
<span class="hljs-built_in">cd</span> sonarqube-&lt;version&gt;/bin/&lt;your-OS-folder&gt;
</code></pre>
<h3 id="heading-start-sonarqube"><strong>Start SonarQube</strong></h3>
<p>On Linux/Mac, you need to run the below command:</p>
<pre><code class="lang-bash">./sonar.sh start
</code></pre>
<p>On Windows, you need to run this one:</p>
<pre><code class="lang-plaintext">StartSonar.bat
</code></pre>
<h3 id="heading-access-sonarqube"><strong>Access SonarQube</strong></h3>
<p>To access SonarQube, you need to open browser and go to: <a target="_blank" href="http://localhost:9000">http://localhost:9000</a></p>
<p>Enter the default credentials:</p>
<ul>
<li><p><strong>Username:</strong> <code>admin</code></p>
</li>
<li><p><strong>Password:</strong> <code>admin</code> (you’ll be prompted to change it)</p>
</li>
</ul>
<p>The page will look similar to below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746152681985/0b1829cb-bd2a-4961-bc69-18f5d677d9dd.png" alt="SonarQube project creation page" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-set-up-sonarqube-in-your-project">Set Up SonarQube in Your Project</h3>
<p>To set up SonarQube in your project, start by opening the Java project on your machine. In the project root, create a <strong>sonar-project.properties</strong> file.</p>
<p>Add the below key value pairs in the file:</p>
<pre><code class="lang-bash">sonar.projectKey=spring-myproject
sonar.projectName=My Project
sonar.projectVersion=1.0
sonar.sources=.
sonar.host.url=http://localhost:9000
</code></pre>
<h2 id="heading-how-to-run-your-first-code-analysis">How to Run Your First Code Analysis</h2>
<h3 id="heading-configure-and-run-sonarscanner">Configure and Run SonarScanner</h3>
<p>SonarScanner is the tool that actually sends your code to SonarQube for analysis. Below are the detailed steps to follow to use it:</p>
<h4 id="heading-install-sonarscanner">Install SonarScanner:</h4>
<p>On Windows/Linux, download the software from <a target="_blank" href="https://docs.sonarsource.com/sonarqube-server/10.4/analyzing-source-code/scanners/sonarscanner/">SonarSource</a> and unzip it:</p>
<pre><code class="lang-bash">unzip sonar-scanner-cli-&lt;version&gt;.zip
</code></pre>
<p>On MacOS, run the below command:</p>
<pre><code class="lang-plaintext">&gt;brew install sonar-scanner
</code></pre>
<p>For both Windows/Linux and MacOS, verify the install by running the below command:</p>
<pre><code class="lang-plaintext">&gt;sonar-scanner -v
</code></pre>
<h4 id="heading-configure-sonarscanner">Configure SonarScanner</h4>
<p>After installing SonarScanner, you’ll need to configure it by setting the <strong>SonarQube server</strong> URL and <strong>authentication token</strong>. Then go to your SonarQube profile (top-right corner &gt; My Account &gt; Security) and generate a token.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746154994148/02ccf0cd-68ce-4447-bb1f-12ff04cd9e59.png" alt="Generate tokens in SolarQube" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Provide a name for the token and click ‘Generate’:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746155102747/834dcbac-070e-4958-9cb7-44a738059343.png" alt="Name token and then generate" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In the <code>sonar-project.properties</code> file in your project, add ‘sonar.login’ property and save.</p>
<pre><code class="lang-plaintext">sonar.projectKey=test-project
sonar.projectName=Test Project
sonar.host.url=http://localhost:9000
sonar.login=&lt;YOUR_TOKEN_HERE&gt;
</code></pre>
<h4 id="heading-run-the-analysis">Run the Analysis</h4>
<p>Once the SonarScanner is configured, you can start scanning your project.</p>
<p>In a terminal or command prompt, go to the root of your project (where sonar-project.properties is located).</p>
<p>Run the following command:</p>
<pre><code class="lang-plaintext">&gt;sonar-scanner
</code></pre>
<p>SonarScanner will analyze your code and push the results to your local SonarQube server. Visit <code>http://localhost:9000</code>, and you’ll see your project listed on the dashboard.</p>
<ul>
<li><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746151289131/d2794dc7-1a53-4787-8137-668849d50d2b.png" alt="Scanner results dashboard" class="image--center mx-auto" width="600" height="400" loading="lazy"></li>
</ul>
<p>To view the analysis report, go to <a target="_blank" href="http://localhost:9000/dashboard?id=java-sonar-demo">http://localhost:9000/dashboard?id=java-sonar-demo</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746151477685/931d1170-3c90-45d2-ab07-b60b551f3856.png" alt="Analysis results" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>If you go to the ‘Issues’ tab at top left corner, you can view different categories of Software Quality, Severity of the Issues, and various other attributes in your code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746151632987/090c61d0-0a37-4bb1-82a1-76f149a4cc86.png" alt="Detailed results" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Now you have installed and configured SonarQube and learned how to scan your code using SonarScanner. You can easily configure it in your projects for continuous code quality analysis.</p>
<p>This is a fantastic tool for keeping your code base clean and maintainable. As the next steps, you can consider adding test coverage reports, enforcing quality gates in your pipeline, and exploring SonarCloud for cloud-based analysis.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Debug and Prevent Buffer Overflows in Embedded Systems ]]>
                </title>
                <description>
                    <![CDATA[ Buffer overflows are one of the most serious software bugs, especially in embedded systems, where hardware limitations and real-time execution make them hard to detect and fix. A buffer overflow happens when a program writes more data into a buffer t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-debug-and-prevent-buffer-overflows-in-embedded-systems/</link>
                <guid isPermaLink="false">67d84f228d156200bc7d3d8c</guid>
                
                    <category>
                        <![CDATA[ embedded systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ embedded ]]>
                    </category>
                
                    <category>
                        <![CDATA[ memory-management ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Buffer Overfow ]]>
                    </category>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Firmware Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming basics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ C ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Coding Best Practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Soham Banerjee ]]>
                </dc:creator>
                <pubDate>Mon, 17 Mar 2025 16:34:42 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742229245130/858b21cc-443e-43ee-82ce-091438f6c5c0.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Buffer overflows are one of the most serious software bugs, especially in embedded systems, where hardware limitations and real-time execution make them hard to detect and fix.</p>
<p>A buffer overflow happens when a program writes more data into a buffer than it was allocated, leading to memory corruption, crashes, or even security vulnerabilities. A buffer corruption occurs when unintended modifications overwrite unread data or modify memory in unexpected ways.</p>
<p>In safety-critical systems like cars, medical devices, and spacecraft, buffer overflows can cause life-threatening failures. Unlike simple software bugs, buffer overflows are unpredictable and depend on the state of the system, making them difficult to diagnose and debug.</p>
<p>To prevent these issues, it's important to understand how buffer overflows and corruptions occur, and how to detect and fix them.</p>
<h2 id="heading-article-scope">Article Scope</h2>
<p>In this article, you will learn:</p>
<ol>
<li><p>What buffers, buffer overflows, and corruptions are. I’ll give you a beginner-friendly explanation with real-world examples.</p>
</li>
<li><p>How to debug buffer overflows. You’ll learn how to use tools like GDB, LLDB, and memory maps to find memory corruption.</p>
</li>
<li><p>How to prevent buffer overflows. We’ll cover some best practices like input validation, safe memory handling, and defensive programming.</p>
</li>
</ol>
<p>I’ll also show you some hands-on code examples – simple C programs that demonstrate buffer overflow issues and how to fix them.</p>
<p>What this article doesn’t cover:</p>
<ol>
<li><p>Security exploits and hacking techniques. We’ll focus on preventing accidental overflows, not hacking-related buffer overflows.</p>
</li>
<li><p>Operating system-specific issues. This guide is for embedded systems, not general-purpose computers or servers.</p>
</li>
<li><p>Advanced RTOS memory management. While we discuss interrupt-driven overflows, we won’t dive deep into real-time operating system (RTOS) concepts.</p>
</li>
</ol>
<p>Now that you know what this article covers (and what it doesn’t), let’s go over the skills that will help you get the most out of it.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>This article is designed for developers who have some experience with C programming and want to understand how to debug and prevent buffer overflows in embedded systems. Still, beginners can follow along, as I’ll explain key concepts in a clear and structured way.</p>
<p>Before reading, it helps if you know:</p>
<ol>
<li><p>Basic C programming.</p>
</li>
<li><p>How memory works – the difference between stack, heap, and global variables.</p>
</li>
<li><p>Basic debugging concepts – if you’ve used a debugger like GDB or LLDB, that’s a plus, but not required.</p>
</li>
<li><p>What embedded systems are – a basic idea of how microcontrollers store and manage memory.</p>
</li>
</ol>
<p>Even if you’re not familiar with these topics, this guide will walk you through them in an easy-to-understand way.</p>
<p>Before you dive into buffer overflows, debugging, and prevention, let’s take a step back and understand what a buffer is and why it’s important in embedded systems. Buffers play a crucial role in managing data flow between hardware and software but when handled incorrectly, they can lead to serious software failures.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-buffer-and-how-does-it-work">What is a Buffer, and How Does it Work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-buffer-overflow">What is a Buffer Overflow?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-causes-of-buffer-overflows-and-corruption">Common Causes of Buffer Overflows and Corruption</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-consequences-of-buffer-overflows">Consequences of Buffer Overflows</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-debug-buffer-overflows">How to Debug Buffer Overflows</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prevent-buffer-overflows">How to Prevent Buffer Overflows</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-a-buffer-and-how-does-it-work">What is a Buffer, and How Does it Work?</h2>
<p>A buffer is a contiguous block of memory used to temporarily store data before it is processed. Buffers are commonly used in two scenarios:</p>
<ol>
<li><p>Data accumulation: When the system needs to collect a certain amount of data before processing.</p>
</li>
<li><p>Rate matching: When the data producer generates data faster than the data consumer can process it.</p>
</li>
</ol>
<p>Buffers are typically implemented as arrays in C, where elements are indexed from 0 to N-1 (where N is the buffer size).</p>
<p>Let’s look at an example of a buffer in a sensor system.</p>
<p>Consider a system with a sensor task that generates data at 400 Hz (400 samples per second or 1 sample every 2.5 ms). But the data processor (consumer) operates at only 100 Hz (100 samples per second or 1 sample every 10 ms). Since the consumer task is slower than the producer, we need a buffer to store incoming data until it is processed.</p>
<p>To determine the buffer size, we calculate:</p>
<p>Buffer Size = Time to consume 1 sample / Time to generate 1 sample = 10 ms/ 2.5 ms = 4</p>
<p>This means the buffer must hold at least 4 samples at a time to avoid data loss.</p>
<p>Once the buffer reaches capacity, there are several strategies to decide which data gets passed to the consumer task:</p>
<ol>
<li><p>Max/min sampling: Use the maximum or minimum value in the buffer.</p>
</li>
<li><p>Averaging: Compute the average of all values in the buffer.</p>
</li>
<li><p>Random access: Pick a sample from a specific location (for example, the most recent or the first).</p>
</li>
</ol>
<p>In real-world applications, it’s beneficial to use circular buffers or double buffering to prevent data corruption.</p>
<ul>
<li><p>Circular buffer approach: A circular buffer (also called a ring buffer) continuously wraps around when it reaches the end, ensuring old data is overwritten safely without exceeding memory boundaries. The buffer size should be multiplied by 2 (4 × 2 = 8) to hold 8 samples. This allows the consumer task to process 4 samples while the next 4 samples are being filled, preventing data overwrites.</p>
</li>
<li><p>Double buffer approach: Double buffering is useful when data loss is unacceptable. It allows continuous data capture while the processor is busy handling previous data. A second buffer of the same size is added. When the first buffer is full, the write pointer switches to the second buffer, allowing the consumer task to process data from the first buffer while the second buffer is being filled. This prevents data overwrites and ensures a continuous data flow.</p>
</li>
</ul>
<p>Buffers help manage data efficiently, but what happens when they are mismanaged? This is where buffer overflows and corruptions come into play.</p>
<h2 id="heading-what-is-a-buffer-overflow">What is a Buffer Overflow?</h2>
<p>A buffer overflow occurs when a program writes more data into a buffer than it was allocated, causing unintended memory corruption. This can lead to unpredictable behavior, ranging from minor bugs to critical system failures.</p>
<p>To understand buffer overflow, let's use a simple analogy. Imagine a jug with a tap near the bottom. The jug represents a buffer, while the tap controls how much liquid (data) is consumed.</p>
<p>The jug is designed to hold a fixed amount of liquid. As long as water flows into the jug at the same rate or slower than it flows out, everything works fine. But if water flows in faster than it flows out, the jug will eventually overflow.</p>
<p>Similarly, in software, if data enters a buffer faster than it is processed, it exceeds the allocated memory space, causing a buffer overflow. In the case of a circular buffer, this can cause the write pointer to wrap around and overwrite unread data, leading to buffer corruption.</p>
<h3 id="heading-buffer-overflows-in-software">Buffer Overflows in Software</h3>
<p>Unlike the jug, where water simply spills over, a buffer overflow in software overwrites adjacent memory locations. This can cause a variety of hard-to-diagnose issues, including:</p>
<ol>
<li><p>Corrupting other data stored nearby.</p>
</li>
<li><p>Altering program execution, leading to crashes.</p>
</li>
<li><p>Security vulnerabilities, where attackers exploit overflows to inject malicious code.</p>
</li>
</ol>
<p>When a buffer overflow occurs, data can overwrite variables, function pointers, or even return addresses, depending on where the buffer is allocated.</p>
<p>Buffer overflows can occur in different memory regions:</p>
<ol>
<li><p>Buffer overflows in global/static memory (.bss / .data sections)</p>
<ul>
<li><p>These occur when global or static variables exceed their allocated size.</p>
</li>
<li><p>The overflow can corrupt adjacent variables, leading to unexpected behavior in other modules.</p>
</li>
<li><p>Debugging is easier because memory addresses are fixed at compile time unless the compiler optimizes them. Map files provide a memory layout of variables during the compilation and linking.</p>
</li>
</ul>
</li>
<li><p>Stack-based buffer overflow (more predictable, easier to debug):</p>
<ul>
<li><p>Happens when a buffer is allocated in the stack (for example, local variables inside functions).</p>
</li>
<li><p>Overflowing the stack can affect adjacent local variables or return addresses, potentially crashing the program.</p>
</li>
<li><p>In embedded systems with small stack sizes, this often leads to a crash or execution of unintended code.</p>
</li>
</ul>
</li>
<li><p>Heap-based buffer overflow (harder to debug):</p>
<ul>
<li><p>Happens when a buffer is dynamically allocated in the heap (for example, using malloc() in C).</p>
</li>
<li><p>Overflowing a heap buffer can corrupt adjacent dynamically allocated objects or heap management structures.</p>
</li>
<li><p>Debugging is harder because heap memory is allocated dynamically at runtime, causing memory locations to vary.</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-buffer-overflow-vs-buffer-corruption">Buffer Overflow vs Buffer Corruption</h4>
<p>Buffer overflow and buffer corruption are of course related, but refer to different situations.</p>
<p>A buffer overflow happens when data is written beyond the allocated buffer size, leading to memory corruption, unpredictable behavior, or system crashes.</p>
<p>A buffer corruption happens when unintended data modifications result in unexpected software failures, even if the write remains within buffer boundaries.</p>
<p>Both issues typically result from poor write pointer management, lack of boundary checks, and unexpected system behavior.</p>
<p>Now that we've covered what a buffer overflow is and how it can overwrite memory, let’s take a closer look at how these issues affect embedded systems.</p>
<p>In the next section, we’ll explore how buffer overflows and corruption happen in real-world embedded systems and break down common causes, including pointer mismanagement and boundary violations.</p>
<h2 id="heading-common-causes-of-buffer-overflows-and-corruption">Common Causes of Buffer Overflows and Corruption</h2>
<p>Embedded systems use buffers to store data from sensors, communication interfaces (like UART (Universal Asynchronous Receiver-Transmitter), SPI (Serial Peripheral Interface), I2C (Inter-integrated Circuit), and real-time tasks. These buffers are often statically allocated to avoid memory fragmentation, and many implementations use circular (ring) buffers to efficiently handle continuous data streams.</p>
<p>Here are three common scenarios where buffer overflows or corruptions occur in embedded systems:</p>
<h3 id="heading-writing-data-larger-than-the-available-space">Writing Data Larger Than the Available Space</h3>
<p><strong>Issue</strong>: The software writes incoming data to the buffer without checking if there is enough space.</p>
<p><strong>Example</strong>: Imagine a 100-byte buffer to store sensor data. The buffer receives variable-sized packets. If an incoming packet is larger than the remaining space, it will overwrite adjacent memory, leading to corruption.</p>
<p>So why does this happen?</p>
<ul>
<li><p>Some embedded designs increment the write pointer after copying data, making it too late to prevent overflow.</p>
</li>
<li><p>Many low-level memory functions (memcpy, strcpy, etc.) do not check buffer boundaries, leading to unintended writes.</p>
</li>
<li><p>Without proper bound checking, a large write can exceed the buffer size and corrupt nearby memory.</p>
</li>
</ul>
<p>Here’s a code sample to demonstrate buffer overflow in a .bss / .data section:</p>
<pre><code class="lang-c">  <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdint.h&gt;</span></span>
  <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
  <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string.h&gt;</span></span>

  <span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> BUFFER_SIZE 300</span>

  <span class="hljs-keyword">static</span> <span class="hljs-keyword">uint16_t</span> sample_count = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">uint8_t</span> buffer[BUFFER_SIZE] = {<span class="hljs-number">0</span>};

  <span class="hljs-comment">// Function to simulate a buffer overflow scenario</span>
  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">updateBufferWithData</span><span class="hljs-params">(<span class="hljs-keyword">uint8_t</span> *data, <span class="hljs-keyword">uint16_t</span> size)</span>
  </span>{
      <span class="hljs-comment">// Simulating a buffer overflow: No boundary check!</span>
      <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Attempting to write %d bytes at position %d...\n"</span>, size, sample_count);

      <span class="hljs-comment">// Deliberate buffer overflow for demonstration</span>
      <span class="hljs-keyword">if</span> (sample_count + size &gt; BUFFER_SIZE)
      {
          <span class="hljs-built_in">printf</span>(<span class="hljs-string">"WARNING: Buffer Overflow Occurred! Writing beyond allocated memory!\n"</span>);
      }

      <span class="hljs-comment">// Copy data (unsafe, can cause overflow)</span>
      <span class="hljs-built_in">memcpy</span>(&amp;buffer[sample_count], data, size);

      <span class="hljs-comment">// Increment sample count (incorrectly, leading to wraparound issues)</span>
      sample_count += size;
  }

  <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
  </span>{   
      <span class="hljs-comment">// Save 1 byte to buffer</span>
      <span class="hljs-keyword">uint8_t</span> data_to_buffer = <span class="hljs-number">10</span>;
      updateBufferWithData(&amp;data_to_buffer, <span class="hljs-number">1</span>);

      <span class="hljs-comment">// Save an array of 20 bytes to buffer</span>
      <span class="hljs-keyword">uint8_t</span> data_to_buffer_1[<span class="hljs-number">20</span>] = {<span class="hljs-number">5</span>};
      updateBufferWithData(data_to_buffer_1, <span class="hljs-keyword">sizeof</span>(data_to_buffer_1));

      <span class="hljs-comment">// Intentional buffer overflow: Save an array of 50 x 8 bytes (400 bytes)</span>
      <span class="hljs-keyword">uint64_t</span> data_to_buffer_2[<span class="hljs-number">50</span>] = {<span class="hljs-number">7</span>};
      updateBufferWithData((<span class="hljs-keyword">uint8_t</span>*)data_to_buffer_2, <span class="hljs-keyword">sizeof</span>(data_to_buffer_2));

      <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
  }
</code></pre>
<h3 id="heading-interrupt-driven-overflows-real-time-systems">Interrupt-Driven Overflows (Real-time Systems)</h3>
<p><strong>Issue</strong>: The interrupt service routine (ISR) may write data faster than the main task can process, leading to buffer corruption or buffer overflow if the write pointer is not properly managed.</p>
<p><strong>Example</strong>: Imagine a sensor ISR that writes incoming data into a buffer every time a new reading arrives. Meanwhile, a low-priority processing task reads and processes the data.</p>
<p>What can go wrong?</p>
<ul>
<li><p>If the ISR triggers too frequently (due to a misbehaving sensor or high interrupt priority), the buffer may fill up faster than the processing task can keep up.</p>
</li>
<li><p>This can result in one of two failures:</p>
<ol>
<li><p>Buffer Corruption: The ISR overwrites unread data, leading to loss of information.</p>
</li>
<li><p>Buffer Overflow: The ISR exceeds buffer boundaries, causing memory corruption or system crashes.</p>
</li>
</ol>
</li>
</ul>
<p>So why does this happen?</p>
<ul>
<li><p>In real-time embedded systems, ISR execution preempts lower-priority tasks.</p>
</li>
<li><p>If the processing task doesn't not get enough CPU time, the buffer may become overwritten or overflow beyond its allocated scope.</p>
</li>
</ul>
<h3 id="heading-system-state-changes-amp-buffer-corruption">System State Changes &amp; Buffer Corruption</h3>
<p><strong>Issue</strong>: The system may unexpectedly reset, enter low-power mode, or changes operating state, leaving the buffer write pointers in an inconsistent state. This can result in buffer corruption (stale or incorrect data) or buffer overflow (writing past the buffer’s limits.</p>
<p><strong>Example Scenarios</strong>:</p>
<ol>
<li><p>Low-power wake-up issue (Buffer Overflow risk): Some embedded systems enter deep sleep to conserve energy. Upon waking up, if the buffer write pointer is not correctly reinitialized, it may point outside buffer boundaries, leading to buffer overflow and unintended memory corruption.</p>
</li>
<li><p>Unexpected mode transitions: If a sensor task is writing data and the system suddenly switches modes, the buffer states and pointers may not be cleaned up. The next time the sensor task runs, it may continue writing without clearing previous data. This can cause undefined behavior due to presence of stale data.</p>
</li>
</ol>
<p>Now that you understand how buffer overflows and corruptions happen, let’s examine their consequences in embedded systems ranging from incorrect sensor readings to complete system failures, making debugging and prevention critical.</p>
<h2 id="heading-consequences-of-buffer-overflows">Consequences of Buffer Overflows</h2>
<p>Buffer overflows can be catastrophic in embedded systems, leading to system crashes, data corruption, and unpredictable behavior. Unlike general-purpose computers, many embedded devices lack memory protection, making them particularly vulnerable to buffer overflows.</p>
<p>A buffer overflow can corrupt two critical types of memory:</p>
<h3 id="heading-1-data-variables-corruption">1. Data Variables Corruption</h3>
<p>A buffer overflow can overwrite data variables, corrupting the inputs for other software modules. This can cause unexpected behavior or even system crashes if critical parameters are modified.</p>
<p>For example, a buffer overflow could accidentally overwrite a sensor calibration value stored in memory. As a result, the system would start using incorrect sensor readings, leading to faulty operation and potentially unsafe conditions.</p>
<h3 id="heading-2-function-pointer-corruption">2. Function Pointer Corruption</h3>
<p>In embedded systems, function pointers are often used for interrupt handlers, callback functions, and RTOS task scheduling. If a buffer overflow corrupts a function pointer, the system may execute unintended instructions, leading to a crash or unexpected behavior.</p>
<p>As an example, a function pointer controlling motor speed regulation could be overwritten. Instead of executing the correct function, the system would jump to a random memory address, causing a system fault or erratic motor behavior.</p>
<p>Buffer overflows are among the hardest bugs to identify and fix because their effects depend on which data is corrupted and the values it contains. A buffer overflow can affect memory in different ways:</p>
<ul>
<li><p>If a buffer overflow corrupts unused memory, the system may seem fine during testing, making the issue harder to detect.</p>
</li>
<li><p>if a buffer overflow alters critical data variables, it can cause hidden logic errors that cause unpredictable behavior.</p>
</li>
<li><p>If a buffer overflow corrupts function pointers, it may crash immediately, making the problem easier to identify.</p>
</li>
</ul>
<p>During development, if tests focus only on detecting crashes, they may overlook silent memory corruption caused by a buffer overflow. In real-world deployments, new use cases not covered in testing can trigger previously undetected buffer overflow issues, leading to unpredictable failures.</p>
<p>Buffer overflows can cause a chain reaction, where one overflow leads to another overflow or buffer corruption, resulting in widespread system failures. So how does this happen?</p>
<ol>
<li><p>A buffer overflow corrupts a critical variable (for example, a timer interval).</p>
</li>
<li><p>The corrupted variable disrupts another module (for example, triggers the timer interrupt too frequently, causing it to push more data into a buffer than intended.).</p>
</li>
<li><p>This increased interrupt frequency forces a sensor task to write data faster than intended, eventually causing another buffer overflow or corruption by overwriting unread data.</p>
</li>
</ol>
<p>This chain reaction can spread across multiple software modules, making debugging nearly impossible. In real-word applications, buffer overflows in embedded systems can be life-threatening:</p>
<ul>
<li><p>In cars: A buffer overflow in an ECU (Electronic Control Unit) could cause brake failure or unintended acceleration.</p>
</li>
<li><p>In a spacecraft: A memory corruption issue could disable navigation systems, leading to mission failure.</p>
</li>
</ul>
<p>Now that we’ve seen how buffer overflows can corrupt memory, disrupt system behavior, and even cause critical failures, the next step is understanding how to detect and fix them before they lead to serious issues.</p>
<h2 id="heading-how-to-debug-buffer-overflows">How to Debug Buffer Overflows</h2>
<p>Debugging buffer overflows in embedded systems can be complex, as their effects range from immediate crashes to silent data corruption, making them difficult to trace. A buffer overflow can cause either:</p>
<ol>
<li><p>A system crash, which is easier to detect since it halts execution or forces a system reboot.</p>
</li>
<li><p>Unexpected behavior, which is much harder to debug as it requires tracing how corrupted data affects different modules.</p>
</li>
</ol>
<p>This section focuses on embedded system debugging techniques using memory map files, debuggers (GDB/LLDB), and a structured debugging approach. Let’s look into the debuggers and memory map files.</p>
<h3 id="heading-memory-map-file-map-file">Memory Map File (.map file)</h3>
<p>A memory map file is generated during the linking process. It provides a memory layout of global/static variables, function addresses, and heap/stack locations. It provides a memory layout of Flash and RAM, including:</p>
<ul>
<li><p>Text section (.text): Stores executable code.</p>
</li>
<li><p>Read-only section (.rodata): Stores constants and string literals.</p>
</li>
<li><p>BSS section (.bss): Stores uninitialized global and static variables.</p>
</li>
<li><p>Data section (.data): Stores initialized global and static variables.</p>
</li>
<li><p>Heap and stack locations, depending on the linker script.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739064875727/1e01992d-4d9d-42fb-b971-6f4e92452c22.png" alt="Figure 1: A visual of the memory layout" class="image--center mx-auto" width="1256" height="425" loading="lazy"></p>
<p>If a buffer overflow corrupts a global variable, the .map file can identify nearby variables that may also be affected, provided the compiler has not optimized the memory allocation. Similarly, if a function pointer is corrupted, the .map file can reveal where it was stored in memory.</p>
<h3 id="heading-debuggers-gdb-amp-lldb">Debuggers (GDB &amp; LLDB)</h3>
<p>Debugging tools like GDB (GNU Debugger) and LLDB (LLVM Debugger) allow:</p>
<ul>
<li><p>Controlling execution (breakpoints, stepping through code).</p>
</li>
<li><p>Inspecting variable values and memory addresses.</p>
</li>
<li><p>Getting backtraces (viewing function calls before a crash).</p>
</li>
<li><p>Extracting core dumps from microcontrollers for post-mortem analysis.</p>
</li>
</ul>
<p>If the system halts on a crash, a backtrace (bt command in GDB) can reveal which function was executing before failure. If the overflow affects a heap-allocated variable, GDB can inspect heap memory usage to detect corruption.</p>
<h3 id="heading-the-debugging-process">The Debugging Process</h3>
<p>Now, let’s go through a step-by-step debugging process to identify and fix buffer overflows. Once a crash or unexpected behavior occurs, follow these techniques to trace the root cause:</p>
<h4 id="heading-step-1-identify-the-misbehaving-module">Step 1: Identify the misbehaving module</h4>
<p>If the system crashes, use GDB or LLDB backtrace (bt command) to locate the last executed function. If the system behaves unexpectedly, determine which software module controls the affected functionality.</p>
<h4 id="heading-step-2-analyze-inputs-and-outputs-of-the-module">Step 2: Analyze inputs and outputs of the module</h4>
<p>Every function or module has inputs and outputs. Create a truth table listing expected outputs for all possible inputs. Check if the unexpected behavior matches any undefined input combination, which may indicate corruption.</p>
<h4 id="heading-step-3-locate-memory-corruption-using-address-analysis">Step 3: Locate memory corruption using address analysis</h4>
<p>If a variable shows incorrect values, determine its physical memory location. Depending on where the variable is stored:</p>
<ol>
<li><p>Global/static variables (.bss / .data): Look up the memory map file for nearby buffers.</p>
</li>
<li><p>Heap variables: Snapshot heap allocations using GDB.  </p>
<p> Here’s an example of using GDB to find corrupted variables:</p>
<pre><code class="lang-c"> (gdb) print &amp;my_variable  # Get memory address of the variable
 $<span class="hljs-number">1</span> = (<span class="hljs-keyword">int</span> *) <span class="hljs-number">0x20001000</span>
 (gdb) x/<span class="hljs-number">10</span>x <span class="hljs-number">0x20001000</span>   # Examine memory near <span class="hljs-keyword">this</span> address, Display <span class="hljs-number">10</span> memory words in hexadecimal format starting from <span class="hljs-number">0x20001000</span>
</code></pre>
</li>
</ol>
<h4 id="heading-step-4-identify-the-overflowing-buffer">Step 4: Identify the overflowing buffer</h4>
<p>If a buffer is located just before the corrupted variable, inspect its usage in the code. Review all possible code paths that write to the buffer. Check if any design limitations could cause an overflow under a specific use cases.</p>
<h4 id="heading-step-5-fix-the-root-cause">Step 5: Fix the root cause</h4>
<p>If the buffer overflow happened due to missing bounds checks, add proper input validation to prevent it. Buffer design should enforce strict memory limits. The module should implement strict boundary checks for all inputs and maintain a consistent state.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739065828677/74322607-5997-4275-87d0-b3d0acf54373.png" alt="Figure 2: Steps to debug a buffer overflow" class="image--center mx-auto" width="1105" height="325" loading="lazy"></p>
<p>In addition to GDB/LLDB, you can also use techniques like hardware tracing and fault injection to simulate buffer overflows and observe system behavior in real-time.</p>
<p>While debugging helps identify and fix buffer overflows, prevention is always the best approach. Let’s explore techniques that can help avoid buffer overflows altogether.</p>
<h2 id="heading-how-to-prevent-buffer-overflows">How to Prevent Buffer Overflows</h2>
<p>You can often prevent buffer overflows through good software design, defensive programming, hardware protections, and rigorous testing. Embedded systems, unlike general-purpose computers, often lack memory protection mechanisms, which means that buffer overflow prevention critical for system reliability and security.</p>
<p>Here are some key techniques to help prevent buffer overflows:</p>
<h3 id="heading-defensive-programming">Defensive Programming</h3>
<p>Defensive programming helps minimize buffer overflow risks by ensuring all inputs are validated and unexpected conditions are handled safely.</p>
<p>First, it’s crucial to validate input size before writing to a buffer. Always check the write index by adding the size of data to be written prior to writing data to make sure more data is not written than the available buffer space.</p>
<p>Then you’ll want to make sure you have proper error handling and fail-safe mechanisms in place. If an input is invalid, halt execution, log the error, or switch to a safe state. Also, functions should indicate success/failure with helpful error codes to prevent misuse.</p>
<p>Sample Code:</p>
<pre><code class="lang-c">   <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdint.h&gt;</span></span>
   <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string.h&gt;</span></span>
   <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdbool.h&gt;</span></span>
   <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

   <span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> BUFFER_SIZE 300</span>

   <span class="hljs-keyword">static</span> <span class="hljs-keyword">uint16_t</span> sample_count = <span class="hljs-number">0</span>;
   <span class="hljs-keyword">static</span> <span class="hljs-keyword">uint8_t</span> buffer[BUFFER_SIZE] = {<span class="hljs-number">0</span>};

   <span class="hljs-keyword">typedef</span> <span class="hljs-keyword">enum</span>
   {
       SUCCESS = <span class="hljs-number">0</span>,
       NOT_ENOUGH_SPACE = <span class="hljs-number">1</span>,
       DATA_IS_INVALID = <span class="hljs-number">2</span>,
   } buffer_err_code_e;


   <span class="hljs-function">buffer_err_code_e <span class="hljs-title">updateBufferWithData</span><span class="hljs-params">(<span class="hljs-keyword">uint8_t</span> *data, <span class="hljs-keyword">uint16_t</span> size)</span>
   </span>{
       <span class="hljs-keyword">if</span> (data == <span class="hljs-literal">NULL</span> || size == <span class="hljs-number">0</span> || size &gt; BUFFER_SIZE)  
       {
           <span class="hljs-keyword">return</span> DATA_IS_INVALID; <span class="hljs-comment">// Invalid input size</span>
       }

       <span class="hljs-keyword">uint16_t</span> available_space = BUFFER_SIZE - sample_count;
       <span class="hljs-keyword">bool</span> can_write = (available_space &gt;= size) ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;

       <span class="hljs-keyword">if</span> (!can_write)  
       {
           <span class="hljs-keyword">return</span> NOT_ENOUGH_SPACE;
       }

       <span class="hljs-comment">// Copy data safely</span>
       <span class="hljs-built_in">memcpy</span>(&amp;buffer[sample_count], data, size);
       sample_count += size;

       <span class="hljs-keyword">return</span> SUCCESS;
   }

   <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
   </span>{   
       buffer_err_code_e ret;

       <span class="hljs-comment">// Save 1 byte to buffer</span>
       <span class="hljs-keyword">uint8_t</span> data_to_buffer = <span class="hljs-number">10</span>;
       ret = updateBufferWithData(&amp;data_to_buffer, <span class="hljs-keyword">sizeof</span>(data_to_buffer));
       <span class="hljs-keyword">if</span> (ret)  
       {
           <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Buffer update didn't succeed, Err:%d\n"</span>, ret);
       }

       <span class="hljs-comment">// Save an array of 20 bytes to buffer</span>
       <span class="hljs-keyword">uint8_t</span> data_to_buffer_1[<span class="hljs-number">20</span>] = {<span class="hljs-number">5</span>};
       ret = updateBufferWithData(data_to_buffer_1, <span class="hljs-keyword">sizeof</span>(data_to_buffer_1));
       <span class="hljs-keyword">if</span> (ret)  
       {
           <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Buffer update didn't succeed, Err:%d\n"</span>, ret);
       }

       <span class="hljs-comment">// Save an array of 50 x 8 bytes, Intentional buffer overflow</span>
       <span class="hljs-keyword">uint64_t</span> data_to_buffer_2[<span class="hljs-number">50</span>] = {<span class="hljs-number">7</span>};
       ret = updateBufferWithData((<span class="hljs-keyword">uint8_t</span>*)data_to_buffer_2, <span class="hljs-keyword">sizeof</span>(data_to_buffer_2));  
       <span class="hljs-keyword">if</span> (ret)  
       {
           <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Buffer update didn't succeed, Err:%d\n"</span>, ret);
       }

       <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
   }
</code></pre>
<h3 id="heading-choosing-the-right-buffer-design-and-size">Choosing the Right Buffer Design And Size</h3>
<p>Some buffer designs handle overflow better than others. Choosing the correct buffer type and size for the application reduces the risk of corruption.</p>
<ul>
<li><p>Circular Buffers (Ring Buffers) prevent out-of-bounds writes by wrapping around. They overwrite the oldest data instead of corrupting memory. These are useful for real-time streaming data (for example, UART, sensor readings). This approach is ideal for applications where data loss is unacceptable.</p>
</li>
<li><p>Ping-Pong Buffers (Double Buffers) use two buffers. One buffer fills up with data. Then, once it’s full, it switches to the second buffer while the first one is processed. This approach is beneficial for application that have strict requirements on no data loss. The buffer design should be based on the speed of write and read tasks.</p>
</li>
</ul>
<h3 id="heading-hardware-protection">Hardware Protection</h3>
<h4 id="heading-memory-protection-unit-mpu">Memory Protection Unit (MPU)</h4>
<p>An MPU (Memory Protection Unit) helps detect unauthorized memory accesses, including buffer overflows, by restricting which regions of memory can be written to. It prevents buffer overflows from modifying critical memory regions and triggers a MemManage Fault if a process attemps to write outside an allowed region.</p>
<p>But keep in mind that, an MPU does not prevent buffer overflows – it only detects and stops execution when they occur. Not all microcontrollers have an MPU, and some low-end MCUs lack hardware protection, making software-based safeguards even more critical.</p>
<p>Modern C compilers provide several flags to identify memory errors at compile-time:</p>
<ol>
<li><p>-Wall -Wextra: Enables useful warnings</p>
</li>
<li><p>-Warray-bounds: Detects out-of-bounds array access when the array size is known at compile-time</p>
</li>
<li><p>-Wstringop-overflow: Warns about possible overflows in string functions like memcpy and strcpy.</p>
</li>
</ol>
<h3 id="heading-testing-and-validation">Testing and Validation</h3>
<p>Testing helps detect buffer overflows before deployment, reducing the risk of field failures. Unit testing each function independently with valid inputs, boundary cases, and invalid inputs helps detect buffer-related issues early. Automated testing involves feeding random and invalid inputs into the system to uncover crashes and unexpected behavior. Static Analysis Tools like Coverity, Clang Static Analyzer help detect buffer overflows before runtime. Run real-world inputs on embedded hardware to detect issues.</p>
<p>Now that we've explored how to identify, debug, and prevent buffer overflows, it’s clear that these vulnerabilities pose a significant threat to embedded systems. From silent data corruption to catastrophic system failures, the consequences can be severe.</p>
<p>But with the right debugging tools, systematic analysis, and preventive techniques, you can effectively either prevent or mitigate buffer overflows in your systems.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Buffer overflows and corruption are major challenges in embedded systems, leading to crashes, unpredictable behavior, and security risks. Debugging these issues is difficult because their symptoms vary based on system state, requiring systematic analysis using memory map files, GDB/LLDB, and structured debugging approaches.</p>
<p>In this article, we explored:</p>
<ul>
<li><p>The causes and consequences of buffer overflows and corruptions</p>
</li>
<li><p>How to debug buffer overflows using memory analysis and debugging tools</p>
</li>
<li><p>Best practices for prevention</p>
</li>
</ul>
<p>Buffer overflow prevention requires a multi-layered approach:</p>
<ol>
<li><p>Follow a structured software design process to identify risks early.</p>
</li>
<li><p>Apply defensive programming principles to validate inputs and handle errors gracefully.</p>
</li>
<li><p>Use hardware-based protections like MPUs where available.</p>
</li>
<li><p>Enable compiler flags that help identify memory errors.</p>
</li>
<li><p>Test extensively, unit testing, automated testing, and code reviews help catch vulnerabilities early.</p>
</li>
</ol>
<p>By implementing these best practices, you can minimize the risk of buffer overflows in embedded systems, improving reliability and security.</p>
<p>In embedded systems, where reliability and safety are critical, preventing buffer overflows is not just a best practice, it is a necessity. A single buffer overflow can compromise an entire system. Defensive programming, rigorous testing, and hardware protections are essential for building secure and robust embedded applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Improve Your ReactJS Code – Tips for Code Readability and Performance ]]>
                </title>
                <description>
                    <![CDATA[ By Neha sharma ReactJS is one of the most popular JavaScript libraries for building scalable and performant applications.  When you're working on ReactJS projects, whether they're large or small, you'll need to focus on code quality, readability, mai... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/improve-reactjs-code/</link>
                <guid isPermaLink="false">66d4604033b83c4378a51802</guid>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 11 Sep 2023 20:34:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/Group-5.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Neha sharma</p>
<p>ReactJS is one of the most popular JavaScript libraries for building scalable and performant applications. </p>
<p>When you're working on ReactJS projects, whether they're large or small, you'll need to focus on code quality, readability, maintainable, and scalability. </p>
<p>Writing good code will also help you reduce PR comments from your teammates (and let's be honest – who doesn't like comments like LGTM :) ).</p>
<p>In this tutorial, you will learn how to improve your React code. I'll share my favorite tips along with code examples to show you how everything works. These will help you write maintainable, scalable, and readable code.</p>
<p>You should have basic familiarity with React to get the most out of this guide.</p>
<h2 id="heading-1-use-constants">1. Use Constants</h2>
<p>In JavaScript we can declare constants by using the <code>const</code> keyword. This helps us avoid re-declaring the same value. So constants are a great choice for storing API keys and other values like that.</p>
<p>Constants improve the scalability, readability, and internationalization of any React codebase.  </p>
<p>In every ReactJS project, you should avoid hard-coding strings (content) in your components. </p>
<p>This will make your project more maintainable, scalable, and readable, as it isolates the UI, data, and content layers from each other.</p>
<p>Constants include:</p>
<ul>
<li>API keys</li>
<li>URLs</li>
<li>Content</li>
</ul>
<p>Many websites support multiple languages, like English, French, Spanish, and so on. This is known as internationalization (or i18n for short). </p>
<p>If you're enabling i18n features on your site, you should create separate constant files for your content – for example <code>en.js</code> and <code>fr.js</code>. Even if you don't have multiple language support or no i18n, it's still a good idea to keep your content outside your code in a constant file.</p>
<p>You can either name your constant file<code>[LANGUAGE_INITIAL].js</code>, or <code>constants.js</code>. These are the most common file names developers use for this purpose.</p>
<h3 id="heading-how-to-create-your-constant-file">How to create your constant file:</h3>
<p>Constants are simply JavaScript objects with key/values. We start with declaring the object with a name which reflects the content it’s holding. As these are strings, we use quotes to wrap them. Before exporting the messages, do an <code>Object.freeze()</code> – this will avoid any accidental value change from outside any key. </p>
<p>To use the constants, we need to import the file into the component file. Once imported, we can use the dot operator to access the keys:</p>
<pre><code class="lang-Javascript"><span class="hljs-comment">// constants.js or en.js</span>
<span class="hljs-keyword">const</span> MESSAGES = { 
    <span class="hljs-string">'HEADING'</span>: <span class="hljs-string">'welcome to the website",
    '</span>ENTER_YOUR_NAME<span class="hljs-string">': '</span>Enter user name<span class="hljs-string">',
    '</span>HOME<span class="hljs-string">': [{
        '</span>HEADING<span class="hljs-string">': '</span>welcome to the home<span class="hljs-string">'
     }]
}

Object.freeze(MESSAGES);

export default MESSAGES;</span>
</code></pre>
<pre><code class="lang-javaScript">
<span class="hljs-comment">// Using constants.js in component</span>
<span class="hljs-keyword">import</span> MESSAGES <span class="hljs-keyword">from</span> <span class="hljs-string">'../constants/constants

const Home = () =&gt; {
    return(
        &lt;p&gt;{MESSAGES.HEADING}&lt;/h1&gt;
    )
}

export default Home;</span>
</code></pre>
<h2 id="heading-2-use-helpers-utils">2. Use Helpers / Utils</h2>
<p>While working on a ReactJS codebase it's crucial to identify the parts in the code which can be independent utils or helpers, instead of tightly coupling the components.</p>
<p>Helpers or utils are responsible for performing a task that can be used in multiple places and by multiple devs. Examples include a Date format, string formation, API call code, and DOM manipulation, to name a few.</p>
<h3 id="heading-why-use-helpers-utils">Why Use Helpers / Utils?</h3>
<p>Every component should be responsible for only one job, which is something known as the “Single responsibility principle”. </p>
<p>We should identify reusable functions and move them to utils for the following reasons:</p>
<ol>
<li>It results in cleaner components and cleaner code</li>
<li>No tight coupling</li>
<li>Easily scalable functionality</li>
<li>Easy to maintain and debug</li>
<li>Better reusability</li>
<li>Components are now responsible only for the UI</li>
</ol>
<pre><code class="lang-javascript">
</code></pre>
<p>// dateUtils.js : Moved the formatDate to a seprate util file to have reusability</p>
<p>export function formatDate(date) {
    const options = { year: 'numeric', month: 'long', day: 'numeric' };
    return new Date(date).toLocaleDateString(undefined, options);
}</p>
<pre><code>
<span class="hljs-string">``</span><span class="hljs-string">`react
// Updated Blog.jsx component after util
import React, { Component } from 'react';
import { formatDate } from './dateUtils'; 

const Blog = ({title, content, date}) =&gt; {
    return (
        &lt;div&gt;
            &lt;h2&gt;{title}&lt;/h2&gt;
            &lt;p&gt;{content}&lt;/p&gt;
            &lt;p&gt;Published on: {formatDate(date)}&lt;/p&gt;
        &lt;/div&gt;
    );
}
}</span>
</code></pre><p>For example, in the above code, you can see that we have a <code>formatDate</code> function inside the component <code>Blog</code>. Here we can move the <code>formatDate</code> to utils. Why?</p>
<ul>
<li><code>formatDate</code> is responsible for formatting the date, and not for publishing the date</li>
<li><code>formatDate</code> can be used by another component</li>
<li><code>formatDate</code> can have different formats based on the business requirements. For example, now we are passing a second argument based on this component requirement. If any new requirement comes up, the developer needs to re-write the component.</li>
</ul>
<h2 id="heading-3-learn-how-to-use-props">3. Learn How to Use Props</h2>
<p>To communicate between components in ReactJS, <a target="_blank" href="https://www.freecodecamp.org/news/props-in-react/">we use <code>props</code></a>. But there are different ways to do that.</p>
<p>It is crucial to choose only one style to consume props in the component in your codebase. This will make the codebase consistent. There's more than one way to destructure props which is why you should pick only one for consistency and readability of your code.</p>
<p>Let's talk about the ways you can work with props in React.</p>
<h3 id="heading-how-to-use-props">How to Use <code>Props</code></h3>
<p>In this approach we have to repeat <code>props</code> every time we are using <code>props</code>.</p>
<p>This approach is not a great way of consuming <code>props</code> because we are repeating props whenever we want to use them. Besides being repetitive, when it comes to creating nested props, it will require too much typing.</p>
<p>Your time as a developer is important, and we want to optimize the code wherever possible and not repeat things unless absolutely necessary.</p>
<p>In the below code example, you can see why this approach isn't the best. We have the <code>Input</code> component with <code>props</code> such as <code>type</code>, <code>placeholder</code>, <code>name</code>, and <code>changeHandler</code>. In the <code>return</code> section, we are repeating <code>props</code> with every <code>attribute</code> such as <code>props.type</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Input = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
    <span class="hljs-attr">type</span>=<span class="hljs-string">{props.type}</span> 
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{props.placeholder}</span> 
    <span class="hljs-attr">name</span>=<span class="hljs-string">{props.name}</span> 
    <span class="hljs-attr">className</span>=<span class="hljs-string">"block p-2 my-2 text-black"</span> 
    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{props.changeHandler}/</span>&gt;</span></span>
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Input;
</code></pre>
<h3 id="heading-how-to-destructure-props">How to destructure props</h3>
<p>In the second way of working with <code>props</code>, we use the <a target="_blank" href="https://www.freecodecamp.org/news/destructuring-patterns-javascript-arrays-and-objects/">JavaScript destructuring assignment</a>. </p>
<p>This is an improvement over the first approach, as in this one we won't repeat <code>props</code> whenever we're using props.</p>
<p>Here is an example of destructuring <code>props</code>. In the first code snippet, we are getting <code>type</code>, <code>placeholder</code>, <code>name</code>, and <code>changeHandler</code> from the <code>props</code> the first thing in the component.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { type, placeholder, name, changeHandler } = props
</code></pre>
<p>In the below code example, we can see the improvement in the code. We have <code>Input</code> component with <code>props</code>  but instead of repeating <code>props.name</code> we are destructing the props. It is a huge improvement in readability, and developer experience.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Input = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { type, placeholder, name, changeHandler } = props;
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
    <span class="hljs-attr">type</span>=<span class="hljs-string">{type}</span> 
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{placeholder}</span> 
    <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span> 
    <span class="hljs-attr">className</span>=<span class="hljs-string">"block p-2 my-2 text-black"</span> 
    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{changeHandler}/</span>&gt;</span></span>
}
</code></pre>
<h3 id="heading-how-to-destructure-props-in-component-arguments">How to destructure props in component arguments</h3>
<p>This is my favourite method of destructuring props. Developers can see at the start of the component which props would get used in the component. We also don't have any repetition of the <code>props</code> keywords.</p>
<p>Compared with the last approach, it is:</p>
<ul>
<li>DRY (Don't Repeat Yourself): we are not repeating the props</li>
<li>Readable: At the component's first line (definition), we know which props it is expecting. This improves the readability and clarity of the component.</li>
</ul>
<p>In the below code, we can see that we are destructing <code>props</code> in the definition of the component. This makes readability way better. As now developers can look at the first line and understand how many and what all <code>props</code> are expected in this component.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Input = <span class="hljs-function">(<span class="hljs-params">{ type, placeholder, name, changeHandler }</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
    <span class="hljs-attr">type</span>=<span class="hljs-string">{type}</span> 
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{placeholder}</span> 
    <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span> 
    <span class="hljs-attr">className</span>=<span class="hljs-string">"block p-2 my-2 text-black"</span> 
    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{changeHandler}/</span>&gt;</span></span>
}
</code></pre>
<h2 id="heading-4-have-one-file-for-each-component">4. Have One File for Each Component</h2>
<p>In ReactJS, it is important to have one file per component. This helps make your code cleaner and more maintainable.</p>
<p>It also follows the <a target="_blank" href="https://en.wikipedia.org/wiki/Single-responsibility_principle">single responsibility principle</a> I mentioned earlier.</p>
<p>It is tempting to have one file and write all the code inside it for isolation – but we should break it into smaller components.</p>
<p>In the below example, we have one file <code>Input.jsx</code> which has two components <code>Input</code> and <code>Icon</code>. We are using <code>Icon</code> in the <code>return</code> section of <code>Input</code>.</p>
<p>It looks like <code>Input</code> and <code>Icon</code> are related and its logical to group them into one file. But we should not do this, as it is not a scalable solution (and isn't reusable, either).</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Don't do this:</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// File name: Input.jsx</span>
<span class="hljs-comment">// This example shows how we are exporting 2 components from one file</span>
<span class="hljs-comment">// We should NOT do this</span>
<span class="hljs-keyword">const</span> Input = <span class="hljs-function">(<span class="hljs-params">{ type, placeholder, name, changeHandler }</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
    <span class="hljs-attr">type</span>=<span class="hljs-string">{type}</span> 
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{placeholder}</span> 
    <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span> 
    <span class="hljs-attr">className</span>=<span class="hljs-string">"block p-2 my-2 text-black"</span> 
    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{changeHandler}/</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"warning"</span>/&gt;</span>
}
        <span class="hljs-tag">&lt;&gt;</span>

const Icon = ({ type, url}) =&gt; {
    return <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{url}</span> <span class="hljs-attr">data-type</span>=<span class="hljs-string">{type}</span> /&gt;</span>
}

export {Input, Icon};</span>
</code></pre>
<p>Instead, we should be making two separate components for <code>Input</code> and <code>Icon</code>, as shown below. This will help you reuse both components and scale them individually.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Do this instead:</span>
<span class="hljs-comment">// Input.jsx: create 2 separate files for Input and InputIcon</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> Input = <span class="hljs-function">(<span class="hljs-params">{ type, placeholder, name, changeHandler }</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
    <span class="hljs-attr">type</span>=<span class="hljs-string">{type}</span> 
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{placeholder}</span> 
    <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span> 
    <span class="hljs-attr">className</span>=<span class="hljs-string">"block p-2 my-2 text-black"</span> 
    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{changeHandler}/</span>&gt;</span></span>
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Input;
</code></pre>
<h2 id="heading-5-dont-use-inline-functions">5. Don't Use Inline Functions</h2>
<p>It is common to write inline functions in JavaScript, but it is better to avoid adding them when possible.</p>
<p>You should keep your JSX separate from your logical code. Inline functions are not reusable, don't help with code abstraction, and are hard to test.</p>
<p>This is why you should always avoid inline functions.</p>
<p>In the below code snippet we have the <code>handleIncrement</code> function as an inline function on <code>button</code>.  It is not reusable, and it's tightly coupled with the component:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Don't do this:</span>
<span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CounterInline</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> handleIncrement = <span class="hljs-function">() =&gt;</span> {
    setCount(count + <span class="hljs-number">1</span>);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleIncrement}</span>&gt;</span>Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> CounterInline;
</code></pre>
<p>Then how we can move away from inline functions? Let's look at how you can refactor of the above code.</p>
<p>In the below code, we can have <code>incrementCount</code> used on <code>button</code> and it is expecting two arguments. We have made the function here reusable:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Do this instead:</span>
<span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// Standalone function for incrementing</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">incrementCount</span>(<span class="hljs-params">currentCount, setCount</span>) </span>{
  setCount(currentCount + <span class="hljs-number">1</span>);
}

<span class="hljs-keyword">const</span> CounterStandalone = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Count: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> incrementCount(count, setCount)}&gt;Increment<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> CounterStandalone;
</code></pre>
<h2 id="heading-6-implement-a-404-component-and-route">6. Implement a 404 Component and Route</h2>
<p>While implementing routing in ReactJS we should add a 404 component.</p>
<p>When the user tries to access a page which doesn't exist, the status code from the server will be 404. As a front-end developer, it’s a good idea to show the user an error message to give them some context here.</p>
<p>React-router provides an easy way to display the error when the server returns a 404.  You'll need to create a component that should be rendered when the 404 status code returns from the server.</p>
<p>Whenever a user types in or reaches a route which is not found, the 404 page will show the error to the user, which is better user experience (rather than just seeing an unexplained "404").</p>
<p>Tip: In the component, add a link to the homepage of your website. This will help the user redirect to the homepage of your website.</p>
<pre><code class="lang-JavaScript">    &lt;route path=<span class="hljs-string">"*"</span> component={<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Error404</span>/&gt;</span></span>} /&gt;
</code></pre>
<h2 id="heading-7-fetch-data-progressively">7. Fetch Data Progressively</h2>
<p>In React applications, you'll often fetch data through APIs. </p>
<p>Instead of fetching and creating the UI in one go, we should fetch the data on-demand – for example, on scrolling into view, on clicking of the pagination, and so on.</p>
<p>This will improve the performance of the application as well as the User Experience. </p>
<p>There are a few packages that can help you implement lazy-loading. Lazy loading is a technique you can use to load the data on-demand or progressively as needed. Instead of showing whole API data on the screen at one time, it'll only show the data on-demand.</p>
<p>Here's how you can install the <code>react-lazyload</code> package:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// install react-lazyload package</span>
npm install react-lazyload
</code></pre>
<p>And here's the code:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Create a component - ItemList.jsx</span>
<span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">const</span> ItemList = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Fetch data from your API here</span>
    axios.get(<span class="hljs-string">'https://example.com/api/items'</span>)
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
        setItems(response.data);
      })
      .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error fetching data:'</span>, error);
      });
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Item List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
        {items.map(item =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
            {item.name}
          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ItemList;
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-comment">// App.js</span>
<span class="hljs-keyword">import</span> React, { lazy, Suspense } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> LazyLoad <span class="hljs-keyword">from</span> <span class="hljs-string">'react-lazyload'</span>;

<span class="hljs-comment">// Import the lazy-loaded component</span>
<span class="hljs-keyword">const</span> ItemList = lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./ItemList'</span>));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>React LazyLoad with API Data Example<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

      {/* Use React LazyLoad to lazy-load the component */}
      <span class="hljs-tag">&lt;<span class="hljs-name">LazyLoad</span> <span class="hljs-attr">height</span>=<span class="hljs-string">{200}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>}&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">ItemList</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">LazyLoad</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In the above example of code, have created a component which will make the API requests and render the API data <code>ItemList.jsx</code>. While using the <code>ItemList</code> in <code>App</code>, instead of rendering whole data in one go, we will use the <code>LazLoad</code> to load the component. </p>
<p>As a result, component is loaded lazily when it's close to being visible in the viewport, and the data from the API will be displayed.</p>
<p>Some of the packages you can use for lazy loading are <code>react-lazyload</code>, <code>react-infinite-scroll-component</code> , and <code>react-paginate</code>.</p>
<h2 id="heading-8-use-unique-values-for-key-attributes">8. Use Unique Values for Key Attributes</h2>
<p>One of the reasons React is popular is because of its "virtual DOM".</p>
<p>The virtual DOM (VDOM) helps you optimize the process of updating the UI. </p>
<p>React will only update nodes that get changed and not the whole DOM unless it is required. This is one of the secrets of the most performant apps. </p>
<p>React needs a <code>key</code> attribute to identify to which node the change happened. This is why we should always use a unique value for <code>key</code>. </p>
<p>A good example of how to do this is to add the <code>id</code> of every item.</p>
<p>Note: use index as a key only when your data is static, not re-ordering or filtered.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// List.jsx</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> List = <span class="hljs-function">(<span class="hljs-params">{ items }</span>) =&gt;</span> (

  <span class="hljs-keyword">return</span>(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {items.map((item, index) =&gt; (
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>{item}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    ))}
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>)
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> List;
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-comment">// App.jsx</span>
<span class="hljs-keyword">import</span> List <span class="hljs-keyword">from</span> <span class="hljs-string">'./List'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> items = [<span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>, <span class="hljs-string">'Item 4'</span>, <span class="hljs-string">'Item 5'</span>];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Simple List Example<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">List</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{items}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In the above code example, we are creating a list by mapping over the data. In the <code>List</code> component we are assigning the <code>index</code> to the <code>key</code> attribute. This will be used by ReactJS under the hood to optimize the performance whenever any <code>li</code> will be updated or changed.</p>
<h2 id="heading-9-use-types">9. Use Types</h2>
<p>Using tools with static type checking built in (like TypeScript) can help you avoid unnecessary bugs in your code.</p>
<p>It will also support your code with quality and type-checking. </p>
<p>If you are someone who is just starting out learning about type checking, then you can start with <code>proptypes</code> and later learn TypeScript. </p>
<p>JavaScript is not strictly typed, which means there's a higher possibility that you'll have unexpected bugs or type errors. </p>
<p>For example, when we expect a prop to be a number, it could end up being a string which would cause an error.</p>
<p>So, strict types and TypeScript can help you avoid such unexpected bugs during development.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> PropTypes <span class="hljs-keyword">from</span> <span class="hljs-string">'prop-types'</span>;

<span class="hljs-keyword">const</span> UserCard = <span class="hljs-function">(<span class="hljs-params">{ name, age, email }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>User Card<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Name: {name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Age: {age}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Email: {email}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-comment">// Define the prop types for the UserCard component</span>
UserCard.propTypes = {
  <span class="hljs-attr">name</span>: PropTypes.string.isRequired, <span class="hljs-comment">// A required string prop</span>
  <span class="hljs-attr">age</span>: PropTypes.number.isRequired,  <span class="hljs-comment">// A required number prop</span>
  <span class="hljs-attr">email</span>: PropTypes.string,           <span class="hljs-comment">// An optional string prop</span>
};
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> UserCard <span class="hljs-keyword">from</span> <span class="hljs-string">'userCard'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>PropTypes Example<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">UserCard</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"John Doe"</span> <span class="hljs-attr">age</span>=<span class="hljs-string">{30}</span> <span class="hljs-attr">email</span>=<span class="hljs-string">"john@example.com"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In the above code example, we have created a component <code>UserCard</code>. This component expects 3 props: name, age, and email. By using <code>proptypes</code> , we will declare two things for props – datatype (what would be the datatype of the props, for example string, number, and so on), and whether it's required or optional. </p>
<p>While using the <code>UserCard</code> component, if anyone passes the wrong datatype or misses a required prop, then the code will throw an error and warn them to fix it. </p>
<h2 id="heading-10-use-the-lazy-and-suspense-functions">10. Use the <code>lazy()</code>  and <code>Suspense()</code> Functions</h2>
<p>ReactJS uses the Webpack bundler (if you are using creat-react-app). </p>
<p>Webpack takes care of bundling of the code, and performs functions like <a target="_blank" href="https://www.freecodecamp.org/news/tree-shaking-es6-modules-in-webpack-2-1add6672f31b/">tree shaking</a>. </p>
<p>But the way React works is it downloads the whole code on the client side even if we don't need it. This is an expensive task. If your bundle size is big then it will impact the performance of your apps. </p>
<p>A good way to avoid this is to lazy load the code on demand by using <code>lazy()</code>, which will let the routes get loaded when they're needed.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> LazyComponent = lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./LazyComponent'</span>));
</code></pre>
<p>While using <code>lazy()</code> we should also use <code>Suspense()</code>, as <code>lazy()</code> is an async way of loading the components. </p>
<p>We don't want to show the user a blank screen until our route is done loading. <code>Suspense()</code> helps by showing a message while the component is loading.</p>
<pre><code class="lang-javascript"> &lt;Suspense fallback={<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>}&gt;
        {<span class="hljs-comment">/* The LazyComponent will only be loaded when needed */</span>}
        &lt;LazyComponent /&gt;
 &lt;/Suspense&gt;
</code></pre>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Phew, we have reached the end. These tips are not just limited to large codebases but to projects of any size. </p>
<p>At high level we learned about the following concepts:</p>
<ol>
<li>Following the DRY principle</li>
<li>Following the Single Responsibility Principle</li>
<li>Creating a good user experience by loading the data progressively </li>
<li>Improving readability</li>
<li>Improving the developer experience</li>
<li>Avoiding bugs at the development time</li>
<li>Improving performance</li>
</ol>
<p>Happy Learning!</p>
<p>Don't be shy. Come and say hi! You can find me on <a target="_blank" href="https://twitter.com/hellonehha">Twitter</a>, <a target="_blank" href="https://www.linkedin.com/in/nehha/">LinkedIn</a>, and <a target="_blank" href="https://youtube.com/@hellonehha">YouTube</a>.</p>
<p>Want to see some calligraphy? Check my art on instagram.com/calligraphyzen.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add ESLint to Your React Project ]]>
                </title>
                <description>
                    <![CDATA[ By Jacob Isah  As a React developer, maintaining code quality is essential for building robust and maintainable applications. Fortunately, there's a powerful tool called ESLint that can significantly improve the quality of your React projects. In thi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-eslint-to-your-react-project/</link>
                <guid isPermaLink="false">66d45f313a8352b6c5a2aa5d</guid>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ eslint ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 08 Aug 2023 16:36:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/How-To-Add-ESLint-To-Your-React-Project-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jacob Isah </p>
<p>As a React developer, maintaining code quality is essential for building robust and maintainable applications. Fortunately, there's a powerful tool called ESLint that can significantly improve the quality of your React projects.</p>
<p>In this article, we will explore how ESLint works and create a sign-up button component to demonstrate its benefits.</p>
<h2 id="heading-what-is-eslint">What is ESLint?</h2>
<p>ESLint is a popular open-source JavaScript linting utility. It analyzes your code for potential errors, and enforces coding standards while improving code quality. </p>
<p>It can also help you as a developer to identify and fix common mistakes, use best practices, and maintain consistency across your codebase. </p>
<p>You can integrate ESLint seamlessly into your React projects, providing real-time feedback and improving your overall code quality.</p>
<h2 id="heading-how-to-set-up-your-project">How to Set Up Your Project</h2>
<p>Let's start by setting up a new React project and installing ESLint. To demonstrate this, we will create a signup app in React. </p>
<p>Imagine that we want to store our project on the desktop, so first we will set up our file structure. Let's start by creating a root directory for our project on the desktop (<code>eslintExample</code> in this case).</p>
<pre><code class="lang-javascript">mkdir eslintExample 
cd eslintExample
</code></pre>
<h3 id="heading-install-the-react-app">Install the React app</h3>
<p>Now we'll use create-react-app to set up our React app.</p>
<pre><code class="lang-javascript">npx create-react-app signup-app
</code></pre>
<h3 id="heading-install-eslint">Install ESLint</h3>
<p>And you can use the following command to set up ESLint:</p>
<pre><code class="lang-javascript">npm install eslint eslint-plugin-react eslint-plugin-react-hooks --save-dev
</code></pre>
<p>Your directory structure should look like this:</p>
<pre><code class="lang-javascript">eslintExample/
  └── signup-app/
      └── node_modules/
      └── public/
      └── src/
          └── App.css
          └── App.js
          └── App.test.js
          └── SignupButton.js
          └── index.css
          └── logo.svg
          └── reportWebVitals.js
          └── setupTests.js
      └── .eslintrc.json
      └── .gitignore
      └── package-lock.json
      └── package.json
      └── README.md
</code></pre>
<h2 id="heading-how-to-configure-eslint-in-a-react-project">How to Configure ESLint in a React Project</h2>
<p>To work with ESLint in our React project, we need to configure it. To do this, the first step is to create a <strong>.eslintrc.json</strong> file in the project's root directory and add the following code:</p>
<pre><code class="lang-javascript">{
    <span class="hljs-string">"env"</span>: {
      <span class="hljs-string">"browser"</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-string">"es2021"</span>: <span class="hljs-literal">true</span>
    },
    <span class="hljs-string">"extends"</span>: [<span class="hljs-string">"eslint:recommended"</span>, <span class="hljs-string">"plugin:react/recommended"</span>, <span class="hljs-string">"plugin:react-hooks/recommended"</span>],
    <span class="hljs-string">"parserOptions"</span>: {
      <span class="hljs-string">"ecmaVersion"</span>: <span class="hljs-number">12</span>,
      <span class="hljs-string">"sourceType"</span>: <span class="hljs-string">"module"</span>,
      <span class="hljs-string">"ecmaFeatures"</span>: {
        <span class="hljs-string">"jsx"</span>: <span class="hljs-literal">true</span>
      }
    },
    <span class="hljs-string">"plugins"</span>: [<span class="hljs-string">"react"</span>, <span class="hljs-string">"react-hooks"</span>],
    <span class="hljs-string">"rules"</span>: {
      <span class="hljs-comment">//add customize rules here as per your project's needs</span>
    }
}
</code></pre>
<p>The above configuration sets up ESLint to work with React and React Hooks using the recommended configurations. You can add or customize rules according to your project's specific requirements.</p>
<p><img src="https://lh5.googleusercontent.com/nEAJArNZ75TidB33XK-0_p4BQea9aTppnnFrk0u7znVKIpsmCortCwaZ0KFYbw_1OOkz_QcXC0cr1WGih89a1OY2REUCSIWKckpaGESNchz8xakqTAntBbpgDXabbrcf6kWZzwxpAZ14PC5xQb9h_A" alt="How to Add ESLint to Your React Project" width="600" height="400" loading="lazy">
<em>Created the.eslintrc.json file and added the configuration that allows ESLint to work with React.</em></p>
<h2 id="heading-how-to-create-the-signup-button-component">How to Create the Signup Button Component</h2>
<p>Now, let's create a simple Signup Button component (SignupButton.js) inside the "src" folder. </p>
<p>Inside the src file, create the SignupButton.js file. It should look like this: <code>src/SignupButton.js</code>. Inside your SignupButton.js, paste the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> SignupButton = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> handleSignup = <span class="hljs-function">() =&gt;</span> {
    alert(<span class="hljs-string">"Sign up successful!"</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">{handleSignup}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"signup-button"</span>&gt;</span>
      Sign Up
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  );
};
</code></pre>
<p>The above component is a basic button that triggers an alert when clicked, simulating the signup process. Now you can run this command:</p>
<pre><code class="lang-javascript">npm start
</code></pre>
<p>This will start our React app at the root of the project. Then you should see this error below:</p>
<p><img src="https://lh3.googleusercontent.com/O1FnEf68qsAo7FOqdNzFrcauVoHs3oKnQsbV4cNUAwFQbAjZZ9XhIHVhDSNiyZ3buIVF4-uCKnrkLjru6xRgjJo3tLJVq8vXn5s_GcdgnMoHCPPnDk0H2IGnhXVGPBZYABP3fbaoOe_GtYA60hU6Hw" alt="How to Add ESLint to Your React Project" width="600" height="400" loading="lazy">
<em>We started the local server, and we are seeing an error coming from the app.js file. React needs to be imported in app.js file. We need to export our button component.</em></p>
<p>This error might confuse you, because you may not know where it's coming from. We are seeing this error because we set up ESLint in our project, and it scans through our project to tell us that React needs to be imported in the <strong>app.js</strong> file.</p>
<p>But let’s run ESLint to see where the exact error is coming from.</p>
<h2 id="heading-how-to-run-eslint">How to Run ESLint</h2>
<p>With ESLint configured, let's run it to analyze our SignupButton component for potential issues. Open your terminal and run the following command at the root of your project:</p>
<pre><code class="lang-javascript">npx eslint src/SignupButton.js
</code></pre>
<p>ESLint will analyze the SignupButton.js file and display any problems it finds below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-101.png" alt="How to Add ESLint to Your React Project" width="600" height="400" loading="lazy">
<em>We run the <code>eslint</code> command to show us where we are having error: in the signup button and app.js</em></p>
<h2 id="heading-how-to-fix-the-eslint-issues">How to Fix the ESLint Issues</h2>
<p>From the above, you can see that ESLint identifies where we are having errors. We did not import React in our App.js file, and we did not export our signup button component. Let’s fix that.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-100.png" alt="How to Add ESLint to Your React Project" width="600" height="400" loading="lazy">
<em>We imported React in the app.js file and exported SignupButton component.</em></p>
<p>As you can see, our code was now built successfully.</p>
<p>We were able to export our SignupButton component and imported React in App.js component. This solves our problem.</p>
<p>If ESLint identifies any further issues in our SignupButton component, it will display them along with suggestions on how to fix them. </p>
<p>For example, ESLint might detect missing semicolons, unused variables, or violations of React best practices like the import React from “react” in the app.js file.</p>
<p>By addressing the issues highlighted by ESLint, we can ensure that our code adheres to best practices, is easier to read, and has fewer potential bugs.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>ESLint is an indispensable tool for React developers to maintain code quality and improve productivity. By integrating ESLint into your React projects, you can catch errors early, follow coding standards, and foster collaboration within your team.</p>
<p>In this article, I have explained how to set up ESLint in a React project and demonstrate its benefits with a simple Signup Button component. By utilizing ESLint effectively, you can write cleaner, more consistent code and deliver higher-quality React applications.</p>
<p>So, why wait? Start using ESLint in your React projects and watch your code quality soar. Happy coding! 🚀</p>
<p>Your feedback is highly appreciated.<br>you can follow me on <a target="_blank" href="https://twitter.com/_jayky">twitter</a> and <a target="_blank" href="https://www.linkedin.com/in/isahjacob/">linkedIn</a>  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Measure Django Code Quality Using SonarQube, Pytest, and Coverage ]]>
                </title>
                <description>
                    <![CDATA[ By Ridwan Yusuf Greetings, fellow coding enthusiasts! We're going to dive deep into the realm of Django code quality assessment. In this comprehensive guide, I'll walk you through an in-depth approach to measuring the code quality of your Django-base... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-measure-django-code-quality-using-sonarqube-pytest-and-coverage/</link>
                <guid isPermaLink="false">66d460c7787a2a3b05af43f4</guid>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 18 Jul 2023 16:36:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/istockphoto-91813442-612x612.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ridwan Yusuf</p>
<p>Greetings, fellow coding enthusiasts!</p>
<p>We're going to dive deep into the realm of Django code quality assessment. In this comprehensive guide, I'll walk you through an in-depth approach to measuring the code quality of your Django-based application.</p>
<p>By the end of this tutorial, you will be able to:</p>
<ol>
<li>Build CRUD APIs using Django and DRF (Django REST Framework)</li>
<li>Write automated tests for the APIs using Pytest</li>
<li>Measure code test coverage using Coverage</li>
<li>Utilize SonarQube to assess code quality, identify code smells, security vulnerabilities, and more</li>
</ol>
<p>Prerequisites to follow along in this tutorial include:</p>
<ol>
<li>Python 3 installation on your chosen Operating System (OS). We'll use Python 3.10 in this tutorial.</li>
<li>Basic knowledge of Python and Django</li>
<li>Any code editor of your choice</li>
</ol>
<p>Without any further delay, let's jump right in and get started.</p>
<h2 id="heading-how-to-get-the-apis-up-and-running">How to Get the APIs Up and Running</h2>
<p>To begin, open your Terminal or bash. Create a directory or folder for your project using the command:</p>
<pre><code class="lang-bash">mkdir django-quality &amp;&amp; <span class="hljs-built_in">cd</span> django-quality
</code></pre>
<p>In my case, the folder name is "django-quality".</p>
<p>To isolate the project dependencies, we need to utilize a Python virtual environment.</p>
<p>To create a virtual environment, use the following command in your Terminal or bash:</p>
<pre><code class="lang-bash">python3 -m venv venv
</code></pre>
<p>Activate the virtualenv by running this command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> venv/bin/activate
</code></pre>
<p>If everything works fine, you should see the virtual environment indicator enclosed in brackets, similar to the image shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/venv-activated.png" alt="Image" width="600" height="400" loading="lazy">
<em>Python Virtualenv activated successfully</em></p>
<p>At the root directory of your project, create a folder called "requirements" that will house the external packages required for various development stages, such as dev (development) and staging.</p>
<p>Inside the "requirements" folder, create two files: "<strong>base.txt</strong>" and "<strong>dev.txt</strong>". The "base.txt" file will include generic packages required by the application, while the "dev.txt" file will contain dependencies specific to development mode.</p>
<p>By now, the contents in your project folder should have the following structure</p>
<pre><code class="lang-bash">- requirements
    ├── base.txt
    └── dev.txt
- venv
</code></pre>
<p>Here are the updated contents for the "base.txt" and "dev.txt" files:</p>
<p><code>base.txt</code></p>
<pre><code class="lang-bash">Django==4.0.6
djangorestframework==3.13.1
drf-spectacular==0.22.1
</code></pre>
<p><code>dev.txt</code></p>
<pre><code class="lang-bash">-r base.txt
pytest-django==4.5.2
pytest-factoryboy==2.5.0
pytest-cov==4.1.0
</code></pre>
<ul>
<li>djangorestframework: Used for API development.</li>
<li>drf-spectacular : Used for automated documentation of the APIs.</li>
<li>pytest-cov: Utilized for measuring code coverage during testing. </li>
<li>pytest-factoryboy: Used for creating test data using factory patterns.</li>
</ul>
<p>Make sure your virtual environment is activated, then run the following command at the root directory to install the dependencies specified in "dev.txt":</p>
<pre><code class="lang-bash">pip install -r requirements/dev.txt
</code></pre>
<p>To create a new Django project, you can run the following command:</p>
<pre><code class="lang-bash">django-admin startproject core .
</code></pre>
<p>The name of the project is 'core'. You can decide to use any suitable name that fits your use case.</p>
<p>By now, you should see a couple of files and folders automatically created after running the command.</p>
<p>Here is the current project structure:</p>
<pre><code class="lang-bash">├── core
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── requirements
│   ├── base.txt
│   └── dev.txt
└── venv
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/project-folder-structurefold-min.png" alt="Image" width="600" height="400" loading="lazy">
<em>Current Folder Structure in VSCode</em></p>
<p>The APIs we will create will be a basic blog API with CRUD functionality. Let's create a new app within the project to host all the files related to the blog features.</p>
<p>Run this command to create a new app called 'blog':</p>
<pre><code class="lang-bash">python manage.py startapp blog
</code></pre>
<p>By now, a new folder named 'blog' has been auto-created by the command.</p>
<p>Here is the folder structure:</p>
<pre><code class="lang-bash">├── blog
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── core
├── manage.py
├── requirements
└── venv
</code></pre>
<p>Update the <code>models.py</code> file in the <code>blog</code> folder. The <code>Blog</code> class defines the database schema for the blog.</p>
<p><code>blog/models.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Blog</span>(<span class="hljs-params">models.Model</span>):</span>
    title = models.CharField(max_length=<span class="hljs-number">50</span>)
    body = models.TextField()
    published = models.BooleanField(default=<span class="hljs-literal">True</span>)
    created_at = models.DateTimeField(auto_now_add=<span class="hljs-literal">True</span>)
</code></pre>
<p>Create a new file named 'serializers.py' inside the 'blog' folder and update its content as shown below:</p>
<p><code>blog/serializers.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> rest_framework <span class="hljs-keyword">import</span> serializers

<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Blog

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BlogSerializer</span>(<span class="hljs-params">serializers.ModelSerializer</span>):</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        model = Blog
        fields = <span class="hljs-string">'__all__'</span>

    extra_kwargs = {
            <span class="hljs-string">"created_at"</span>: {<span class="hljs-string">"read_only"</span>: <span class="hljs-literal">True</span>},
        }
</code></pre>
<p>The <code>BlogSerializer</code> class is utilized for validating incoming blog data sent by the client (such as from the frontend or mobile app) to ensure it adheres to the expected format.</p>
<p>Additionally, the serializer class is used for both serialization (converting Python objects to a transmittable format like JSON) and deserialization (converting a transmittable format like JSON back to Python objects).</p>
<p>Let's create the view to handle CRUD functionality, leveraging the DRF <code>ModelViewSet</code> to effortlessly create APIs with just a few lines of code.</p>
<p><code>blog/views.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> rest_framework <span class="hljs-keyword">import</span> filters, viewsets

<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Blog
<span class="hljs-keyword">from</span> .serializers <span class="hljs-keyword">import</span> BlogSerializer


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BlogViewSet</span>(<span class="hljs-params">viewsets.ModelViewSet</span>):</span>
    queryset = Blog.objects.all()
    http_method_names = [<span class="hljs-string">"get"</span>, <span class="hljs-string">"post"</span>, <span class="hljs-string">"delete"</span>, <span class="hljs-string">"patch"</span>,<span class="hljs-string">"put"</span>]
    serializer_class = BlogSerializer
    filter_backends = [
        filters.SearchFilter,
        filters.OrderingFilter,
    ]
    filterset_fields = [<span class="hljs-string">"published"</span>]
    search_fields = [<span class="hljs-string">"title"</span>, <span class="hljs-string">"body"</span>]
    ordering_fields = [
        <span class="hljs-string">"created_at"</span>,
    ]
</code></pre>
<p>Create a new file named 'blog.urls' in the 'blog' folder.</p>
<p>By utilizing the DRF router for URL configuration, the URLs are automatically generated based on the allowed methods defined in the <code>BlogViewSet</code>.</p>
<p><code>blog/urls.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> include, path

<span class="hljs-keyword">from</span> rest_framework.routers <span class="hljs-keyword">import</span> DefaultRouter

<span class="hljs-keyword">from</span> .views <span class="hljs-keyword">import</span> BlogViewSet

app_name = <span class="hljs-string">"blog"</span>

router = DefaultRouter()
router.register(<span class="hljs-string">""</span>, BlogViewSet)

urlpatterns = [
    path(<span class="hljs-string">""</span>, include(router.urls)),
]
</code></pre>
<p>The next step is to register the <code>urls.py</code> file defined in the 'blog' app within the main project's <code>urls.py</code> file. To do this, you should locate the project's <code>urls.py</code> file, which serves as the starting point for URL routing.</p>
<p><code>core/urls.py</code></p>
<pre><code class="lang-python">
<span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path, include
<span class="hljs-keyword">from</span> drf_spectacular.views <span class="hljs-keyword">import</span> (
    SpectacularAPIView,
    SpectacularRedocView,
    SpectacularSwaggerView,
)

urlpatterns = [
    path(<span class="hljs-string">'api/schema/'</span>, SpectacularAPIView.as_view(), name=<span class="hljs-string">'schema'</span>),
    path(<span class="hljs-string">'api/v1/doc/'</span>, SpectacularSwaggerView.as_view(url_name=<span class="hljs-string">'schema'</span>), name=<span class="hljs-string">'swagger-ui'</span>),
    path(<span class="hljs-string">'api/v1/redoc/'</span>, SpectacularRedocView.as_view(url_name=<span class="hljs-string">'schema'</span>), name=<span class="hljs-string">'redoc'</span>),
    path(<span class="hljs-string">'admin/'</span>, admin.site.urls),
    path(<span class="hljs-string">'api/v1/blogs/'</span>, include(<span class="hljs-string">'blog.urls'</span>)),
]
</code></pre>
<p>The <code>api/v1/blogs/</code> URL is mapped to the URLs defined in <code>blog.urls</code>. Additionally, other URLs are utilized for automated API documentation.</p>
<p>Update the <code>settings.py</code> file located inside the <code>core</code> folder. This file contains configurations for the Django application.</p>
<p>In the <code>INSTALLED_APPS</code> section, register the newly created 'blog' app, along with any desired third-party apps. Note that for brevity, the default Django apps are not included in the following list:</p>
<p><code>settings.py</code></p>
<pre><code class="lang-python">INSTALLED_APPS = [


    <span class="hljs-comment">#Third-party Apps</span>
    <span class="hljs-string">'drf_spectacular'</span>,

    <span class="hljs-comment">#Local Apps</span>
    <span class="hljs-string">'blog'</span>,
]
</code></pre>
<p>Update the <code>settings.py</code> file to include configurations related to Django REST Framework (DRF) and documentation.</p>
<p><code>settings.py</code></p>
<pre><code class="lang-python">
REST_FRAMEWORK = {
    <span class="hljs-string">"DEFAULT_SCHEMA_CLASS"</span>: <span class="hljs-string">"drf_spectacular.openapi.AutoSchema"</span>,
    <span class="hljs-string">"TEST_REQUEST_DEFAULT_FORMAT"</span>: <span class="hljs-string">"json"</span>,
}


SPECTACULAR_SETTINGS = {
    <span class="hljs-string">'SCHEMA_PATH_PREFIX'</span>: <span class="hljs-string">r'/api/v1'</span>,
    <span class="hljs-string">'DEFAULT_GENERATOR_CLASS'</span>: <span class="hljs-string">'drf_spectacular.generators.SchemaGenerator'</span>,
    <span class="hljs-string">'SERVE_PERMISSIONS'</span>: [<span class="hljs-string">'rest_framework.permissions.AllowAny'</span>],
    <span class="hljs-string">'COMPONENT_SPLIT_PATCH'</span>: <span class="hljs-literal">True</span>,
    <span class="hljs-string">'COMPONENT_SPLIT_REQUEST'</span>: <span class="hljs-literal">True</span>,
    <span class="hljs-string">"SWAGGER_UI_SETTINGS"</span>: {
        <span class="hljs-string">"deepLinking"</span>: <span class="hljs-literal">True</span>,
        <span class="hljs-string">"persistAuthorization"</span>: <span class="hljs-literal">True</span>,
        <span class="hljs-string">"displayOperationId"</span>: <span class="hljs-literal">True</span>,
        <span class="hljs-string">"displayRequestDuration"</span>: <span class="hljs-literal">True</span>
    },
    <span class="hljs-string">'UPLOADED_FILES_USE_URL'</span>: <span class="hljs-literal">True</span>,
    <span class="hljs-string">'TITLE'</span>: <span class="hljs-string">'Django-Pytest-Sonarqube - Blog API'</span>,
    <span class="hljs-string">'DESCRIPTION'</span>: <span class="hljs-string">'A simple API setup with Django, Pytest &amp; Sonarqube'</span>,
    <span class="hljs-string">'VERSION'</span>: <span class="hljs-string">'1.0.0'</span>,
    <span class="hljs-string">'LICENCE'</span>: {<span class="hljs-string">'name'</span>: <span class="hljs-string">'BSD License'</span>},
    <span class="hljs-string">'CONTACT'</span>: {<span class="hljs-string">'name'</span>: <span class="hljs-string">'Ridwan Ray'</span>, <span class="hljs-string">'email'</span>: <span class="hljs-string">'ridwanray.com'</span>},
    <span class="hljs-comment">#OAUTH2 SPEC</span>
    <span class="hljs-string">'OAUTH2_FLOWS'</span>: [],
    <span class="hljs-string">'OAUTH2_AUTHORIZATION_URL'</span>: <span class="hljs-literal">None</span>,
    <span class="hljs-string">'OAUTH2_TOKEN_URL'</span>: <span class="hljs-literal">None</span>,
    <span class="hljs-string">'OAUTH2_REFRESH_URL'</span>: <span class="hljs-literal">None</span>,
    <span class="hljs-string">'OAUTH2_SCOPES'</span>: <span class="hljs-literal">None</span>,
}
</code></pre>
<p>With all the necessary configurations in place, let's run the migrations command to ensure that the models in the application are synchronized with the database schema.</p>
<p>Execute the following commands in the root directory to synchronize the models with the database schema:</p>
<pre><code class="lang-bash">python manage.py makemigrations
python manage.py migrate
</code></pre>
<p>To start the development server, run the following command:</p>
<pre><code class="lang-bash">python manage.py runserver
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dev-server.png" alt="Image" width="600" height="400" loading="lazy">
<em>Starting local development server with runserver command</em></p>
<p>The application is now running at <a target="_blank" href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>.<br>To access the documentation, visit <a target="_blank" href="http://127.0.0.1:8000/api/v1/doc/">http://127.0.0.1:8000/api/v1/doc/</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/blog-doc-min-1--1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Automated Blog API documentation using drf-spectacular</em></p>
<h2 id="heading-how-to-write-automated-tests-with-pytest">How to Write Automated Tests with Pytest</h2>
<p>Pytest, the testing tool we're using for writing automated tests, is included as part of the dependencies declared in the requirement folder. Now, let's write some tests and explore its functionality.</p>
<p>In the blog folder, a file named "tests.py" is automatically generated when starting the blog app. To organize the tests, create a new folder called "tests" within the blog directory.</p>
<p>Move the initial "tests.py" file into the newly created "tests" folder. To make the "tests" folder a module, create an empty file named "<strong><strong>init</strong>.py</strong>".</p>
<p>Create a new file named 'conftest.py' inside the 'tests' folder. This file will store any pytest fixtures (that is, reusable components) required during the test writing process.</p>
<p>Test folder structure:</p>
<pre><code class="lang-bash">├── tests
│   ├── conftest.py
│   ├── factories.py
│   ├── __init__.py
│   ├── __pycache__
│   └── tests.py
</code></pre>
<p><code>tests/conftests.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest
<span class="hljs-keyword">from</span> rest_framework.test <span class="hljs-keyword">import</span> APIClient

<span class="hljs-meta">@pytest.fixture</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">api_client</span>():</span>
    <span class="hljs-keyword">return</span> APIClient()
</code></pre>
<p>The <code>api_client()</code> is a Pytest fixture utilized for making actual API calls.</p>
<p>Create a new file named 'factories.py'. This file will include the factories used during test writing. Factories provide a convenient way to create objects (that is, model instances) without the need to specify all attributes each time.</p>
<p><code>tests/factories.py</code></p>
<pre><code class="lang-python">
<span class="hljs-keyword">import</span> factory
<span class="hljs-keyword">from</span> faker <span class="hljs-keyword">import</span> Faker
<span class="hljs-keyword">from</span> blog.models <span class="hljs-keyword">import</span> Blog

fake = Faker()

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BlogFactory</span>(<span class="hljs-params">factory.django.DjangoModelFactory</span>):</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        model = Blog

    title = fake.name()
    body = fake.text()
    published = <span class="hljs-literal">True</span>
</code></pre>
<p><code>tests/tests.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> reverse
<span class="hljs-keyword">from</span> .factories <span class="hljs-keyword">import</span> BlogFactory

pytestmark = pytest.mark.django_db


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestBlogCRUD</span>:</span>
    blog_list_url = reverse(<span class="hljs-string">'blog:blog-list'</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_create_blog</span>(<span class="hljs-params">self, api_client</span>):</span>
        data = {
            <span class="hljs-string">"title"</span>: <span class="hljs-string">"Good news"</span>,
            <span class="hljs-string">"body"</span>: <span class="hljs-string">"Something good starts small"</span>,
            <span class="hljs-string">"published"</span>: <span class="hljs-literal">True</span>
            }

        response = api_client.post(self.blog_list_url, data)
        <span class="hljs-keyword">assert</span> response.status_code == <span class="hljs-number">201</span>
        returned_json = response.json()
        <span class="hljs-keyword">assert</span> <span class="hljs-string">'id'</span> <span class="hljs-keyword">in</span> returned_json
        <span class="hljs-keyword">assert</span> returned_json[<span class="hljs-string">'title'</span>] == data[<span class="hljs-string">'title'</span>]
        <span class="hljs-keyword">assert</span> returned_json[<span class="hljs-string">'body'</span>] == data[<span class="hljs-string">'body'</span>]
        <span class="hljs-keyword">assert</span> returned_json[<span class="hljs-string">'published'</span>] == data[<span class="hljs-string">'published'</span>]

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_retrieve_blogs</span>(<span class="hljs-params">self, api_client</span>):</span>
        BlogFactory.create_batch(<span class="hljs-number">5</span>)
        response = api_client.get(self.blog_list_url)
        <span class="hljs-keyword">assert</span> response.status_code == <span class="hljs-number">200</span>
        <span class="hljs-keyword">assert</span> len(response.json()) == <span class="hljs-number">5</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_delete_blog</span>(<span class="hljs-params">self, api_client</span>):</span>
        blog = BlogFactory()
        url = reverse(<span class="hljs-string">"blog:blog-detail"</span>,
                      kwargs={<span class="hljs-string">"pk"</span>: blog.id})
        response = api_client.delete(url)
        <span class="hljs-keyword">assert</span> response.status_code == <span class="hljs-number">204</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_update_blog</span>(<span class="hljs-params">self, api_client</span>):</span>
        blog = BlogFactory(published= <span class="hljs-literal">True</span>)
        data = {
            <span class="hljs-string">"title"</span>: <span class="hljs-string">"New title"</span>,
            <span class="hljs-string">"body"</span>: <span class="hljs-string">"New body"</span>,
            <span class="hljs-string">"published"</span>: <span class="hljs-literal">False</span>,
        }
        url = reverse(<span class="hljs-string">"blog:blog-detail"</span>,
                      kwargs={<span class="hljs-string">"pk"</span>: blog.id})

        response = api_client.patch(url, data)
        <span class="hljs-keyword">assert</span> response.status_code == <span class="hljs-number">200</span>
        returned_json = response.json()
        <span class="hljs-keyword">assert</span> returned_json[<span class="hljs-string">'title'</span>] == data[<span class="hljs-string">'title'</span>]
        <span class="hljs-keyword">assert</span> returned_json[<span class="hljs-string">'body'</span>] == data[<span class="hljs-string">'body'</span>]
        <span class="hljs-keyword">assert</span> returned_json[<span class="hljs-string">'published'</span>] == data[<span class="hljs-string">'published'</span>]
</code></pre>
<p>The TestBlogCRUD class tests the CRUD functionalities of the application. The class defines four methods, each testing a specific CRUD functionality.</p>
<p>Create a Pytest configuration file named <code>pytest.ini</code> in the root directory. This file will contain settings that instruct Pytest on how to locate the test files.</p>
<p><code>pytest.ini</code></p>
<pre><code class="lang-ini"><span class="hljs-section">[pytest]</span>
<span class="hljs-attr">DJANGO_SETTINGS_MODULE</span> = core.settings
<span class="hljs-attr">python_files</span> = tests.py test_*.py *_tests.py
<span class="hljs-attr">addopts</span> = -p <span class="hljs-literal">no</span>:warnings --<span class="hljs-literal">no</span>-migrations --reuse-db
</code></pre>
<p>To run the tests, execute the <code>pytest</code> command in the root directory as shown below:</p>
<pre><code class="lang-bash">pytest
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/pytest-output.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pytest testcases result</em></p>
<p>The test results indicate that all four test cases have passed successfully.</p>
<p>As of the time of writing, two popular tools used in the Python community for reporting test coverage in a codebase are Coverage and pytest-cov.</p>
<p>In our case, we'll be using <strong>pytest-cov</strong> for its flexibility when it comes to reporting test coverage.</p>
<p>Create a new file named 'setup.cfg' in the root directory. This file serves as the configuration file for coverage.</p>
<p><code>setup.cfg</code></p>
<pre><code class="lang-bash">[coverage:run]
<span class="hljs-built_in">source</span> = .
branch = True
[coverage:report]
show_missing = True
skip_covered = True
</code></pre>
<p>The <code>source</code> value in the <code>[coverage:run]</code> section specifies the root directory location from which test coverage will be measured.</p>
<p>In addition to statement coverage in the test report, branch coverage identifies uncovered branches when using conditional statements (for example if, else, case).</p>
<p>Note: It is possible to specify folders to omit from test coverage, such as migration folders, in the <code>setup.cfg</code> file. We will configure these settings in SonarQube.</p>
<p>Let's rerun the test cases using the following command:</p>
<pre><code class="lang-bash">pytest --cov --cov-report=xml
</code></pre>
<p>The <code>--cov-report</code> option specifies the format of the coverage report. Various formats like HTML, XML, JSON, and so on are supported. In this case, we specify <code>xml</code> because it is supported by SonarQube.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-from-2023-07-13-05-20-43-min.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pytest coverage report in XML format</em></p>
<p>For HTML format, a folder named 'htmlcov' will be generated in the root directory. This folder contains the 'index.html' file, which allows you to visualize the coverage results and areas that are not covered.</p>
<h2 id="heading-how-to-setup-sonarqube">How to Setup SonarQube</h2>
<p>SonarQube is a tool used for static code analysis. It helps in identifying code quality issues, bugs, vulnerabilities, and code smells in software projects.</p>
<p>To simplify the process, we can run a Docker container based on the SonarQube image.</p>
<p>Execute the following command in the command line:</p>
<pre><code class="lang-bash">docker run -d -p 9000:9000 -p 9092:9092 sonarqube
</code></pre>
<p>After a few moments, depending on your internet speed, visit <a target="_blank" href="http://0.0.0.0:9000/">http://0.0.0.0:9000/</a>.</p>
<p>You can use the following login credentials to access the application: Username: admin Password: admin</p>
<p>Next, you need to download Sonar Scanner. Visit this <a target="_blank" href="https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/">link</a> and select the option that is compatible with your operating system (OS).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/sonar-scanner.png" alt="Image" width="600" height="400" loading="lazy">
<em>SonarScanner download on the Sonarsource.com website</em></p>
<p>Unzip the sonar-scanner and move it from the 'Downloads' folder to a secure directory .</p>
<pre><code class="lang-bash">unzip sonar-scanner-cli-4.8.0.2856-linux.zip

mv sonar-scanner-4.2.0.1873-linux /opt/sonar-scanner
</code></pre>
<p>Add the following lines to the content of the <code>sonar-scanner.properties</code> file located at <code>/opt/sonar-scanner/conf/sonar-scanner.properties</code>:</p>
<pre><code class="lang-bash">vim  /opt/sonar-scanner/conf/sonar-scanner.properties
</code></pre>
<p>Add these two lines and save the file:</p>
<pre><code class="lang-bash">sonar.host.url=http://localhost:9000
sonar.sourceEncoding=UTF-8
</code></pre>
<p>Add /opt/sonar-scanner/bin to the system's PATH environment variable by executing this command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> PATH=<span class="hljs-string">"<span class="hljs-variable">$PATH</span>:/opt/sonar-scanner/bin</span>
</code></pre>
<p>Update the content of .bashrc:</p>
<pre><code class="lang-bash">vim ~/.bashrc
</code></pre>
<p>Add this line to the .bashrc file and save it:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> PATH=<span class="hljs-string">"<span class="hljs-variable">$PATH</span>:/opt/sonar-scanner/bin</span>
</code></pre>
<p>Run the following command to apply the changes to your current terminal session:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> ~/.bashrc
</code></pre>
<p>To ensure that everything is functioning properly, execute the following command:</p>
<pre><code class="lang-bash">sonar-scanner -v
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/scanner2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Checking sonarqube version on the terminal</em></p>
<p>Navigate to the 'Projects' tab on the SonarQube dashboard and proceed to manually create a new project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/WhatsApp-Image-2023-07-13-at-06.22.56.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new project on the sonarqube dashboard</em></p>
<p>Provide a suitable name for the project, then select the option "Use the global setting" before proceeding to create the project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/create-suitable-name.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing appropriate name as the name of the new preoject</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/create-globa-setting.png" alt="Image" width="600" height="400" loading="lazy">
<em>Configuring new project to use global settings</em></p>
<p>After creating the project, you will be prompted to select the analysis method for your project. Choose the 'Locally' option.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/WhatsApp-Image-2023-07-13-at-06.34.22.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Run analysis on the project locally</em></p>
<p>After selecting the 'Locally' option, you will be required to generate a token. Click on 'Continue' to proceed. Next, select the programming language of your project and the operating system (OS) it will be running on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/lang-os.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choose the programming language of project and OS</em></p>
<p>Copy the command displayed, as we'll use it to execute the analysis for the project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/WhatsApp-Image-2023-07-13-at-06.38.29.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Code needed to run analyis</em></p>
<p>Here is the content of the command:</p>
<pre><code class="lang-bash">sonar-scanner \
  -Dsonar.projectKey=newretailer \
  -Dsonar.sources=. \
  -Dsonar.host.url=http://0.0.0.0:9000 \
  -Dsonar.token=sqp_7b6aada8ce53e97ebb7b2bf5e9b64d53b8938a6f \
  -Dsonar.python.version=3
</code></pre>
<p>Note: We have added an additional line to the command to specify the Python version as <code>-Dsonar.python.version=3</code>.</p>
<p>Before executing the analysis command, follow these steps:</p>
<ol>
<li>Click on "Project Settings" and then select "General Settings".</li>
<li>Next, navigate to the "Analysis Scope" tab.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/source-file-exclusion.png" alt="Image" width="600" height="400" loading="lazy">
<em>Source files that should be ignored by the analysis</em></p>
<p>Source File Exclusions are used to specify files or folders that SonarQube should not analyze as part of the codebase. These may include files or directories that are not directly part of the code but are still present in the project directory. </p>
<p>Some common examples of such files or folders are:</p>
<ul>
<li>venv (virtualenv)</li>
<li>htmlcov (coverage HTML format)</li>
<li>node_modules (Node.js modules directory)</li>
</ul>
<p>Code Coverage Exclusions are used to specify files or folders that should be excluded when calculating the coverage percentage.</p>
<p>Here are the patterns for the files and folders ignored:<br><strong>/tests/</strong>, <strong>/migrations/</strong>, <strong>/admin.py, </strong>/apps.py, core/asgi.py, core/wsgi.py, manage.py</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-from-2023-07-13-06-55-38.png" alt="Image" width="600" height="400" loading="lazy">
<em>Patterns used to exclude some files from coverage report and coverage percent calculation</em></p>
<p>On the "Languages" tab, select "Python" as the programming language for the project. Then update the path to the coverage report as "<em>coverage</em>.xml".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/uo.png" alt="Image" width="600" height="400" loading="lazy">
<em>Programming language selection and XML coverage report location</em></p>
<p>Execute the previously provided command at the root directory:</p>
<pre><code class="lang-bash">sonar-scanner   -Dsonar.projectKey=DjangoSonar   -Dsonar.sources=.   -Dsonar.host.url=http://0.0.0.0:9000   -Dsonar.token=sqp_bb1dc2534249bf567c681f4acc440c2e278cb43f   -Dsonar.python.coverage.reportPaths=coverage.xml -Dsonar.python.version=3
</code></pre>
<p>If everything is functioning properly, you should see a successful result.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/sonarsuccess.png" alt="Image" width="600" height="400" loading="lazy">
<em>Running sonarqube analysis on the project with command given on the dashboard</em></p>
<p>If you encounter errors related to unauthorized access or permission issues when trying to analyze a project locally, follow these steps:</p>
<ol>
<li>Visit the SonarQube Administrator interface.</li>
<li>Navigate to the 'Security' section.</li>
<li>Look for the option labeled 'Force user authentication' and disable it.</li>
<li>Save the changes and rerun the analysis using the previous command.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/force-user-auth.png" alt="Image" width="600" height="400" loading="lazy">
<em>Debugging authentication error during project analysis</em></p>
<p>Another way to troubleshoot any errors is to visit the warning notifications and check for any errors encountered during the project analysis.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/WhatsApp-Image-2023-07-13-at-07.50.30.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Warning messages for analysis</em></p>
<p>Click on "Overall Code" to access the overall code analysis section:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-from-2023-07-13-07-18-26-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>SonarQube analysis result for the project on the dashboard</em></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>The complete source code for this project is available on <a target="_blank" href="https://github.com/ridwanray/django-sonarqube-pytest-coverage">Github</a>.</p>
<p>Remember to create a <code>.gitignore</code> file in the root directory of your GitHub repository to specify files and directories that should be ignored and not committed.</p>
<p>This article has explored the process of measuring Django code quality using powerful tools such as SonarQube, Pytest, and Coverage. By integrating these tools, you can gain insights into code health, write effective tests, and ensure adequate code coverage. </p>
<p>Applying these practices enhances code quality, resulting in efficient development processes and high-quality software.</p>
<p>If you enjoyed this article, you can check out my <a target="_blank" href="https://youtube.com/@ridwanray/">video collection</a> on <a target="_blank" href="https://youtube.com/@ridwanray/">YouTube</a> to find more fun stuff to learn. And follow me on <a target="_blank" href="https://www.linkedin.com/in/ridwan-yusufa/">LinkedIn</a></p>
<h3 id="heading-references">References:</h3>
<ul>
<li><a target="_blank" href="https://github.com/amirajoodani/sonarqube">https://github.com/amirajoodani/sonarqube</a></li>
<li><a target="_blank" href="https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/">https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/</a></li>
<li><a target="_blank" href="https://coverage.readthedocs.io/en/7.2.7/">https://coverage.readthedocs.io/en/7.2.7/</a></li>
<li><a target="_blank" href="https://docs.pytest.org/en/7.1.x/getting-started.html">https://docs.pytest.org/en/7.1.x/getting-started.html</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Better Way to Structure React Projects ]]>
                </title>
                <description>
                    <![CDATA[ Hello, everyone! A lot of e-ink has already been spilt on the relatively easier pickings of “Doing X in React” or “Using React with technology X”. So instead, I want to talk about the experiences I've had building frontends from scratch at DelightCha... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-better-way-to-structure-react-projects/</link>
                <guid isPermaLink="false">66d45d59a3a4f04fb2dd2e2b</guid>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Akash Joshi ]]>
                </dc:creator>
                <pubDate>Tue, 02 Feb 2021 22:54:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/02/z02wxvp94dwg84c4ifhj.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hello, everyone! A lot of e-ink has already been spilt on the relatively easier pickings of “Doing X in React” or “Using React with technology X”.</p>
<p>So instead, I want to talk about the experiences I've had building frontends from scratch at <a target="_blank" href="https://delightchat.io/">DelightChat</a> and at my previous companies.</p>
<p>These projects require a deeper understanding of React and extended usage in a production setting.</p>
<p>If you want to watch a video version of this tutorial to supplement your reading, <a target="_blank" href="https://www.youtube.com/watch?v=lViIdphWTwY">you can do so here</a>.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/lViIdphWTwY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-introduction">Introduction</h2>
<p>In a nutshell, a complex React project should be structured like this. Although I use NextJS in production, this file structure should be quite useful in any React setting.</p>
<pre><code class="lang-javascript">src
|---adapters
|---contexts
|---components
|---styles
|---pages
</code></pre>
<p><em>Note: In the above file structure, the assets or static files should be placed in whatever the variant of</em> <code>public *</code> <em>folder for your framework is.</em></p>
<p>For each of the above folders, let’s discuss them in order of precedence.</p>
<h2 id="heading-1-adapters">1. Adapters</h2>
<p><code>Adapters</code> are the connectors of your application with the outside world. Any form of API call or websocket interaction which needs to happen, to share data with an external service or client, should happen within the adapter itself.</p>
<p>There are cases where some data is always shared between all the adapters – for example, sharing of cookies, base URL and headers across your AJAX (XHR) adapters. These can be initialized in the xhr folder, and then imported inside of your other adapters to be used further.</p>
<p>This structure will look like this:</p>
<pre><code class="lang-javascript">adapters
|---xhr
|---page1Adapter
|---page2Adapter
</code></pre>
<p>In the case of axios, you can use <code>axios.create</code> to create a base adapter, and either export this initialized instance, or create different functions for get, post, patch and delete to abstract it further. This would look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// adapters/xhr/index.tsx</span>

<span class="hljs-keyword">import</span> Axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">returnAxiosInstance</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> Axios.create(initializers);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">get</span>(<span class="hljs-params">url</span>)</span>{
  <span class="hljs-keyword">const</span> axios = returnAxiosInstance();
  <span class="hljs-keyword">return</span> axios.get(url);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">post</span>(<span class="hljs-params">url, requestData</span>)</span>{
  <span class="hljs-keyword">const</span> axios = returnAxiosInstance();
  <span class="hljs-keyword">return</span> axios.post(url, requestData);
}

... and so on ...
</code></pre>
<p>After you have your base file (or files) ready, create a separate adapter file for each page, or each set of functionalities, depending on how complex your app is. A well-named function makes it very easy to understand what each API call does and what it should accomplish.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// adapters/page1Adapter/index.tsx</span>

<span class="hljs-keyword">import</span> { get, post } <span class="hljs-keyword">from</span> <span class="hljs-string">"adapters/xhr"</span>;
<span class="hljs-keyword">import</span> socket <span class="hljs-keyword">from</span> <span class="hljs-string">"socketio"</span>;

<span class="hljs-comment">// well-named functions</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getData</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-keyword">return</span> get(someUrl);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setData</span>(<span class="hljs-params">requestData</span>)</span>{
  <span class="hljs-keyword">return</span> post(someUrl, requestData);
}

... and so on ...
</code></pre>
<p>But how will these adapters be of any use? Let’s find out in the next section.</p>
<h2 id="heading-2-components">2. Components</h2>
<p>Although in this section we should talk about contexts, I want to talk about components first. This is to understand why context is required (and needed) in complex applications.</p>
<p><code>Components</code> are the life-blood of your application. They will hold the UI for your application, and can sometimes hold the Business Logic and also any State which has to be maintained.</p>
<p>In case a component becomes too complex to express Business Logic with your UI, it is good to be able to split it into a separate bl.tsx file, with your root index.tsx importing all of the functions and handlers from it.</p>
<p>This structure would look like this:</p>
<pre><code class="lang-javascript">components
|---page1Components
        |--Component1
        |--Component2
|---page2Component
        |--Component1
               |---index.tsx
               |---bl.tsx
</code></pre>
<p>In this structure, each page gets its own folder inside of components, so that it’s easy to figure out which component affects what.</p>
<p>It’s also important to limit the scope of a component. Hence, a component should only use <code>adapters</code> for data-fetching, have a separate file for complex Business Logic, and only focus on the UI part.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// components/page1Components/Component1/index.tsx</span>

<span class="hljs-keyword">import</span> businessLogic <span class="hljs-keyword">from</span> <span class="hljs-string">"./bl.tsx"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Component2</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">const</span> { state and functions } = businessLogic();

  <span class="hljs-keyword">return</span> {
    <span class="hljs-comment">// JSX</span>
  }
}
</code></pre>
<p>While the BL file only imports data and returns it:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// components/page1Components/Component1/bl.tsx</span>

<span class="hljs-keyword">import</span> React, {useState, useEffect} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { adapters } <span class="hljs-keyword">from</span> <span class="hljs-string">"adapters/path_to_adapter"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Component1Bl</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-keyword">const</span> [state, setState] = useState(initialState);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetchDataFromAdapter().then(updateState);
  }, [])
}
</code></pre>
<p>However, there’s a problem which is common across all complex apps. State Management, and how to share state across distant components. For example, consider the following file structure:</p>
<pre><code class="lang-javascript">components
|---page1Components
        |--Component1
               |---ComponentA
|---page2Component
        |--ComponentB
</code></pre>
<p>If some state has to be shared across ComponentA and B in the above example, it will have to be passed through all the intermediate components, and also to any other components who want to interact with the state.</p>
<p>To solve this, their are several solutions which can be used like Redux, Easy-Peasy, and React Context, each of them having their own pros and cons. Generally, React Context should be “good enough” to solve this problem. We store all of the files related to context in <code>contexts</code>.</p>
<h2 id="heading-3-contexts">3. Contexts</h2>
<p>The <code>contexts</code> folder is a bare minimum folder only containing the state which has to be shared across these components. Each page can have several nested contexts, with each context only passing the data forward in a downward direction. But to avoid complexity, it is best to only have a single context file. This structure will look like this:</p>
<pre><code class="lang-javascript">contexts
|---page1Context
        |---index.tsx (Exports consumers, providers, ...)
        |---Context1.tsx (Contains part <span class="hljs-keyword">of</span> the state)
        |---Context2.tsx (Contains part <span class="hljs-keyword">of</span> the state)
|---page2Context
        |---index.tsx (Simple enough to also have state)
</code></pre>
<p>In the above case, since <code>page1</code> may be a bit more complex, we allow some nested context by passing the child context as a child to the parent. However, generally a single <code>index.tsx</code> file containing state and exporting relevant files should be enough.</p>
<p>I won’t go into the implementation part of React state management libraries since each of them are their own beasts and have their own upsides and downsides. So, I recommend going through the tutorial of whatever you decide to use to learn their best practises.</p>
<p>The context is allowed to import from <code>adapters</code> to fetch and react to external effects. In case of React Context, the providers are imported inside pages to share state across all components, and something like <code>useContext</code> is used inside these <code>components</code> to be able to utilize this data.</p>
<p>Moving on to the final major puzzle-piece, <code>pages</code>.</p>
<h2 id="heading-4-pages">4. Pages</h2>
<p>I want to avoid being biased to a framework for this piece, but in general, having a specific folder for route-level components to be placed is a good practise.</p>
<p>Gatsby &amp; NextJS enforce having all routes in a folder named <code>pages</code>. This is quite a readable way of defining route-level components, and mimicking this in your CRA-generated application would also result in better code readability.</p>
<p>A centralized location for routes also helps you utilize the “Go To File” functionality of most IDEs by jumping to a file by using (Cmd or Ctrl) + Click on an import.</p>
<p>This helps you move through the code quickly and with clarity of what belongs where. It also sets a clear hierarchy of differentiation between <code>pages</code> and <code>components</code>, where a page can import a component to display it and do nothing else, not even Business Logic.</p>
<p>However, it’s possible to import Context Providers inside of your page so the child components can consume it. Or, in the case of NextJS, write some server-side code which can pass data to your components using getServerSideProps or getStaticProps.</p>
<h2 id="heading-5-styles">5. Styles</h2>
<p>Finally, we come to styles. Although my go-to way is to just embed styles inside of the UI by using a CSS-in-JS solution like Styled-Components, it’s sometimes helpful to have a global set of styles in a CSS file.</p>
<p>A plain old CSS file is more shareable across projects, and can also affect the CSS of components which styled-components can’t reach (for example, third-party components).</p>
<p>So, you can store all of these CSS files inside of the <code>styles</code> folder, and import or link to them freely from wherever you wish.</p>
<p>Those were my thoughts. Feel free to email me in case you want to discuss something or have any more inputs on how this can be improved!</p>
<p>For further updates or discussions, you can follow me on Twitter <a target="_blank" href="https://twitter.com/thewritingdev">here</a>.</p>
<p>My last article on freeCodeCamp was written on how you can get started with Deno by building a URL shortener, which <a target="_blank" href="https://www.freecodecamp.org/news/build-a-url-shortener-in-deno/">you can read here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Environment Variables the Right Way ]]>
                </title>
                <description>
                    <![CDATA[ By Stanley Nguyen Environment variables are one of the foundational concepts for application developers. And they're something we use on a daily basis.  Environment variables have even claimed a part in the de-facto twelve-factor app. They have a lon... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/using-environment-variables-the-right-way/</link>
                <guid isPermaLink="false">66d4614f230dff0166905887</guid>
                
                    <category>
                        <![CDATA[ Application Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 02 Dec 2020 18:27:57 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/12/cover.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Stanley Nguyen</p>
<p>Environment variables are one of the foundational concepts for application developers. And they're something we use on a daily basis. </p>
<p>Environment variables have even claimed a part in <a target="_blank" href="https://12factor.net/config">the de-facto twelve-factor app</a>. They have a long list of benefits that includes application configurability and security, which are covered in many resources like <a target="_blank" href="https://hyperlane.co/blog/the-benefits-of-environment-variables-and-how-to-use-them">this one</a>, or even <a target="_blank" href="https://serverfault.com/questions/892481/what-are-the-advantages-of-putting-secret-values-of-a-website-as-environment-var">this one from StackOverflow</a>.</p>
<p>Environment variables are great and I'm completely behind the idea. However, everything comes at a cost – and environment variables, if wielded carelessly, can have harmful effects on our codebases and applications.</p>
<h2 id="heading-the-curse-of-environment-variables">The curse of environment variables</h2>
<p>How could environment variables be a bad thing if they help us write more secure code and more easily configure our applications for different environments? </p>
<p>Funny enough, environment variables' shortcomings actually derive from their very nature that makes them great: they're global and external, through which application developers are able to inject configurations and manage these secrets somewhere that's more difficult to compromise.</p>
<p>As developers, we all know how bad global states are for our applications. And please don't take my word for it, these evils have been discussed in a lot of places like <a target="_blank" href="https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil">here</a>, <a target="_blank" href="https://thevaluable.dev/global-variable-explained/">here</a>, and <a target="_blank" href="https://stackoverflow.com/questions/19209468/why-is-global-state-bad">here</a>.</p>
<p>For this article, I will be focusing on the 2 main flaws that I mostly encounter when dealing with environment variables:</p>
<ul>
<li>Inflexibility / Poor testability</li>
<li>Code comprehension / readability</li>
</ul>
<h2 id="heading-how-to-use-environment-variables-properly">How to use environment variables properly</h2>
<p>Similarly to how I deal with global variables or global patterns (like singleton) that are applied in bad locations, my favourite weapon is <a target="_blank" href="https://en.wikipedia.org/wiki/Dependency_injection">dependency injection</a>.</p>
<p>It's not going to be the exact same thing that we do to code dependencies, but the principles are the same. Instead of using environment variables (dependencies) directly, we inject them at callsites (that is, the place they are actually used). This inverts the relationship from "callsites depending" to "callsites requiring". </p>
<p>Dependency injection solves these issues by:</p>
<ul>
<li>allowing developers to inject configurations more easily at test time</li>
<li>reducing the mental scope for code readers to the package only, eliminating all externalities</li>
</ul>
<h2 id="heading-so-how-do-we-apply-these-principles">So how do we apply these principles?</h2>
<p>I will be using a Node.js example to demonstrate how we can refactor a codebase and eliminate scattered environment variables.</p>
<h3 id="heading-hypothetical-situation">Hypothetical situation</h3>
<p>Let's say we have a simple app with a single endpoint that will query for all TODOs in a PostGres database. Here is our database module with environment variables scattered into it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { Client } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"pg"</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Postgres</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> c = <span class="hljs-keyword">new</span> Client({
    <span class="hljs-attr">connectionString</span>: process.env.POSTGRES_CONNECTION_URL,
  });
  <span class="hljs-built_in">this</span>.client = c;
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
}

Postgres.prototype.init = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">await</span> c.connect();
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
};

Postgres.prototype.getTodos = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.client.query(<span class="hljs-string">"SELECT * FROM todos"</span>);
};

<span class="hljs-built_in">module</span>.exports = Postgres;
</code></pre>
<p>and this module will be injected into our HTTP controller through the application's entrypoint:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> TodoController = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./controller/todo"</span>);
<span class="hljs-keyword">const</span> Postgres = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./pg"</span>);

<span class="hljs-keyword">const</span> app = express();

(<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> db = <span class="hljs-keyword">new</span> Postgres();
  <span class="hljs-keyword">await</span> db.init();
  <span class="hljs-keyword">const</span> controller = <span class="hljs-keyword">new</span> TodoController(db);
  controller.install(app);

  app.listen(process.env.PORT, <span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (err) <span class="hljs-built_in">console</span>.error(err);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`UP AND RUNNING @ <span class="hljs-subst">${process.env.PORT}</span>`</span>);
  });
})();
</code></pre>
<p>Glancing at the above entry point file, we have no way of telling what the app's requirements for environment variables (or environment config in general) are (minus point for code glanceability 👎 ).</p>
<h3 id="heading-refactoring-the-code">Refactoring the code</h3>
<p>The first step to improve the previously laid-out code is to identify all locations that environment variables are being used directly. </p>
<p>For our specific case above, it's pretty straightforward as the codebase is small. But for larger codebases, you can use linting tools like <a target="_blank" href="https://github.com/eslint/eslint">eslint</a> to scan for all locations that use environment variables directly. Just set up a rule, for example, forbidding environment variables (like <code>node/no-process-env</code> from <a target="_blank" href="https://github.com/mysticatea/eslint-plugin-node#readme">eslint-plugin-node</a>).</p>
<p>Now it's time to remove direct uses of environment variables from our app's modules and include these configurations as part of the module's requirements:</p>
<pre><code class="lang-js">...
function Postgres(opts) {
  <span class="hljs-keyword">const</span> { connectionString } = opts;
  <span class="hljs-keyword">const</span> c = <span class="hljs-keyword">new</span> Client({
    connectionString,
  });
  <span class="hljs-built_in">this</span>.client = c;
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
}
...
</code></pre>
<p>These configurations will then be supplied only from our application's entrypoint:</p>
<pre><code class="lang-js">...
const db = <span class="hljs-keyword">new</span> Postgres({
  <span class="hljs-attr">connectionString</span>: process.env.POSTGRES_CONNECTION_URL,
});
...
</code></pre>
<p>It's much clearer what the environment requirements for our application are now, looking at the entrypoint. This prevents potential problems with forgotten-to-be-added environment variables.</p>
<p>The full source code for the above demo can be found <a target="_blank" href="https://github.com/stanleynguyen/dispelling-environment-variable-curse-demo">here</a>.</p>
<h2 id="heading-bonus-frequently-asked-questions">Bonus: Frequently-asked-questions</h2>
<p>These are some of the questions that <strong>I think</strong> might be asked by those reading this post. Maybe they're not actual frequently asked questionsk, but hey what's the harm in addressing possible alternative opinions?</p>
<h3 id="heading-why-not-use-a-central-config-filemodule">Why not use a central config file/module?</h3>
<p>I have seen quite a few attempts to solve this problem using a central location for drawing out these values (like a <code>config.js</code> file/module for Node projects). </p>
<p>But this approach is no better than actually using the environment variables provided by the application's runtime (like <code>process.env</code>) because everything is still consolidated in a somewhat global state (a single config object used throughout the app). </p>
<p>In fact, it could be even worse, as now we're introducing another location for code to rot.</p>
<h3 id="heading-what-if-i-want-a-zero-config-setup-for-my-module">What if I want a zero-config setup for my module?</h3>
<p>Yes, who doesn't love zero-config, ready-to-roll modules. Again, I would like to re-iterate that building software is all about making trade-offs, and this comes at the cost of readability as this whole post has been discussing. </p>
<p>If you would still like a possible zero-config setup, I would suggest having config objects (that is, the <code>opts</code> constructor argument in the prior code example) and direct environment variable usage only as a fallback, something like this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Postgres</span>(<span class="hljs-params">opts</span>) </span>{
  <span class="hljs-keyword">const</span> connectionString =
    opts.connectionString || process.env.POSTGRES_CONNECTION_URL;
  <span class="hljs-keyword">const</span> c = <span class="hljs-keyword">new</span> Client({
    connectionString,
  });
  <span class="hljs-built_in">this</span>.client = c;
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
}
</code></pre>
<p>This way, readers of our code will still be able to recognise (although with less glanceability, as it's been traded for zero-configurability) the module's requirements.</p>
<h3 id="heading-thank-you-for-reading">Thank you for reading!</h3>
<p>Last but not least, if you like my writings, please head over to <a target="_blank" href="https://blog.stanleynguyen.me/">my blog</a> for similar commentaries and follow <a target="_blank" href="https://twitter.com/stanley_ngn">me on Twitter</a>. 🎉</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Clean Code Explained – A Practical Introduction to Clean Coding for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ By Yiğit Kemal Erinç "Any fool can write code that a computer can understand. Good programmers write code that humans can understand."                             ]]>
                </description>
                <link>https://www.freecodecamp.org/news/clean-coding-for-beginners/</link>
                <guid isPermaLink="false">66d45e3fd14641365a0508a2</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 05 Oct 2020 21:34:18 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/clean-code-image.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Yiğit Kemal Erinç</p>
<blockquote>
<p>"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."                                       – Martin Fowler</p>
</blockquote>
<p>Writing clean, understandable, and maintainable code is a skill that is crucial for every developer to master.</p>
<p>In this post, we will look at the most important principles to improve code quality and I will give you code examples for each of them.</p>
<p>Most examples are taken from Robert J. Martin's <em>Clean Code</em>. It is a programming classic and I suggest you read the whole text when you have time.</p>
<h2 id="heading-how-to-name-variables-and-other-things">How to Name Variables (and other things)</h2>
<blockquote>
<p>"There are only two hard things in Computer Science: cache invalidation and naming things."                                                                                                                – Phil Karlton</p>
</blockquote>
<p>There is a reason why we do not use memory addresses and have names instead: names are much easier to recall. And, more importantly, they can give you more information about the variable, so someone else can understand its significance. </p>
<p>It can take some time to find a good name but it will save you and your team even more time in the future. And I am sure most readers have faced the situation where you visit your code only a few months later and have a hard time understanding what you did before.</p>
<h3 id="heading-how-to-create-meaningful-names">How to Create Meaningful Names</h3>
<p>Do not use comments to explain why a variable is used. If a name requires a comment, then you should take your time to rename that variable instead of writing a comment.</p>
<blockquote>
<p>"A name should tell you why it exists, what it does, and how it is used. If a name requires a comment, then the name does not reveal its intent."                 – Clean Code</p>
</blockquote>
<p><strong>Bad:</strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> d; <span class="hljs-comment">// elapsed time in days</span>
</code></pre>
<p>I have seen this type of code so many times. It is a common misconception that you should hide your mess with comments. Do not use letters like x, y, a, or b as variable names unless there is a good reason (loop variables are an exception to this).</p>
<p><strong>Good:</strong></p>
<pre><code><span class="hljs-keyword">var</span> elapsedTimeInDays;
<span class="hljs-keyword">var</span> daysSinceCreation;
<span class="hljs-keyword">var</span> daysSinceModification;
</code></pre><p>These names are so much better. They tell you what is being measured and the unit of that measurement.</p>
<h3 id="heading-avoid-disinformation">Avoid Disinformation</h3>
<p>Be careful about words that mean something specific. Do not refer to a grouping of accounts as <em>accountList</em> unless its type is actually a List. The word has a specific meaning and it may lead to false conclusions. </p>
<p>Even if the type is a list, <em>accounts</em> is a simpler and better name.</p>
<p><strong>Bad:</strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> accountList = [];
</code></pre>
<p><strong>Good:</strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> accounts = []
</code></pre>
<h3 id="heading-avoid-noise-words">Avoid Noise Words</h3>
<p>Noise words are the words that do not offer any additional information about the variable. They are redundant and should be removed. </p>
<p>Some popular noise words are:</p>
<ul>
<li>The (prefix) </li>
<li>Info</li>
<li>Data</li>
<li>Variable</li>
<li>Object</li>
<li>Manager</li>
</ul>
<p>If your class is named UserInfo, you can just remove the Info and make it User. Using BookData instead of Book as class name is just a no-brainer, as a class stores Data anyways. </p>
<p>You can also read Jeff Atwood's blog post about SomethingManager naming <a target="_blank" href="https://blog.codinghorror.com/i-shall-call-it-somethingmanager/">here</a>.</p>
<h3 id="heading-use-pronounceable-names">Use Pronounceable Names</h3>
<p>If you can't pronounce a name, you can't discuss it without sounding silly.</p>
<p><strong>Bad:</strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> yyyymmdstr = moment().format(<span class="hljs-string">"YYYY/MM/DD"</span>);
</code></pre>
<p><strong>Good:</strong></p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> currentDate = moment().format(<span class="hljs-string">"YYYY/MM/DD"</span>);
</code></pre>
<h3 id="heading-use-searchable-names">Use Searchable Names</h3>
<p>Avoid using magic numbers in your code. Opt for searchable, named constants. Do not use single-letter names for constants since they can appear in many places and therefore are not easily searchable.</p>
<h3 id="heading-bad">Bad:</h3>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (student.classes.length &lt; <span class="hljs-number">7</span>) {
   <span class="hljs-comment">// Do something</span>
}
</code></pre>
<p><strong>Good:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (student.classes.length &lt; MAX_CLASSES_PER_STUDENT) {
    <span class="hljs-comment">// Do something</span>
}
</code></pre>
<p>This is much better because <strong>MAX_CLASSES_PER_STUDENT</strong> can be used in many places in code. If we need to change it to 6 in the future, we can just change the constant. </p>
<p>The bad example creates question marks in the reader's mind, like what is the importance of 7?</p>
<p>You should also make use of your language's constant naming and declaration conventions such as <strong>private static final</strong> in Java or <strong>const</strong> in JavaScript.</p>
<h3 id="heading-be-consistent">Be Consistent</h3>
<p>Follow the <strong>one word for each concept</strong> rule. Do not use <em>fetch</em>, <em>retrieve,</em> and <em>get</em> for the same operation in different classes. Choose one of them and use it all over the project so people who maintain the codebase or the clients of your API can easily find the methods they are looking for.</p>
<h2 id="heading-how-to-write-functions">How to Write Functions</h2>
<h3 id="heading-keep-them-small">Keep them Small</h3>
<p>Functions should be small, really small. They should rarely be 20 lines long. The longer a function gets, it is more likely it is to do multiple things and have side effects.</p>
<h3 id="heading-make-sure-they-just-do-one-thing">Make Sure They Just Do One Thing</h3>
<blockquote>
<p>Functions should do one thing. They should do it well. They should do it only. – Clean Code</p>
</blockquote>
<p>Your functions should do only one thing. If you follow this rule, it is guaranteed that they will be small. The only thing that function does should be stated in its name.</p>
<p>Sometimes it is hard to look at the function and see if it is doing multiple things or not. One good way to check is to try to extract another function with a different name. If you can find it, that means it should be a different function.</p>
<p>This is probably the most important concept in this article, and it will take some time to get used to. But once you get the hang of it, your code will look much more mature, and it will be more easily refactorable, understandable, and testable for sure.</p>
<h3 id="heading-encapsulate-conditionals-in-functions">Encapsulate Conditionals in Functions</h3>
<p>Refactoring the condition and putting it into a named function is a good way to make your conditionals more readable.</p>
<p>Here is a piece of code from a school project of mine. This code is responsible for inserting a chip on the board of the Connect4 game. </p>
<p>The <em>isValidInsertion</em> method takes care of checking the validity of the column number and allows us the focus on the logic for inserting the chip instead.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">insertChipAt</span><span class="hljs-params">(<span class="hljs-keyword">int</span> column)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        <span class="hljs-keyword">if</span> (isValidInsertion(column)) {
            insertChip(column);
            boardConfiguration += column;
            currentPlayer = currentPlayer == Chip.RED ? Chip.YELLOW : Chip.RED;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">if</span> (!columnExistsAt(column))
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException();
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (isColumnFull(column - <span class="hljs-number">1</span>) || getWinner() != Chip.NONE)
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException();
        }
    }
</code></pre>
<p>Here is the code for isValidInsertion, if you are interested.</p>
<pre><code class="lang-java">    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValidInsertion</span><span class="hljs-params">(<span class="hljs-keyword">int</span> column)</span> </span>{
        <span class="hljs-keyword">boolean</span> columnIsAvailable = column &lt;= NUM_COLUMNS &amp;&amp; column &gt;= <span class="hljs-number">1</span> &amp;&amp; numberOfItemsInColumn[column - <span class="hljs-number">1</span>] &lt; NUM_ROWS;
        <span class="hljs-keyword">boolean</span> gameIsOver = getWinner() != Chip.NONE;
        <span class="hljs-keyword">return</span> columnIsAvailable &amp;&amp; !gameIsOver;
    }
</code></pre>
<p>Without the method, if condition would look like this:</p>
<pre><code><span class="hljs-keyword">if</span> (column &lt;= NUM_COLUMNS
 &amp;&amp; column &gt;= <span class="hljs-number">1</span>
 &amp;&amp; numberOfItemsInColumn[column - <span class="hljs-number">1</span>] &lt; NUM_ROWS 
 &amp;&amp; getWinner() != Chip.NONE)
</code></pre><p>Gross, right? I agree.</p>
<h3 id="heading-fewer-arguments">Fewer Arguments</h3>
<p>Functions should have two or fewer arguments, the fewer the better. Avoid three or more arguments where possible. </p>
<p>Arguments make it harder to read and understand the function. They are even harder from a testing point of view, since they create the need to write test cases for every combination of arguments.</p>
<h3 id="heading-do-not-use-flag-arguments">Do not use Flag Arguments</h3>
<p>A flag argument is a boolean argument that is passed to a function. Two different actions are taken depending on the value of this argument.</p>
<p>For example, say there is a function that is responsible for booking tickets to a concert and there are 2 types of users: Premium and Regular. You can have code like this:</p>
<pre><code class="lang-java">    <span class="hljs-function"><span class="hljs-keyword">public</span> Booking <span class="hljs-title">book</span> <span class="hljs-params">(Customer aCustomer, <span class="hljs-keyword">boolean</span> isPremium)</span> </span>{
      <span class="hljs-keyword">if</span>(isPremium) 
       <span class="hljs-comment">// logic for premium book</span>
      <span class="hljs-keyword">else</span>
       <span class="hljs-comment">// logic for regular booking</span>
    }
</code></pre>
<p>Flag arguments naturally contradict the principle of single responsibility. When you see them, you should consider dividing the function into two.</p>
<h3 id="heading-do-not-have-side-effects">Do Not Have Side Effects</h3>
<p>Side effects are unintended consequences of your code. They may be changing the passed parameters, in case of passing by reference, or maybe changing a global variable. </p>
<p>The key point is, they promised to do another thing and you need to read the code carefully to notice the side-effect. They can result in some nasty bugs.</p>
<p>Here is an example from the book:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserValidator</span> </span>{
      <span class="hljs-keyword">private</span> Cryptographer cryptographer;
      <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">checkPassword</span><span class="hljs-params">(String userName, String password)</span> </span>{ 
        User user = UserGateway.findByName(userName);
        <span class="hljs-keyword">if</span> (user != User.NULL) {
          String codedPhrase = user.getPhraseEncodedByPassword();
          String phrase = cryptographer.decrypt(codedPhrase, password);
          <span class="hljs-keyword">if</span> (<span class="hljs-string">"Valid Password"</span>.equals(phrase)) {
            Session.initialize();
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>; 
          }
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>; 
      }
}
</code></pre>
<p>Can you see the side-effect of this function?</p>
<p>It is checking the password, but when the password is valid, it is also initializing the session which is a side-effect. </p>
<p>You can change the name of the function to something like <em>checkPasswordAndInitializeSession</em> to make this effect explicit. But when you do that, you should notice that your function is actually doing two things and you should not initialize the session here.</p>
<h3 id="heading-dont-repeat-yourself">Don't Repeat Yourself</h3>
<p>Code repetition may be the root of all evil in software. Duplicate code means you need to change things in multiple places when there is a change in logic and it is very error prone. </p>
<p>Use your IDE's refactoring features and extract a method whenever you come across a repeated code segment.</p>
<p><img src="https://erinc.io/wp-content/uploads/2020/10/extract_method-1024x576.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>IntelliJ Extract Method</em></p>
<h2 id="heading-bonus">Bonus</h2>
<h3 id="heading-do-not-leave-code-in-comments">Do not leave code in comments</h3>
<p>Please, do not. This one is serious because others who see the code will be afraid to delete it because they do not know if it is there for a reason. That commented out code will stay there for a long time. Then when variable names or method names change, it gets irrelevant but still nobody deletes it.</p>
<p>Just delete it. Even if it was important, there is version control for that. You can always find it.</p>
<h3 id="heading-know-your-languages-conventions">Know your language's conventions</h3>
<p>You should know your language's conventions in terms of spacing, comments, and naming things. There are style guides available for many languages. </p>
<p>For example, you should use camelCase in Java but snake_case in Python. You put opening braces on a new line in C# but you put them on the same line in Java and JavaScript. </p>
<p>These things change from language to language and there is no universal standard.</p>
<p>Here are some useful links for you:</p>
<ul>
<li><a target="_blank" href="https://www.python.org/dev/peps/pep-0008/">Python Style Guide</a></li>
<li><a target="_blank" href="https://google.github.io/styleguide/jsguide.html">Google's Javascript Style Guide</a></li>
<li><a target="_blank" href="https://google.github.io/styleguide/javaguide.html">Google Java Style Guide</a></li>
</ul>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Clean coding is not a skill that can be acquired overnight. It is a habit that needs to be developed by keeping these principles in mind and applying them whenever you write code.</p>
<p>Thank you for taking your time to read and I hope it was helpful.</p>
<p>If you are interested in reading more articles like this, you can subscribe to my <a target="_blank" href="http://erinc.io/">blog</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Screenshot Testing with Cypress to Your Project ]]>
                </title>
                <description>
                    <![CDATA[ By Leonardo Faria Developers are usually concerned with the quality of their code. There are different kinds of tests that help us avoid breaking code when a new feature is added in a project. But what can we do to ensure that components don't look d... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-screenshot-testing-with-cypress-to-your-project/</link>
                <guid isPermaLink="false">66d85178afbaabf7a144aef7</guid>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Continuous Integration ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 04 Aug 2020 16:02:09 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/cypress-io-logo-social-share-8fb8a1db3cdc0b289fad927694ecb415.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Leonardo Faria</p>
<p>Developers are usually concerned with the quality of their code. There are different kinds of tests that help us avoid breaking code when a new feature is added in a project. But what can we do to ensure that components don't look different over time? </p>
<p>In this post, you will learn how to use Cypress to capture parts of pages of a website. After that, you will integrate the testing tool in CI to ensure that in the future no one will make unwanted changes to your project.</p>
<p>My motivation for creating this testing strategy came from work. At <a target="_blank" href="https://www.thinkific.com">Thinkific</a> we have an internal Design System and we added Cypress to avoid surprises when working in CSS/JS files.</p>
<p>By the end of this post we will have PRs with Cypress tests:</p>
<p><img src="https://leonardofaria.net/wp-content/uploads/2020/08/cypress-bot-comment.jpg" alt="Cypress bot" width="1852" height="2006" loading="lazy"></p>
<h2 id="heading-before-we-start">Before we start</h2>
<p>I created a <a target="_blank" href="https://cypress-example.vercel.app/">sample website</a> to mimic a Component Library. It is a very simple website created with TailwindCSS and hosted in Vercel. It documents 2 components: <a target="_blank" href="https://cypress-example.vercel.app/badge.html">badge</a> and <a target="_blank" href="https://cypress-example.vercel.app/button.html">button</a>.</p>
<p>You can check out the <a target="_blank" href="https://github.com/leonardofaria/cypress-example">source code</a> in GitHub. The website is static and it is inside the <code>public</code> folder. You can see the website locally by running <code>npm run serve</code> and checking in the browser <a target="_blank" href="http://localhost:8000">http://localhost:8000</a>.</p>
<p><img src="https://leonardofaria.net/wp-content/uploads/2020/08/cypress-sample-website.png" alt="Sample website" width="2472" height="1701" loading="lazy"></p>
<h2 id="heading-adding-cypress-and-cypress-image-snapshot">Adding Cypress and Cypress Image Snapshot</h2>
<p>Start by cloning the <a target="_blank" href="https://github.com/leonardofaria/cypress-example">example repository</a>. Next, create a new branch and install <a target="_blank" href="https://www.npmjs.com/package/cypress-image-snapshot">Cypress Image Snapshot</a>, the package responsible for capturing/comparing screenshots.</p>
<pre><code class="lang-bash">git checkout -b add-cypress
npm install -D cypress cypress-image-snapshot
</code></pre>
<p>After adding the packages, a few extra steps are needed to add Cypress Image Snapshot in Cypress.</p>
<p>Create a <code>cypress/plugins/index.js</code> file with the following content:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { addMatchImageSnapshotPlugin } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cypress-image-snapshot/plugin'</span>);

<span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">on, config</span>) =&gt;</span> {
  addMatchImageSnapshotPlugin(on, config);
};
</code></pre>
<p>Next, create a <code>cypress/support/index.js</code> file containing:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { addMatchImageSnapshotCommand } <span class="hljs-keyword">from</span> <span class="hljs-string">'cypress-image-snapshot/command'</span>;

addMatchImageSnapshotCommand();
</code></pre>
<h2 id="heading-creating-the-screenshot-test">Creating the screenshot test</h2>
<p>Time to create the screenshot test. Here is the plan:</p>
<ol>
<li>Cypress will visit each page (badge and button) of the project.</li>
<li>Cypress will take a screenshot of each example in the page. The <a target="_blank" href="https://cypress-example.vercel.app/badge.html">Badge page</a> has 2 examples (Default and Pill), while the <a target="_blank" href="https://cypress-example.vercel.app/badge.html">Button page</a> has 3 examples (Default, Pill and Outline). All these examples are inside a <code>&lt;div&gt;</code> element with a <code>cypress-wrapper</code>. This class was added with the only intention being to identify what needs to be tested.</li>
</ol>
<p>The first step is creating Cypress configuration file (<code>cypress.json</code>):</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"baseUrl"</span>: <span class="hljs-string">"http://localhost:8000/"</span>,
  <span class="hljs-attr">"video"</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<p>The <code>baseUrl</code> is the website running locally. As I mentioned before, <code>npm run serve</code> will serve the content of the <code>public</code> folder. The second option, <code>video</code> disables Cypress video recording, which we won't use in this project.</p>
<p>Time to create the test. In <code>cypress/integration/screenshot.spec.js</code>, add:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> routes = [<span class="hljs-string">'badge.html'</span>, <span class="hljs-string">'button.html'</span>];

describe(<span class="hljs-string">'Component screenshot'</span>, <span class="hljs-function">() =&gt;</span> {
  routes.forEach(<span class="hljs-function">(<span class="hljs-params">route</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> componentName = route.replace(<span class="hljs-string">'.html'</span>, <span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> testName = <span class="hljs-string">`<span class="hljs-subst">${componentName}</span> should match previous screenshot`</span>;

    it(testName, <span class="hljs-function">() =&gt;</span> {
      cy.visit(route);

      cy.get(<span class="hljs-string">'.cypress-wrapper'</span>).each(<span class="hljs-function">(<span class="hljs-params">element, index</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> name = <span class="hljs-string">`<span class="hljs-subst">${componentName}</span>-<span class="hljs-subst">${index}</span>`</span>;

        cy.wrap(element).matchImageSnapshot(name);
      });
    });
  });
});
</code></pre>
<p>In the code above, I am dynamically creating tests based in the <code>routes</code> array. The test will create one image per <code>.cypress-wrapper</code> element that the page has.</p>
<p>Last, inside the <code>package.json</code> let's create the command to trigger the tests:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"test"</span>: <span class="hljs-string">"cypress"</span>
}
</code></pre>
<p>From here, there are 2 options: run Cypress in headless mode with <code>npm run cypress run</code> or use the Cypress Test Runner with <code>npm run cypress open</code>.</p>
<h3 id="heading-headless-option">Headless option</h3>
<p>Using <code>npm run cypress run</code>, the output should be similar to the next image:</p>
<p><img src="https://leonardofaria.net/wp-content/uploads/2020/08/cypress-first-test.jpg" alt="Output of first test" width="1908" height="2336" loading="lazy"></p>
<p>The tests will pass and 5 images will be created under the <code>/snapshots/screenshot.spec.js</code> folder.</p>
<h3 id="heading-test-runner-option">Test Runner option</h3>
<p>Using <code>npm run cypress open</code>, Cypress Test Runner will be opened and you can follow the tests step by step.</p>
<p><img src="https://leonardofaria.net/wp-content/uploads/2020/08/cypress-test-runner.jpg" alt="Cypress Test Runner screenshot" width="2090" height="1332" loading="lazy"></p>
<p>Our first milestone is done, so let's merge this branch to master. If you want to see the work done so far, jump in my <a target="_blank" href="https://github.com/leonardofaria/cypress-example/pull/1">Pull Request</a>. </p>
<h2 id="heading-using-cypress-inside-docker">Using Cypress inside Docker</h2>
<p>If you run the test above alternating between headless and Test Runner, you may notice that the screenshot will vary. </p>
<p>Using the Test Runner with a retina display computer, you may get retina images (2x), while the headless mode doesn't give you high-quality screenshots.</p>
<p>Also, it is important to say that the screenshots may vary according to your Operating System. </p>
<p>Linux and Windows, for instance, have apps with visible scrollbars, while macOS hides the scrollbar. </p>
<p>If the content captured in the screenshot doesn't fit a component, you may or may not have a scrollbar. If your project relies on OS default fonts, screenshots will also be different according to the environment.</p>
<p>In order to avoid these inconsistencies, tests will run inside Docker so the developer's computer won't affect the screenshot captures.</p>
<p>Let's start by creating a new branch:</p>
<pre><code class="lang-bash">git checkout -b add-docker
</code></pre>
<p>Cypress offers different Docker images - you can check out the details in <a target="_blank" href="https://docs.cypress.io/examples/examples/docker.html">their documentation</a> and <a target="_blank" href="https://www.cypress.io/blog/2019/05/02/run-cypress-with-a-single-docker-command/">their blog</a>. </p>
<p>For this example, I will use the <code>cypress/included</code> image, which includes Electron and is ready to be used.</p>
<p>We need to make two changes: change the <code>baseUrl</code> in the <code>cypress.json</code> file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"baseUrl"</span>: <span class="hljs-string">"http://host.docker.internal:8000/"</span>,
}
</code></pre>
<p>and the <code>test</code> command in the <code>package.json</code> file: </p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"test"</span>: <span class="hljs-string">"docker run -it -e CYPRESS_updateSnapshots=$CYPRESS_updateSnapshots --ipc=host -v $PWD:/e2e -w /e2e cypress/included:4.11.0"</span>
}
</code></pre>
<p>Running <code>npm run test</code> will bring us a problem:</p>
<p><img src="https://leonardofaria.net/wp-content/uploads/2020/08/cypress-docker.jpg" alt="Output of test" width="1908" height="1824" loading="lazy"></p>
<p>The images are slightly different but why? Let's see what is inside the <code>__diff_output__</code> folder:</p>
<p><img src="https://leonardofaria.net/wp-content/uploads/2020/08/cypress-button-diff.png" alt="Button's difference" width="339" height="40" loading="lazy"></p>
<p>As I mentioned earlier, typography inconsistencies! The Button component uses the OS default font. Since Docker is running inside Linux, the rendered font won't be the same that I have installed on macOS. </p>
<p>Since now we moved to Docker, these screenshots are outdated. Time to update the snapshots:</p>
<pre><code class="lang-bash">CYPRESS_updateSnapshots=<span class="hljs-literal">true</span> npm run <span class="hljs-built_in">test</span>
</code></pre>
<p>Please notice that I am prefixing the test command with the environment variable <code>CYPRESS_updateSnapshots</code>.</p>
<p>The second milestone is done. In case you need help, check out my <a target="_blank" href="https://github.com/leonardofaria/cypress-example/pull/2">pull request</a>.</p>
<p>Let's merge this branch and move forward.</p>
<h2 id="heading-adding-ci">Adding CI</h2>
<p>Our next step is adding the tests in CI. There are different CI solutions in the market but for this tutorial, I will use Semaphore. I am not affiliated with them and I use their product at work, so it was for me a natural choice. </p>
<p>The configuration is straightforward and it can be adapted to other solutions like CircleCI or Github Actions.</p>
<p>Before we create our Semaphore configuration file, let's prepare our project to run in CI.</p>
<p>The first step is installing <a target="_blank" href="https://www.npmjs.com/package/start-server-and-test">start-server-and-test</a>. As the package name says, it will start a server, wait for the URL, and then run a test command:</p>
<pre><code class="lang-bash">npm install -D start-server-and-test
</code></pre>
<p>Second, edit the <code>package.json</code> file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"test"</span>: <span class="hljs-string">"docker run -it -e CYPRESS_baseUrl=$CYPRESS_baseUrl -e CYPRESS_updateSnapshots=$CYPRESS_updateSnapshots --ipc=host -v $PWD:/e2e -w /e2e cypress/included:4.11.0"</span>,
  <span class="hljs-attr">"test:ci"</span>: <span class="hljs-string">"start-server-and-test serve http://localhost:8000 test"</span>
}
</code></pre>
<p>In the <code>test</code> script, we are adding the <code>CYPRESS_baseUrl</code> environment variable. This will allow us to change the base URL used by Cypress dynamically. Also, we are adding the <code>test:ci</code> script, which will run the package we just installed.</p>
<p>We are ready for Semaphore. Create the <code>.semaphore/semaphore.yml</code> file with the following content:</p>
<pre><code class="lang-yml"> <span class="hljs-attr">1 version:</span> <span class="hljs-string">v1.0</span>
 <span class="hljs-attr">2 name:</span> <span class="hljs-string">Cypress</span> <span class="hljs-string">example</span>
 <span class="hljs-attr">3 agent:</span>
 <span class="hljs-attr">4   machine:</span>
 <span class="hljs-attr">5     type:</span> <span class="hljs-string">e1-standard-2</span>
 <span class="hljs-attr">6     os_image:</span> <span class="hljs-string">ubuntu1804</span>
 <span class="hljs-attr">7 blocks:</span>
 <span class="hljs-attr">8   - name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">Dependencies</span>
 <span class="hljs-attr">9     dependencies:</span> []
<span class="hljs-attr">10     task:</span>
<span class="hljs-attr">11       jobs:</span>
<span class="hljs-attr">12         - name:</span> <span class="hljs-string">NPM</span>
<span class="hljs-attr">13           commands:</span>
<span class="hljs-number">14</span>             <span class="hljs-bullet">-</span> <span class="hljs-string">sem-version</span> <span class="hljs-string">node</span> <span class="hljs-number">12</span>
<span class="hljs-number">15</span>             <span class="hljs-bullet">-</span> <span class="hljs-string">checkout</span>
<span class="hljs-number">16</span>             <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span>
<span class="hljs-attr">17   - name:</span> <span class="hljs-string">Tests</span>
<span class="hljs-attr">18     dependencies:</span> [<span class="hljs-string">'Build Dependencies'</span>]
<span class="hljs-attr">19     task:</span>
<span class="hljs-attr">20       prologue:</span>
<span class="hljs-attr">21         commands:</span>
<span class="hljs-number">22</span>           <span class="hljs-bullet">-</span> <span class="hljs-string">sem-version</span> <span class="hljs-string">node</span> <span class="hljs-number">12</span>
<span class="hljs-number">23</span>           <span class="hljs-bullet">-</span> <span class="hljs-string">checkout</span>
<span class="hljs-attr">24       jobs:</span>
<span class="hljs-attr">25         - name:</span> <span class="hljs-string">Cypress</span>
<span class="hljs-attr">26           commands:</span>
<span class="hljs-number">27</span>             <span class="hljs-bullet">-</span> <span class="hljs-string">export</span> <span class="hljs-string">CYPRESS_baseUrl="http://$(ip</span> <span class="hljs-string">route</span> <span class="hljs-string">|</span> <span class="hljs-string">grep</span> <span class="hljs-string">-E</span> <span class="hljs-string">'(default|docker0)'</span> <span class="hljs-string">|</span> <span class="hljs-string">grep</span> <span class="hljs-string">-Eo</span> <span class="hljs-string">'([0-9]+\.){3}[0-9]+'</span> <span class="hljs-string">|</span> <span class="hljs-string">tail</span> <span class="hljs-number">-1</span><span class="hljs-string">):8000"</span>
<span class="hljs-number">28</span>             <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">test:ci</span>
</code></pre>
<p>Breaking the configuration down in detail:</p>
<ul>
<li>Lines 1-6 define which kind of instance we will use in their environment</li>
<li>Lines 8 and 16 create 2 blocks: the first block, "Build Dependencies" will run <code>npm install</code>, downloading the dependencies we need. The second block, "Tests" will run Cypress, with a few differences.</li>
<li>In line 27, we are dynamically setting the <code>CYPRESS_baseUrl</code> environment variable based on the IP Docker is using at the moment. This will replace <code>http://host.docker.internal:8000/</code>, which may not work in all environments.</li>
<li>In line 28, we finally run the test using <code>start-server-and-test</code>: once the server is ready for connections, Cypress will run the test suite.</li>
</ul>
<p>Another milestone is done, time to merge our branch! You can check out the <a target="_blank" href="https://github.com/leonardofaria/cypress-example/pull/6/files">Pull request</a> that contains all the files from this section and check the <a target="_blank" href="https://leonardofaria.semaphoreci.com/workflows/061f6c9f-8f2d-4351-8a25-e5bc1568f67e">build inside Semaphore</a>.</p>
<h2 id="heading-recording-the-tests-in-cypressio">Recording the tests in cypress.io</h2>
<p>Reading the output of tests in CI is not very friendly. In this step, we will integrate our project with <a target="_blank" href="https://www.cypress.io/">cypress.io</a>. </p>
<p>The following steps are based on the <a target="_blank" href="https://docs.cypress.io/guides/dashboard/projects.html#Setup">Cypress documentation</a>.</p>
<p>Let's start by getting a project ID and a record key. In the terminal, create a new branch and run:</p>
<pre><code class="lang-bash">git checkout -b add-cypress-recording
CYPRESS_baseUrl=http://localhost:8000 ./node_modules/.bin/cypress open
</code></pre>
<p>Earlier I mentioned that we would be using Cypress inside Docker. But here we are opening Cypress locally since this is the only way to integrate with the website dashboard. </p>
<p>Inside Cypress, let's go to the Runs tab, click in "Set up project to record", and choose a name and visibility. We will get a <code>projectId</code> that is automatically added in the <code>cypress.json</code> file and a private record key. Here is a video of the steps:</p>

  


<p>In Semaphore, I added the record key as an environment variable called <code>CYPRESS_recordKey</code>. Next let's update our test script to use the variable:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"test:ci"</span>: <span class="hljs-string">"start-server-and-test 'serve' 8000 'npm run test -- run --record --key $CYPRESS_recordKey'"</span>
}
</code></pre>
<p>That is pretty much all that needs to be done. In the <a target="_blank" href="https://github.com/leonardofaria/cypress-example/pull/8">Pull request</a> we can see the cypress.io integration in the comments. There is even a deep link that takes us to their dashboard and shows all the screenshots. Check out the video below:</p>

  


<p>Time to merge our work, and that is the end of our integration.</p>
<h2 id="heading-testing-in-real-life">Testing in real life</h2>
<p>Imagine we are working on a change that affects the padding of the buttons: time to test if Cypress will capture the difference. </p>
<p>In the example website, let's double the horizontal padding from 16px to 32px. This change is quite simple since we are using Tailwind CSS: <code>px-4</code> gets replaced by <code>px-8</code>. Here is that <a target="_blank" href="https://github.com/leonardofaria/cypress-example/pull/9">Pull request</a>.</p>
<p>As we might expect, Cypress captured that the button doesn't match the screenshots. Visiting the page, we can check the screenshot of the broken test:</p>

  


<p>The diff file shows the original screenshot on the left, the current result on the right, and they are combined in the middle. We also have the option to download the image so we can see the issue better:</p>
<div class="full-width"><img alt="Button before and after" src="https://leonardofaria.net/wp-content/uploads/2020/08/cypress-io-broken-test.png" width="2160" height="44" loading="lazy"></div>

<p>If this is not an issue, update the screenshots:</p>
<pre><code class="lang-bash">CYPRESS_updateSnapshots=<span class="hljs-literal">true</span> npm run <span class="hljs-built_in">test</span>
</code></pre>
<h2 id="heading-the-end">The end</h2>
<p>That's it for today. I hope you have learned how Cypress can be useful to ensure no one is adding unexpected changes to a project. </p>
<p>Also posted on <a target="_blank" href="https://bit.ly/30ncCYj">my blog</a>. If you like this content, follow me on <a target="_blank" href="https://twitter.com/leozera">Twitter</a> and <a target="_blank" href="https://github.com/leonardofaria">GitHub</a>.</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="600" 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[ How (and why) to embed domain concepts in code ]]>
                </title>
                <description>
                    <![CDATA[ Code should clearly reflect the problem it’s solving, and thus openly expose that problem’s domain. Embedding domain concepts in code requires thought and skill, and doesn't drop out automatically from TDD. However, it is a necessary step on the road... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/embedding-domain-concepts-in-code/</link>
                <guid isPermaLink="false">66bb925a867a396452a80286</guid>
                
                    <category>
                        <![CDATA[ Quality Software ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #Domain-Driven-Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Cedd Burge ]]>
                </dc:creator>
                <pubDate>Tue, 12 Nov 2019 07:48:19 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/11/2015-Gran-Paradiso-007.JPG" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Code should clearly reflect the problem it’s solving, and thus openly expose that problem’s domain. Embedding domain concepts in code requires thought and skill, and doesn't drop out automatically from TDD. However, it is a necessary step on the road to writing easily understandable code.</p>
<p>I was at a software craftsmanship meetup recently, where we formed pairs to solve a simplified Berlin Clock Kata. A Berlin Clock displays the time using rows of flashing lights, which you can see below (although in the kata we just output a text representation, and the lights in a row are all the same colour).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/berlin-clock-2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-initial-test-driven-solution">Initial Test Driven solution</h2>
<p>Most pairs used inside out TDD, and there were a lot of solutions that looked something like this (complete <a target="_blank" href="https://github.com/ceddlyburge/berlin-clock-initial-tdd-solution/blob/master/BerlinClock.py">code available on GitHub</a>).</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">berlin_clock_time</span>(<span class="hljs-params">julian_time</span>):</span>
    hours, minutes, seconds = list(map(int, julian_time.split(<span class="hljs-string">":"</span>)))

    <span class="hljs-keyword">return</span> [
        seconds_row_lights(seconds % <span class="hljs-number">2</span>)
        , five_hours_row_lights(hours)
        , single_hours_row_lights(hours % <span class="hljs-number">5</span>)
        , five_minutes_row_lights(minutes)
        , single_minutes_row_lights(minutes % <span class="hljs-number">5</span>)
    ]

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">five_hours_row_lights</span>(<span class="hljs-params">hours</span>):</span>
    lights_on = hours // <span class="hljs-number">5</span>
    lights_in_row = <span class="hljs-number">4</span>
    <span class="hljs-keyword">return</span> lights_for_row(<span class="hljs-string">"R"</span>, lights_on, lights_in_row)

<span class="hljs-comment"># ...</span>
</code></pre>
<p>This type of solution drops out naturally from applying inside out TDD to the problem. You write some tests for the seconds row, then some tests for the five hours row, and so on, and then you put it all together and do some refactoring. This solution does expose some of the domain concepts at a glance:</p>
<ul>
<li>There are 5 rows</li>
<li>There is one second row, 2 hour rows and 2 minute rows</li>
</ul>
<p>Some more concepts are available after a bit of digging, but aren't immediately obvious. The rows are made up of lights that can be on (or presumably off), and that the number of lights on is an indication of the time.</p>
<p>However there are some big parts of the problem that are not exposed. And since I haven't yet explained it, you probably don't know exactly how the Berlin Clock works yet.</p>
<h2 id="heading-elevate-the-concepts">Elevate the concepts</h2>
<p>To improve this we can bring some of the details that are buried in the helper functions (such as <code>get_five_hours</code>) closer to the top of the file. This brings you to something like the following (complete <a target="_blank" href="https://github.com/ceddlyburge/berlin-clock-elevated-concepts/blob/master/BerlinClock.py">code available on GitHub</a>), although the downside is that it breaks nearly all of the tests. Solutions like this are rarer on GitHub, but do exist.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">berlin_clock_time</span>(<span class="hljs-params">julian_time</span>):</span>
    hours, minutes, seconds = list(map(int, julian_time.split(<span class="hljs-string">":"</span>)))

    single_seconds = seconds_row_lights(seconds % <span class="hljs-number">2</span>)
    five_hours = row_lights(
        light_colour=<span class="hljs-string">"R"</span>,
        lights_on=hours // <span class="hljs-number">5</span>,
        lights_in_row=<span class="hljs-number">4</span>)
    single_hours = row_lights(
        light_colour=<span class="hljs-string">"R"</span>,
        lights_on=hours % <span class="hljs-number">5</span>,
        lights_in_row=<span class="hljs-number">4</span>)
    five_minutes = row_lights(
        light_colour=<span class="hljs-string">"Y"</span>,
        lights_on=minutes // <span class="hljs-number">5</span>,
        lights_in_row=<span class="hljs-number">11</span>)
    single_minutes = row_lights(
        light_colour=<span class="hljs-string">"Y"</span>,
        lights_on=minutes % <span class="hljs-number">5</span>,
        lights_in_row=<span class="hljs-number">4</span>)

    <span class="hljs-keyword">return</span> [
        single_seconds,
        five_hours,
        single_hours,
        five_minutes,
        single_minutes
    ]

<span class="hljs-comment"># ...</span>
</code></pre>
<p>This improves the concepts that are now exposed at a glance:</p>
<ul>
<li>There are 5 rows</li>
<li>The seconds row is a special case</li>
<li>There are 2 hour rows and 2 minute rows</li>
<li>The rows use different colour lights</li>
<li>The rows have a different number of lights</li>
</ul>
<p>This is pretty good, and is already better that most of the solutions out there. However, it's still a bit mysterious how the rows are related to each other (there are 2 rows to display the hours and the minutes, so presumably these are linked). It's also not obvious what amount of time each light represents.</p>
<h2 id="heading-name-implicit-concepts">Name implicit concepts</h2>
<p>At the moment some of the concepts (such as the amount of time each light represents) are implicit in the code. Making these explicit, and naming them, forces us to understand them and to embed that understanding in the code.</p>
<p>In order to make the amount of time each light represents explicit, it seems like it would be sensible to pass a <code>time_per_light</code> value to <code>row_lights</code>. This means we have to push the calculation of <code>lights_on</code> down into <code>row_lights</code>.</p>
<p>This in turn makes it obvious that there are two kinds of rows: one related to the quotient (<code>\\</code>) of the time value, and one related to the remainder / modulus (<code>%</code>). If we look at the quotient case, we see that the 2nd parameter to the operation is the <code>time_per_light</code>, which is 5 in both cases (5 hours in one case and 5 minutes in the other).</p>
<p>This allows us to write these rows like this:</p>
<pre><code class="lang-python">five_hour_row = row_lights(
    time_per_light=<span class="hljs-number">5</span>,
    value=hours, 
    light_colour=<span class="hljs-string">"R"</span>,
    lights_in_row=<span class="hljs-number">4</span>)
</code></pre>
<p>If we now turn our attention to the remainder case, we realise that <code>time_per_light</code> is always singular (one hour or one minute), as it is filling in the gaps in the quotient case. </p>
<p>For example, the five hours row can represent 0, 5, 10, 15, or 20 hours, but nothing in between. In order to represent any hour, there must be another row to represent +1, +2, +3 and +4. This means that this row must have exactly 4 lights, and that each light must represent 1 hour.</p>
<p>This implies that the remainder case is dependent on the quotient one, which most people would describe as a parent / child relationship.</p>
<p>With this knowledge in hand, we can now create a function for the child remainder rows, and the solution now looks like this (complete <a target="_blank" href="https://github.com/ceddlyburge/berlin-clock">code on GitHub</a>):</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">berlin_clock_time</span>(<span class="hljs-params">julian_time</span>):</span>
    hours, minutes, seconds = list(map(int, julian_time.split(<span class="hljs-string">":"</span>)))

    <span class="hljs-keyword">return</span> [
        seconds_row_lights(
            seconds % <span class="hljs-number">2</span>),
        parent_row_lights(
            time_per_light=<span class="hljs-number">5</span>,
            value=hours, 
            light_colour=<span class="hljs-string">"R"</span>,
            lights_in_row=<span class="hljs-number">4</span>),
        child_remainder_row_lights(
            parent_time_per_light=<span class="hljs-number">5</span>,
            value=hours,
            light_colour=<span class="hljs-string">"R"</span>),
        parent_row_lights(
            time_per_light=<span class="hljs-number">5</span>,
            value=minutes, 
            light_colour=<span class="hljs-string">"Y"</span>,
            lights_in_row=<span class="hljs-number">11</span>),
        child_remainder_row_lights(
            parent_time_per_light=<span class="hljs-number">5</span>,
            light_colour=<span class="hljs-string">"Y"</span>,
            value=minutes)
    ]

<span class="hljs-comment"># ...</span>
</code></pre>
<p>A quick glance at this code now reveals nearly all the domain concepts</p>
<ul>
<li>The first row represents the seconds and is a special case</li>
<li>On the second row each "R" light represents 5 hours</li>
<li>The third row shows the remainder from the second</li>
<li>On the fourth row each "Y" light represents 5 hours</li>
<li>The fifth row shows the remainder from the fourth</li>
</ul>
<p>This took something thinking about, which will have cost us some time / money. But we increased our understanding of the problem while we did it, and most importantly we embedded that knowledge in to the code. This means that the next person to read the code will not have to do this, which will save some time / money. Since we spend about 10 times longer reading code than we do writing it, this is probably a worthwhile endeavour.</p>
<p>Embedding this understanding has also made it harder for future programmers to make mistakes. For example, the concept of parent / child rows didn't exist in earlier examples, and it would be easy to mismatch them. Now the concept is plain to see, and the values are mostly worked out for you. It is also easier to refactor to support new clock variants, for example where lights in the first hours row represent 6 hours.</p>
<h2 id="heading-how-far-should-you-take-it">How far should you take it?</h2>
<p>There are things we can do to take this further. For example the <code>parent_time_per_light</code> of a child row must match the <code>time_per_light</code> of its parent, and there is nothing enforcing this. There is also a relationship between <code>time_per_light</code> and <code>lights_in_row</code> for the parent rows, and again it is not enforced. </p>
<p>However, at the moment we are only required to support one clock variant, so these probably aren't worth doing. When a change is required for the code, we should refactor so that the change is easy (which might be hard) and then make the easy change.</p>
<h2 id="heading-conclusions">Conclusions</h2>
<p>Embedding domain concepts in code requires thought and skill, and TDD won't necessarily do it for you. It takes longer than a naive solution, but makes the code easier to understand, and will very likely save time in the medium term. Time is money, and finding the right balance of spending time now versus saving time later is also an important skill for a professional programmer to have. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ JavaScript's try-catch hid my bugs! ]]>
                </title>
                <description>
                    <![CDATA[ Let me start by making one thing clear - JavaScript is a great language, and not to blame. I was totally to blame - my mental model of error handling was incomplete, and that caused the trouble. Hence, this post. But first, let me give you some conte... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/javascripts-try-catch-hid-my-bugs/</link>
                <guid isPermaLink="false">66d461d02472e5ed2fa07bd3</guid>
                
                    <category>
                        <![CDATA[ Code Quality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Functional Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zubin Pratap ]]>
                </dc:creator>
                <pubDate>Fri, 08 Nov 2019 14:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/11/thomas-smith-doI0mceCxfk-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Let me start by making one thing clear - JavaScript is a great language, and not to blame. I was totally to blame - my mental model of error handling was incomplete, and that caused the trouble. Hence, this post.</p>
<p>But first, let me give you some context. I was writing a bunch of code involving third party APIs (<a target="_blank" href="https://stripe.com/docs/billing/quickstart">Stripe's recurring billing and subscription APIs</a>, to be specific), and had written a wrapper class and some server route-handlers to respond to requests from the front-end web app. The entire application is React +TypeScript + Node, with a <a target="_blank" href="https://koajs.com/">Koa server</a>.</p>
<p>As part of this, I was trying to handle the following errors:</p>
<ol>
<li><p>Errors thrown by Stripe's API</p>
</li>
<li><p>Errors thrown by my wrapper class, especially when fetching user data from the database</p>
</li>
<li><p>Errors in route-handlers that arise from a combination of the above.</p>
</li>
</ol>
<p>During development, my most common errors were incomplete data in the server requests and incorrect data passed to Stripe.</p>
<p>To help you visualize the flow of data, let me give you some background on the server-side code. Typically this is what the function call chain looked like:</p>
<p><em>Route-Handler -&gt; Stripe Wrapper -&gt; Stripe API</em></p>
<p>The first function being called would be in the Route-Handler, then in the Stripe Wrapper class, inside which the Stripe API method would be called. So the call stack has Route-Handler at the bottom (first called function) and the Stripe API method on the top (last called function).</p>
<p>The problem was that I did not understand where to put my error handling. If I did not put an error handler in the server code, then node would crash (literally, exit execution!) and the front end would receive an error HTTP response (typically a HTTP <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500">5xx err0r</a>). So I put a few <code>try-catch</code> handlers inside the various methods being called, and added logging statements inside the <code>catch</code> block. That way I could debug the error by tracking the logs.</p>
<p>An example of the calling logic:</p>
<pre><code class="lang-javascript"> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stripeAPI</span>(<span class="hljs-params">arg</span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'this is the first function'</span>)
    <span class="hljs-keyword">if</span>(!arg) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'no arg!'</span>)
    <span class="hljs-comment">// else</span>
    saveToDb()
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stripeWrapper</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'this is the second function, about to call the first function'</span>)
    <span class="hljs-keyword">try</span>{
        stripeAPI()
    } <span class="hljs-keyword">catch</span>(err) {
<span class="hljs-comment">//         console.log(' this error will not bubble up to the first function that triggered the function calls!')</span>
    }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">routeHandler</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'this is the third  function, about to call the second function'</span>)
    stripeWrapper()
}


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">callAll</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-keyword">try</span>{
       routeHandler() 
       <span class="hljs-keyword">return</span> <span class="hljs-string">'done'</span>
    } <span class="hljs-keyword">catch</span> (err){
       <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'error in callAll():'</span>, err)
       <span class="hljs-keyword">return</span> <span class="hljs-string">' not done '</span>
    }

}


callAll()
</code></pre>
<p>The problems?</p>
<ol>
<li><p>If I didn't log the error, I <em>lost</em> the error! In the above snippet, note that even though I've called <code>first()</code> without the required arguments, the error defined in the definition of <code>first</code> did not get thrown! Also, there is no <code>saveToDb()</code> method defined... and yet this was not caught! If you run this code above, you will see it returns 'done' - and you've got no idea that your database wasn't updated and something had gone wrong! ☠️☠️☠️</p>
</li>
<li><p>My console had way too many logs, repeating the same error. It also meant that in production, there was excessive logging... ?</p>
</li>
<li><p>The code looked ugly. Almost as ugly as my console.</p>
</li>
<li><p>Others who worked with code found it confusing and a debugging nightmare. ?</p>
</li>
</ol>
<p>None of these are good outcomes, and all are avoidable.</p>
<h2 id="heading-the-concepts">The concepts</h2>
<p>So, let's get some basics out of the way. I'm sure you know them but some people may not, and let's not leave them behind!</p>
<p>Some basic terminology:</p>
<p><strong>Error</strong> - also known as an 'exception', is when something goes wrong in the node code, and the program exits immediately. Errors, if not handled, will cause the program to come to a screeching halt, and ugly messages are spewed into the console, with a long and generally hideous error stack trace message.</p>
<p><strong>Throw</strong> <em>-</em> the <code>throw</code> operator is how the language handles an error. By using <code>throw</code> you generate an exception using the value you put after the operator. Note that the code after <code>throw</code> does not get executed - in that sense it is like a <code>return</code> statement.</p>
<p><strong>Error</strong> - there is a JavaScript <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error">object</a> called <code>Error</code>. An error gets 'thrown' in order to help the programmer know something needs to be handled. Think of it as a little ticking bomb ? that gets thrown from one function to another inside a chain of function calls. Technically, you can throw any data, including JavaScript primitives as an error, but it's generally a good idea to throw an <code>Error</code> object.</p>
<p>You typically construct the <code>Error</code> object by passing in a message string like so: <code>new Error('This is an error')</code>. But simply creating a new <code>Error</code>? object is unhelpful as that's only half the job. You've got to <code>throw</code> it so it can be caught. That's how it becomes useful.</p>
<p>Languages generally come with a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors">standard set of errors,</a> but you can create a custom error message with the <code>new Error('this is my error message')</code> constructor, and your error message should help you work out what's going on. More on <a target="_blank" href="https://nodejs.org/api/errors.html">Node errors.</a></p>
<p><strong>Catch</strong> <em>-</em> this is what you do when someone throws something at you, right? You'd probably do it reflexively even if someone threw you one of these... ?!</p>
<p>The <code>catch</code> statement in JavaScript lets you handle an error ? that gets thrown. If you don't catch the error, then the error 'bubbles up' (or down, depending on how you view the call stack) until it reaches the first called function and there it will crash the program.</p>
<p>In my example an error thrown by the Stripe API will bubble up all the way to my Route-Handler function, unless I catch it somewhere along the way and deal with it. If I don't handle the error, Node will throw an <code>uncaughtException</code> error and then terminate the program.</p>
<p>Let's return to my example:</p>
<p><strong>Call stack</strong></p>
<p><em>Route-Handler -&gt; Stripe Wrapper -&gt; Stripe API</em></p>
<p><strong>Error path</strong></p>
<p><em>Stripe API (</em>? _thrown here) -&gt; API Wrapper (<em>� �_not caught) -&gt;</em> _Route-Handler (_� �still <em>not caught) -&gt; ccrraashh</em> ???</p>
<p>We want to avoid app crashes as it can cause your data to corrupt, your state to be inconsistent, and your user to think your app sucks. So handling errors thoughtfully requires many levels of analysis.</p>
<p>There are some detailed guides to error handling in JavaScript and one of my favourites is <a target="_blank" href="http://javascript.info/try-catch">here</a>, but I will summarize my key leanings for you here.</p>
<h2 id="heading-try-catch-statement">Try-Catch statement</h2>
<p>Use these to gracefully handle errors, but be careful about <em>where</em> and <em>when</em>. When errors are caught and not handled properly they are lost. That 'bubbling up' process happens only up until the error encounters a <code>catch</code> statement. If there is a <code>catch</code> statement in the call chain that intercepts the error then the error won't crash the app, but not handling the error will hide it! Then it gets passed as an argument to <code>catch</code> and it requires you to handle it there.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span>{
<span class="hljs-comment">// code logic</span>
} <span class="hljs-keyword">catch</span> (error) {
<span class="hljs-comment">// handle the error appropriately</span>
}
</code></pre>
<p>So it's very important to catch <em>and</em> handle the error at a point where it makes the most logical sense for you when you have to debug it. It's tempting to think that you must catch it at the very first place it comes up (the last function called that sits right on the top of the call stack), but that isn't true!</p>
<p><em>Route-Handler -&gt; Stripe Wrapper (don't catch here!) -&gt; Stripe API</em></p>
<p>If I put my <code>try-catch</code> in the Stripe Wrapper which directly invokes Stripe's API, then I don't have information on <em>where</em> my Stripe Wrapper function was called. Maybe it was the handler, maybe it was another method inside my wrapper, maybe it was in another file altogether! In this simple example it's obviously called by Route-Handler, but in a real world app, it could be called in multiple places.</p>
<p>Instead, it makes sense for me to put the <code>try-catch</code> in the Route-Handler, which is the very first place where the function calls begin that resulted in the error. That way you can trace the call stack (also called unwinding the call stack) and drill down into the error. If I send bad data to Stripe it will throw an error, and that error will pass through my code until I catch it.</p>
<p>But when I catch it I need to handle it properly, or I could inadvertently conceal this error. Handling errors usually means deciding whether I need my front end user to know something has gone wrong (their payment didn't work, for example), or is it just an internal server error (for example, Stripe could not find the product ID I passed) that I need to handle gracefully without tripping up my front end users and crashing the Node code. If I added things to the database that are not correct, then I should clean up those false writes now.</p>
<p>When handling the error, it is a good idea to log it so I can monitor the app for bugs and failures in production and debug efficiently. So at the very, very least, handling would include logging the error in the <code>catch</code> statement. But...</p>
<pre><code class="lang-javascript"> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stripeAPI</span>(<span class="hljs-params">arg</span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'this is the first function'</span>)
    <span class="hljs-keyword">if</span>(!arg) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'no arg!'</span>)
    <span class="hljs-comment">// else</span>
    saveToDb()
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stripeWrapper</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'this is the second function, about to call the first function'</span>)
    <span class="hljs-keyword">try</span> {
        stripeAPI()
    } <span class="hljs-keyword">catch</span>(err) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Oops!  err will not bubble up to the first function that triggered the function calls!'</span>)
    }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">routeHandler</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'this is the third  function, about to call the second function'</span>)
    stripeWrapper()
}


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">callAll</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-keyword">try</span> {
       routeHandler() 
       <span class="hljs-keyword">return</span> <span class="hljs-string">'done'</span>
    } <span class="hljs-keyword">catch</span> (err){  
       <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'error in callAll():'</span>, err)
       <span class="hljs-keyword">return</span> <span class="hljs-string">' not done '</span>
    }

}


callAll()
</code></pre>
<p>...as you can see above, if I catch it and log it in the middle level (my Stripe Wrapper class), it won't reach <code>routeHandler</code> or <code>callAll</code>, and my app will not know something went wrong. <code>callAll</code> still returns <code>done</code> and the only evidence something went wrong was in the log statement: <code>'Oops! err will not bubble up to to first function that triggered the function calls!'</code>. Had we not put a log statement there the error would have vanished without a trace.</p>
<p>This is 'error hiding' and it makes debugging a pain. If I add a <code>try-catch</code> but don't do anything in the <code>catch</code> statement, I will prevent my program from crashing. But I also end up 'hiding' the problem! It usually leads to inconsistent state - parts of my server code thinks everything is OK, and tells my front end that. But another part of my server code had indicated something was wrong!</p>
<p>In this simple example, it's easy to unravel, but think of deeply nested called across your entire application - what a nightmare!</p>
<p>If you absolutely need to handle the error in the middle of your call stack, then be sure to re-throw the error appropriately. That means ending your <code>catch</code> statement with another <code>throw error</code> operation. That way the error will get thrown again and continue to 'bubble up' towards the first function (bottom of the call stack) that triggered the call chain where it can be properly handled again.</p>
<p>Here's what it looks like, adding just one small re-throw in the <code>stripeWrapper()</code> function. Run the code and see the difference in outcome because <code>callAll()</code> now gets passed the error!</p>
<pre><code class="lang-plaintext">function stripeWrapper(){
    console.log('this is the second function, about to call the first function')
    try{
        stripeAPI()
    } catch(err) {
        console.log('Oops!  err will not bubble up to to first function that triggered the function calls!')

        throw err  // add this to re-throw!

    }
}

function callAll(){
    try{
       routeHandler() 
       return 'done'
    } catch (err){  // catches the re-thrown error and prints it to console!
       console.log('error in callAll():', err)
       return ' not done '
    }

}
</code></pre>
<p>Since you threw the error in the middle stage, it went to the outer boundary, and got caught there. The code returns <code>not done</code> and you can investigate why the error says 'no arg'. You can also then see that it never executed <code>saveToDb()</code>, as the error threw before that code could be executed! That could be a good thing in cases where you're saving things to the database <em>assuming that there were no errors until that point</em>. Imagine saving things to the database that should never have been saved - that's dirty data in the database now! ???</p>
<p>So, don't do what I did in my early days of programming and simply log the error at <em>every</em> step in the call stack and re-throw it. It just means you will get multiple logs for each error as it passes through the call stack! Only intercept the error at a place where you can most efficiently and usefully handle it, ideally once in a given chain of calls.</p>
<p>In general, it really helps if you place your <code>try catch</code> statement at the outermost (first calling) function that lies at the bottom of the call stack. You can identify this as the place the error will bubble up to <em>just before</em> throwing an <code>uncaughtException</code> error. That's a good place to catch, log, and handle it.</p>
<p>To see the difference in handling when you don't use the <code>try-catch</code> simply modify <code>callAll()</code> to look like this:</p>
<pre><code class="lang-plaintext">function callAll(){
    routeHandler()  

    // this won't run!
    console.log('This function is not contained inside a try-catch, so will crash the node program.')
}

callAll()
</code></pre>
<p>You'll note that the <code>console.log</code> statement never runs here because the program crashes when <code>routeHandler()</code> finishes executing.</p>
<h2 id="heading-rules-of-thumb">Rules of Thumb ???</h2>
<p>So let's summarize some quick rules that will cover 90+% of your needs:</p>
<ol>
<li><p>Do not litter your code with <code>try-catch</code> statements</p>
</li>
<li><p>Try as much as possible to <code>catch</code> only once in a given chain of function calls</p>
</li>
<li><p>Try and place that <code>catch</code> at the outermost boundary - the first function that starts the chain of function calls (bottom of the call stack)</p>
</li>
<li><p>Do not leave your <code>catch</code> statement empty as a way to stop your program from crashing! If you don't handle it, chances are it will lead to inconsistent state between your front end and back end. This can be dangerous and lead to a horrible user experience ?!</p>
</li>
<li><p>Do not use a <code>catch</code> statement only in the middle of the call stack, and not at the outer boundary. This will cause the error to get 'hidden' in the middle of your code where it isn't going to help you debug or manage data properly. Others who work with your code will find where you live and cut off your internet connection.</p>
</li>
<li><p>Catch it where you need to know, and where you can meaningfully do all the things necessary to clean things up.</p>
</li>
</ol>
<p><em>Stripe API (</em>? <em>thrown here) -&gt; API Wrapper (</em>? <em>passing through) -&gt;</em> <em>Route-Handler (</em>? <em>caught, handled, logged) -&gt;</em> ???</p>
<p>Thanks for reading!</p>
<p>If you would like to learn more about my journey into code, check out <a target="_blank" href="http://podcast.freecodecamp.org/53-zubin-pratap-from-lawyer-to-developer">episode 53</a> of the <a target="_blank" href="http://podcast.freecodecamp.org/">freeCodeCamp podcast</a>, where Quincy (founder of freeCodeCamp) and I share our experiences as career changers that may help you on your journey. You can also access the podcast on <a target="_blank" href="https://itunes.apple.com/au/podcast/ep-53-zubin-pratap-from-lawyer-to-developer/id1313660749?i=1000431046274&amp;mt=2">iTunes</a>, <a target="_blank" href="https://www.stitcher.com/podcast/freecodecamp-podcast/e/59201373?autoplay=true">Stitcher</a>, and <a target="_blank" href="https://open.spotify.com/episode/4lG0RGpzriG5vXRMgza05C">Spotify</a>.</p>
<p>I will also hold a few AMAs and webinars in the coming months. If this is of interest to you please let me know by going <a target="_blank" href="http://www.matchfitmastery.com/">here</a>. And of course, you can also Tweet me at <a target="_blank" href="https://twitter.com/zubinpratap">@ZubinPratap</a>.</p>
<p>(Banner photo by <a target="_blank" href="https://unsplash.com/@thomastasy?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Thomas Smith</a> on <a target="_blank" href="https://unsplash.com/s/photos/bugs?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>)</p>
 ]]>
                </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="600" 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>
        
    </channel>
</rss>
