<?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[ clean code - 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[ clean code - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 16:27:34 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/clean-code/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build Production-Ready Full Stack Apps with the MERN Stack ]]>
                </title>
                <description>
                    <![CDATA[ As developers, we’re always looking for more efficient tools. The MERN stack (MongoDB, Express.js, React, and Node.js) stands out for its JavaScript-centric nature, offering a unified language across the entire application. In this guide, you'll buil... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-production-ready-full-stack-apps-with-the-mern-stack/</link>
                <guid isPermaLink="false">686bd0446349e98b57ebc099</guid>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mohit Menghnani ]]>
                </dc:creator>
                <pubDate>Mon, 07 Jul 2025 13:48:52 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751502709499/b43b3607-f01b-45c0-9797-75eef92497c6.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As developers, we’re always looking for more efficient tools. The MERN stack (MongoDB, Express.js, React, and Node.js) stands out for its JavaScript-centric nature, offering a unified language across the entire application.</p>
<p>In this guide, you'll build a complete Task Manager app with user authentication, protected routes, and full CRUD functionality, built with React on the frontend and Express/MongoDB on the backend.</p>
<p>This article will serve as your hands-on, code-first guide to building, securing, and deploying a MERN application, drawing from my own practical experience. Every section has code you can run, and I’ll give concise explanations along the way.</p>
<p>It doesn’t matter if you're just getting started with MERN or looking to level up your architecture and production deployment knowledge – this article is designed to get you from zero to production with confidence.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-tools-amp-tech-stack">Tools &amp; Tech Stack</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-skills-amp-setup">Skills &amp; Setup</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-project-setup-laying-the-groundwork">Project Setup: Laying the Groundwork</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-project-structure">Project Structure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-code-quality-linting-and-formatting">Code Quality: Linting and Formatting</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-ensuring-robustness">Testing: Ensuring Robustness</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-backend-testing-nodejsexpressjs">Backend Testing (Node.js/Express.js)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-frontend-testing-react-testing-library-cypress">Frontend Testing (React Testing Library + Cypress)</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-the-task-manager">How to Build the Task Manager</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-backend-implementation-nodejsexpressjs">Backend Implementation (Node.js/Express.js)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-frontend-implementation-react">Frontend Implementation (React)</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-deployment-from-localhost-to-live">Deployment: From</a> <a target="_blank" href="http://Localhost">Localhost</a> <a class="post-section-overview" href="#heading-deployment-from-localhost-to-live">to Live</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-backend-deployment-nodejsexpressjs">Backend Deployment (Node.js/Express.js)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-frontend-deployment-react">Frontend Deployment (React)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-database-deployment-mongodb-atlas">Database Deployment (MongoDB Atlas)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-1-env-configuration-example">1. .env Configuration Example</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-connect-to-mongodb-in-appjs">2. Connect to MongoDB in app.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-other-deployment-options">Other Deployment Options</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-security-best-practices-fortifying-your-application">Security Best Practices: Fortifying Your Application</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-setup-input-validation-and-sanitization">Setup Input Validation and Sanitization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-add-authentication-and-authorization">Add Authentication and Authorization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-implement-rate-limiting">Implement Rate Limiting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-setup-cors-configuration-cross-origin-resource-sharing">Setup CORS Configuration (Cross-Origin Resource Sharing)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-environment-variables">Use Environment Variables</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-monitoring-and-logging-with-winston-and-morgan">Monitoring and Logging with Winston and Morgan</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-frontend-error-monitoring-sentry">Frontend Error Monitoring (Sentry)</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before jumping in the project, here’s what you’ll need to get the most out of this tutorial:</p>
<h3 id="heading-tools-amp-tech-stack">Tools &amp; Tech Stack</h3>
<p>You’ll be using the following technologies throughout the project:</p>
<ul>
<li><p><strong>Node.js &amp; npm</strong> – Backend runtime and package manager</p>
</li>
<li><p><strong>Express.js</strong> – Web framework for Node</p>
</li>
<li><p><strong>MongoDB Atlas</strong> – Cloud-hosted NoSQL database</p>
</li>
<li><p><strong>Mongoose</strong> – ODM for MongoDB</p>
</li>
<li><p><strong>React</strong> – Frontend UI library</p>
</li>
<li><p><strong>React Router</strong> – For client-side routing</p>
</li>
<li><p><strong>Axios</strong> – For making API requests</p>
</li>
<li><p><strong>Jest &amp; Supertest</strong> – For backend tests</p>
</li>
<li><p><strong>React Testing Library &amp; Cypress</strong> – For Frontend unit and E2E tests</p>
</li>
<li><p><strong>ESLint + Prettier</strong> – For code formatting, linting</p>
</li>
<li><p><strong>Husky</strong> – To setup pre-commit hooks</p>
</li>
<li><p><strong>Helmet, Joi, express-rate-limit, cors</strong> – For security, validation, and best practices</p>
</li>
<li><p><strong>PM2 &amp; NGINX</strong> – For backend deployment</p>
</li>
<li><p><strong>Sentry</strong> – For error monitoring</p>
</li>
</ul>
<h3 id="heading-skills-amp-setup">Skills &amp; Setup</h3>
<ul>
<li><p>Basic knowledge of JavaScript, React, and Node.js</p>
</li>
<li><p>Familiarity with REST APIs and HTTP request/response flows</p>
</li>
<li><p>Git and a GitHub account for version control</p>
</li>
<li><p>A free MongoDB Atlas account</p>
</li>
<li><p>Node.js and npm installed locally (Node 18+ recommended)</p>
</li>
</ul>
<h2 id="heading-project-setup-laying-the-groundwork"><strong>Project Setup: Laying the Groundwork</strong></h2>
<p>A well-structured project is crucial for maintainability. We'll adopt a clear separation between the front end and the back end here.</p>
<h3 id="heading-project-structure"><strong>Project Structure</strong></h3>
<p>This structure clearly separates the React front end (client/) from the Node.js/Express.js back end (server/), promoting modularity and easier management.</p>
<pre><code class="lang-javascript">my-mern-app/                # Root folder
├── client/                 # React frontend
│   ├── public/
│   ├── src/
│   │   ├── components/
│   │   ├── pages/
│   │   ├── App.js
│   │   └── index.js
│   └── package.json
├── server/                 # Node.js/Express.js backend
│   ├── config/
│   ├── controllers/
│   ├── models/
│   ├── routes/
│   ├── services/
│   ├── app.js
│   └── package.json
</code></pre>
<h3 id="heading-code-quality-linting-and-formatting"><strong>Code Quality: Linting and Formatting</strong></h3>
<p>Consistency is key when you’re building a production-grad application like this one. We'll use ESLint with Airbnb style and Prettier for automated code quality and formatting.</p>
<p>To install these tools, run this in your terminal:</p>
<pre><code class="lang-bash">npm install --save-dev eslint prettier eslint-config-airbnb-base eslint-plugin-prettier
</code></pre>
<p>And here are some setups with their recommended configurations:</p>
<p>This configuration sets up ESLint for a Node.js project using the Airbnb and Prettier style guides, with custom rules to relax strict linting constraints like allowing <code>console.log</code> and disabling mandatory function names.</p>
<h4 id="heading-eslintrcjs-server-side-example"><strong>.eslintrc.js (server-side example)</strong></h4>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {

  <span class="hljs-attr">env</span>: {

    <span class="hljs-attr">node</span>: <span class="hljs-literal">true</span>,

    <span class="hljs-attr">commonjs</span>: <span class="hljs-literal">true</span>,

    <span class="hljs-attr">es2021</span>: <span class="hljs-literal">true</span>,

  },

  <span class="hljs-attr">extends</span>: [<span class="hljs-string">"airbnb-base"</span>, <span class="hljs-string">"prettier"</span>],

  <span class="hljs-attr">plugins</span>: [<span class="hljs-string">"prettier"</span>],

  <span class="hljs-attr">parserOptions</span>: {

    <span class="hljs-attr">ecmaVersion</span>: <span class="hljs-number">12</span>,

  },

  <span class="hljs-attr">rules</span>: {

    <span class="hljs-string">"prettier/prettier"</span>: <span class="hljs-string">"error"</span>,

    <span class="hljs-string">"no-console"</span>: <span class="hljs-string">"off"</span>,

    <span class="hljs-string">"func-names"</span>: <span class="hljs-string">"off"</span>,

    <span class="hljs-string">"no-process-exit"</span>: <span class="hljs-string">"off"</span>,

    <span class="hljs-string">"class-methods-use-this"</span>: <span class="hljs-string">"off"</span>,

    <span class="hljs-string">"import/no-extraneous-dependencies"</span>: <span class="hljs-string">"off"</span>,

  },

};
</code></pre>
<h4 id="heading-prettierrc"><strong>.prettierrc</strong></h4>
<p>This config enforces consistent formatting: add semicolons, use trailing commas where valid, and prefer single quotes for strings.</p>
<pre><code class="lang-json">{

  <span class="hljs-attr">"semi"</span>: <span class="hljs-literal">true</span>,

  <span class="hljs-attr">"trailingComma"</span>: <span class="hljs-string">"all"</span>,

  <span class="hljs-attr">"singleQuote"</span>: <span class="hljs-literal">true</span>

}
</code></pre>
<h3 id="heading-version-control-git-essentials"><strong>Version Control: Git Essentials</strong></h3>
<p>Git is indispensable. You can use feature branches and pull requests for collaborative development, making it easier to work on large projects with coworkers. Consider using Husky for pre-commit hooks to enforce linting and testing.</p>
<h4 id="heading-install-husky">Install Husky:</h4>
<p>Install Husky to easily manage Git hooks, allowing you to automate tasks like linting and testing before commits.</p>
<pre><code class="lang-bash">npm install husky --save-dev
</code></pre>
<h4 id="heading-packagejson-add-script">package.json (add script)</h4>
<p>This <code>package.json</code> file sets up a Node.js project named <code>my-mern-app</code>, and configures a <code>prepare</code> script to install Git hooks using Husky (v7). It's ready for adding pre-commit automation, such as linting or testing.</p>
<pre><code class="lang-json">{

  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"my-mern-app"</span>,

  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,

  <span class="hljs-attr">"description"</span>: <span class="hljs-string">""</span>,

  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"index.js"</span>,

  <span class="hljs-attr">"scripts"</span>: {

    <span class="hljs-attr">"prepare"</span>: <span class="hljs-string">"husky install"</span>

  },

  <span class="hljs-attr">"keywords"</span>: [],

  <span class="hljs-attr">"author"</span>: <span class="hljs-string">""</span>,

  <span class="hljs-attr">"license"</span>: <span class="hljs-string">"ISC"</span>,

  <span class="hljs-attr">"devDependencies"</span>: {

    <span class="hljs-attr">"husky"</span>: <span class="hljs-string">"^7.0.0"</span>

  }

}
</code></pre>
<h4 id="heading-create-a-pre-commit-hook">Create a pre-commit hook</h4>
<p>The below command sets up a pre-commit hook that automatically runs your tests and linter before each commit, ensuring code quality and preventing errors from entering your codebase.</p>
<pre><code class="lang-json">npx husky add .husky/pre-commit <span class="hljs-string">"npm test &amp;&amp; npm run lint"</span>
</code></pre>
<h2 id="heading-testing-ensuring-robustness"><strong>Testing: Ensuring Robustness</strong></h2>
<p>Automated testing is vital. We'll cover unit, integration, and end-to-end testing in this guide.</p>
<h3 id="heading-backend-testing-nodejsexpressjs">Backend Testing (Node.js/Express.js)</h3>
<p>You’ll use Jest for unit testing and Supertest for API integration tests.</p>
<h5 id="heading-install-them-like-this">Install them like this:</h5>
<pre><code class="lang-bash">npm install --save-dev jest supertest
</code></pre>
<p>You’ll use Jest to write unit tests for your JavaScript code and Supertest to test HTTP requests against your Express.js API.</p>
<h4 id="heading-example-test-servertestsauthtestjs">Example Test (server/tests/auth.test.js):</h4>
<p>This test suite uses Supertest to simulate API calls for user registration and login, asserting that the responses have the expected status codes and properties.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> request = <span class="hljs-built_in">require</span>(<span class="hljs-string">'supertest'</span>);

<span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../app'</span>); <span class="hljs-comment">// Your Express app instance</span>

describe(<span class="hljs-string">'Auth API'</span>, <span class="hljs-function">() =&gt;</span> {

  it(<span class="hljs-string">'should register a new user'</span>, <span class="hljs-keyword">async</span> () =&gt; {

    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)

      .post(<span class="hljs-string">'/api/auth/register'</span>)

      .send({

        <span class="hljs-attr">username</span>: <span class="hljs-string">'testuser'</span>,

        <span class="hljs-attr">email</span>: <span class="hljs-string">'test@example.com'</span>,

        <span class="hljs-attr">password</span>: <span class="hljs-string">'password123'</span>,

      });

    expect(res.statusCode).toEqual(<span class="hljs-number">201</span>);

    expect(res.body).toHaveProperty(<span class="hljs-string">'_id'</span>);

  });


  it(<span class="hljs-string">'should login an existing user'</span>, <span class="hljs-keyword">async</span> () =&gt; {

    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)

      .post(<span class="hljs-string">'/api/auth/login'</span>)

      .send({

        <span class="hljs-attr">email</span>: <span class="hljs-string">'test@example.com'</span>,

        <span class="hljs-attr">password</span>: <span class="hljs-string">'password123'</span>,

      });

    expect(res.statusCode).toEqual(<span class="hljs-number">200</span>);

    expect(res.headers[<span class="hljs-string">'set-cookie'</span>]).toBeDefined();

  });

});
</code></pre>
<h3 id="heading-frontend-testing-react-testing-library-cypress">Frontend Testing (React Testing Library + Cypress)</h3>
<p>You’ll use Jest and the React Testing Library for unit/integration tests, and Cypress for E2E tests.</p>
<h5 id="heading-you-can-install-these-like-this">You can install these like this:</h5>
<pre><code class="lang-bash">npm install --save-dev @testing-library/react @testing-library/jest-dom jest cypress
</code></pre>
<p>React Testing Library will help you test your React components, and Cypress will provide comprehensive end-to-end testing of your frontend application.</p>
<h4 id="heading-example-component-test-clientsrccomponentsbuttontestjs">Example Component Test (client/src/components/Button.test.js):</h4>
<p>This unit test uses the React Testing Library to render a Button component and verifies that the specified text content is present in the rendered output.</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> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;

<span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">'./Button'</span>;


test(<span class="hljs-string">'renders button with text'</span>, <span class="hljs-function">() =&gt;</span> {

  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Button</span>&gt;</span>Click Me<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>);

  <span class="hljs-keyword">const</span> buttonElement = screen.getByText(<span class="hljs-regexp">/Click Me/i</span>);

  expect(buttonElement).toBeInTheDocument();

});
</code></pre>
<p>The following Cypress test simulates a complete user authentication flow, from registration to login and logout, asserting expected URL changes and page content.</p>
<pre><code class="lang-javascript">Example E2E Test (cypress/e2e/auth.cy.js)

describe(<span class="hljs-string">'Authentication Flow'</span>, <span class="hljs-function">() =&gt;</span> {

  it(<span class="hljs-string">'should allow a user to register and login'</span>, <span class="hljs-function">() =&gt;</span> {

    cy.visit(<span class="hljs-string">'/register'</span>);

    cy.get(<span class="hljs-string">'input[name="username"]'</span>).type(<span class="hljs-string">'e2euser'</span>);

    cy.get(<span class="hljs-string">'input[name="email"]'</span>).type(<span class="hljs-string">'e2e@example.com'</span>);

    cy.get(<span class="hljs-string">'input[name="password"]'</span>).type(<span class="hljs-string">'password123'</span>);

    cy.get(<span class="hljs-string">'button[type="submit"]'</span>).click();

    cy.url().should(<span class="hljs-string">'include'</span>, <span class="hljs-string">'/dashboard'</span>);

    cy.contains(<span class="hljs-string">'Welcome, e2euser'</span>);

    cy.get(<span class="hljs-string">'button'</span>).contains(<span class="hljs-string">'Logout'</span>).click();

    cy.url().should(<span class="hljs-string">'include'</span>, <span class="hljs-string">'/login'</span>);

    cy.get(<span class="hljs-string">'input[name="email"]'</span>).type(<span class="hljs-string">'e2e@example.com'</span>);

    cy.get(<span class="hljs-string">'input[name="password"]'</span>).type(<span class="hljs-string">'password123'</span>);

    cy.get(<span class="hljs-string">'button[type="submit"]'</span>).click();

    cy.url().should(<span class="hljs-string">'include'</span>, <span class="hljs-string">'/dashboard'</span>);

  });

});
</code></pre>
<h2 id="heading-how-to-build-the-task-manager"><strong>How to Build the Task Manager</strong></h2>
<p>We'll build a simple Task Manager with user authentication and CRUD operations for tasks so you can see how the whole thing comes together.</p>
<h3 id="heading-backend-implementation-nodejsexpressjs">Backend Implementation (Node.js/Express.js)</h3>
<h4 id="heading-dependencies">Dependencies</h4>
<p>Start by installing our core backend libraries: Express for routing, Mongoose for MongoDB interactions, dotenv for environment variables, bcrypt/jsonwebtoken/cookie-parser for secure authentication, and helmet for setting secure HTTP headers:</p>
<pre><code class="lang-bash">npm install express mongoose dotenv bcryptjs jsonwebtoken cookie-parser
</code></pre>
<h4 id="heading-serverappjs-entry-point">server/app.js (Entry Point)</h4>
<p>Next, we’ll set up the first or the main entry point for the backend. This is the main Express.js application file, which configures middleware, establishes a MongoDB connection, and sets up API routes for authentication and task management.</p>
<pre><code class="lang-javascript"><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> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);

<span class="hljs-keyword">const</span> dotenv = <span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>);

<span class="hljs-keyword">const</span> cookieParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cookie-parser'</span>);

<span class="hljs-keyword">const</span> helmet = <span class="hljs-built_in">require</span>(<span class="hljs-string">'helmet'</span>);

<span class="hljs-keyword">const</span> authRoutes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./routes/authRoutes'</span>);

<span class="hljs-keyword">const</span> taskRoutes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./routes/taskRoutes'</span>);

<span class="hljs-keyword">const</span> { notFound, errorHandler } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./middleware/errorMiddleware'</span>);

dotenv.config();


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

app.use(helmet());

app.use(express.json());

app.use(cookieParser());


mongoose.connect(process.env.MONGO_URI)

  .then(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'MongoDB connected!'</span>))

  .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'MongoDB connection error:'</span>, err));


app.use(<span class="hljs-string">'/api/auth'</span>, authRoutes);

app.use(<span class="hljs-string">'/api/tasks'</span>, taskRoutes);


app.get(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {

  res.send(<span class="hljs-string">'MERN Task Manager API is running!'</span>);

});


app.use(notFound);

app.use(errorHandler);


<span class="hljs-keyword">const</span> PORT = process.env.PORT || <span class="hljs-number">5000</span>;

app.listen(PORT, <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running on port <span class="hljs-subst">${PORT}</span>`</span>);

});
</code></pre>
<h4 id="heading-serverenv">server/.env</h4>
<p>To avoid hardcoding secrets, we’ll add a <code>.env</code> file where we can securely store environment variables, such as our database URI and JWT secret. This file stores sensitive environment variables such as your MongoDB connection string, server port, and JWT secret, keeping them secure and separate from your codebase.</p>
<pre><code class="lang-bash">MONGO_URI=your_mongodb_connection_string_here

PORT=5000

JWT_SECRET=supersecretjwtkey
</code></pre>
<h4 id="heading-servermodelsuserjs">server/models/User.js</h4>
<p>Now, let’s define our User model using MongoDB. This schema includes fields for username, email, and password, with pre-save hooks for password hashing and a method for password comparison.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);

<span class="hljs-keyword">const</span> bcrypt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'bcryptjs'</span>);


<span class="hljs-keyword">const</span> UserSchema = <span class="hljs-keyword">new</span> mongoose.Schema({

  <span class="hljs-attr">username</span>: {

    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,

    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,

    <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span>,

  },

  <span class="hljs-attr">email</span>: {

    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,

    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,

    <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span>,

  },

  <span class="hljs-attr">password</span>: {

    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,

    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,

  },

});

UserSchema.pre(<span class="hljs-string">'save'</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">next</span>) </span>{

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.isModified(<span class="hljs-string">'password'</span>)) {

    next();

  }

  <span class="hljs-keyword">const</span> salt = <span class="hljs-keyword">await</span> bcrypt.genSalt(<span class="hljs-number">10</span>);

  <span class="hljs-built_in">this</span>.password = <span class="hljs-keyword">await</span> bcrypt.hash(<span class="hljs-built_in">this</span>.password, salt);

});


UserSchema.methods.matchPassword = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">enteredPassword</span>) </span>{

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> bcrypt.compare(enteredPassword, <span class="hljs-built_in">this</span>.password);

};


<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'User'</span>, UserSchema);
</code></pre>
<h4 id="heading-servermodelstaskjs">server/models/Task.js</h4>
<p>Next, we’ll create the Task model. This schema defines the Task model, which links each task to a user and includes fields for title, description, completion status, and creation timestamp.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);


<span class="hljs-keyword">const</span> TaskSchema = <span class="hljs-keyword">new</span> mongoose.Schema({

  <span class="hljs-attr">user</span>: {

    <span class="hljs-attr">type</span>: mongoose.Schema.Types.ObjectId,

    <span class="hljs-attr">ref</span>: <span class="hljs-string">'User'</span>,

    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,

  },

  <span class="hljs-attr">title</span>: {

    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,

    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,

    <span class="hljs-attr">trim</span>: <span class="hljs-literal">true</span>,

  },

  <span class="hljs-attr">description</span>: {

    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,

    <span class="hljs-attr">trim</span>: <span class="hljs-literal">true</span>,

  },

  <span class="hljs-attr">completed</span>: {

    <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>,

    <span class="hljs-attr">default</span>: <span class="hljs-literal">false</span>,

  },

  <span class="hljs-attr">createdAt</span>: {

    <span class="hljs-attr">type</span>: <span class="hljs-built_in">Date</span>,

    <span class="hljs-attr">default</span>: <span class="hljs-built_in">Date</span>.now,

  },

});


<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'Task'</span>, TaskSchema);
</code></pre>
<h4 id="heading-servercontrollersauthcontrollerjs">server/controllers/authController.js</h4>
<p>Let’s build out the authentication controller. This controller handles user authentication flows, including registration, login, logout, and fetching user profiles, using JWTs and secure HTTP-only cookies.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/User'</span>);

<span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);

<span class="hljs-keyword">const</span> generateToken = <span class="hljs-function">(<span class="hljs-params">id</span>) =&gt;</span> {

  <span class="hljs-keyword">return</span> jwt.sign({ id }, process.env.JWT_SECRET, {

    <span class="hljs-attr">expiresIn</span>: <span class="hljs-string">'1h'</span>,

  });

};

<span class="hljs-built_in">exports</span>.registerUser = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">const</span> { username, email, password } = req.body;

  <span class="hljs-keyword">try</span> {

    <span class="hljs-keyword">const</span> userExists = <span class="hljs-keyword">await</span> User.findOne({ email });

    <span class="hljs-keyword">if</span> (userExists) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'User already exists'</span> });

    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.create({ username, email, password });

    <span class="hljs-keyword">if</span> (user) {

      <span class="hljs-keyword">const</span> token = generateToken(user._id);

      res.cookie(<span class="hljs-string">'token'</span>, token, { <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">secure</span>: process.env.NODE_ENV === <span class="hljs-string">'production'</span>, <span class="hljs-attr">maxAge</span>: <span class="hljs-number">3600000</span> });

      res.status(<span class="hljs-number">201</span>).json({ <span class="hljs-attr">id</span>: user.id, <span class="hljs-attr">username</span>: user.username, <span class="hljs-attr">email</span>: user.email });

    } <span class="hljs-keyword">else</span> {

      res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Invalid user data'</span> });

    }

  } <span class="hljs-keyword">catch</span> (error) {

    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: error.message });

  }

};


<span class="hljs-built_in">exports</span>.loginUser = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">const</span> { email, password } = req.body;

  <span class="hljs-keyword">try</span> {

    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findOne({ email });

    <span class="hljs-keyword">if</span> (user &amp;&amp; (<span class="hljs-keyword">await</span> user.matchPassword(password))) {

      <span class="hljs-keyword">const</span> token = generateToken(user._id);

      res.cookie(<span class="hljs-string">'token'</span>, token, { <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">secure</span>: process.env.NODE_ENV === <span class="hljs-string">'production'</span>, <span class="hljs-attr">maxAge</span>: <span class="hljs-number">3600000</span> });

      res.json({ <span class="hljs-attr">id</span>: user.id, <span class="hljs-attr">username</span>: user.username, <span class="hljs-attr">email</span>: user.email });

    } <span class="hljs-keyword">else</span> {

      res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Invalid email or password'</span> });

    }

  } <span class="hljs-keyword">catch</span> (error) {

    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: error.message });

  }

};


<span class="hljs-built_in">exports</span>.logoutUser = <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {

  res.cookie(<span class="hljs-string">'token'</span>, <span class="hljs-string">''</span>, { <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">expires</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-number">0</span>) });

  res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Logged out successfully'</span> });

};


<span class="hljs-built_in">exports</span>.getUserProfile = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">try</span> {

    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findById(req.user._id).select(<span class="hljs-string">'-password'</span>);

    <span class="hljs-keyword">if</span> (user) {

      res.json(user);

    } <span class="hljs-keyword">else</span> {

      res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'User not found'</span> });

    }

  } <span class="hljs-keyword">catch</span> (error) {

    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: error.message });

  }

};
</code></pre>
<h4 id="heading-servercontrollerstaskcontrollerjs">server/controllers/taskController.js</h4>
<p>Now it’s time to implement the task controller. This controller provides the logic for fetching, creating, updating, and deleting tasks, ensuring that users can only interact with their tasks.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Task = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/Task'</span>);


<span class="hljs-built_in">exports</span>.getTasks = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">try</span> {

    <span class="hljs-keyword">const</span> tasks = <span class="hljs-keyword">await</span> Task.find({ <span class="hljs-attr">user</span>: req.user._id });

    res.status(<span class="hljs-number">200</span>).json(tasks);

  } <span class="hljs-keyword">catch</span> (error) {

    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: error.message });

  }

};


<span class="hljs-built_in">exports</span>.createTask = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">const</span> { title, description } = req.body;

  <span class="hljs-keyword">if</span> (!title) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Please add a title'</span> });

  <span class="hljs-keyword">try</span> {

    <span class="hljs-keyword">const</span> task = <span class="hljs-keyword">await</span> Task.create({ title, description, <span class="hljs-attr">user</span>: req.user._id });

    res.status(<span class="hljs-number">201</span>).json(task);

  } <span class="hljs-keyword">catch</span> (error) {

    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: error.message });

  }

};


<span class="hljs-built_in">exports</span>.updateTask = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">try</span> {

    <span class="hljs-keyword">const</span> task = <span class="hljs-keyword">await</span> Task.findById(req.params.id);

    <span class="hljs-keyword">if</span> (!task) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Task not found'</span> });

    <span class="hljs-keyword">if</span> (task.user.toString() !== req.user._id.toString()) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Not authorized'</span> });


    <span class="hljs-keyword">const</span> updatedTask = <span class="hljs-keyword">await</span> Task.findByIdAndUpdate(req.params.id, req.body, { <span class="hljs-attr">new</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">runValidators</span>: <span class="hljs-literal">true</span> });

    res.status(<span class="hljs-number">200</span>).json(updatedTask);

  } <span class="hljs-keyword">catch</span> (error) {

    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: error.message });

  }

};


<span class="hljs-built_in">exports</span>.deleteTask = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">try</span> {

    <span class="hljs-keyword">const</span> task = <span class="hljs-keyword">await</span> Task.findById(req.params.id);

    <span class="hljs-keyword">if</span> (!task) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Task not found'</span> });

    <span class="hljs-keyword">if</span> (task.user.toString() !== req.user._id.toString()) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Not authorized'</span> });


    <span class="hljs-keyword">await</span> Task.deleteOne({ <span class="hljs-attr">_id</span>: req.params.id });

    res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Task removed'</span> });

  } <span class="hljs-keyword">catch</span> (error) {

    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: error.message });

  }

};
</code></pre>
<h4 id="heading-servermiddlewareauthmiddlewarejs">server/middleware/authMiddleware.js</h4>
<p>To protect private routes<strong>,</strong> we will create a middleware that verifies the JWT from the request's cookies, ensuring that only authenticated users can access specific endpoints.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);

<span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/User'</span>);

<span class="hljs-built_in">exports</span>.protect = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {

  <span class="hljs-keyword">let</span> token;

  <span class="hljs-keyword">if</span> (req.cookies.token) {

    <span class="hljs-keyword">try</span> {

      token = req.cookies.token;

      <span class="hljs-keyword">const</span> decoded = jwt.verify(token, process.env.JWT_SECRET);

      req.user = <span class="hljs-keyword">await</span> User.findById(decoded.id).select(<span class="hljs-string">'-password'</span>);

      next();

    } <span class="hljs-keyword">catch</span> (error) {

      res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Not authorized, token failed'</span> });

    }

  } <span class="hljs-keyword">else</span> {

    res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Not authorized, no token'</span> });

  }

};
</code></pre>
<h4 id="heading-servermiddlewareerrormiddlewarejs">server/middleware/errorMiddleware.js</h4>
<p>To handle errors cleanly across our backend, we’ll add global error-handling middleware that can handle 404 Not Found errors and provide a centralized error-handling mechanism for consistent API error responses.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">exports</span>.notFound = <span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> error = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Not Found - <span class="hljs-subst">${req.originalUrl}</span>`</span>);

  res.status(<span class="hljs-number">404</span>);

  next(error);

};


<span class="hljs-built_in">exports</span>.errorHandler = <span class="hljs-function">(<span class="hljs-params">err, req, res, next</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> statusCode = res.statusCode === <span class="hljs-number">200</span> ? <span class="hljs-number">500</span> : res.statusCode;

  res.status(statusCode);

  res.json({

    <span class="hljs-attr">message</span>: err.message,

    <span class="hljs-attr">stack</span>: process.env.NODE_ENV === <span class="hljs-string">'production'</span> ? <span class="hljs-literal">null</span> : err.stack,

  });

};
</code></pre>
<h4 id="heading-serverroutesauthroutesjs">server/routes/authRoutes.js</h4>
<p>Next, let’s define our authentication routes. These endpoints enable user authentication and map HTTP methods to their corresponding controller functions.</p>
<pre><code class="lang-javascript"><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> { registerUser, loginUser, logoutUser, getUserProfile } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../controllers/authController'</span>);

<span class="hljs-keyword">const</span> { protect } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../middleware/authMiddleware'</span>);


<span class="hljs-keyword">const</span> router = express.Router();


router.post(<span class="hljs-string">'/register'</span>, registerUser);

router.post(<span class="hljs-string">'/login'</span>, loginUser);

router.get(<span class="hljs-string">'/logout'</span>, logoutUser);

router.get(<span class="hljs-string">'/profile'</span>, protect, getUserProfile);


<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<h4 id="heading-serverroutestaskroutesjs">server/routes/taskRoutes.js</h4>
<p>Now we’ll add the routes for task operations. This file defines the API routes for task management, applying the protect middleware to secure all task-related operations.</p>
<pre><code class="lang-javascript"><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> { getTasks, createTask, updateTask, deleteTask } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../controllers/taskController'</span>);

<span class="hljs-keyword">const</span> { protect } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../middleware/authMiddleware'</span>);

<span class="hljs-keyword">const</span> router = express.Router();

router.route(<span class="hljs-string">'/'</span>).get(protect, getTasks).post(protect, createTask);

router.route(<span class="hljs-string">'/:id'</span>).put(protect, updateTask).delete(protect, deleteTask);

<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<h3 id="heading-frontend-implementation-react">Frontend Implementation (React)</h3>
<h4 id="heading-dependencies-1">Dependencies</h4>
<p>Now, you’ll need to initialize a new React project and install your essential libraries: Axios for HTTP requests, React Router for navigation, and React Toastify for displaying notifications.</p>
<pre><code class="lang-bash">npm install axios react-router-dom react-toastify
</code></pre>
<h4 id="heading-clientsrcindexjs">client/src/index.js</h4>
<p>Let’s start the frontend by setting up the entry point. Here we are rendering the main App component and wrapping it with AuthProvider to provide authentication context globally.</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> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;

<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;

<span class="hljs-keyword">import</span> { AuthProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'./context/AuthContext'</span>;


<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>));

root.render(

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">AuthProvider</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">AuthProvider</span>&gt;</span>

  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>

);
</code></pre>
<h4 id="heading-clientsrcappjs">client/src/App.js</h4>
<p>Next, we’ll define our main App component. This sets up the client-side routing for the application, and defines public and private routes, and includes a navigation bar and toast notification system.</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> { BrowserRouter <span class="hljs-keyword">as</span> Router, Routes, Route } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-keyword">import</span> { ToastContainer } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-toastify'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'react-toastify/dist/ReactToastify.css'</span>;


<span class="hljs-keyword">import</span> Navbar <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Navbar'</span>;

<span class="hljs-keyword">import</span> Register <span class="hljs-keyword">from</span> <span class="hljs-string">'./pages/Register'</span>;

<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">'./pages/Login'</span>;

<span class="hljs-keyword">import</span> Dashboard <span class="hljs-keyword">from</span> <span class="hljs-string">'./pages/Dashboard'</span>;

<span class="hljs-keyword">import</span> PrivateRoute <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/PrivateRoute'</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">Router</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">Navbar</span> /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">ToastContainer</span> /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container"</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/register"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Register</span> /&gt;</span>} /&gt;

          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/login"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Login</span> /&gt;</span>} /&gt;

          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">PrivateRoute</span> /&gt;</span>}&gt;

            <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">index</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span> /&gt;</span>} /&gt;

          <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">h1</span>&gt;</span>Welcome to Task Manager!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>} /&gt;

        <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span></span>

  );

}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h4 id="heading-clientsrccontextauthcontextjs">client/src/context/AuthContext.js</h4>
<p>We’ll create an authentication context that manages the global authentication state. It provides functions for user login, registration, and logout, and automatically loads user data on component mount.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { createContext, 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> AuthContext = createContext();

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

  <span class="hljs-keyword">const</span> [user, setUser] = useState(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);


  useEffect(<span class="hljs-function">() =&gt;</span> {

    <span class="hljs-keyword">const</span> loadUser = <span class="hljs-keyword">async</span> () =&gt; {

      <span class="hljs-keyword">try</span> {

        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'/api/auth/profile'</span>);

        setUser(res.data);

      } <span class="hljs-keyword">catch</span> (err) {

        setUser(<span class="hljs-literal">null</span>);

      } <span class="hljs-keyword">finally</span> {

        setLoading(<span class="hljs-literal">false</span>);

      }

    };

    loadUser();

  }, []);


  <span class="hljs-keyword">const</span> login = <span class="hljs-keyword">async</span> (email, password) =&gt; {

    <span class="hljs-keyword">try</span> {

      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.post(<span class="hljs-string">'/api/auth/login'</span>, { email, password });

      setUser(res.data);

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

    } <span class="hljs-keyword">catch</span> (err) {

      <span class="hljs-built_in">console</span>.error(err.response.data.message);

      <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    }

  };


  <span class="hljs-keyword">const</span> register = <span class="hljs-keyword">async</span> (username, email, password) =&gt; {

    <span class="hljs-keyword">try</span> {

      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.post(<span class="hljs-string">'/api/auth/register'</span>, { username, email, password });

      setUser(res.data);

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

    } <span class="hljs-keyword">catch</span> (err) {

      <span class="hljs-built_in">console</span>.error(err.response.data.message);

      <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    }

  };


  <span class="hljs-keyword">const</span> logout = <span class="hljs-keyword">async</span> () =&gt; {

    <span class="hljs-keyword">try</span> {

      <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'/api/auth/logout'</span>);

      setUser(<span class="hljs-literal">null</span>);

    } <span class="hljs-keyword">catch</span> (err) {

      <span class="hljs-built_in">console</span>.error(err);

    }

  };


  <span class="hljs-keyword">return</span> (

    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AuthContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">user</span>, <span class="hljs-attr">loading</span>, <span class="hljs-attr">login</span>, <span class="hljs-attr">register</span>, <span class="hljs-attr">logout</span> }}&gt;</span>

      {children}

    <span class="hljs-tag">&lt;/<span class="hljs-name">AuthContext.Provider</span>&gt;</span></span>

  );

};


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AuthContext;
</code></pre>
<h4 id="heading-clientsrccomponentsnavbarjs">client/src/components/Navbar.js</h4>
<p>Here’s a dynamic navigation bar component that dynamically displays links based on the user's authentication status, showing either login/register options or a welcome message and logout button.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-keyword">import</span> AuthContext <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AuthContext'</span>;


<span class="hljs-keyword">const</span> Navbar = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">const</span> { user, logout } = useContext(AuthContext);


  <span class="hljs-keyword">return</span> (

    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Task Manager<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

        {user ? (

          <span class="hljs-tag">&lt;&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Welcome, {user.username}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{logout}</span>&gt;</span>Logout<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/dashboard"</span>&gt;</span>Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

          <span class="hljs-tag">&lt;/&gt;</span>

        ) : (

          <span class="hljs-tag">&lt;&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/login"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/register"</span>&gt;</span>Register<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

          <span class="hljs-tag">&lt;/&gt;</span></span>

        )}

      &lt;/div&gt;

    &lt;/nav&gt;

  );

};


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Navbar;
</code></pre>
<h4 id="heading-clientsrccomponentsprivateroutejs">client/src/components/PrivateRoute.js</h4>
<p>To protect certain pages, we can create a Private Route component. This will be a guard for private routes, ensuring that only authenticated users can access them and redirecting unauthenticated users to the login page.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> { Navigate, Outlet } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-keyword">import</span> AuthContext <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AuthContext'</span>;


<span class="hljs-keyword">const</span> PrivateRoute = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">const</span> { user, loading } = useContext(AuthContext);


  <span class="hljs-keyword">if</span> (loading) {

    <span class="hljs-keyword">return</span> <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>; <span class="hljs-comment">// Or a spinner</span>

  }


  <span class="hljs-keyword">return</span> user ? <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Outlet</span> /&gt;</span></span> : <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Navigate</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/login"</span> <span class="hljs-attr">replace</span> /&gt;</span></span>;

};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> PrivateRoute;
</code></pre>
<h4 id="heading-clientsrcpagesregisterjs">client/src/pages/Register.js</h4>
<p>Now, let’s create the Register component, which provides a user registration form, handles input state and form submission, and displays success or error messages using toast notifications.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-keyword">import</span> { toast } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-toastify'</span>;

<span class="hljs-keyword">import</span> AuthContext <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AuthContext'</span>;


<span class="hljs-keyword">const</span> Register = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">const</span> [username, setUsername] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> { register } = useContext(AuthContext);

  <span class="hljs-keyword">const</span> navigate = useNavigate();


  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (e) =&gt; {

    e.preventDefault();

    <span class="hljs-keyword">const</span> success = <span class="hljs-keyword">await</span> register(username, email, password);

    <span class="hljs-keyword">if</span> (success) {

      toast.success(<span class="hljs-string">'Registration successful!'</span>);

      navigate(<span class="hljs-string">'/dashboard'</span>);

    } <span class="hljs-keyword">else</span> {

      toast.error(<span class="hljs-string">'Registration failed. Please try again.'</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>Register<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Username:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{username}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setUsername(e.target.value)} required /&gt;

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setEmail(e.target.value)} required /&gt;

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Password:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setPassword(e.target.value)} required /&gt;

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Register<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">form</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> Register;
</code></pre>
<h4 id="heading-clientsrcpagesloginjs">client/src/pages/Login.js</h4>
<p>Now, for the login form, it works similarly to the register page but logs users into the system instead. This page manages input fields, handles form submissions, and provides feedback via toast notifications.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-keyword">import</span> { toast } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-toastify'</span>;

<span class="hljs-keyword">import</span> AuthContext <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AuthContext'</span>;


<span class="hljs-keyword">const</span> Login = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> { login } = useContext(AuthContext);

  <span class="hljs-keyword">const</span> navigate = useNavigate();


  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (e) =&gt; {

    e.preventDefault();

    <span class="hljs-keyword">const</span> success = <span class="hljs-keyword">await</span> login(email, password);

    <span class="hljs-keyword">if</span> (success) {

      toast.success(<span class="hljs-string">'Login successful!'</span>);

      navigate(<span class="hljs-string">'/dashboard'</span>);

    } <span class="hljs-keyword">else</span> {

      toast.error(<span class="hljs-string">'Login failed. Invalid credentials.'</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>Login<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setEmail(e.target.value)} required /&gt;

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Password:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setPassword(e.target.value)} required /&gt;

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">form</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> Login;
</code></pre>
<h4 id="heading-clientsrcpagesdashboardjs">client/src/pages/Dashboard.js</h4>
<p>Finally, we’ll build the Dashboard page. This dashboard component displays a user's tasks, allowing them to create new tasks, mark tasks as complete or incomplete, and delete tasks, with real-time updates.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useEffect, useContext } <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">import</span> { toast } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-toastify'</span>;

<span class="hljs-keyword">import</span> AuthContext <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AuthContext'</span>;


<span class="hljs-keyword">const</span> Dashboard = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">const</span> { user } = useContext(AuthContext);

  <span class="hljs-keyword">const</span> [tasks, setTasks] = useState([]);

  <span class="hljs-keyword">const</span> [newTaskTitle, setNewTaskTitle] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> [newTaskDescription, setNewTaskDescription] = useState(<span class="hljs-string">''</span>);


  useEffect(<span class="hljs-function">() =&gt;</span> {

    <span class="hljs-keyword">if</span> (user) {

      fetchTasks();

    }

  }, [user]);


  <span class="hljs-keyword">const</span> fetchTasks = <span class="hljs-keyword">async</span> () =&gt; {

    <span class="hljs-keyword">try</span> {

      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'/api/tasks'</span>);

      setTasks(res.data);

    } <span class="hljs-keyword">catch</span> (err) {

      toast.error(<span class="hljs-string">'Failed to fetch tasks.'</span>);

      <span class="hljs-built_in">console</span>.error(err);

    }

  };


  <span class="hljs-keyword">const</span> handleCreateTask = <span class="hljs-keyword">async</span> (e) =&gt; {

    e.preventDefault();

    <span class="hljs-keyword">try</span> {

      <span class="hljs-keyword">await</span> axios.post(<span class="hljs-string">'/api/tasks'</span>, { <span class="hljs-attr">title</span>: newTaskTitle, <span class="hljs-attr">description</span>: newTaskDescription });

      setNewTaskTitle(<span class="hljs-string">''</span>);

      setNewTaskDescription(<span class="hljs-string">''</span>);

      toast.success(<span class="hljs-string">'Task created successfully!'</span>);

      fetchTasks();

    } <span class="hljs-keyword">catch</span> (err) {

      toast.error(<span class="hljs-string">'Failed to create task.'</span>);

      <span class="hljs-built_in">console</span>.error(err);

    }

  };


  <span class="hljs-keyword">const</span> handleUpdateTask = <span class="hljs-keyword">async</span> (id, completed) =&gt; {

    <span class="hljs-keyword">try</span> {

      <span class="hljs-keyword">await</span> axios.put(<span class="hljs-string">`/api/tasks/<span class="hljs-subst">${id}</span>`</span>, { completed });

      toast.success(<span class="hljs-string">'Task updated successfully!'</span>);

      fetchTasks();

    } <span class="hljs-keyword">catch</span> (err) {

      toast.error(<span class="hljs-string">'Failed to update task.'</span>);

      <span class="hljs-built_in">console</span>.error(err);

    }

  };


  <span class="hljs-keyword">const</span> handleDeleteTask = <span class="hljs-keyword">async</span> (id) =&gt; {

    <span class="hljs-keyword">try</span> {

      <span class="hljs-keyword">await</span> axios.delete(<span class="hljs-string">`/api/tasks/<span class="hljs-subst">${id}</span>`</span>);

      toast.success(<span class="hljs-string">'Task deleted successfully!'</span>);

      fetchTasks();

    } <span class="hljs-keyword">catch</span> (err) {

      toast.error(<span class="hljs-string">'Failed to delete task.'</span>);

      <span class="hljs-built_in">console</span>.error(err);

    }

  };


  <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>Welcome, {user ? user.username : 'Guest'}!<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Your Tasks<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleCreateTask}</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>

          <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>

          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"New Task Title"</span>

          <span class="hljs-attr">value</span>=<span class="hljs-string">{newTaskTitle}</span>

          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setNewTaskTitle(e.target.value)}

          required

        /&gt;

        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>

          <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>

          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Description (optional)"</span>

          <span class="hljs-attr">value</span>=<span class="hljs-string">{newTaskDescription}</span>

          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setNewTaskDescription(e.target.value)}

        /&gt;

        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Add Task<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>

        {tasks.map((task) =&gt; (

          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{task._id}</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">textDecoration:</span> <span class="hljs-attr">task.completed</span> ? '<span class="hljs-attr">line-through</span>' <span class="hljs-attr">:</span> '<span class="hljs-attr">none</span>' }}&gt;</span>

              {task.title}: {task.description}

            <span class="hljs-tag">&lt;/<span class="hljs-name">span</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> handleUpdateTask(task._id, !task.completed)}&gt;

              {task.completed ? 'Mark Incomplete' : 'Mark Complete'}

            <span class="hljs-tag">&lt;/<span class="hljs-name">button</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> handleDeleteTask(task._id)}&gt;Delete<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

          <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> Dashboard;
</code></pre>
<h2 id="heading-deployment-from-localhost-to-live"><strong>Deployment: From Localhost to Live</strong></h2>
<p>Deploying a MERN stack application involves deploying the backend API and the frontend React application separately.</p>
<p>Let’s talk about why we do it separately. As you have seen from above, in a MERN stack app, the frontend and backend are separate by design. React handles the UI, while Express and Node handle server logic and API calls. Because they serve different roles, you'll need to deploy them separately.</p>
<p>The backend runs on a Node.js compatible server, which connects to a database such as MongoDB Atlas. The frontend, once it is built, becomes static files that can be hosted from anywhere, from NGINX to hosting platforms like Netlify or Vercel.</p>
<p>This separation provides you with flexibility and improved scalability. Let’s walk through how to deploy each part.</p>
<h3 id="heading-backend-deployment-nodejsexpressjs"><strong>Backend Deployment (Node.js/Express.js)</strong></h3>
<p>For backend deployment, platforms like Heroku, Render, or AWS EC2 are common choices. Here, I’ll outline a general approach for a cloud VM on AWS EC2</p>
<h4 id="heading-1-prepare-for-production">1. Prepare for Production</h4>
<p>To start, set the environment to <code>production</code> and install only the dependencies your app needs to run, optimizing your application's performance. Skipping devDependencies helps reduce its footprint.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> NODE_ENV=production

npm install --production
</code></pre>
<h4 id="heading-2-process-manager-pm2">2. Process Manager (PM2)</h4>
<p>Next, we’ll set up a process manager to keep our backend server running reliably. PM2 is a popular tool that handles automatic restarts if your Node.js application crashes, manages multiple app instances, and also helps ensure high availability in production environments.</p>
<pre><code class="lang-bash">npm install -g pm2

pm2 start server/app.js --name mern-api

pm2 save

pm2 startup
</code></pre>
<h4 id="heading-3-nginx-as-a-reverse-proxy">3. NGINX as a Reverse Proxy</h4>
<p>Now that our backend is running with PM2, we need a way to handle incoming web traffic. That’s where NGINX comes in. We'll install NGINX to serve as a high-performance reverse proxy directing incoming web traffic to your Node.js backend and serving static frontend files.</p>
<pre><code class="lang-bash">sudo apt update

sudo apt install nginx
</code></pre>
<p>Once NGINX is installed, it’s time to configure it (/etc/nginx/sites-available/default or a new config file). We’ll set it up to forward API requests to the backend and serve the React app, acting as the single entry point. You can update the default configuration file or create a new one:</p>
<pre><code class="lang-nginx"><span class="hljs-comment"># /etc/nginx/sites-available/default</span>
<span class="hljs-section">server</span> {

    <span class="hljs-attribute">listen</span> <span class="hljs-number">80</span>;

    <span class="hljs-attribute">server_name</span> your_domain_or_ip;


    <span class="hljs-attribute">location</span> /api/ {

        <span class="hljs-attribute">proxy_pass</span> http://localhost:5000;

        <span class="hljs-attribute">proxy_http_version</span> <span class="hljs-number">1</span>.<span class="hljs-number">1</span>;

        <span class="hljs-attribute">proxy_set_header</span> Upgrade <span class="hljs-variable">$http_upgrade</span>;

        <span class="hljs-attribute">proxy_set_header</span> Connection <span class="hljs-string">'upgrade'</span>;

        <span class="hljs-attribute">proxy_set_header</span> Host <span class="hljs-variable">$host</span>;

        <span class="hljs-attribute">proxy_cache_bypass</span> <span class="hljs-variable">$http_upgrade</span>;

    }


    <span class="hljs-attribute">location</span> / {

        <span class="hljs-attribute">root</span> /var/www/my-mern-app/client/build; <span class="hljs-comment"># Path to your React build folder</span>

        <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> /index.html;

    }

}
</code></pre>
<p>With the NGINX configuration created, we’ll enable it and restart the service to apply the changes, making your application go live:</p>
<pre><code class="lang-bash">sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/

sudo systemctl restart nginx
</code></pre>
<h4 id="heading-4-https-with-certbot-lets-encrypt">4. HTTPS with Certbot (Let's Encrypt)</h4>
<p>To secure your app with HTTPS, we can install Certbot and use it to automatically obtain and configure a free SSL/TLS certificate from Let’s Encrypt, enabling secure HTTPS connections for your domain.</p>
<pre><code class="lang-bash">sudo snap install --classic certbot

sudo certbot --nginx -d your_domain_or_ip
</code></pre>
<h3 id="heading-frontend-deployment-react"><strong>Frontend Deployment (React)</strong></h3>
<p>With the backend deployed, let’s move to the frontend. For the React frontend, we’ll build the application and serve the static files via NGINX (as shown above) or a dedicated static site hosted on platforms like Netlify, Vercel, or AWS S3 + CloudFront.</p>
<h4 id="heading-build-the-react-app">Build the React App</h4>
<p>This command compiles and optimizes your React application into a build folder containing static assets, ready for efficient deployment to any web server or static hosting service.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> client

npm run build
</code></pre>
<h3 id="heading-database-deployment-mongodb-atlas"><strong>Database Deployment (MongoDB Atlas)</strong></h3>
<p>For production, we’ll use a managed MongoDB service like MongoDB Atlas. It handles replication, sharding, and backups, simplifying database management significantly.</p>
<h4 id="heading-create-a-cluster-on-mongodb-atlas">Create a Cluster on MongoDB Atlas</h4>
<ul>
<li><p>Sign up/Log in to MongoDB Atlas.</p>
</li>
<li><p>Create a new cluster (choose a cloud provider and region).</p>
</li>
<li><p>Set up a database user with appropriate permissions.</p>
</li>
<li><p>Configure network access (allow connections from your server's IP address).</p>
</li>
<li><p>Get your connection string and update MONGO_URI in your server/.env file.</p>
</li>
</ul>
<h4 id="heading-1-env-configuration-example">1. <code>.env</code> Configuration Example</h4>
<p>After creating the cluster and user in MongoDB Atlas, you’ll receive a connection string. You need to update your <code>.env</code> file with it</p>
<pre><code class="lang-ini"><span class="hljs-comment"># server/.env</span>
<span class="hljs-attr">MONGO_URI</span>=mongodb+srv://yourUser:yourPassword@cluster0.mongodb.net/yourDBName
<span class="hljs-attr">JWT_SECRET</span>=your_secret_jwt_key
<span class="hljs-attr">NODE_ENV</span>=production
</code></pre>
<h4 id="heading-2-connect-to-mongodb-in-appjs">2. Connect to MongoDB in <code>app.js</code></h4>
<p>Next, in the <code>server/app.js</code> file, make sure you're using the connection string from the environment variable:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);
<span class="hljs-keyword">const</span> dotenv = <span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>);
dotenv.config();

mongoose.connect(process.env.MONGO_URI)
  .then(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'MongoDB connected!'</span>))
  .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Connection error:'</span>, err));
</code></pre>
<h3 id="heading-other-deployment-options"><strong>Other Deployment Options</strong></h3>
<p>While this article drives you through manual deployment with EC2 and NGINX, other platforms can simplify the process:</p>
<ul>
<li><p><strong>Render</strong>, <strong>Railway</strong>, and <strong>Heroku</strong> offer easy full-stack deployment with GitHub integration.</p>
</li>
<li><p><strong>Vercel</strong> and <strong>Netlify</strong> are ideal for hosting the React frontend.</p>
</li>
<li><p>You may consider using <strong>Docker</strong> to maintain consistent environments across development and production.</p>
</li>
<li><p>For CI/CD, Linting, Testing, &amp; Deployment can be automated on every push using tools like <strong>GitHub Actions</strong></p>
</li>
</ul>
<p>There is no right or wrong choice here. Select the setup that best suits your project’s scale, team experience, and desired level of control.</p>
<h2 id="heading-security-best-practices-fortifying-your-application"><strong>Security Best Practices: Fortifying Your Application</strong></h2>
<p>Security is paramount. You can implement these best practices to protect your MERN application.</p>
<h3 id="heading-setup-input-validation-and-sanitization"><strong>Setup Input Validation and Sanitization</strong></h3>
<p>Always validate and sanitize input on the server side. You can use libraries like Joi or Zod to make this process easier.</p>
<h4 id="heading-example-with-joi">Example with Joi:</h4>
<p>To validate and sanitize incoming data on the server, we will utilize Joi, a powerful library for defining schemas and enforcing input rules.</p>
<pre><code class="lang-bash">npm install joi
</code></pre>
<p>Now that we’ve installed Joi, we will use it to define strict validation rules for user registration and login inputs. This ensures data quality and prevents common injection attacks.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// server/validators/authValidator.js</span>

<span class="hljs-keyword">const</span> Joi = <span class="hljs-built_in">require</span>(<span class="hljs-string">'joi'</span>);


<span class="hljs-keyword">const</span> registerSchema = Joi.object({

  <span class="hljs-attr">username</span>: Joi.string().min(<span class="hljs-number">3</span>).max(<span class="hljs-number">30</span>).required(),

  <span class="hljs-attr">email</span>: Joi.string().email().required(),

  <span class="hljs-attr">password</span>: Joi.string().min(<span class="hljs-number">6</span>).required(),

});


<span class="hljs-keyword">const</span> loginSchema = Joi.object({

  <span class="hljs-attr">email</span>: Joi.string().email().required(),

  <span class="hljs-attr">password</span>: Joi.string().required(),

});


<span class="hljs-built_in">module</span>.exports = { registerSchema, loginSchema };
</code></pre>
<p>Next, we’ll integrate these schemas directly into our authentication controller to automatically validate incoming request bodies against predefined schemas.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// server/controllers/authController.js (snippet)</span>

<span class="hljs-keyword">const</span> { registerSchema, loginSchema } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../validators/authValidator'</span>);


<span class="hljs-built_in">exports</span>.registerUser = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">const</span> { error } = registerSchema.validate(req.body);

  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: error.details[<span class="hljs-number">0</span>].message });

  <span class="hljs-comment">// ... rest of the registration logic</span>

};


<span class="hljs-built_in">exports</span>.loginUser = <span class="hljs-keyword">async</span> (req, res) =&gt; {

  <span class="hljs-keyword">const</span> { error } = loginSchema.validate(req.body);

  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: error.details[<span class="hljs-number">0</span>].message });

  <span class="hljs-comment">// ... rest of the login logic</span>

};
</code></pre>
<h3 id="heading-add-authentication-and-authorization"><strong>Add Authentication and Authorization</strong></h3>
<p>You can use JWTs for authentication and implement middleware for protected routes.</p>
<h4 id="heading-jwt-implementation-covered-in-authcontrollerjs-and-authmiddlewarejs-above">JWT Implementation (covered in authController.js and authMiddleware.js above)</h4>
<p>Key aspects:</p>
<ul>
<li><p>HttpOnly Cookies: Store JWTs in HttpOnly cookies to prevent client-side JavaScript access, mitigating XSS attacks.</p>
</li>
<li><p>Secure Flag: Use secure: true in production to ensure cookies are only sent over HTTPS.</p>
</li>
</ul>
<p>These practices ensure that authentication tokens are securely transmitted and stored, protecting against common web vulnerabilities like Cross-Site Scripting (XSS).</p>
<h3 id="heading-implement-rate-limiting"><strong>Implement Rate Limiting</strong></h3>
<p>To protect our API from abuse and malicious intent, we will implement basic rate limiting. This helps protect against brute-force login attempts and DDoS attacks.</p>
<h4 id="heading-installation">Installation</h4>
<p>We will install express-rate-limit package for it</p>
<pre><code class="lang-bash">npm install express-rate-limit
</code></pre>
<h4 id="heading-serverappjs-snippet">server/app.js (snippet)</h4>
<p>Once it is installed, let’s configure the rate limiter and apply it to all incoming requests. This ensures that no single IP can overwhelm your server with repeated calls. The following middleware limits each IP address to 200 requests within a 15-minute window.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> rateLimit = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express-rate-limit'</span>);

<span class="hljs-keyword">const</span> limiter = rateLimit({

  <span class="hljs-attr">windowMs</span>: <span class="hljs-number">15</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>, <span class="hljs-comment">// 15 minutes</span>

  <span class="hljs-attr">max</span>: <span class="hljs-number">200</span>, <span class="hljs-comment">// Limit each IP to 200 requests per windowMs</span>

  <span class="hljs-attr">message</span>: <span class="hljs-string">'Too many requests from this IP, please try again after 15 minutes'</span>,

});

app.use(limiter); <span class="hljs-comment">// Apply to all requests</span>
</code></pre>
<h3 id="heading-setup-cors-configuration-cross-origin-resource-sharing"><strong>Setup CORS Configuration (Cross-Origin Resource Sharing)</strong></h3>
<p>Next, we move our focus to enable secure communication between your frontend and backend. By default, all browsers block cross-origin requests, so we need to configure CORS (Cross-Origin Resource Sharing) to permit the React app to communicate with the Express API.</p>
<h4 id="heading-installation-1">Installation</h4>
<pre><code class="lang-bash">npm install cors
</code></pre>
<h4 id="heading-serverappjs-snippet-1">server/app.js (snippet)</h4>
<p>Once installed<strong>,</strong> we can configure CORS for our Express application, specifying allowed origins and enabling credential sharing for secure cross-origin requests. Remember to replace the origin with your actual production URL when deploying.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> cors = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cors'</span>);

app.use(cors({

  <span class="hljs-attr">origin</span>: <span class="hljs-string">'http://localhost:3000'</span>, <span class="hljs-comment">// Replace with your frontend URL in production</span>

  <span class="hljs-attr">credentials</span>: <span class="hljs-literal">true</span>,

}));
</code></pre>
<h3 id="heading-use-environment-variables"><strong>Use Environment Variables</strong></h3>
<p>To keep sensitive information secure and out of your codebase, we will use environment variables. This allows us to efficiently manage secrets, such as database connection strings and JWT keys, without hardcoding them or including them in the source code.</p>
<p>Create a <code>.env</code> file in your <code>server/</code> directory:</p>
<h4 id="heading-env-example">.env (example)</h4>
<p>This .env file stores sensitive configuration details like database connection strings and API keys</p>
<pre><code class="lang-ini"><span class="hljs-attr">MONGO_URI</span>=your_mongodb_connection_string

<span class="hljs-attr">JWT_SECRET</span>=your_super_secret_jwt_key

<span class="hljs-attr">NODE_ENV</span>=production
</code></pre>
<h2 id="heading-monitoring-and-logging-with-winston-and-morgan"><strong>Monitoring and Logging with Winston and Morgan</strong></h2>
<p>Once the application is live, it's critical to monitor the behavior and catch issues promptly. Monitoring and logging help you measure performance, find bugs, and keep a log of all server activity.</p>
<p>We’ll use Morgan for logging HTTP requests and Winston for more general-purpose application logging.</p>
<h3 id="heading-installation-2">Installation</h3>
<p>We will install Morgan for logging HTTP requests and Winston for comprehensive and customizable application logging.</p>
<pre><code class="lang-bash">npm install morgan winston
</code></pre>
<h3 id="heading-serverconfigloggerjs">server/config/logger.js</h3>
<p>Next, let’s configure Winston to handle our application logs. This will output logs to the console by default, with options to enable file-based logging for errors and general information.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> winston = <span class="hljs-built_in">require</span>(<span class="hljs-string">'winston'</span>);

<span class="hljs-keyword">const</span> logger = winston.createLogger({

  <span class="hljs-attr">level</span>: <span class="hljs-string">'info'</span>,

  <span class="hljs-attr">format</span>: winston.format.combine(

    winston.format.timestamp(),

    winston.format.json()

  ),

  <span class="hljs-attr">transports</span>: [

    <span class="hljs-keyword">new</span> winston.transports.Console(),

    <span class="hljs-comment">// new winston.transports.File({ filename: 'error.log', level: 'error' }),</span>

    <span class="hljs-comment">// new winston.transports.File({ filename: 'combined.log', level: 'info' }),</span>

  ],

});

<span class="hljs-built_in">module</span>.exports = logger;
</code></pre>
<h3 id="heading-serverappjs-snippet-2">server/app.js (snippet)</h3>
<p>With Winston and Morgan set up, now let’s integrate them into our <code>app.js</code> file. We’ll use Morgan for request logging during development and replace standard <code>console.log</code> calls with Winston logs for structured and configurable application logging.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> morgan = <span class="hljs-built_in">require</span>(<span class="hljs-string">'morgan'</span>);

<span class="hljs-keyword">const</span> logger = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./config/logger'</span>);

<span class="hljs-keyword">if</span> (process.env.NODE_ENV === <span class="hljs-string">'development'</span>) {

  app.use(morgan(<span class="hljs-string">'dev'</span>));

}

<span class="hljs-comment">// Replace console.log with logger.info for database connection</span>

mongoose.connect(process.env.MONGO_URI)

  .then(<span class="hljs-function">() =&gt;</span> logger.info(<span class="hljs-string">'MongoDB connected!'</span>))

  .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> logger.error(<span class="hljs-string">'MongoDB connection error:'</span>, err));


<span class="hljs-comment">// Replace console.log in app.listen</span>

app.listen(PORT, <span class="hljs-function">() =&gt;</span> {

  logger.info(<span class="hljs-string">`Server running on port <span class="hljs-subst">${PORT}</span>`</span>);

});
</code></pre>
<h3 id="heading-frontend-error-monitoring-sentry"><strong>Frontend Error Monitoring (Sentry)</strong></h3>
<p>To monitor errors in the frontend, we’ll integrate Sentry. It’s a fantastic tool for tracking exceptions and performance issues in real time. It helps us capture and report client-side errors.</p>
<h4 id="heading-installation-3">Installation</h4>
<pre><code class="lang-bash">npm install @sentry/react @sentry/tracing
</code></pre>
<h4 id="heading-clientsrcindexjs-snippet">client/src/index.js (snippet)</h4>
<p>After installation, let’s initialize Sentry in the React application so that it can automatically capture errors and performance data. We’ll add this to our <code>index.js</code> file.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> Sentry <span class="hljs-keyword">from</span> <span class="hljs-string">'@sentry/react'</span>;

<span class="hljs-keyword">import</span> { BrowserTracing } <span class="hljs-keyword">from</span> <span class="hljs-string">'@sentry/tracing'</span>;


Sentry.init({

  <span class="hljs-attr">dsn</span>: <span class="hljs-string">"YOUR_SENTRY_DSN"</span>, <span class="hljs-comment">// Replace with your Sentry DSN</span>

  <span class="hljs-attr">integrations</span>: [<span class="hljs-keyword">new</span> BrowserTracing()],

  <span class="hljs-attr">tracesSampleRate</span>: <span class="hljs-number">1.0</span>,

  <span class="hljs-attr">environment</span>: process.env.NODE_ENV,

});
</code></pre>
<p>And that’s it! Congratulations on building and deploying a full-stack MERN app.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This article provided a code-first walkthrough of building, securing, and deploying a MERN stack application. By focusing on practical code examples and essential configurations, you now have a solid foundation for your MERN projects.</p>
<p>Remember, continuous learning and adaptation are key in the ever-evolving world of web development. Happy coding!</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[ Simple Tips to Help You Write Clean Code ]]>
                </title>
                <description>
                    <![CDATA[ Being a developer isn’t as straightforward as many people think. It’s not just about learning a programming language and typing out code to build software. There’s a lot more to it. And one of the most confusing (and often frustrating) topics for dev... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/tips-for-writing-clean-code/</link>
                <guid isPermaLink="false">67a2380b9af7e36332fde944</guid>
                
                    <category>
                        <![CDATA[ programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nitin Sharma ]]>
                </dc:creator>
                <pubDate>Tue, 04 Feb 2025 15:53:47 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738684292390/6e844cd5-28f8-42e9-b9e3-cc6ded9ec72f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Being a developer isn’t as straightforward as many people think.</p>
<p>It’s not just about learning a programming language and typing out code to build software. There’s a lot more to it. And one of the most confusing (and often frustrating) topics for developers is clean code.</p>
<p>So, what is clean code?</p>
<p>Simply put, it’s about writing code that’s so clear and well-organized that neither you nor anyone else will get frustrated trying to understand it six months later.</p>
<p>Think of clean code as the programming equivalent of great design — it’s functional, beautiful, and easy to work with.</p>
<p>And today, I won’t spend a lot of time explaining why clean code is important — you probably already know that. Instead, I’ll get straight to the point and share seven powerful hacks to help you write cleaner, better code.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-write-code-like-youre-explaining-it-to-a-5-year-old">1. Write Code Like You’re Explaining it to a 5-Year Old</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-use-ai-tools-or-an-ai-code-reviewer">2. Use AI Tools (or an AI Code Reviewer)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-get-rid-of-unnecessary-comments">3. Get Rid of Unnecessary Comments</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-follow-the-dry-principle">4. Follow the DRY Principle</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-fix-your-code-formatting-amp-follow-a-consistent-style">5. Fix Your Code Formatting &amp; Follow a Consistent Style</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-dont-let-your-functions-do-too-much">6. Don’t Let Your Functions Do Too Much</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-7-organize-your-files-and-folders-properly">7. Organize Your Files and Folders Properly</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-1-write-code-like-youre-explaining-it-to-a-5-year-old"><strong>1. Write Code Like You’re Explaining it to a 5-Year Old</strong></h2>
<p>Let me be honest — if you are writing exceedingly clever code that your teammates or someone else can’t easily read, it won’t be helpful to anyone.</p>
<p>You need to write code so simple that anyone, including someone who just opened the file for the first time, can easily go through it.</p>
<p>For example, if your variable names look like this:</p>
<pre><code class="lang-plaintext">let x = y + z;
</code></pre>
<p>This isn’t helpful. No one will know what x, y, and z mean — not even you, three weeks later.</p>
<p>Variables should describe what they hold. Think of them as self-documenting comments. Here’s a better example:</p>
<pre><code class="lang-plaintext">let totalPrice = productPrice + shippingCost;
</code></pre>
<p>This simple best practice can be applied even when writing functions, comments, and more.</p>
<p>Here’s an example of hard to understand code:</p>
<pre><code class="lang-plaintext">function calc(itm) {
 let t = 0;
 for (let i = 0; i &lt; itm.length; i++) {
 t += itm[i].p;
 }
 return t;
}
</code></pre>
<p>You see, it doesn’t give you a proper idea about the function other than the logic.</p>
<p>Instead, try to write it like this:</p>
<pre><code class="lang-plaintext">function calculateTotalPrice(cartItems) {
    let totalPrice = 0;
    for (let i = 0; i &lt; cartItems.length; i++) {
        totalPrice += cartItems[i].price;
    }
    return totalPrice;
}
</code></pre>
<p>Now it’s clear just from looking at the code what’s going on.</p>
<h2 id="heading-2-use-ai-tools-or-an-ai-code-reviewer">2. Use AI Tools (or an AI Code Reviewer)</h2>
<p>AI is evolving quickly and is being used in almost every industry.</p>
<p>Well, as a developer, you can use AI to help you write clean and readable code — all thanks to AI tools like <a target="_blank" href="https://chatgpt.com/">ChatGPT</a>, <a target="_blank" href="https://claude.ai/">Claude</a>, and <a target="_blank" href="https://github.com/features/copilot">GitHub Copilot</a>.</p>
<p>For starters, you can copy and paste your code into an LLM and ask it to review your code. </p>
<p>Here’s an example of a request I made to ChatGPT:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738673389541/558c64b6-f92e-4ede-bd00-8fe9c98623c0.png" alt="558c64b6-f92e-4ede-bd00-8fe9c98623c0" class="image--center mx-auto" width="1146" height="826" loading="lazy"></p>
<p>And here’s what ChatGPT recommended:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738673434670/badadf50-2e1f-46f9-9f3b-c9b189dfaeeb.png" alt="badadf50-2e1f-46f9-9f3b-c9b189dfaeeb" class="image--center mx-auto" width="1696" height="1078" loading="lazy"></p>
<p>It even provided me with an improved version of the code. Here it is as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738673489244/3cf70568-a418-460b-9aa6-768a544965c2.png" alt="3cf70568-a418-460b-9aa6-768a544965c2" class="image--center mx-auto" width="1566" height="1178" loading="lazy"></p>
<p>Along with that, you can also use AI-powered code reviewers like <a target="_blank" href="https://www.coderabbit.ai/">CodeRabbit AI</a>, which integrates with your pull requests to offer automated code reviews, walkthroughs, and more.</p>
<p>In simple terms, when you install CodeRabbit AI, add it to your pull request, and then create a pull request, CodeRabbit AI provides you with summaries, code reviews, walkthroughs, and more.</p>
<p>Here’s an example from an open-source repository “<a target="_blank" href="https://github.com/bitbomdev/minefield/pull/158">minefield</a>” of a summary generated by CodeRabbit AI:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738675580325/ef823a77-6969-4e8a-a141-640468d0169d.png" alt="ef823a77-6969-4e8a-a141-640468d0169d" class="image--center mx-auto" width="1600" height="967" loading="lazy"></p>
<p>In the above examples, CodeRabbit AI simply goes through the code and provides a great summary highlighting the new features, bug fixes, and unit tests added via a pull request.</p>
<p>If you want to learn more, <a target="_blank" href="https://docs.coderabbit.ai/getting-started/quickstart/">here’s</a> a quickstart guide that provides more info on how to get started and use CodeRabbit AI.</p>
<p>Note that, AI tools can be a great help in improving your code, but they should never replace your own thinking.</p>
<p>When AI suggests changes, always ask yourself: Does this actually make sense?</p>
<p>After all, AI isn’t perfect—it can generate incorrect code. It might also miss important details that only a human can fully understand.</p>
<p>So instead of blindly accepting AI’s suggestions, take a moment to understand why they were made.</p>
<p>Remember, the goal is to use AI to speed up your workflow, catch errors, and more—while keeping full control over your code.</p>
<h2 id="heading-3-get-rid-of-unnecessary-comments">3. Get Rid of Unnecessary Comments</h2>
<p>Writing good code comments can help others understand why your code is doing what it’s doing.</p>
<p>But I see developers writing too many comments, even where there is no need.</p>
<p>I believe that, whenever possible, good code should document itself.</p>
<p>Here’s an example of a not so helpful comment:</p>
<pre><code class="lang-plaintext">// Adding 10 to the result 
total = total + 10;
</code></pre>
<p>You see, here the comment doesn’t make sense, and it doesn’t really add anything to the code (or our understanding of it).</p>
<p>It’s a better practice to write comments only if they’re important in helping a reviewer understand why you did something in particular or if there’s some ambiguity that needs explaining.</p>
<p>Here’s an example:</p>
<pre><code class="lang-plaintext">// Adding 10 because the client requires a 10% buffer for calculations 
total = total + 10;
</code></pre>
<p>Now you can see that here the comment gives a clear idea about why the programmer added 10 to the total.</p>
<h2 id="heading-4-follow-the-dry-principle">4. Follow the DRY Principle</h2>
<p>I’ve seen a lot of programmers repeating the same logic or adding the same functionality in different files.</p>
<p>Well, you don’t need to repeat the same code everywhere because it makes the process much more complex. Keep your code DRY (Don’t Repeat Yourself).</p>
<p>Instead, abstract that logic into a single reusable function.</p>
<p>For example, instead of writing the same logic in different files:</p>
<pre><code class="lang-plaintext">if (user.age &gt; 18 &amp;&amp; user.age &lt; 65) { 
 // Do something 
}

if (user.age &gt; 18 &amp;&amp; user.age &lt; 65) { 
 // Do something else 
}
</code></pre>
<p>You can create a reusable function so that you can use the logic everywhere, as shown below:</p>
<pre><code class="lang-plaintext">function isWorkingAge(age) { 
 return age &gt; 18 &amp;&amp; age &lt; 65; 
}

if (isWorkingAge(user.age)) { 
 // Do something 
}
</code></pre>
<p>In short — write once, and use everywhere.</p>
<h2 id="heading-5-fix-your-code-formatting-amp-follow-a-consistent-style">5. Fix Your Code Formatting &amp; Follow a Consistent Style</h2>
<p>This is another simple hack, but many devs don’t even think about it.</p>
<p>First of all, you need to format your code with proper indentation.</p>
<p>You can just install a VS Code extension/linters like <a target="_blank" href="https://prettier.io/">Prettier</a>, <a target="_blank" href="https://eslint.org/">ESLint</a>, or <a target="_blank" href="https://pypi.org/project/flake8/">Flake8</a>, depending on the programming language you use. Configure a few settings, and you’re good to go.</p>
<p>These linters can help you write better code by finding mistakes, helping you follow coding rules, and keeping your code consistent. They can also catch errors, make your code easier to read, and save time on fixing bugs and reviews.</p>
<p>But fixing your formatting doesn’t just mean it’s clean code – it’s way more than that.</p>
<p>Beyond formatting, you should stick to a consistent style guide for things like function names or variable names.</p>
<p>For example, here’s some code that has an inconsistent style:</p>
<pre><code class="lang-plaintext">let total_price;  
let UserData;  
function getuser() {}
</code></pre>
<p>But some of you may ask, why is the code inconsistent?</p>
<p>Well, it uses several different naming conventions – like <code>total_price</code> uses snake_case, <code>UserData</code> uses PascalCase, and <code>getuser()</code> is in lowercase instead of camelCase.</p>
<p>This makes your code harder to read and more confusing. Instead, you can follow a consistent style. Here’s how:</p>
<pre><code class="lang-plaintext">let userData; 
let totalPrice; 
function getUser() {}
</code></pre>
<p>And just to let you know, JavaScript typically follows camelCase for variables and functions, so names like <code>getUser(), userData, and totalPrice</code> would be more consistent.</p>
<p>No matter whether you’re working in a team or solo, sticking to one style is a good idea. It makes the code clean, and the reviewer can easily go through it.</p>
<h2 id="heading-6-dont-let-your-functions-do-too-much">6. Don’t Let Your Functions Do Too Much</h2>
<p>As a programmer, I know that sometimes you need to write complex logic inside a function.</p>
<p>But most often, programmers include too much logic in a single function, causing it to do more than one thing at a time. These functions become too complex, making them hard to read or understand.</p>
<p>It’s better to create multiple smaller functions, with each function handling a single responsibility.</p>
<p>Here’s an example of a slightly too complex function:</p>
<pre><code class="lang-plaintext">function calculateCart(items) {
 let total = 0;
 for (let i = 0; i &lt; items.length; i++) {
 total += items[i].price * items[i].quantity;
 }
 return total &gt; 100 ? total * 0.9 : total;
}
</code></pre>
<p>You see, this single function does too much—it applies discounts if applicable, and calculates the total price based on quantity, making it hard to reuse for specific use cases.</p>
<p>A better way is to split it into three functions:</p>
<ul>
<li><p>One to apply the discount (if applicable).</p>
</li>
<li><p>One to calculate the total price based on quantity.</p>
</li>
<li><p>One to get the total and apply the discount if needed.</p>
</li>
</ul>
<p>This makes the code cleaner and easier to manage. Here’s an improved version:</p>
<pre><code class="lang-plaintext">function calculateCart(items) {
 const total = getCartTotal(items);
 return applyDiscount(total);
}

function getCartTotal(items) {
 return items.reduce((sum, item) =&gt; sum + item.price * item.quantity, 0);
}

function applyDiscount(total) {
 return total &gt; 100 ? total * 0.9 : total;
}
</code></pre>
<p>You see, instead of writing everything in one long block, the logic is broken into smaller, clearer functions.</p>
<p>And that’s what makes it easier for you (and everyone else) to understand.</p>
<h2 id="heading-7-organize-your-files-and-folders-properly">7. Organize Your Files and Folders Properly</h2>
<p>Now comes the most important part.</p>
<p>When you’re working on a big project, it makes no sense to dump all your code into one single folder with a bunch of random files. It’s become a nightmare for anyone trying to review the code or find a specific file.</p>
<p>Think about it — going through 50 files just to fix a bug. Nobody wants that.</p>
<p>Instead, try organizing your project into multiple folders based on pages or features.</p>
<p>And don’t stop there — break large files into smaller, specific modules based on functionality. This way, everything is neat, easy to find, and makes sense at first glance.</p>
<p>Here’s a bad example of a project structure: </p>
<pre><code class="lang-plaintext">project-folder/  
│  
├── index.html  
├── app.js  
├── helpers.js  
├── data.js  
├── user.js  
├── product.js
</code></pre>
<p>It’s messy, right? Now, here’s how you can improve it:</p>
<pre><code class="lang-plaintext">project-folder/  
│  
├── pages/  
│   ├── home/  
│   │   ├── HomePage.js  
│   │   ├── HomePage.css  
│   │   └── HomePage.test.js  
│   ├── user/  
│   │   ├── UserPage.js  
│   │   ├── UserPage.css  
│   │   └── UserPage.test.js  
│   └── product/  
│       ├── ProductPage.js  
│       ├── ProductPage.css  
│       └── ProductPage.test.js  
├── components/  
│   ├── Header.js  
│   ├── Footer.js  
│   └── Button.js  
├── utils/  
│   └── api.js  
└── index.js
</code></pre>
<p>See how simple this is?</p>
<p>You have separate folders for pages, components, and utilities. Inside each folder, files are organized by purpose and given clear names.</p>
<p>For example, if you need something for the product page, you’ll know exactly where to find it.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this article, you learned the basics you need to get started writing clean, efficient, and maintainable code.</p>
<p>We discussed how to write clean code, use AI tools, apply proper code formatting techniques, structure functions effectively, and follow other best practices.</p>
<p>If you apply these tips consistently, you’ll significantly improve your coding skills and write cleaner code.</p>
<p>I hope you liked it.</p>
<p>You can connect with me on <a target="_blank" href="https://substack.com/@nitinfab">Substack</a>, and <a target="_blank" href="https://x.com/Nitinfab">Twitter</a>.</p>
<p>Also, if you're interested in learning more about AI, you can subscribe to my newsletter, <a target="_blank" href="https://aimadesimple0.substack.com/">AI Made Simple</a>, where I dive deeper into practical AI strategies for everyday people.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Clean Code Handbook: How to Write Better Code for Agile Software Development ]]>
                </title>
                <description>
                    <![CDATA[ Building scalable software applications requires writing clean code that’s so simple that any dev can understand it. In this article, I’ll explain and demonstrate what clean code is. Then I’ll share my favorite clean code patterns for building modern... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-clean-code-handbook/</link>
                <guid isPermaLink="false">679a5fa86177eb24200d0f7f</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ agile ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Programming with Shahan ]]>
                </dc:creator>
                <pubDate>Wed, 29 Jan 2025 17:04:40 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738170236859/edacf21e-7180-4f65-9e7e-f7cf95b4f9d8.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building scalable software applications requires writing clean code that’s so simple that any dev can understand it.</p>
<p>In this article, I’ll explain and demonstrate what clean code is. Then I’ll share my favorite clean code patterns for building modern Agile applications.</p>
<p>I won’t use complex jargon. I’ll hit you with simple, clear JavaScript examples that focus on the core concepts. Straight to the point, no nonsense – that’s how I roll.</p>
<p>Let’s get started.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-the-cost-of-bad-code">The Cost of Bad Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-clean-coder-vs-messy-coder">Clean Coder vs. Messy Coder</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-ai-cant-save-you-if-your-code-is-a-mess">AI Can’t Save You If Your Code is a Mess 🗑️</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-12-clean-code-design-patterns-for-building-agile-applications">12 Clean Code Design Patterns for Building Agile Applications ⚖️</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-use-names-that-mean-something">🌿 Use Names That Mean Something</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-keep-functions-laser-focused-srp">🔨 Keep Functions Laser-Focused (SRP)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-comments-thoughtfully">🚪 Use Comments Thoughtfully</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-for-writing-good-comments">⚡ Best Practices for Writing Good Comments</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-make-your-code-readable">🧩 Make Your Code Readable</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-test-everything-you-write">🏌️ Test Everything You Write</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-dependency-injection">💉 Use Dependency Injection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-clean-project-structures">📂 Clean Project Structures</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-be-consistent-with-formatting">🤹‍♂️ Be Consistent with Formatting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-stop-hardcoding-values">✋ Stop Hardcoding Values</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-keep-functions-short">🤏 Keep Functions Short</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-follow-the-boy-scout-rule">⛺ Follow the Boy Scout Rule</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-follow-the-openclosed-principle">🏟️ Follow the Open/Closed Principle</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-modern-best-practices-to-help-you-write-clean-code-a-summary">Modern Best Practices to Help You Write Clean Code: A Summary 🥷</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-automated-tools-for-maintaining-clean-code">Automated Tools for Maintaining Clean Code ⚓</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-static-analysis">1️⃣ Static Analysis</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-automated-code-formatting">2️⃣ Automated Code Formatting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-continuous-integration-ci-testing">3️⃣ Continuous Integration (CI) Testing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-cicd-pipelines">4️⃣ CI/CD pipelines</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-the-role-of-documentation-in-agile-software-development">The Role of Documentation in Agile Software Development 🚣</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion 🏁</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-frequently-asked-questions-about-clean-code">Frequently Asked Questions About Clean Code 🧯</a></p>
</li>
</ol>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh3j6ccn1hc3euc3lfyl.png" alt="Image of agile software development meme" width="3125" height="1250" loading="lazy"></p>
<p>In Agile, where change is the only constant, clean code is your armor. It makes you adaptable, swift, and, most importantly, in control.</p>
<p>Here’s the truth: writing clean code is not optional if you want to survive in the software development industry. Fortunately, we human beings are able to master clean code with some effort and practice.</p>
<h2 id="heading-the-cost-of-bad-code">The Cost of Bad Code</h2>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wdai6npb55j71sguj6kl.png" alt="Image of cost of messy code vs clean code graph by shahan" class="image--center mx-auto" width="500" height="600" loading="lazy"></p>
<p>To explain this stack bar graph, in the initial development phase, bad code is <strong>slightly</strong> more costly to change than clean code.</p>
<p>But as we move into the maintenance and refactoring phases, the gap widens significantly, with bad code costing nearly twice as much as clean code.</p>
<p>By the legacy phase, bad code reaches 100% cost – now it’s extremely expensive to update, while clean code remains more manageable at 45%.</p>
<p>As of now, the most recent analysis on the cost of poor software quality in the U.S. is the 2022 report by the Consortium for Information and Software Quality (<a target="_blank" href="http://cisq.org">cisq.org</a>). This report estimates that poor software quality cost the U.S. economy at least $2.41 trillion in 2022, with technical debt accounting for about $1.52 trillion of this amount.</p>
<p>You can <a target="_blank" href="https://www.it-cisq.org/the-cost-of-poor-quality-software-in-the-us-a-2022-report/">read more about that here</a>.</p>
<p>Recent discussions continue to highlight the significant impact of technical debt on software quality and business performance.</p>
<p>For instance, <a target="_blank" href="https://vfunction.com/blog/how-to-manage-technical-debt">a 2024 survey</a> indicated that for more than 50% of companies, technical debt accounts for greater than a quarter of their total IT budget. And this can really hinder innovation if it’s not addressed.</p>
<p>As you can see, there’s no doubt that bad code is a costly problem in software development.</p>
<h2 id="heading-clean-coder-vs-messy-coder"><strong>Clean Coder vs. Messy Coder</strong></h2>
<p>Here’s a graph that shows the journey of <strong>two types</strong> of coders:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c6ubf77uwipf4gtucw8q.png" alt="Image of clean code vs bad code graph chart" class="image--center mx-auto" width="604" height="340" loading="lazy"></p>
<ul>
<li><p><strong>⚠️ The Messy Coder (Red line):</strong> Starts fast but crashes hard. The more lines they write, the more trouble they make.</p>
</li>
<li><p><strong>⚡ The Clean Coder (Blue line):</strong> Starts slow but stays consistent. Growth doesn’t stop — it accelerates.</p>
</li>
</ul>
<p>🫵 Now, you decide which line you want to follow.</p>
<h2 id="heading-ai-cant-save-you-if-your-code-is-a-mess">AI Can’t Save You If Your Code is a Mess 🗑️</h2>
<p>When you get stuck writing code, you might turn to AI. But let me tell you something: AI can’t save you if your code is a mess.</p>
<p>It’s like building a house on sand. Sure, it stands for a while, but one strong gust of wind or big wave, and it collapses.</p>
<p>Remember: AI is just a tool. If you don’t know how to write clean, scalable applications, you're setting yourself up for failure.</p>
<p>If you can’t maintain the code you write, you’re in trouble.</p>
<p>I’ve seen it over and over again: developers who know five programming languages. They can build apps, websites, software. They know algorithms and data structures like the back of their hand.</p>
<p>But when faced with a large project or someone else’s messy code, they crumble.</p>
<p>They’re like an aerospace engineer who designs and builds their own planes but doesn’t know how to fly them. They crash into their own code.</p>
<p>This was me...once upon a time. I’d write thousands of lines of code, only to realize I couldn’t even understand what I wrote last week. It was chaos for me.</p>
<p>But then it hit me — every developer struggles with this. It wasn't about how much I knew. It was about how I organized and structured what I knew. In other words, it was about knowing the art of programming itself.</p>
<p>I decided to escape this trap. After five months of intense work — four to five hours a day writing, designing, and researching — I created something I wish I had when I started programming. A book that’s a complete beginner’s guide: <strong>Clean Code Zero to One.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737731329839/c4c862d9-7fdc-460a-ae2e-18b19468b6ec.png" alt="cover image of clean code zero to one: from messy code to masterpiece" class="image--center mx-auto" width="1920" height="1080" loading="lazy"></p>
<p>If you want to learn more about the book, I give you all the details at the end of this tutorial. So read on to learn more about writing clean code.</p>
<h2 id="heading-12-clean-code-design-patterns-for-building-agile-applications">12 Clean Code Design Patterns for Building Agile Applications ⚖️</h2>
<p>If your code doesn’t follow these modern clean code design patterns, you could be creating a ticking time bomb. These patterns are your tools. Master them and enjoy the success of your projects. Let me show you one by one.</p>
<h3 id="heading-use-names-that-mean-something"><strong>🌿 Use Names That Mean Something</strong></h3>
<p>Naming your variables or functions b or x is not helpful. Call them what they are so they’re easier to understand. Here’s an example of both a bad and good variable name:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Weak and vague</span>
<span class="hljs-keyword">let</span> b = <span class="hljs-number">5</span>;

<span class="hljs-comment">// Strong and clear</span>
<span class="hljs-keyword">let</span> numberOfUsers = <span class="hljs-number">5</span>;
</code></pre>
<p>People who write unclear names don’t want to own their mistakes. Don’t be that person.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736165724746/37b2edc3-3c68-47a8-ab6f-f131a2239a01.png" alt="Comic showing a bad vs a good variable name, by Shahan" class="image--center mx-auto" width="2000" height="800" loading="lazy"></p>
<h3 id="heading-keep-functions-laser-focused-srp"><strong>🔨 Keep Functions Laser-Focused (SRP)</strong></h3>
<p>A function should do <strong>one thing</strong>—and do it perfectly. This is called the Single Responsibility Principle (<strong>SRP</strong>).</p>
<p>Good code is like a hammer. It hits one nail, not ten. For example, if you are hiring someone to do everything in your company — finance, sales, marketing, janitorial work, and so on — they’ll likely fail miserably because they can’t focus one one thing. The same goes for your classes in code.</p>
<p>🚧 When a class or function does more than one thing, it becomes a tangled mess. Debugging it feels like solving a puzzle upside down. If your class handles both user input and database operations, for example, it’s not multitasking — it’s madness. Break it up. One method, one job.</p>
<p><strong>🔥 My Rule:</strong> Your code works for you. Keep it sharp, focused, and controllable, or it’s going to control you. Here is how to make that happen:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Clean: One job, one focus</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTotal</span>(<span class="hljs-params">a, b</span>) </span>{
    <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">logTotal</span>(<span class="hljs-params">user, total</span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`User: <span class="hljs-subst">${user}</span>, Total: <span class="hljs-subst">${total}</span>`</span>);
}

<span class="hljs-comment">// Messy: Trying to do EVERYTHING</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateAndLogTotal</span>(<span class="hljs-params">a, b, user</span>) </span>{
    <span class="hljs-keyword">let</span> total = a + b;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`User: <span class="hljs-subst">${user}</span>, Total: <span class="hljs-subst">${total}</span>`</span>);
}
</code></pre>
<p>🪧 When you mix tasks, you mix in confusion. As simple as that.</p>
<h3 id="heading-use-comments-thoughtfully"><strong>🚪 Use Comments Thoughtfully</strong></h3>
<p>There is a great saying among professional developers:</p>
<blockquote>
<p>“ Code speaks for itself. ”</p>
</blockquote>
<p>You don’t explain what a door does every time someone walks into a room, do you? Your code should work the same way.</p>
<p>Comments aren’t bad, but if your code can’t stand on its own, then you may have a problem.</p>
<p>🪧 A good comment should tell “why” not “how or what”. If a developer doesn’t understand “how” something works, then they likely aren’t going to understand “why” either.</p>
<p>Here are some short examples of good comments vs bad comments. I’ll also show you a real-world project for writing clean comments.</p>
<p><strong>Example 1: Bad Comment 👎</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Multiply the price by the quantity to calculate the total</span>
<span class="hljs-keyword">const</span> total = price * quantity;
</code></pre>
<p>This is a <strong>bad comment</strong> because it simply repeats what the code already says. The code <code>price * quantity</code> is self-explanatory, so the comment doesn’t add anything useful.</p>
<p><strong>Good Comment: 👍</strong></p>
<p>If the code is clear and simple, <strong>you don’t need a comment.</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> total = price * quantity;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736165891398/6a942ad7-5b09-4990-9c7f-95358dafcbf3.png" alt="Image illustrating unnecessary comment vs &quot;silent comment&quot;, by Shahan" class="image--center mx-auto" width="2000" height="800" loading="lazy"></p>
<p><strong>Example 2: Bad Comment 👎</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Check if the user logged in</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isUserLoggedIn</span>(<span class="hljs-params">session</span>) </span>{
    <span class="hljs-keyword">return</span> !!session.user;
}
</code></pre>
<p>This comment is bad because it doesn’t explain why the <code>isUserLoggin()</code> exists. It just explains what happens. But we already know that this is an auth function. This comment is a waste of time.</p>
<p><strong>Good Example 👍</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// The user is authenticated before accessing protected resources</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isUserLoggedIn</span>(<span class="hljs-params">session</span>) </span>{
    <span class="hljs-keyword">return</span> !!session.user;
}
</code></pre>
<p>This is a <strong>good comment</strong> because it explains <strong>why</strong> the code exists. It tells us that the function checks if the user is authenticated before allowing access to sensitive parts of the app. It focuses on the bigger picture.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736166143011/b3ddae3d-41cf-4534-8f1a-af710579922c.png" alt="Before: &quot;Check if the user is logged in&quot;. After: &quot;The user is authenticated before accessing protected resources.&quot; By Shahan." class="image--center mx-auto" width="2000" height="800" loading="lazy"></p>
<h3 id="heading-best-practices-for-writing-good-comments"><strong>⚡ Best Practices for Writing Good Comments</strong></h3>
<ol>
<li><p><strong>Explain the “Why,” not the “What”:</strong><br> Write comments to explain the purpose or context of the code, not what the code is doing.</p>
</li>
<li><p><strong>Avoid obvious comments:</strong><br> Don’t write comments for things the code already makes clear.</p>
</li>
<li><p><strong>Keep them short and precise:</strong><br> Write concise comments that are easy to read and directly explain the purpose.</p>
</li>
<li><p><strong>Update comments regularly:</strong><br> Outdated comments can mislead developers, so always update them when the code changes.</p>
</li>
</ol>
<p><strong>Real-World Example (with Good Comments) 🛒</strong></p>
<p>Let’s implement these practices into a real-world project: a large e-commerce application. One function calculates shipping costs based on the order details. Here's the full code, I will explain each comment below:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Shipping rules:</span>
<span class="hljs-comment">// - Free shipping for orders over $100</span>
<span class="hljs-comment">// - Standard shipping ($10) for orders below $100</span>
<span class="hljs-comment">// - Additional $5 for international orders</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateShipping</span>(<span class="hljs-params">order</span>) </span>{
    <span class="hljs-keyword">let</span> shippingCost = <span class="hljs-number">0</span>;

    <span class="hljs-comment">// Check if the order qualifies for free shipping</span>
    <span class="hljs-keyword">if</span> (order.total &gt;= <span class="hljs-number">100</span>) {
        shippingCost = <span class="hljs-number">0</span>; <span class="hljs-comment">// Free shipping</span>
    } <span class="hljs-keyword">else</span> {
        shippingCost = <span class="hljs-number">10</span>; <span class="hljs-comment">// Standard shipping cost</span>
    }

    <span class="hljs-comment">// Add additional cost for international orders</span>
    <span class="hljs-keyword">if</span> (order.isInternational) {
        shippingCost += <span class="hljs-number">5</span>;
    }

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

<span class="hljs-comment">// Example usage</span>
<span class="hljs-keyword">const</span> order1 = { <span class="hljs-attr">total</span>: <span class="hljs-number">120</span>, <span class="hljs-attr">isInternational</span>: <span class="hljs-literal">false</span> };
<span class="hljs-keyword">const</span> order2 = { <span class="hljs-attr">total</span>: <span class="hljs-number">80</span>, <span class="hljs-attr">isInternational</span>: <span class="hljs-literal">true</span> };

<span class="hljs-built_in">console</span>.log(calculateShipping(order1)); <span class="hljs-comment">// Output: 0</span>
<span class="hljs-built_in">console</span>.log(calculateShipping(order2)); <span class="hljs-comment">// Output: 15</span>
</code></pre>
<p>At the start of the function, we include a comment explaining the rules for shipping costs. This gives the reader an overview of the logic without needing to read the full code.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Shipping rules:</span>
<span class="hljs-comment">// - Free shipping for orders over $100</span>
<span class="hljs-comment">// - Standard shipping ($10) for orders below $100</span>
<span class="hljs-comment">// - Additional $5 for international orders</span>
</code></pre>
<p>Then, the first condition checks if the order total is greater than or equal to $100. A comment here clarifies <strong>why</strong> free shipping is applied.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Check if the order qualifies for free shipping</span>
<span class="hljs-keyword">if</span> (order.total &gt;= <span class="hljs-number">100</span>) {
    shippingCost = <span class="hljs-number">0</span>; <span class="hljs-comment">// Free shipping</span>
}
</code></pre>
<p>The second condition applies an additional charge for international shipping. The comment explains <strong>why</strong> the extra cost is added.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Add additional cost for international orders</span>
<span class="hljs-keyword">if</span> (order.isInternational) {
    shippingCost += <span class="hljs-number">5</span>;
}
</code></pre>
<p><strong>Why are these comments good?</strong></p>
<p>Imagine you’re working in a team of 20 developers. Someone reads the <code>calculateShipping</code> function six months later. Without these comments, they might waste time guessing why international orders have an extra fee. Good comments clarify the why and save hours of frustration.</p>
<h3 id="heading-make-your-code-readable"><strong>🧩 Make Your Code Readable</strong></h3>
<p>If someone reading your code feels like they’re solving a riddle, you’ve already become a troublemaker. Here is the proof:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Clean: Reads like a story</span>
<span class="hljs-keyword">if</span> (isLoggedIn) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Welcome!"</span>);
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Please log in."</span>);
}

<span class="hljs-comment">// Messy: Feels like chaos</span>
<span class="hljs-keyword">if</span>(isLoggedIn){<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Welcome!"</span>);}<span class="hljs-keyword">else</span>{<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Please log in."</span>);}
</code></pre>
<p>If your code is messy and hard to read, it will confuse others—and even yourself later! Imagine coming back to your own code after six months and feeling like you’re reading a foreign language. Readable code saves time, reduces bugs, and makes everyone’s life easier.</p>
<p><strong>🍵 Why is Readability Important?</strong></p>
<ol>
<li><p><strong>For yourself:</strong> When you revisit your code after weeks or months, clean code helps you pick up where you left off without wasting time figuring out what you did.</p>
</li>
<li><p><strong>For your team:</strong> If someone else reads your code, they shouldn’t have to solve a puzzle. Clean code makes teamwork smoother and prevents miscommunication.</p>
</li>
<li><p><strong>Fewer bugs:</strong> Clear code is easier to debug because you can quickly spot mistakes.</p>
</li>
</ol>
<p><strong>🧙‍♂️ How to Write Readable Code</strong></p>
<p>Let’s build a simple program to manage books in a library. We’ll make it clean and readable and then I will break down this code below:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// A class to represent a book</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> </span>{
    <span class="hljs-keyword">constructor</span>(title, author, isAvailable) {
        <span class="hljs-built_in">this</span>.title = title;
        <span class="hljs-built_in">this</span>.author = author;
        <span class="hljs-built_in">this</span>.isAvailable = isAvailable;
    }

    borrow() {
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isAvailable) {
            <span class="hljs-built_in">this</span>.isAvailable = <span class="hljs-literal">false</span>;
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`You borrowed "<span class="hljs-subst">${<span class="hljs-built_in">this</span>.title}</span>".`</span>);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Sorry, "<span class="hljs-subst">${<span class="hljs-built_in">this</span>.title}</span>" is not available.`</span>);
        }
    }

    returnBook() {
        <span class="hljs-built_in">this</span>.isAvailable = <span class="hljs-literal">true</span>;
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`You returned "<span class="hljs-subst">${<span class="hljs-built_in">this</span>.title}</span>".`</span>);
    }
}

<span class="hljs-comment">// A function to display available books</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayAvailableBooks</span>(<span class="hljs-params">books</span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Available books:"</span>);
    books.forEach(<span class="hljs-function">(<span class="hljs-params">book</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (book.isAvailable) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`- <span class="hljs-subst">${book.title}</span> by <span class="hljs-subst">${book.author}</span>`</span>);
        }
    });
}

<span class="hljs-comment">// Example usage</span>
<span class="hljs-keyword">const</span> book1 = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"The Clean Coder"</span>, <span class="hljs-string">"Robert Martin"</span>, <span class="hljs-literal">true</span>);
<span class="hljs-keyword">const</span> book2 = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"You Don’t Know JS"</span>, <span class="hljs-string">"Kyle Simpson"</span>, <span class="hljs-literal">false</span>);
<span class="hljs-keyword">const</span> book3 = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"Eloquent JavaScript"</span>, <span class="hljs-string">"Marijn Haverbeke"</span>, <span class="hljs-literal">true</span>);

<span class="hljs-keyword">const</span> library = [book1, book2, book3];

displayAvailableBooks(library); <span class="hljs-comment">// Show available books</span>
book1.borrow(); <span class="hljs-comment">// Borrow a book</span>
displayAvailableBooks(library); <span class="hljs-comment">// Show available books again</span>
book1.returnBook(); <span class="hljs-comment">// Return the book</span>
displayAvailableBooks(library); <span class="hljs-comment">// Final list</span>
</code></pre>
<p>We created a <code>Book</code> class to represent each book. It has properties like <code>title</code>, <code>author</code>, and <code>isAvailable</code> to track its status.</p>
<ul>
<li><p>The <code>borrow</code> method checks if the book is available. If yes, it marks it as unavailable and prints a message.</p>
</li>
<li><p>The <code>returnBook</code> method makes the book available again.</p>
</li>
<li><p>The <code>displayAvailableBooks</code> function loops through the library and prints only the books that are available.</p>
</li>
<li><p>We create three books (<code>book1</code>, <code>book2</code>, <code>book3</code>) and store them in a <code>library</code> array.</p>
</li>
<li><p>We borrow and return books, showing how the list of available books changes.</p>
</li>
</ul>
<p>As you can see, readable code is not just about style. It saves time, prevents bugs, and preserves your code as useful for years to come.</p>
<h3 id="heading-test-everything-you-write"><strong>🏌️ Test Everything You Write</strong></h3>
<p>If you don’t take the time to write tests, you shouldn’t be surprised if your code breaks. If you do want to write tests, follow this unit testing strategy to catch problems ahead.</p>
<p><strong>What Is Unit Testing?</strong></p>
<p>Concretely, unit testing checks individual parts of your code (like functions or classes) to ensure they work correctly. Just like checking each brick of your house for soundness before building the walls.</p>
<p>Let me give you an example of how unit testing works:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> </span>{
    add(a, b) { <span class="hljs-keyword">return</span> a + b; }
    subtract(a, b) { <span class="hljs-keyword">return</span> a - b; }
}

<span class="hljs-comment">// Test it (Unit Test)</span>
<span class="hljs-keyword">const</span> calculator = <span class="hljs-keyword">new</span> Calculator();
<span class="hljs-built_in">console</span>.assert(calculator.add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">5</span>, <span class="hljs-string">"Addition failed"</span>);
<span class="hljs-built_in">console</span>.assert(calculator.subtract(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">2</span>, <span class="hljs-string">"Subtraction failed"</span>);
</code></pre>
<p>Here’s what’s going on in this code:</p>
<p>First, we create the calculator class:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> </span>{
    add(a, b) { <span class="hljs-keyword">return</span> a + b; }
    subtract(a, b) { <span class="hljs-keyword">return</span> a - b; }
}
</code></pre>
<p>The <code>Calculator</code> class has two methods: <code>add</code> and <code>subtract</code>.</p>
<ul>
<li><p><code>add(a, b)</code> takes two numbers and returns their sum.</p>
</li>
<li><p><code>subtract(a, b)</code> takes two numbers and returns their difference.</p>
</li>
</ul>
<p>Next, we set up the tests:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> calculator = <span class="hljs-keyword">new</span> Calculator();
</code></pre>
<p>Here, we’re creating an instance of the <code>Calculator</code> class to test its methods.</p>
<p>Then we write test cases:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.assert(calculator.add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">5</span>, <span class="hljs-string">"Addition failed"</span>);
<span class="hljs-built_in">console</span>.assert(calculator.subtract(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">2</span>, <span class="hljs-string">"Subtraction failed"</span>);
</code></pre>
<p><code>console.assert(condition, message)</code> checks if the condition is <code>true</code>. If it’s <code>false</code>, the message ("Addition failed" or "Subtraction failed") is displayed in the console.</p>
<ul>
<li><p><strong>First test</strong>: <code>calculator.add(2, 3) === 5</code></p>
<ul>
<li><p>Calls the <code>add</code> method with <code>2</code> and <code>3</code>.</p>
</li>
<li><p>Checks if the result is <code>5</code>.</p>
</li>
</ul>
</li>
<li><p><strong>Second test</strong>: <code>calculator.subtract(5, 3) === 2</code></p>
<ul>
<li><p>Calls the <code>subtract</code> method with <code>5</code> and <code>3</code>.</p>
</li>
<li><p>Checks if the result is <code>2</code>.</p>
</li>
</ul>
</li>
</ul>
<p>So what happens if something breaks? It’s pretty simple to solve any issues that arise here. In this case, if the <code>add</code> or <code>subtract</code> method doesn’t work correctly, the test will fail. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.assert(calculator.add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">6</span>, <span class="hljs-string">"Addition failed"</span>);
</code></pre>
<ul>
<li><p>The condition <code>calculator.add(2, 3) === 6</code> is <code>false</code>.</p>
</li>
<li><p>The console will display: <code>"Addition failed"</code>.</p>
</li>
</ul>
<p><strong>Real-World Example: Testing a Login System 👥</strong></p>
<p>Let’s test a simple login system to see how unit testing works in a real-world scenario.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Auth</span> </span>{
    login(username, password) {
        <span class="hljs-keyword">return</span> username === <span class="hljs-string">"admin"</span> &amp;&amp; password === <span class="hljs-string">"1234"</span>;
    }
}

<span class="hljs-comment">// Test the Auth class</span>
<span class="hljs-keyword">const</span> auth = <span class="hljs-keyword">new</span> Auth();
<span class="hljs-built_in">console</span>.assert(auth.login(<span class="hljs-string">"admin"</span>, <span class="hljs-string">"et5t45#@"</span>) === <span class="hljs-literal">true</span>, <span class="hljs-string">"Login failed for valid credentials"</span>);
<span class="hljs-built_in">console</span>.assert(auth.login(<span class="hljs-string">"user"</span>, <span class="hljs-string">"wrongpassword"</span>) === <span class="hljs-literal">false</span>, <span class="hljs-string">"Login succeeded for invalid credentials"</span>);
</code></pre>
<p>First, create the <code>Auth</code> class:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Auth</span> </span>{
    login(username, password) {
        <span class="hljs-keyword">return</span> username === <span class="hljs-string">"admin"</span> &amp;&amp; password === <span class="hljs-string">"1234"</span>;
    }
}
</code></pre>
<p>The <code>login</code> method checks if the username is <code>"admin"</code> and the password is <code>"1234"</code>. If both match, it returns <code>true</code> – otherwise, <code>false</code>.</p>
<p>Next, set up the tests:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> auth = <span class="hljs-keyword">new</span> Auth();
</code></pre>
<p>Create an instance of the <code>Auth</code> class. Then write the test cases:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.assert(auth.login(<span class="hljs-string">"admin"</span>, <span class="hljs-string">"1234"</span>) === <span class="hljs-literal">true</span>, <span class="hljs-string">"Login failed for valid credentials"</span>);
<span class="hljs-built_in">console</span>.assert(auth.login(<span class="hljs-string">"user"</span>, <span class="hljs-string">"wrongpassword"</span>) === <span class="hljs-literal">false</span>, <span class="hljs-string">"Login succeeded for invalid credentials"</span>);
</code></pre>
<ul>
<li><p><strong>First test</strong>: Checks if valid credentials (<code>"admin"</code>, <code>"1234"</code>) succeed. If not, <code>"Login failed for valid credentials"</code> is displayed.</p>
</li>
<li><p><strong>Second test</strong>: Checks if invalid credentials (<code>"user"</code>, <code>"wrongpassword"</code>) fail. If not, <code>"Login succeeded for invalid credentials"</code> is displayed.</p>
</li>
</ul>
<p><strong>🌱 Why testing results in clean code:</strong></p>
<ol>
<li><p>You naturally write smaller, more focused functions to make your code testable</p>
</li>
<li><p>Tests verify that your code behaves as expected under different conditions.</p>
</li>
<li><p>With tests in place, you can confidently update your code, knowing the tests will catch any mistakes.</p>
</li>
</ol>
<h3 id="heading-use-dependency-injection"><strong>💉 Use Dependency Injection</strong></h3>
<p>Hardcoding dependencies is like tattooing someone’s name on your forehead — it’s permanent, can be abrasive, and locks you in.</p>
<p>So, what does Dependency Injection do? It lets you manage your code's relationships by passing dependencies as arguments. It’s flexible, adaptable, and maintainable.</p>
<p>To demonstrate how it works, here I’m using the Nodemailer dependency for sending emails to users:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Dependency: Sending emails with Nodemailer</span>
<span class="hljs-keyword">const</span> nodemailer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'nodemailer'</span>);
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendEmail</span>(<span class="hljs-params">to, subject, message</span>) </span>{
    <span class="hljs-keyword">const</span> transporter = nodemailer.createTransport({ <span class="hljs-comment">/* config */</span> });
    <span class="hljs-keyword">return</span> transporter.sendMail({ <span class="hljs-attr">from</span>: <span class="hljs-string">"programmingwithshahan@gmail.com"</span>, to, subject, <span class="hljs-attr">text</span>: message });
}
</code></pre>
<p>⚠️ To save yourself from risk, make sure to avoid <strong>hardcoding</strong> dependencies. Use abstraction or configuration files for secure maintenance.</p>
<p>This is just one example. As a developer, you may use hundreds of libraries or dependencies.</p>
<p>I’m not saying you shouldn’t rely on dependencies/libraries at all, as nowadays it is hard to avoid them. But you should be very careful before installing them in your coding projects.</p>
<p>You should check the security, performance, quality, or functionality of an organization's software systems. Because they sometimes contain risks that can ruin your entire project.</p>
<p>🚧 Always control your tools, don't let them control you.</p>
<h3 id="heading-clean-project-structures"><strong>📂 Clean Project Structures</strong></h3>
<p>A well-organized project is the difference between a <strong>trash heap</strong> and a high-end <strong>boutique</strong>.</p>
<p>Here is how each folder should be organized:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9xwyg9iqqcybz21lsgxz.png" alt="Image of clean code project structure by shahan" width="1563" height="1250" loading="lazy"></p>
<p>If your codebase looks like a junk drawer, you’ve already caused trouble for your future self.</p>
<p>Let’s go through the clean project structure you can see above to better understand it:</p>
<p><strong>1.</strong> <code>myProjet/src</code></p>
<p>This is the main container for your entire application. Everything your app needs is stored inside this folder. It has subfolders to keep things tidy and managed in one place.</p>
<p><strong>2.</strong> <code>components</code></p>
<p>This is where you keep all the reusable pieces of your app. You can use these components in multiple places without building them again.</p>
<p><strong>3.</strong> <code>services</code></p>
<p>This is the "brain" of your app. It handles all the work behind the scenes for both the frontend and backend. <code>emailService.js</code>, <code>userService.js</code> and <code>productService.js</code> are some of the example files for your <code>services</code> folder.</p>
<p><strong>4.</strong> <code>utils</code></p>
<p>This contains all the small, handy tools you need to make your application run smoothly and make your life easier. For example, <code>formatedate.js</code>, <code>validateEmail.js</code> and <code>generateId.js</code> are some of the common utils files to make reusable pieces of components for your entire project.</p>
<h4 id="heading-5-tests"><strong>5.</strong> <code>tests</code></h4>
<p>Conventionally, test files are typically located <strong>outside</strong> the <code>src</code> folder, at the project root level. This keeps your production code (<code>src</code>) separate from your test code (<code>tests</code>), making it cleaner and easier to manage. Have a look:</p>
<pre><code class="lang-bash">myProject/
├── src/              <span class="hljs-comment"># Production code</span>
│   ├── components/
│   ├── services/
│   └── utils/
├── tests/            <span class="hljs-comment"># Test files</span>
│   ├── components/
│   ├── services/
│   └── utils/
├── package.json      <span class="hljs-comment"># Project configuration</span>
└── README.md         <span class="hljs-comment"># Documentation</span>
</code></pre>
<p>Some developers may prefer creating one testing file inside the <code>test</code> folder to test everything in one place. Unfortunately, it may feel clean at first, but as your project grows, you’ll have to find and search for specific code blocks. It’s ugly and can produce unexpected testing results. So breaking them into multiple testing files inside the <code>tests</code> folder is highly recommended.</p>
<p><strong>Real-world example 📧</strong></p>
<p>So let me create a clean, durable project structure for you to apply in any future projects you might work on. Needless to say, clean project structure is the foundation of building a maintainable project.</p>
<p>From our previous email sending application example, we will write a clean project structure for this app. We want to build an application that sends emails to users. Your clean project structure for this app should look like this:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v6rlc5qiplgxz1h4dps.png" alt="Image of email app clean code project structure by shahan" width="1563" height="1250" loading="lazy"></p>
<p>As you can see, I packed every subfolder and file inside the <code>src</code> folder which is the main container of our application. Inside the <code>src</code> folder, we created <code>components</code>, <code>services</code>, <code>utiles</code>. Finally, we have a manageable <code>test</code> folder outside the <code>src</code> folder to test each component independently. This test folder has nothing to do with our production code that is located inside the <code>src</code> folder.</p>
<h3 id="heading-be-consistent-with-formatting"><strong>🤹‍♂️ Be Consistent with Formatting</strong></h3>
<p>Don’t write code like you’re 10 different people. Be consistent with your formatting.</p>
<p>Use tools like <a target="_blank" href="https://prettier.io/">Prettier</a> or <a target="_blank" href="https://eslint.org/">ESLint</a> to enforce a consistent style. If every file looks different, you’re creating chaos that no one wants to fix.</p>
<p>I would say that consistency in formatting is one of the most important aspects of writing clean code.</p>
<p>Have a look...</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/46zu4k5nnrkcdesgqrye.png" alt="Image of consistent formatting snippets from clean code zero to one book" width="1562" height="1875" loading="lazy"></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Always use 2 spaces for indentation</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateArea</span>(<span class="hljs-params">width, height</span>) </span>{
  <span class="hljs-keyword">if</span> (width &lt;= <span class="hljs-number">0</span> || height &lt;= <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Dimensions must be positive numbers."</span>);
  }
  <span class="hljs-keyword">return</span> width * height;
}

<span class="hljs-comment">// Add meaningful whitespace for readability</span>
<span class="hljs-keyword">const</span> rectangle = {
  <span class="hljs-attr">width</span>: <span class="hljs-number">10</span>,
  <span class="hljs-attr">height</span>: <span class="hljs-number">20</span>,
};

<span class="hljs-comment">// Clear separation of logic</span>
<span class="hljs-keyword">try</span> {
  <span class="hljs-keyword">const</span> area = calculateArea(rectangle.width, rectangle.height);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Area: <span class="hljs-subst">${area}</span>`</span>);
} <span class="hljs-keyword">catch</span> (error) {
  <span class="hljs-built_in">console</span>.error(error.message);
}
</code></pre>
<p>Let’s examine some of the aspects of this code that make it clean:</p>
<h4 id="heading-1-consistent-indentation">1️⃣ Consistent Indentation</h4>
<p>Why 2 or 4 spaces? It’s clean, minimal, and universally accepted in many JavaScript style guides. It doesn’t overwhelm the eyes, and the code structure stands out clearly. When you mix inconsistent indentation (2 spaces here, 4 spaces there), you confuse people—and confused people make mistakes.</p>
<h4 id="heading-2-meaningful-whitespace-giving-code-room-to-breathe">2️⃣ Meaningful Whitespace: Giving Code Room to Breathe</h4>
<p>That extra line break between the rectangle definition and the <code>try</code> block is like a pause in a sentence — it gives the reader time to process.</p>
<h4 id="heading-3-clear-separation-of-logic-modular-thinking">3️⃣ Clear Separation of Logic: Modular Thinking</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span> {
  <span class="hljs-keyword">const</span> area = calculateArea(rectangle.width, rectangle.height);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Area: <span class="hljs-subst">${area}</span>`</span>);
} <span class="hljs-keyword">catch</span> (error) {
  <span class="hljs-built_in">console</span>.error(error.message);
}
</code></pre>
<p>Look at how the logic is divided into clear sections:</p>
<ul>
<li><p>First, the calculation (<code>calculateArea</code> function).</p>
</li>
<li><p>Then, the output (<code>console.log</code>).</p>
</li>
<li><p>Finally, error handling (<code>catch</code> block).</p>
</li>
</ul>
<p>Each task has its own space and purpose.</p>
<h4 id="heading-4-readable-error-handling">4️⃣ Readable Error Handling</h4>
<p>When you throw errors or log messages, you format them cleanly. No vague or cryptic messages here. A developer seeing this will immediately know the problem.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Dimensions must be positive numbers."</span>);
</code></pre>
<p><strong>🐦‍⬛ General tips for consistent formatting:</strong></p>
<ul>
<li><p>Use 2 or 4 spaces for indentation consistently throughout your codebase. Avoid tabs to maintain uniformity across different editors.</p>
</li>
<li><p>Keep lines to a maximum of 100-120 characters to prevent horizontal scrolling and improve readability.</p>
</li>
<li><p>Group related logic together and separate blocks of code with blank lines to highlight their purpose.</p>
</li>
<li><p>Finally, avoid over-aligning code. Instead, let indentation naturally guide the flow of logic.</p>
</li>
</ul>
<h3 id="heading-stop-hardcoding-values"><strong>✋ Stop Hardcoding Values</strong></h3>
<p>Hardcoding values is a lazy way to code. Here is the proof:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Bad: Hardcoded and rigid</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUser</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> maxUsers = <span class="hljs-number">100</span>;
    <span class="hljs-keyword">if</span> (currentUsers &gt;= maxUsers) <span class="hljs-keyword">throw</span> <span class="hljs-string">"Too many users!"</span>;
}

<span class="hljs-comment">// Clean: Dynamic and flexible</span>
<span class="hljs-keyword">const</span> MAX_USERS = <span class="hljs-number">100</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUser</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (currentUsers &gt;= MAX_USERS) <span class="hljs-keyword">throw</span> <span class="hljs-string">"Too many users!"</span>;
}
</code></pre>
<p>You see, changing this variable won’t surprise you in the future. You know exactly where to find it to change uncertain values.</p>
<p>Its best to store your fixed values in the global configuration (config) file.</p>
<p>🪧 So, avoid hardcoding values at all costs. Hardcoding is the shortcut that may drive your future self (or others) crazy.</p>
<h3 id="heading-keep-functions-short"><strong>🤏 Keep Functions Short</strong></h3>
<p>If your function is longer than 20 lines, it’s probably trying to do too much<em>.</em></p>
<p>Short functions are sharp functions. They hit their mark every time.</p>
<p>Long, bloated functions are messy and hard to read, but short functions are clear and focused. Here is how your large functions should break down:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateCart</span>(<span class="hljs-params">cart, item</span>) </span>{
    addItemToCart(cart, item);
    <span class="hljs-keyword">let</span> total = calculateTotal(cart);
    logTransaction(item, total);
    <span class="hljs-keyword">return</span> total;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addItemToCart</span>(<span class="hljs-params">cart, item</span>) </span>{
    cart.items.push(item);
}
</code></pre>
<p>Let me explain this code so you understand why breaking down large functions is a winning strategy.</p>
<ol>
<li><p><strong>The Main Function:</strong> <code>updateCart()</code> calls smaller helper functions to handle specific tasks like:</p>
<ul>
<li><p>Adds the item to the cart.</p>
</li>
<li><p>Calculates the total price.</p>
</li>
<li><p>Logs the details of the transaction.</p>
</li>
<li><p>Finally, it returns the total price.</p>
</li>
</ul>
</li>
</ol>
<p>Instead of one long block of code that tries to do everything, it delegates tasks to helper functions.</p>
<ol start="2">
<li><strong>Helper Function:</strong> <code>addItemToCart()</code> This function <strong>only</strong> handles adding the item to the cart. if you need to change how items are added (for example, checking for duplicates). You could just edit this small function instead of digging through a giant block of code in <code>updateCart</code>. That’s how you write clean code functions that’s a joy to read and easy to maintain.</li>
</ol>
<p><strong>What Happens If Functions Are Too Long? 💤</strong></p>
<p>Let’s say you didn’t break down the <code>updateCart</code> function. Here’s what it might look like:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateCart</span>(<span class="hljs-params">cart, item</span>) </span>{
    cart.items.push(item);
    <span class="hljs-keyword">let</span> total = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; cart.items.length; i++) {
        total += cart.items[i].price;
    }
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Added <span class="hljs-subst">${item.name}</span>. Total is now $<span class="hljs-subst">${total}</span>.`</span>);
    <span class="hljs-keyword">return</span> total;
}
</code></pre>
<p>What are the problems here?</p>
<ul>
<li><p>It’s trying to do everything.</p>
</li>
<li><p>It’s hard to read, especially if it grows bigger.</p>
</li>
<li><p>If something breaks, you’ll waste time figuring out which part is the problem.</p>
</li>
</ul>
<p>Now the choice is yours: stick with the messy all-in-one approach or practice the clean one function one job mindset.</p>
<h3 id="heading-follow-the-boy-scout-rule"><strong>⛺ Follow the Boy Scout Rule</strong></h3>
<blockquote>
<p>Always leave your campsite cleaner than you found it.</p>
</blockquote>
<p>Let me break it down for you. You don’t just use something and leave it worse than before. That’s inconsiderate behavior. Real professionals leave things better than they found them.</p>
<p>In coding terms, every time you touch the codebase, <strong>make it better.</strong> Clean it up, refactor messy parts, and improve readability. If you don’t, you’re just piling on garbage that will eventually collapse on your head.</p>
<p>Here is an example. Instead of improving it, we’re just adding more layers of complexity:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Original code: Hard to read, poorly named variables</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calc</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">let</span> x = a + b;
  <span class="hljs-keyword">let</span> y = x * <span class="hljs-number">0.2</span>;
  <span class="hljs-keyword">return</span> y;
}

<span class="hljs-comment">// We're adding to it but not cleaning it up</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calcDiscount</span>(<span class="hljs-params">a, b, discountRate</span>) </span>{
  <span class="hljs-keyword">let</span> total = calc(a, b);
  <span class="hljs-keyword">let</span> final = total - discountRate;
  <span class="hljs-keyword">return</span> final;
}
</code></pre>
<p>After: it gets better every time. Here’s how a disciplined coder works — they improve as they go:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Improved code: Clear names, refactored for clarity</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateSubtotal</span>(<span class="hljs-params">price, quantity</span>) </span>{
  <span class="hljs-keyword">return</span> price * quantity;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateDiscountedTotal</span>(<span class="hljs-params">price, quantity, discountRate</span>) </span>{
  <span class="hljs-keyword">const</span> subtotal = calculateSubtotal(price, quantity);
  <span class="hljs-keyword">const</span> discount = subtotal * discountRate;
  <span class="hljs-keyword">return</span> subtotal - discount;
}
</code></pre>
<p>Now, anyone can tell what’s happening at a glance. Because we’ve broken down the code into smaller, more focused functions. Thus, adding new features won’t break existing functionality. 🏕️</p>
<h3 id="heading-follow-the-openclosed-principle"><strong>🏟️ Follow the Open/Closed Principle</strong></h3>
<p>This design principle suggests your code should be designed to allow extensions without changing the existing foundation.</p>
<p>You want to add features <em>—</em> not rip it apart every time you upgrade<em>.</em> Modifying old code to fit new requirements is exactly like trying to rebuild your house every time you buy new furniture. It’s not sustainable.</p>
<p>Let’s see how you can build smarter, scalable code that lets you add features without breaking everything else.</p>
<h4 id="heading-before-violating-the-principle">Before: Violating the principle</h4>
<p>You’ve got a class to handle payments — simple enough. At first, it just handles credit cards.</p>
<p>But then your boss shows up and says, <em>“Hey, now we need PayPal support.”</em></p>
<p>And because you didn’t bother learning clean code, your code looks like a spaghetti monster straight out of a legacy enterprise system from 1995. Here’s the masterpiece you’ve crafted:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentProcessor</span> </span>{
  processPayment(paymentType, amount) {
    <span class="hljs-keyword">if</span> (paymentType === <span class="hljs-string">"creditCard"</span>) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Processing credit card payment of $<span class="hljs-subst">${amount}</span>`</span>);
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (paymentType === <span class="hljs-string">"paypal"</span>) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Processing PayPal payment of $<span class="hljs-subst">${amount}</span>`</span>);
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Unsupported payment type"</span>);
    }
  }
}

<span class="hljs-keyword">const</span> paymentProcessor = <span class="hljs-keyword">new</span> PaymentProcessor();
paymentProcessor.processPayment(<span class="hljs-string">"creditCard"</span>, <span class="hljs-number">100</span>);
paymentProcessor.processPayment(<span class="hljs-string">"paypal"</span>, <span class="hljs-number">200</span>);
</code></pre>
<p>Alas! Every new payment type (like Apple Pay, Google Pay, and so on) requires modifying the <code>processPayment</code> method. Needless to say, you risk breaking existing functionality while adding new features. If you had learned this principle, you might not be in this mess.</p>
<p>Don’t worry: I’ll help you to fix this. First, we need to refactor the code. Instead of modifying the existing class, we’ll extend its functionality using <a target="_blank" href="https://stackify.com/oop-concept-polymorphism/">polymorphism</a>:</p>
<pre><code class="lang-javascript">javascriptCopy code<span class="hljs-comment">// Base class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentProcessor</span> </span>{
  processPayment(amount) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"processPayment() must be implemented"</span>);
  }
}

<span class="hljs-comment">// Credit card payment</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreditCardPayment</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">PaymentProcessor</span> </span>{
  processPayment(amount) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Processing credit card payment of $<span class="hljs-subst">${amount}</span>`</span>);
  }
}

<span class="hljs-comment">// PayPal payment</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PayPalPayment</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">PaymentProcessor</span> </span>{
  processPayment(amount) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Processing PayPal payment of $<span class="hljs-subst">${amount}</span>`</span>);
  }
}

<span class="hljs-comment">// Adding a new payment type? Just extend the class!</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApplePayPayment</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">PaymentProcessor</span> </span>{
  processPayment(amount) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Processing Apple Pay payment of $<span class="hljs-subst">${amount}</span>`</span>);
  }
}

<span class="hljs-comment">// Usage</span>
<span class="hljs-keyword">const</span> payments = [
  <span class="hljs-keyword">new</span> CreditCardPayment(),
  <span class="hljs-keyword">new</span> PayPalPayment(),
  <span class="hljs-keyword">new</span> ApplePayPayment(),
];

payments.forEach(<span class="hljs-function">(<span class="hljs-params">payment</span>) =&gt;</span> payment.processPayment(<span class="hljs-number">100</span>));
</code></pre>
<p>Now, adding new payment methods doesn’t require changing the existing <code>PaymentProcessor</code> class. You just created a new subclass. So the original code remains untouched, meaning there’s no risk of breaking existing features.</p>
<p>Each payment type has its own class, and adding PayPal payment support, for example, doesn’t break the code. Now you can reply to your boss: <em>“Of course, I will add this feature in 5 minutes.”</em> Your promotion is waiting for you to accept it.</p>
<p>I share even more tips in my book <a target="_blank" href="https://codewithshahan.gumroad.com/l/cleancode-zero-to-one">Clean Code Zero to One</a>.</p>
<h2 id="heading-modern-best-practices-to-help-you-write-clean-code-a-summary">Modern Best Practices to Help You Write Clean Code: A Summary 🥷</h2>
<p>Now let me show you the best practices and summarise our 12 Clean Code design principles to help you write clean code for agile application development.</p>
<h3 id="heading-common-code-smells-and-how-to-fix-them">🔎 Common Code Smells and How to Fix Them</h3>
<ul>
<li><p>💊 Duplication: If you're copying code, you’re creating more work for yourself. Extract it into a function, and do it right.</p>
</li>
<li><p>🛤️ Long methods: If your method needs a scroll bar, it's doing too much. Break it down, keep it focused.</p>
</li>
<li><p>👑 King objects: No class should be doing everything. Simplify responsibilities, or your codebase will become messy.</p>
</li>
</ul>
<h3 id="heading-effective-commenting-practices">💬 Effective Commenting Practices</h3>
<ul>
<li><p>💭 When to comment: Only comment if the code isn't clear. If it is, comments are just clutter.</p>
</li>
<li><p>🫗 Clarity: Comments should tell why, not what. If your code needs explaining, it might be too complex.</p>
</li>
<li><p>🌴 Avoid redundancy: Don't comment what's obvious. If your function is addNumbers, don't comment it does that.</p>
</li>
</ul>
<h3 id="heading-refactoring-techniques-for-clean-code">🧼 Refactoring Techniques for Clean Code</h3>
<ul>
<li><p>🏭 Extract methods: Big methods? Break them down. It's not just about cleanliness –– it's about control.</p>
</li>
<li><p>🫕Rename variables: If your variable names don’t shout their purpose, change and improve them. Precision in naming is precision in thought.</p>
</li>
<li><p>🍃 Simplify conditionals: If your conditionals look like algebra, simplify them. If a == true, just write if(a).</p>
</li>
</ul>
<h3 id="heading-testing-and-clean-code">🧪 Testing and Clean Code</h3>
<ul>
<li><p>🧙 Unit tests: Test every piece of code like you're interrogating a suspect. No stone unturned.</p>
</li>
<li><p>🏇TDD (Test Driven Development): Write tests first. It's not just about catching bugs, it's about knowing exactly what your code should do before you write it.</p>
</li>
<li><p>🧽 Clean tests: Your tests should be as clean as your code. If they're messy, they’re not going to be helpful.</p>
</li>
</ul>
<h3 id="heading-error-handling-and-clean-code">🐛 Error Handling and Clean Code</h3>
<ul>
<li><p>⁉️ Exceptions: Use them. They're not just for errors, they're also for keeping your code clean from error clutter.</p>
</li>
<li><p>🖍️ Fail fast: If something's wrong, stop right there. Don't let errors add up. Deal with them immediately.</p>
</li>
<li><p>🚨 Logging: Log like you're documenting a crime scene. Clear, precise, and only what's necessary.</p>
</li>
</ul>
<h3 id="heading-code-reviews-and-clean-code">🌱 Code Reviews and Clean Code</h3>
<ul>
<li><p>🚢 Process: Have a system. No cowboy coding. Review, critique, improve.</p>
</li>
<li><p>🔪 Tools: Use tools that make reviews easy. They're not just for catching mistakes, they're also for teaching discipline.</p>
</li>
<li><p>🧦 Culture: Cultivate a culture where feedback is gold. Help your team learn how to handle and receive critiques.</p>
</li>
</ul>
<h2 id="heading-automated-tools-for-maintaining-clean-code">Automated Tools for Maintaining Clean Code ⚓</h2>
<p>Tools and automation techniques can be really helpful in writing clean code. If you’re not using the right tools and automating things to save yourself time, you’re missing out.</p>
<p>You think you can "eyeball" your way through code quality? Guess again. Without automation, this is what happens:</p>
<ol>
<li><p>👎 You miss obvious mistakes because you're "too busy."</p>
</li>
<li><p>🤕 Your code looks different in every file, making collaboration a headache.</p>
</li>
<li><p>🪦 Deployment breaks because you skipped a critical test.</p>
</li>
</ol>
<p>Successful developers use the right tools to automate code and get things done. Here are four strategies for maintaining clean code using modern tools.</p>
<h3 id="heading-1-static-analysis"><strong>1️⃣ Static Analysis</strong></h3>
<p>Static analysis is actually a code inspector that reads through your code and points out potential issues early on. The best part? It works <strong>before</strong> runtime, catching errors that could otherwise lead to crashes, downtime, or embarrassing bugs.</p>
<h4 id="heading-how-does-it-work"><strong>How does it work?</strong></h4>
<ol>
<li><p><strong>Syntax checking</strong>: It looks at your code to analyze everything written in the correct syntax. If you misspell a variable or forget a closing bracket, it’ll call you out instantly.</p>
</li>
<li><p><strong>Code quality rules</strong>: Tools like ESLint enforce rules like consistent indentation, avoiding unused variables, and sticking to best practices.</p>
</li>
<li><p><strong>Error prevention</strong>: It identifies logic errors, such as using variables that haven’t been defined, or making comparisons that don’t make sense.</p>
</li>
</ol>
<p>Here’s how static analysis works in action:</p>
<h4 id="heading-before-static-analysis">🚨 Before static analysis:</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> sum = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> { <span class="hljs-keyword">return</span> a + b; }
<span class="hljs-built_in">console</span>.log(sume(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>)); <span class="hljs-comment">// Typo, unnoticed until runtime</span>
</code></pre>
<ul>
<li><strong>Problem</strong>: The typo in <code>sume</code> will only cause an error when the code runs, and that could lead to frustrating debugging sessions or worse — breaking the app in production.</li>
</ul>
<h4 id="heading-after-static-analysis-using-eslint">🚑 After static analysis (using ESLint):</h4>
<pre><code class="lang-javascript">codeError: <span class="hljs-string">'sume'</span> is not defined.
</code></pre>
<ul>
<li><strong>Solution</strong>: <a target="_blank" href="https://eslint.org/">ESLint</a> immediately flags the typo before you even run the code. The error is caught early, saving you time and headaches.</li>
</ul>
<h3 id="heading-2-automated-code-formatting"><strong>2️⃣ Automated Code Formatting</strong></h3>
<p>Before Formatting:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculate</span> (<span class="hljs-params"> x , y </span>)</span>{ <span class="hljs-keyword">return</span> x+ y;}
<span class="hljs-built_in">console</span>.log( calculate (<span class="hljs-number">2</span>,<span class="hljs-number">3</span> ) )
</code></pre>
<ul>
<li><strong>Problem</strong>: Inconsistent spacing and formatting make the code harder to read.</li>
</ul>
<h4 id="heading-after-using-prettier">After using Prettier:</h4>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculate</span>(<span class="hljs-params">x, y</span>) </span>{
  <span class="hljs-keyword">return</span> x + y;
}
<span class="hljs-built_in">console</span>.log(calculate(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>));
</code></pre>
<ul>
<li><strong>Solution</strong>: Clean, consistent, and professional formatting is applied automatically. No more nitpicking over spaces or alignment.</li>
</ul>
<p>Pretty basic stuff though. I covered this in case you write code in notepad or something where IDE is not provided (for example, a job interview).</p>
<h3 id="heading-3-continuous-integration-ci-testing"><strong>3️⃣ Continuous Integration (CI) Testing</strong></h3>
<p>CI testing make sure every new change to your code is verified automatically. It’s like a safety net that catches bugs introduced during development. CI tools run your tests every time you push code, so nothing breaks after deployment.</p>
<h4 id="heading-how-does-ci-testing-work"><strong>How Does CI Testing Work?</strong></h4>
<ol>
<li><p><strong>Triggers on change</strong>: Each time code is committed, the CI tool (like <a target="_blank" href="https://github.com/features/actions">GitHub Actions</a>, <a target="_blank" href="https://www.jenkins.io/">Jenkins</a>) runs automated tests.</p>
</li>
<li><p><strong>Feedback</strong>: It gives you instant feedback if something fails.</p>
</li>
<li><p><strong>Prevents broken code</strong>: Commits only clean, and the working code gets merged into the main branch.</p>
</li>
</ol>
<h3 id="heading-4-cicd-pipelines"><strong>4️⃣ CI/CD pipelines</strong></h3>
<p>We also use CI/CD pipelines as a continuous process that includes code building, testing, and deployment, while CI testing is a part of that process that focuses on automating the testing of code changes. </p>
<p><strong>Differece between CI/CD pipelines vs CI testing:</strong></p>
<ul>
<li><p><strong>CI/CD pipelines:</strong> A CI/CD pipeline combines code building, testing, and deployment into a single process. This process make sure that all changes to the main branch code are releasable to production. CI/CD pipelines can reduce deployment time, decrease costs, and improve team collaboration. </p>
</li>
<li><p><strong>CI testing:</strong> CI testing is the process of automatically testing code changes that are integrated into a central repository. CI testing focuses on making sure the codebase is stable and that integration issues are resolved. CI testing help developer build software that is stable, bug-free, and meets functional requirements</p>
</li>
</ul>
<p>🚧 This is what CI testing CI/CD pipelines concepts are really about. Not as complex as it seems. So let me elaborate more on CI testing with GitHub Actions, as we usually run tests through automated tools nowadays.</p>
<h3 id="heading-continuous-integration-ci-testing-with-github-actions"><strong>⚡ Continuous Integration (CI) Testing with GitHub Actions</strong></h3>
<p>As I said earlier, CI tools run automated tests every time you push code or open a pull request. This guarantees that only working, bug-free code gets merged into the main branch.</p>
<h4 id="heading-how-to-set-up-ci-testing-with-github-actions">How to Set Up CI Testing with GitHub Actions</h4>
<p><strong>Step 1: Create Your Repository</strong></p>
<p>Set up a GitHub repository for your project. Then, push your code to GitHub using the following commands:</p>
<pre><code class="lang-bash">git init
git add .
git commit -m <span class="hljs-string">"Initial commit for CI Testing"</span>
git branch -M main
git remote add origin https://github.com/codewithshahan/codewithshahan.git
git push -u origin main
</code></pre>
<p>Or you can create a new repo from your GitHub account without using the command. Just login to your GItHub account and visit dashboard. Here you will find a “New” button to create a brand new repo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737618697327/dcef8be8-0d08-45d7-8000-34c4c65df425.png" alt="image of creating a new repo on github by Shahan" class="image--center mx-auto" width="1371" height="553" loading="lazy"></p>
<p><strong>Step 2: Add a GitHub Actions Workflow</strong></p>
<p>Navigate to your repository’s <strong>Actions</strong> tab. To do this, first, you have to visit your repo on Github (you will find the link after creating your repo). In this case, I created a new repo called “codewithshahan”. Here, look for the <strong>Actions</strong> tab on the right side of the navigation bar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737618879398/7c5aa37a-72be-4701-a8f8-9ea9e05c0d5d.png" alt="Image of github actions navigation tab by shahan" class="image--center mx-auto" width="1885" height="724" loading="lazy"></p>
<p>After navigating the Actions tab, scroll down a little and you will find the <strong>continuous integration</strong> section:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737619002674/60003e57-f2b2-48f1-bef8-9bde39149faf.png" alt="Image of CI (Continuous Integration) testing on Github Actions Page by Shahan" class="image--center mx-auto" width="1496" height="508" loading="lazy"></p>
<p>Choose a setup workflow yourself. I will use Node.js for this project.</p>
<p>After clicking the configure button, a <code>node.js.yml</code> file will be created automatically, and you can adjust the code depending on your goals.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737619475568/74da6d46-c105-42c8-8662-fc72e9410bda.png" alt="Image of GitHub workflow snippet for automated testing by Shahan" class="image--center mx-auto" width="1879" height="854" loading="lazy"></p>
<p>I won’t go into detail about how should modify your <code>.yml</code> file. It depends on your project goals and personal preference. Also, it is a whole different broader topic and as this article has already become quite long, so I’ll explain it in a future article. For now, just stick with this foundational knowledge.</p>
<p>This CI Testing workflow is best for modern application development. Your app remains stable while incorporating key features including testing (e,g. Dark Mode), Building and deploying applications directly within your GitHub repository. This way, you can push your code confidently, knowing your code is always clean and ready for production.</p>
<h2 id="heading-the-role-of-documentation-in-agile-software-development">The Role of Documentation in Agile Software Development 🚣</h2>
<p>If you want your code to be top-notch, you need to understand how to write good documentation. If you think documentation is just about scribbling down how the code works, you’re wrong. It's about explaining <strong>why</strong> it works, not just how it works. That’s where most people miss the mark.</p>
<h3 id="heading-1-create-useful-docs-explain-why-not-just-how">1. 🚡 Create <strong>Useful Docs (Explain Why, Not Just How)</strong></h3>
<p>When you write documentation, you're not just throwing down some instructions for how to use the code. You're telling the next person (or even yourself in the future) why this piece of code exists in the first place. That’s the difference between good and bad documentation.</p>
<p>Bad docs leave people scratching their heads. They’re too vague, too simple, and they don’t answer the big questions. If your documentation is unclear, that likely means your thinking is unclear. You’re basically saying, <em>"I don’t care if you understand this, it works, just use it."</em> That’s not helpful.</p>
<p>Great documentation answers the tough questions:</p>
<ul>
<li><p>✅ Why did you choose this approach over another?</p>
</li>
<li><p>✅ Why does this function exist? What problem does it solve?</p>
</li>
<li><p>✅ Why did you write this code the way you did?</p>
</li>
</ul>
<p>If your docs are just regurgitating how to use the code, you’re not being as helpful as you can be. Start thinking deeper and explaining the reasoning behind everything.</p>
<h3 id="heading-2-keep-the-docs-updated-outdated-docs-are-worse-than-no-docs">2. ⏳ <strong>Keep the Docs Updated (Outdated Docs Are Worse Than No Docs)</strong></h3>
<p>Outdated documentation is the worst. In fact, it can be worse than having no docs at all. When you leave documentation that’s out of sync with the code, you’re doing your future self — or whoever has to deal with it next — a huge disservice.</p>
<p>Every time your code changes, your documentation needs to change too. It has to reflect the current state of things. Don’t mislead future developers (or yourself) by leaving outdated info that will only confuse them and waste their time. If something is no longer relevant, delete it. Outdated documentation is the equivalent of a cluttered mind — it holds you back.</p>
<p>Make it a habit to check and update your documentation regularly. The minute a line of code changes, so should your documentation. Period.</p>
<h3 id="heading-3-integrate-comments-good-comments-in-code-are-part-of-documentation">3. 🚆 <strong>Integrate Comments (Good Comments in Code Are Part of Documentation)</strong></h3>
<p>Here’s the deal — comments in your code should <strong>integrate</strong> with your documentation. Good comments aren’t just a crutch for developers who can’t explain their code elsewhere. They should improve your docs, not replace them.</p>
<p>Comments are supplements to your documentation. You write clean, understandable code that needs minimal explanation, but when something isn’t crystal clear, throw in a comment. Remember the rule for comments in your code: explain the <strong>why</strong>, not the <strong>how</strong>. It’s the same here. Don’t repeat yourself. Let your code do the talking. Comments should complement the bigger picture of your documentation, not act as a band-aid for sloppy code.</p>
<p>🪧 Great code should be self-explanatory. Fix the code, then add comments for clarification if necessary. Keep comments clean, short, and to the point.</p>
<p>If you want to write clean, efficient, and maintainable code, documentation is key. Stop thinking of docs as an afterthought or something you do to fill space. It’s an extension of your code — your way of communicating clearly and effectively. It’s your roadmap for future developers, and it’s a reflection of your thought process.</p>
<h2 id="heading-conclusion">Conclusion 🏁</h2>
<p>Clean code isn't a nice-to-have –– it's a must-have for those who aim to lead. It's about control, efficiency, and improvement over time in the long run. And ultimately, it’ll help you succeed in the game of agile software development.</p>
<p>🪧 If you want to truly master your craftsmanship, write clean code, and let the efficiency speak for itself.</p>
<h2 id="heading-frequently-asked-questions-about-clean-code">Frequently Asked Questions About Clean Code 🧯</h2>
<ol>
<li><p><strong>What is clean code?</strong> It's code that doesn't make you want to throw your laptop out the window.</p>
</li>
<li><p><strong>Why is clean code important in Agile?</strong> Because Agile is about speed and change, and you can't be quick with a mess.</p>
</li>
<li><p><strong>What are code smells?</strong> Signs that you're about to lose control of your codebase.</p>
</li>
<li><p><strong>How can I improve commenting?</strong> Only comment on what's necessary, and make sure each comment adds value, not noise.</p>
</li>
</ol>
<p>Thank you for being with me. You can visit my <a target="_blank" href="https://x.com/shahancd">Twitter account</a> or <a target="_blank" href="https://www.codewithshahan.com">my website</a> to read more posts about clean code and Agile application development. Until next time… keep improving your codebase.</p>
<p>If you’re serious about mastering clean code and taking your programming career to the next level, then my book is for you: <a target="_blank" href="https://codewithshahan.gumroad.com/l/cleancode-zero-to-one"><strong>Clean Code Zero to One</strong></a>. This book is your full guide from zero to one in clean code, from messy code to masterpiece. I am offering a 50% discount using the code "earlybird" — only for the first 50 copies. Plus, there’s a 30-day money-back guarantee — no risk, all reward.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Code That's Easy to Read – Tips for Developers ]]>
                </title>
                <description>
                    <![CDATA[ Programs are meant to be read by humans and only incidentally for computers to execute. - Donald Knuth Have you ever heard that programmers spend more time reading code than writing it? Well, I’ve found that this is often true: as a developer, you’l... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-code-thats-easy-to-read/</link>
                <guid isPermaLink="false">675098030c45d94ee71d4e04</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Orim Dominic Adah ]]>
                </dc:creator>
                <pubDate>Wed, 04 Dec 2024 17:57:23 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733334801650/9c73c253-246a-4678-8d65-6679ff7f35f2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <blockquote>
<p>Programs are meant to be read by humans and only incidentally for computers to execute. - Donald Knuth</p>
</blockquote>
<p>Have you ever heard that programmers spend more time reading code than writing it? Well, I’ve found that this is often true: as a developer, you’ll often spend more time reading and thinking about code than actually writing code.</p>
<p>This means that, however optimally you intend to make your code run, it’s also important that it’s delightful and easy to read.</p>
<p>In this article, we’ll look at an example function: <code>createOrUpdateUserOnLogin</code>. It lives in a JavaScript codebase far away and it’s begging to be made delightful to read. We will look at <code>createOrUpdateUserOnLogin</code>, highlight what makes it hard to read and why, and eventually refactor it to make it easier to read and understand.</p>
<p>The function is written in JavaScript and uses <a target="_blank" href="https://jsdoc.app/">JSDoc</a> to document its parameters. Knowledge of JavaScript is not necessarily important because the logic in the function will be explained in detail. JSDoc is only used to document what the function’s parameters represent.</p>
<h2 id="heading-the-problematic-function">The Problematic Function</h2>
<p>This function is not made-up. It is a real function in the codebase of an application with more than a thousand users. Here it is:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{Object}</span> <span class="hljs-variable">dto</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>dto.email
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>dto.firstName
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>dto.lastName
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>[dto.photoUrl]
 * <span class="hljs-doctag">@param <span class="hljs-type">{'apple' | 'google'}</span> </span>[dto.loginProvider]
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> </span>[dto.appleId]
 * <span class="hljs-doctag">@returns <span class="hljs-type">{string}</span> <span class="hljs-variable">token</span></span> - access token
 */</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createOrUpdateUserOnLogin</span>(<span class="hljs-params">dto</span>) </span>{
  <span class="hljs-keyword">let</span> user;

  <span class="hljs-keyword">if</span> (dto.loginProvider == <span class="hljs-string">"apple"</span>) {
    user = <span class="hljs-keyword">await</span> findOneByAppleId(dto.appleId);
    <span class="hljs-keyword">if</span> (user?.isDisabled) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Unable to login"</span>);
    }

    <span class="hljs-keyword">if</span> (user &amp;&amp; !user.verified) {
      user = <span class="hljs-keyword">await</span> setUserAsVerified(user.email);
    }

    <span class="hljs-keyword">if</span> (!user) {
      user = <span class="hljs-keyword">await</span> findOneByEmail(dto.email);

      <span class="hljs-keyword">if</span> (user &amp;&amp; dto.appleId) {
        user = <span class="hljs-keyword">await</span> updateUserAppleId(user, dto.appleId);
      }

      <span class="hljs-keyword">if</span> (user &amp;&amp; !user.verified) {
        user = <span class="hljs-keyword">await</span> setUserAsVerified(user.email);
      }
    }
  } <span class="hljs-keyword">else</span> {
    user = <span class="hljs-keyword">await</span> findOneByEmail(dto.email);
    <span class="hljs-keyword">if</span> (user?.isDisabled) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Unable to login"</span>);
    }

    <span class="hljs-keyword">if</span> (user &amp;&amp; !user.photoUrl &amp;&amp; dto.photoUrl) {
      user.photoUrl = dto.photoUrl;
      user = <span class="hljs-keyword">await</span> updateUserDetails(user._id, user);
    }

    <span class="hljs-keyword">if</span> (user &amp;&amp; !user.verified) {
      user = <span class="hljs-keyword">await</span> setUserAsVerified(user.email);
    }
  }

  <span class="hljs-keyword">if</span> (!user) {
    user = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.create(loginProviderDto);
  }

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.createToken(user);
}
</code></pre>
<p>Perhaps you can tell by reading through and studying the code that it is quite hard to follow. If you leave your computer for a break right after reading this function, there is a good chance you won’t remember what exactly it does when you get back.</p>
<p>But this isn’t, and shouldn’t be, the case when you read a good story, regardless of its length. You can follow it easily and remember the basic details after hearing it.</p>
<p>The function is executed when a user attempts to sign in or sign up. Users can be authenticated using their Google account or their Apple account and the function has to return an access token on a successful attempt.</p>
<p>Some users have disabled their account. Those users are not allowed to authenticate successfully. The logic of the function also includes operations for updating the data of already-registered users based on some conditions.</p>
<p>The function does one of two things:</p>
<ol>
<li><p>It creates an authentication token for an existing account and returns it after updating the account details or,</p>
</li>
<li><p>It creates an account if none exists and returns an authentication token.</p>
</li>
</ol>
<p>This violates the Single Responsibility Principle – but fixing that is a challenge for another article.</p>
<p>The goal here is to refactor this function so that it reads so well that even a non-programmer can read it and understand what it does. Even better, we also want them to be able to remember it after they’ve been away from it for a while.</p>
<p>The function is well-tested, so there are no worries about breaking any functionality while refactoring. Tests will report any breaking changes.</p>
<h3 id="heading-what-makes-this-code-hard-to-read">What Makes This Code Hard to Read?</h3>
<p>A number of factors make this code harder to read. Here are the main ones:</p>
<ol>
<li><p><strong>Deep nesting</strong> (<code>if</code> statements within <code>if</code> statements) makes it hard to keep track of the changes that occur through the execution of the code. In the case of <code>createOrUpdateUserOnLogin</code>, it is nested conditionals. Other cases can include logic like an <code>if</code> statement inside a <code>while</code> loop which is nested inside another <code>if</code> statement.</p>
<p> Deep nesting increases the complexity of reading and understanding code. Its flow isn’t pleasant to the eyes and it makes writing tests more complicated because you have to cater for the operations inside the nested code blocks.</p>
</li>
<li><p><strong>Complex conditionals</strong> like <code>user &amp;&amp; !user.photoUrl &amp;&amp; dto.photoUrl</code> hold a lot of logic which has to be kept in your short-term memory and remembered as you read on.</p>
</li>
<li><p><strong>Haphazard flow</strong> which makes it hard for you to tell at a glance what the function is doing. The function seems to be doing a lot, but it really is not. Two operations are repeated: preventing disabled users from logging in (twice) and updating users’ verification status (three times). Finding a user by email is also repeated twice.</p>
</li>
</ol>
<h2 id="heading-how-to-refactor-the-code-for-easier-more-delightful-reading">How to Refactor the Code for Easier, More Delightful Reading</h2>
<p>After examining the function for issues that make it difficult to read, here are a couple of changes you’ll want to implement:</p>
<p><strong>Handle failure cases first</strong>: Consider failure cases first and get them out of the story so that the function can focus on the success cases for a smooth narration of the logic of the code.</p>
<p>This involves the use of <code>return</code> statements or throwing errors early in the function for operations that prevent the goal of the function from being achieved.</p>
<p><strong>Rearrange the flow</strong>: If it’s possible that some operations can occur before others and it will make the flow of the code memorable and enjoyable to read, while still achieving the purpose of the function, then you should rearrange it accordingly.</p>
<p><strong>Use everyday grammar</strong>: This involves updating identifiers and compressing complex conditionals into memorable identifier names. Everyday grammar is easy to read because it is familiar and relatable.</p>
<p><strong>Avoid nested code blocks</strong>: When debugging code mentally or trying to understand it, changes in the value of identifiers in nested code blocks are hard to keep track of. This is because with each nested conditional, there is at least a 2x increase in the number of paths that the logic execution can take to update the value of one identifier – and that gets worse if there is more than one identifier that is updated.</p>
<p>This means that your mind has to keep track of those paths which can escalate quickly into a mental memory overload, potentially resulting in mental grief and bugs when updating the code.</p>
<p>The visual effect of nested code is also not pleasant to the eyes and it makes writing tests more complex than it should be.</p>
<p>After refactoring the code using the guidelines above, we have the following snippet (I’ve numbered different parts of the code for reference in the explanations below):</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUserOnLogin</span>(<span class="hljs-params">dto</span>) </span>{
  <span class="hljs-keyword">let</span> user = <span class="hljs-keyword">await</span> findUserByEmail(dto.email); <span class="hljs-comment">// 1</span>
  <span class="hljs-keyword">if</span> (!user) {
    user = <span class="hljs-keyword">await</span> createUser(dto);
  }

  <span class="hljs-keyword">if</span> (user.isDisabled) { <span class="hljs-comment">// 2a</span>
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Unable to login"</span>); <span class="hljs-comment">// 2b</span>
  }

  <span class="hljs-keyword">const</span> userIsNotVerified = <span class="hljs-built_in">Boolean</span>(user.isVerified) == <span class="hljs-literal">false</span> <span class="hljs-comment">// 3a</span>
  <span class="hljs-keyword">if</span> (userIsNotVerified) { <span class="hljs-comment">// 3b</span>
    <span class="hljs-keyword">await</span> setUserAsVerified(user.email);
  }

  <span class="hljs-keyword">const</span> shouldUpdateAppleId = dto.loginProvider == <span class="hljs-string">"apple"</span> &amp;&amp; dto.appleId <span class="hljs-comment">// 4a</span>
  <span class="hljs-keyword">if</span> (shouldUpdateAppleId) { <span class="hljs-comment">// 4b</span>
    <span class="hljs-keyword">await</span> setUserAppleId(user.email, dto.appleId);
  }

  <span class="hljs-keyword">const</span> shouldUpdatePhotoUrl = !user.photoUrl &amp;&amp; dto.photoUrl <span class="hljs-comment">// 5a</span>
  <span class="hljs-keyword">if</span> (shouldUpdatePhotoUrl) { <span class="hljs-comment">// 5b</span>
    <span class="hljs-keyword">await</span> updateUserDetails(user._id, { <span class="hljs-attr">photoUrl</span>: dto.photoUrl });
  }

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.createToken(user);
}
</code></pre>
<p>Alright, now let’s see what exactly we’ve done here to make the code more enjoyable to read.</p>
<h3 id="heading-1-rearranging-the-flow">1. Rearranging the Flow</h3>
<p>Judging by the JSDoc comment above the function, <code>email</code> is a required argument field. Existing accounts have an email address irrespective of their login provider. We can fetch an account by <code>email</code> first and decide to create a new one if none exists (code section 1). By doing this, failure cases are handled early.</p>
<p>Choosing to throw an error if the account is disabled at the beginning (section 2b) is also an attempt to handle failure cases early. This does not affect new accounts because new accounts are not disabled by default.</p>
<p>Handling failure cases early helps us understand the code easier because we’re free to consider only what is going to happen without keeping track of error cases from before (like remembering if the <code>user</code> object has a value or not (section 5)) as we read on.</p>
<p>The refactored code has also eliminated nested conditionals and still works as expected.</p>
<h3 id="heading-2-using-everyday-grammar">2. Using Everyday Grammar</h3>
<p>In trying to make the code read like everyday grammar, we’ve used clear and relatable variable names (see sections 2a, 3, 4, 5). Written this way, even non-programmers like product managers can read the code and understand what is happening.</p>
<p>Everyday grammar reads like pseudocode - “If user is not verified then set user to verified” and “If should update apple id then update appleId”.</p>
<p>Using everyday grammar is key to making code read like a story.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Code that is delightful to read promotes maintainability and thus, longevity of software. Contributors can read it, understand it, and eventually update it with ease. Like reading a well-written story, reading code can be an enjoyable activity.</p>
<p>Image credit: <a target="_blank" href="https://storyset.com/work">Work illustrations by Storyset</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Clean Code – Tips for Developers with Examples ]]>
                </title>
                <description>
                    <![CDATA[ Imagine a messy room with clothes, books, and other items scattered everywhere. Finding something in that room would be tough, right? Now, think about writing messy code – it’s just as confusing, if not more! On the other hand, clean code is like an ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-clean-code-tips-for-developers/</link>
                <guid isPermaLink="false">672a51c02bb94277a075a484</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Blogs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Programming with Shahan ]]>
                </dc:creator>
                <pubDate>Tue, 05 Nov 2024 17:11:28 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730737606075/5cb4369b-9f2e-4f97-9765-ac00a62800c6.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Imagine a messy room with clothes, books, and other items scattered everywhere. Finding something in that room would be tough, right?</p>
<p>Now, think about writing messy code – it’s just as confusing, if not more!</p>
<p>On the other hand, clean code is like an organized room: you can easily find what you need, understand what’s happening, and get things done faster.</p>
<p>Let’s have a look at this graph. It shows two different ways of writing code and how they affect the time it takes to add more lines:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730728342241/3fa8f5a1-0af4-4ffd-aa3a-bb70001b026d.png" alt="3fa8f5a1-0af4-4ffd-aa3a-bb70001b026d" class="image--center mx-auto" width="604" height="340" loading="lazy"></p>
<ol>
<li><p>⚠️ <strong>Quick &amp; Dirty Code</strong> (Red line): This is when you write code quickly without planning or organizing it well. At first, it may seem faster, but as more lines are added, it becomes harder to understand and fix. So, over time, it takes longer and longer to add each new line.</p>
</li>
<li><p><strong>⚡ Thoughtful &amp; Clean Code</strong> (Blue line): This is when you write code carefully, making it easy to understand and change. At first, it might take a bit longer, but over time, it remains easy to work with. This way, adding new lines doesn't become more difficult.</p>
</li>
</ol>
<p>In simple terms, writing clean code might seem slower at the beginning, but in the long run, it saves a lot of time and makes work easier. It also leads to more reliable software and better products.</p>
<p>Writing clean code is a habit that professional developers cultivate, showing dedication to quality and a strong work ethic. And in this article, I’ll walk you through some best practices for keeping your code clean.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-1-use-meaningful-names">Use Meaningful Names</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-follow-the-single-responsibility-principle-srp">Follow the Single Responsibility Principle (SRP)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-avoid-unnecessary-comments">Avoid Unnecessary Comments</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-make-your-code-readable">Make Your Code Readable</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-write-unit-tests">Write Unit Tests</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-be-careful-with-dependencies">Be Careful with Dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-7-organize-your-project">Organize Your Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-8-use-consistent-formatting">Use Consistent Formatting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-9-avoid-hardcoding-values">Avoid Hardcoding Values</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-10-limit-function-length">Limit Function Length</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-10-essential-tips-for-writing-clean-code">10 Essential Tips for Writing Clean Code</h2>
<p>To help you get started on your clean code journey, here are 10 practical tips to keep your code readable, organized, and efficient.</p>
<h3 id="heading-1-use-meaningful-names">1. Use Meaningful Names</h3>
<p>When naming variables, functions, and classes, pick names that clearly describe their purpose.</p>
<p>Instead of calling a variable <code>b</code>, try <code>numberOfUsers</code>. This way, anyone reading your code can easily understand its purpose without needing additional comments. A meaningful name eliminates guesswork and avoids confusion.</p>
<p><strong>Example</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Good</span>
<span class="hljs-keyword">let</span> numberOfUsers = <span class="hljs-number">5</span>; <span class="hljs-comment">// Clear and easy to understand</span>

<span class="hljs-comment">// Bad</span>
<span class="hljs-keyword">let</span> b = <span class="hljs-number">5</span>; <span class="hljs-comment">// Vague and unclear</span>
</code></pre>
<p><strong>💡 Naming Tips</strong></p>
<ul>
<li><p><strong>Variables</strong>: Use nouns that describe the data, like <code>userAge</code> or <code>totalAmount</code>.</p>
</li>
<li><p><strong>Functions</strong>: Use action words, like <code>calculateTotal()</code> or <code>fetchUserData()</code>.</p>
</li>
<li><p><strong>Classes</strong>: Use singular nouns, like <code>User</code> or <code>Order</code>, to represent what they are.</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Variable: Describes the data it holds</span>
<span class="hljs-keyword">let</span> userAge = <span class="hljs-number">25</span>;

<span class="hljs-comment">// Function: Uses an action word to describe what it does</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTotal</span>(<span class="hljs-params">price, quantity</span>) </span>{
    <span class="hljs-keyword">return</span> price * quantity;
}

<span class="hljs-comment">// Class: Singular noun representing a type of object</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">constructor</span>(name, age) {
        <span class="hljs-built_in">this</span>.name = name;
        <span class="hljs-built_in">this</span>.age = age;
    }
}
</code></pre>
<h3 id="heading-2-follow-the-single-responsibility-principle-srp">2. Follow the Single Responsibility Principle (SRP)</h3>
<p>The <strong>Single Responsibility Principle</strong> means that each function or method should have <strong>one specific job.</strong></p>
<p>This keeps your functions short and focused which makes them easier to read, test, and maintain.</p>
<p>Imagine a toolbox where each tool has a unique purpose—clean code functions should work the same way.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730728643183/77666f78-7ec9-4a5c-af4f-253e6de4acac.jpeg" alt="77666f78-7ec9-4a5c-af4f-253e6de4acac" class="image--center mx-auto" width="474" height="355" loading="lazy"></p>
<p>For instance, if you have a function called <code>calculateTotal</code>, it should only handle calculating the total. If you add extra tasks, it can lead to confusing code that’s hard to maintain.</p>
<p>Here's an example to show why it's important to keep functions focused:</p>
<p>Let’s say you want to calculate a total and return an object with extra information, like who calculated it and when. Instead of adding these directly into <code>calculateTotal</code>, we can use a second function.</p>
<ol>
<li><p><strong>Good Example (Separate Tasks)</strong></p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// This function only calculates the total</span>
 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTotal</span>(<span class="hljs-params">a, b</span>) </span>{
     <span class="hljs-keyword">return</span> a + b;
 }

 <span class="hljs-comment">// This function creates an object with extra details</span>
 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createCalculationRecord</span>(<span class="hljs-params">a, b, user</span>) </span>{
     <span class="hljs-keyword">let</span> sum = calculateTotal(a, b); <span class="hljs-comment">// Calls the calculate function</span>
     <span class="hljs-keyword">return</span> {
         <span class="hljs-attr">user</span>: user,
         <span class="hljs-attr">total</span>: sum,
         <span class="hljs-attr">timestamp</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
     };
 }

 <span class="hljs-keyword">let</span> record = createCalculationRecord(<span class="hljs-number">5</span>, <span class="hljs-number">10</span>, <span class="hljs-string">"Shahan"</span>);
 <span class="hljs-built_in">console</span>.log(record);
</code></pre>
<p> <strong>👍 Why this is good</strong>: Each function has a clear, focused task. <code>calculateTotal</code> only does the math, while <code>createCalculationRecord</code> adds the extra details. If you want to change how the total is calculated, you only update <code>calculateTotal</code>, and if you want to change the record format, you only update <code>createCalculationRecord</code>.</p>
</li>
<li><p><strong>Bad Example (Mixed Tasks in One Function)</strong></p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// This function calculates the total and creates an object in one step</span>
 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTotalAndReturnRecord</span>(<span class="hljs-params">a, b, user</span>) </span>{
     <span class="hljs-keyword">let</span> sum = a + b;
     <span class="hljs-keyword">return</span> {
         <span class="hljs-attr">user</span>: user,
         <span class="hljs-attr">total</span>: sum,
         <span class="hljs-attr">timestamp</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
     };
 }

 <span class="hljs-keyword">let</span> record = calculateTotalAndReturnRecord(<span class="hljs-number">5</span>, <span class="hljs-number">10</span>, <span class="hljs-string">"Shahan"</span>);
 <span class="hljs-built_in">console</span>.log(record);
</code></pre>
<p> <strong>👎 Why this is bad</strong>: The function name <code>calculateTotalAndReturnRecord</code> shows that it’s trying to do multiple things. If you want to use just the calculation, you can’t reuse this function without the record part. It’s also harder to update and test each task separately.</p>
</li>
</ol>
<h3 id="heading-3-avoid-unnecessary-comments">3. Avoid Unnecessary Comments</h3>
<p>Good code should be self-explanatory without needing excessive comments. Focus on writing code that’s clear and understandable on its own.</p>
<p>Comments are helpful when explaining complex logic or a unique approach, but too many comments can clutter your code and make it hard to follow.</p>
<p><strong>💬 When to Use Comments</strong>:</p>
<ul>
<li><p>To clarify why something is done in a particular way.</p>
</li>
<li><p>When working with complex algorithms or calculations.</p>
</li>
<li><p>To add notes about potential limitations.</p>
</li>
</ul>
<p><strong>Example</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Clear name, no comment needed</span>
<span class="hljs-keyword">let</span> userAge = <span class="hljs-number">25</span>;

<span class="hljs-comment">// Unclear name, comment needed</span>
<span class="hljs-keyword">let</span> a; <span class="hljs-comment">// age of the user</span>
</code></pre>
<h3 id="heading-4-make-your-code-readable">4. Make Your Code Readable</h3>
<p>Readable code uses <strong>indentation</strong>, <strong>line breaks</strong>, and <strong>spaces</strong> to keep everything neat and organized.</p>
<p>Think of it like writing a story: paragraphs make reading easier by breaking up large chunks of text. In coding, line breaks serve the same purpose.</p>
<p><strong>Example</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Good Code</span>
<span class="hljs-keyword">if</span> (isLoggedIn) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Welcome!"</span>);
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Please log in."</span>);
}

<span class="hljs-comment">// Bad Code</span>
<span class="hljs-keyword">if</span>(isLoggedIn){<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Welcome!"</span>);}<span class="hljs-keyword">else</span>{<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Please log in."</span>);}
</code></pre>
<p>In VS Code, <strong>Prettier</strong> and <strong>Black</strong> are popular formatters that automatically apply clean code styling for multiple languages.</p>
<p><strong>PyCharm</strong> and <strong>IntelliJ</strong> have powerful built-in formatters with customizable rules, supporting PEP 8 for Python and other standard guides. These tools ensure consistent, readable code across projects with minimal manual effort.</p>
<h3 id="heading-5-write-unit-tests">5. Write Unit Tests</h3>
<p>Unit tests help make sure each part of your code works as expected.</p>
<p>By testing small, individual parts (like functions), you can catch bugs early and prevent them from spreading to other parts of the code.</p>
<p>Concretely, unit tests are actually mini quality checks for each part of your code to ensure they’re working as intended.</p>
<p><strong>🍎 Real-world Example:</strong></p>
<p>Let’s look at how to test a complex JavaScript object with multiple methods, using a <code>Calculator</code> class as an example.</p>
<p>This approach will help you see why it’s important to keep each method focused on one task and ensure each one works correctly through unit testing.</p>
<p>Here is the <code>Calculator</code> class that includes methods for basic arithmetic operations: addition, subtraction, multiplication, and division.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> </span>{
    <span class="hljs-keyword">constructor</span>() {
        <span class="hljs-built_in">this</span>.result = <span class="hljs-number">0</span>;
    }

    add(a, b) {
        <span class="hljs-keyword">return</span> a + b;
    }

    subtract(a, b) {
        <span class="hljs-keyword">return</span> a - b;
    }

    multiply(a, b) {
        <span class="hljs-keyword">return</span> a * b;
    }

    divide(a, b) {
        <span class="hljs-keyword">if</span> (b === <span class="hljs-number">0</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Cannot divide by zero"</span>);
        <span class="hljs-keyword">return</span> a / b;
    }
}
</code></pre>
<p>As you can see, each method performs one specific operation. The <code>divide</code> method has additional logic to handle division by zero, which would otherwise cause an error.</p>
<p>Now, we’ll write unit tests to confirm that each method behaves as expected. 🔬</p>
<p><strong>🧪 Writing Unit Tests for Each Method</strong></p>
<p>To test our <code>Calculator</code> class, we can write unit tests that cover normal cases as well as edge cases. Here’s how we would set up tests for each method:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Initialize the Calculator instance</span>
<span class="hljs-keyword">const</span> calculator = <span class="hljs-keyword">new</span> Calculator();

<span class="hljs-comment">// Test add method</span>
<span class="hljs-built_in">console</span>.assert(calculator.add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">5</span>, <span class="hljs-string">'Test failed: 2 + 3 should be 5'</span>);
<span class="hljs-built_in">console</span>.assert(calculator.add(<span class="hljs-number">-1</span>, <span class="hljs-number">1</span>) === <span class="hljs-number">0</span>, <span class="hljs-string">'Test failed: -1 + 1 should be 0'</span>);

<span class="hljs-comment">// Test subtract method</span>
<span class="hljs-built_in">console</span>.assert(calculator.subtract(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">2</span>, <span class="hljs-string">'Test failed: 5 - 3 should be 2'</span>);
<span class="hljs-built_in">console</span>.assert(calculator.subtract(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>) === <span class="hljs-number">0</span>, <span class="hljs-string">'Test failed: 0 - 0 should be 0'</span>);

<span class="hljs-comment">// Test multiply method</span>
<span class="hljs-built_in">console</span>.assert(calculator.multiply(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">6</span>, <span class="hljs-string">'Test failed: 2 * 3 should be 6'</span>);
<span class="hljs-built_in">console</span>.assert(calculator.multiply(<span class="hljs-number">-1</span>, <span class="hljs-number">2</span>) === <span class="hljs-number">-2</span>, <span class="hljs-string">'Test failed: -1 * 2 should be -2'</span>);

<span class="hljs-comment">// Test divide method</span>
<span class="hljs-built_in">console</span>.assert(calculator.divide(<span class="hljs-number">6</span>, <span class="hljs-number">3</span>) === <span class="hljs-number">2</span>, <span class="hljs-string">'Test failed: 6 / 3 should be 2'</span>);
<span class="hljs-keyword">try</span> {
    calculator.divide(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);
    <span class="hljs-built_in">console</span>.assert(<span class="hljs-literal">false</span>, <span class="hljs-string">'Test failed: Division by zero should throw an error'</span>);
} <span class="hljs-keyword">catch</span> (e) {
    <span class="hljs-built_in">console</span>.assert(e.message === <span class="hljs-string">"Cannot divide by zero"</span>, <span class="hljs-string">'Test failed: Incorrect error message for division by zero'</span>);
}
</code></pre>
<p><strong>🫧 Explanation of the tests:</strong></p>
<ol>
<li><p><strong>Addition</strong> (<code>add</code> method): We test that <code>add(2, 3)</code> returns <code>5</code>, and <code>add(-1, 1)</code> returns <code>0</code>. If these tests pass, we know that the addition logic is working correctly.</p>
</li>
<li><p><strong>Subtraction</strong> (<code>subtract</code> method): We verify that <code>subtract(5, 3)</code> returns <code>2</code>, and <code>subtract(0, 0)</code> returns <code>0</code>. These checks confirm that subtraction is accurate.</p>
</li>
<li><p><strong>Multiplication</strong> (<code>multiply</code> method): We test the multiplication function with both positive and negative values, ensuring that <code>multiply(2, 3)</code> returns <code>6</code>, and <code>multiply(-1, 2)</code> returns <code>-2</code>.</p>
</li>
<li><p><strong>Division</strong> (<code>divide</code> method): We verify that dividing <code>6</code> by <code>3</code> returns <code>2</code>. For division by zero, we use a <code>try...catch</code> block to confirm that an error is thrown with the correct message. This test make sure the method handles errors properly.</p>
</li>
</ol>
<p>You can see that if any method fails, the test will produce a clear error message, allowing us to quickly identify and fix the issue. Testing methods individually helps us catch bugs early and maintain reliable, clean code as the project grows.</p>
<h3 id="heading-6-be-careful-with-dependencies">6. Be Careful with Dependencies</h3>
<p>Dependencies are pieces of software that your code relies on. 🔌</p>
<p>Imagine you’re building a web app that sends emails. Instead of writing the email-sending code yourself, you use an external library like <a target="_blank" href="https://nodemailer.com/"><strong>Nodemailer</strong></a>. Here, Nodemailer is a <strong>dependency</strong>—your app relies on it to handle the email-sending functionality.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> nodemailer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'nodemailer'</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendEmail</span>(<span class="hljs-params">to, subject, message</span>) </span>{
    <span class="hljs-keyword">const</span> transporter = nodemailer.createTransport({
        <span class="hljs-attr">service</span>: <span class="hljs-string">'gmail'</span>,
        <span class="hljs-attr">auth</span>: {
            <span class="hljs-attr">user</span>: <span class="hljs-string">'your-email@gmail.com'</span>,
            <span class="hljs-attr">pass</span>: <span class="hljs-string">'your-email-password'</span>
        }
    });

    <span class="hljs-keyword">const</span> mailOptions = {
        <span class="hljs-attr">from</span>: <span class="hljs-string">'your-email@gmail.com'</span>,
        <span class="hljs-attr">to</span>: to,
        <span class="hljs-attr">subject</span>: subject,
        <span class="hljs-attr">text</span>: message
    };

    <span class="hljs-keyword">return</span> transporter.sendMail(mailOptions);
}
</code></pre>
<p>In this code, <code>nodemailer</code> is imported and used to create a transporter for sending emails. Without it, you’d need to build all the email functionality from scratch, which would be complex and time-consuming. By using Nodemailer as a dependency, your app can send emails easily.</p>
<p>Even though dependencies are useful, you should try to avoid over-dependence on external software or libraries. Use dependencies only when they simplify your work or add important functionality.</p>
<p>Managing dependencies effectively is key to writing clean code. Here are some tips:</p>
<ul>
<li><p><strong>Limit Dependencies</strong>: Only include libraries or modules that are essential for your project.</p>
</li>
<li><p><strong>Keep Versions Updated</strong>: Use updated versions of libraries to avoid security risks.</p>
</li>
<li><p><strong>Separate Logic</strong>: Write core functions yourself whenever possible. This way, if you ever need to remove a dependency, it won’t break your code.</p>
</li>
</ul>
<p>Let me give you an example with our previous Nodemailer code to implement the concept of separating logic in your code.</p>
<p>You can create a wrapper function that abstracts away the details of email sending. This way, you can change the underlying email service or remove the dependency on Nodemailer without affecting the rest of your code.</p>
<p>Here's how you can structure your code to accomplish this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> nodemailer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'nodemailer'</span>);

<span class="hljs-comment">// Core function to send email</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendEmail</span>(<span class="hljs-params">to, subject, message</span>) </span>{
    <span class="hljs-keyword">const</span> transporter = createTransporter();
    <span class="hljs-keyword">const</span> mailOptions = createMailOptions(to, subject, message);
    <span class="hljs-keyword">return</span> transporter.sendMail(mailOptions);
}

<span class="hljs-comment">// Function to create the transporter</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createTransporter</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> nodemailer.createTransport({
        <span class="hljs-attr">service</span>: <span class="hljs-string">'gmail'</span>,
        <span class="hljs-attr">auth</span>: {
            <span class="hljs-attr">user</span>: <span class="hljs-string">'your-email@gmail.com'</span>,
            <span class="hljs-attr">pass</span>: <span class="hljs-string">'your-email-password'</span>
        }
    });
}

<span class="hljs-comment">// Function to create mail options</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createMailOptions</span>(<span class="hljs-params">to, subject, message</span>) </span>{
    <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">from</span>: <span class="hljs-string">'your-email@gmail.com'</span>,
        <span class="hljs-attr">to</span>: to,
        <span class="hljs-attr">subject</span>: subject,
        <span class="hljs-attr">text</span>: message
    };
}

<span class="hljs-comment">// Example usage</span>
sendEmail(<span class="hljs-string">'recipient@example.com'</span>, <span class="hljs-string">'Test Subject'</span>, <span class="hljs-string">'Hello, this is a test email.'</span>)
    .then(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Email sent successfully!'</span>);
    })
    .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 sending email:'</span>, error);
    });
</code></pre>
<p><strong>🗝️ Key points:</strong></p>
<ol>
<li><p><strong>Core Functions</strong>: The <code>sendEmail</code>, <code>createTransporter</code>, and <code>createMailOptions</code> functions are separate, allowing you to modify one without affecting the others.</p>
</li>
<li><p><strong>Easy Modifications</strong>: If you want to switch to another email service in the future, you can simply modify the <code>createTransporter</code> function.</p>
</li>
<li><p><strong>Maintainability</strong>: This structure makes your code more maintainable and easier to understand.</p>
</li>
</ol>
<h3 id="heading-7-organize-your-project">7. Organize Your Project</h3>
<p>A well-organized project structure is as important as the code itself.</p>
<p>Think of this like organizing your workspace—you need designated places for everything so that you can find them easily. For coding projects, create folders for specific parts, like <code>components</code>, <code>utils</code>, and <code>services</code>.</p>
<p><strong>📂 How to Organize Your Project</strong></p>
<p>To set up a clean and organized project, you should categorize different parts of your code into designated folders. Here’s a simple example of what a well-organized project structure might look like:</p>
<pre><code class="lang-yaml"><span class="hljs-string">myProject</span>
<span class="hljs-string">├──</span> <span class="hljs-string">src</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">components</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">services</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">utils</span>
<span class="hljs-string">└──</span> <span class="hljs-string">tests</span>
</code></pre>
<h4 id="heading-breakdown-of-the-project-structure">Breakdown of the project structure:</h4>
<ol>
<li><p><strong>myProject</strong>: This is the root folder of your project. It contains everything related to your application.</p>
</li>
<li><p><strong>src (Source)</strong>: This folder holds all the source code for your project. It’s where you’ll spend most of your time coding.</p>
</li>
<li><p><strong>components</strong>: This subfolder contains reusable UI components. For example, if you're building a web app, you might have individual files for buttons, headers, or forms here. Each component can be in its own file to keep things modular.</p>
<ul>
<li>Example structure within <code>components</code>:</li>
</ul>
</li>
</ol>
<pre><code class="lang-yaml">    <span class="hljs-string">components</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">Button.js</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">Header.js</span>
    <span class="hljs-string">└──</span> <span class="hljs-string">Form.js</span>
</code></pre>
<ol start="4">
<li><p><strong>services</strong>: This folder includes functions that perform specific tasks or handle business logic. For example, if you're sending emails, you could have a file here with all the email-related functions.</p>
<ul>
<li>Example structure within <code>services</code>:</li>
</ul>
</li>
</ol>
<pre><code class="lang-yaml">    <span class="hljs-string">services</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">emailService.js</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">userService.js</span>
    <span class="hljs-string">└──</span> <span class="hljs-string">productService.js</span>
</code></pre>
<ol start="5">
<li><p><strong>utils (Utilities)</strong>: Here, you place helper functions that can be used across your project. These might include functions for formatting dates, validating inputs, or any other common tasks that don't belong to specific components or services.</p>
<ul>
<li>Example structure within <code>utils</code>:</li>
</ul>
</li>
</ol>
<pre><code class="lang-yaml">    <span class="hljs-string">utils</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">formatDate.js</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">validateEmail.js</span>
    <span class="hljs-string">└──</span> <span class="hljs-string">generateId.js</span>
</code></pre>
<ol start="6">
<li><p><strong>tests</strong>: This folder is dedicated to your testing files. Keeping your tests organized helps ensure that as you build new features, you can easily test them without digging through your codebase.</p>
<ul>
<li>Example structure within <code>tests</code>:</li>
</ul>
</li>
</ol>
<pre><code class="lang-yaml">    <span class="hljs-string">tests</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">emailService.test.js</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">userService.test.js</span>
    <span class="hljs-string">└──</span> <span class="hljs-string">component.test.js</span>
</code></pre>
<p><strong>📨 Real-World Example: Working with Nodemailer</strong></p>
<p>Let's say you are building an application that sends emails to users. You might structure your project like this:</p>
<pre><code class="lang-yaml"><span class="hljs-string">myEmailApp</span>
<span class="hljs-string">├──</span> <span class="hljs-string">src</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">components</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">EmailForm.js</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">SuccessMessage.js</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">services</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">emailService.js</span>
<span class="hljs-string">│</span>   <span class="hljs-string">├──</span> <span class="hljs-string">utils</span>
<span class="hljs-string">│</span>   <span class="hljs-string">│</span>   <span class="hljs-string">└──</span> <span class="hljs-string">validateEmail.js</span>
<span class="hljs-string">└──</span> <span class="hljs-string">tests</span>
    <span class="hljs-string">├──</span> <span class="hljs-string">emailService.test.js</span>
    <span class="hljs-string">└──</span> <span class="hljs-string">EmailForm.test.js</span>
</code></pre>
<ul>
<li><p><strong>EmailForm.js</strong>: This component handles the user interface for sending an email, like the input fields for the recipient, subject, and message.</p>
</li>
<li><p><strong>SuccessMessage.js</strong>: This component displays a success message once the email has been sent.</p>
</li>
<li><p><strong>emailService.js</strong>: This service contains the logic for sending emails using Nodemailer, keeping your code modular and clean.</p>
</li>
<li><p><strong>validateEmail.js</strong>: A utility function that checks if an email address is formatted correctly.</p>
</li>
<li><p><strong>tests</strong>: Here, you would write tests to ensure your email service and components are functioning as expected.</p>
</li>
</ul>
<p><strong>🍱 Benefits of a Well-Organized Project</strong></p>
<ol>
<li><p><strong>Ease of Navigation</strong>: Anyone looking at your project can quickly understand where to find specific parts of the code.</p>
</li>
<li><p><strong>Better Collaboration</strong>: If you’re working with others, a clear structure helps everyone know where to contribute without stepping on each other’s toes.</p>
</li>
<li><p><strong>Scalability</strong>: As your project grows, maintaining a clear structure helps manage the complexity and keeps your codebase clean.</p>
</li>
<li><p><strong>Improved Maintenance</strong>: When you need to update or fix something, you can find the relevant files quickly, which saves time and reduces errors.</p>
</li>
</ol>
<h3 id="heading-8-use-consistent-formatting"><strong>8. Use Consistent Formatting</strong></h3>
<p>Consistency in formatting improves readability.</p>
<p>Establish a pattern for how you write your code, such as using two spaces for indentation or always including a line break before comments.</p>
<p>Following consistent formatting makes your code look clean and well-organized.</p>
<p><strong>🛠️ Tools for Formatting</strong></p>
<ul>
<li><p><a target="_blank" href="https://prettier.io/"><strong>Prettier</strong></a>: Automatically formats code based on a set of rules. <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-prettier-in-visual-studio-code/">Here’s a tutorial</a> that explains how to set up and use Prettier in VSCode.</p>
</li>
<li><p><a target="_blank" href="https://eslint.org/"><strong>ESLint</strong></a>: Helps enforce coding standards by highlighting issues. <a target="_blank" href="https://www.freecodecamp.org/news/how-to-set-up-eslint-prettier-stylelint-and-lint-staged-in-nextjs/#heading-set-up-eslint">Here’s a tutorial</a> that includes a helpful and in-depth section on setting up ESLint for your projects.</p>
</li>
</ul>
<h3 id="heading-9-avoid-hardcoding-values">9. Avoid Hardcoding Values</h3>
<p>Hardcoding is directly embedding data values in code, like setting a user ID as <code>123</code> instead of using a variable.</p>
<p>Avoiding hardcoded values allows you to reuse code without making constant changes. Store values in variables, constants, or configuration files instead.</p>
<p>Here’s a scenario where hardcoding can lead to issues:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Bad: Hardcoding user limit</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUser</span>(<span class="hljs-params">name</span>) </span>{
    <span class="hljs-keyword">let</span> numberOfUsers = <span class="hljs-number">100</span>; <span class="hljs-comment">// Hardcoded value</span>
    <span class="hljs-keyword">if</span> (numberOfUsers &gt;= <span class="hljs-number">100</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-string">'User limit reached.'</span>;
    }
    <span class="hljs-comment">// Code to create the user</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">'User created.'</span>;
}
</code></pre>
<p>In this example, <code>numberOfUsers</code> is hardcoded to <code>100</code>. If you want to change the user limit, you have to find and modify this value in the code. If it appears in multiple places, this task becomes cumbersome and error-prone.</p>
<h4 id="heading-improved-example-using-constants"><strong>🏗️ Improved Example Using Constants</strong></h4>
<p>Now, let’s refactor this code to use a constant instead:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Good: Using a constant</span>
<span class="hljs-keyword">const</span> MAX_USERS = <span class="hljs-number">100</span>; <span class="hljs-comment">// Store the limit in a constant</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUser</span>(<span class="hljs-params">name</span>) </span>{
    <span class="hljs-keyword">let</span> numberOfUsers = getCurrentUserCount(); <span class="hljs-comment">// Get the current count from a function or database</span>
    <span class="hljs-keyword">if</span> (numberOfUsers &gt;= MAX_USERS) {
        <span class="hljs-keyword">return</span> <span class="hljs-string">'User limit reached.'</span>;
    }
    <span class="hljs-comment">// Code to create the user</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">'User created.'</span>;
}

<span class="hljs-comment">// Example function to get current user count</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCurrentUserCount</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Simulate fetching the current count, e.g., from a database</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">90</span>; <span class="hljs-comment">// Example count</span>
}
</code></pre>
<p><strong>🥣 Breakdown of the improved example:</strong></p>
<ol>
<li><p><strong>Using Constants</strong>: The <code>MAX_USERS</code> constant is defined at the top. This way, if you ever need to change the maximum number of users, you only have to update it in one place.</p>
</li>
<li><p><strong>Dynamic Values</strong>: The <code>getCurrentUserCount()</code> function dynamically retrieves the current user count from a database or any other source. This approach prevents hardcoding the count and allows for easy changes.</p>
</li>
<li><p><strong>Maintainability</strong>: By storing values in constants, your code becomes more maintainable. If the business requirement changes and you need to increase the user limit to <code>150</code>, you can simply change <code>MAX_USERS</code> from <code>100</code> to <code>150</code>, and the change will reflect throughout your application.</p>
</li>
<li><p><strong>Clarity</strong>: Using descriptive names for your constants (like <code>MAX_USERS</code>) improves the readability of your code. Anyone looking at your code can quickly understand what this value represents.</p>
</li>
</ol>
<p><strong>🤐 When to Use Configuration Files</strong></p>
<p>In larger applications, you might also consider using configuration files (like JSON, YAML, or environment variables) to store values that may change between environments (development, staging, production).</p>
<p>For instance in your <strong>config.json</strong> file you can hardcode <code>maxUsers</code> as follows (keep in mind that in config.json, its recommended to use camelCase as it follows consistent formatting):</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"maxUsers"</span>: <span class="hljs-number">100</span>,
    <span class="hljs-attr">"emailService"</span>: {
        <span class="hljs-attr">"service"</span>: <span class="hljs-string">"gmail"</span>,
        <span class="hljs-attr">"user"</span>: <span class="hljs-string">"your-email@gmail.com"</span>,
        <span class="hljs-attr">"pass"</span>: <span class="hljs-string">"your-email-password"</span>
    }
}
</code></pre>
<p><strong>🪴 Using Configuration in Your Code:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> config = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./config.json'</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUser</span>(<span class="hljs-params">name</span>) </span>{
    <span class="hljs-keyword">let</span> numberOfUsers = getCurrentUserCount(); 
    <span class="hljs-keyword">if</span> (numberOfUsers &gt;= config.maxUsers) {
        <span class="hljs-keyword">return</span> <span class="hljs-string">'User limit reached.'</span>;
    }
    <span class="hljs-comment">// Code to create the user</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">'User created.'</span>;
}
</code></pre>
<h3 id="heading-10-limit-function-length">10. Limit Function Length</h3>
<p>Long functions are harder to understand and maintain.</p>
<p>There’s no strict rule, but in general, functions should ideally be no more than 20-30 lines. If a function has multiple responsibilities or contains many steps, that’s a good indication it might be too long. Breaking down these functions into smaller "helper" functions can make them more manageable and understandable.</p>
<p>Here’s what a long, complex function might look like:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateCart</span>(<span class="hljs-params">cart, item, discountCode</span>) </span>{
    <span class="hljs-comment">// Add the item to the cart</span>
    cart.items.push(item);

    <span class="hljs-comment">// Calculate the new total</span>
    <span class="hljs-keyword">let</span> total = <span class="hljs-number">0</span>;
    cart.items.forEach(<span class="hljs-function"><span class="hljs-params">cartItem</span> =&gt;</span> {
        total += cartItem.price * cartItem.quantity;
    });

    <span class="hljs-comment">// Apply discount if available</span>
    <span class="hljs-keyword">if</span> (discountCode) {
        total = applyDiscount(total, discountCode);
    }

    <span class="hljs-comment">// Log the transaction</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Item added: <span class="hljs-subst">${item.name}</span>, New total: $<span class="hljs-subst">${total}</span>`</span>);

    <span class="hljs-keyword">return</span> total;
}
</code></pre>
<p>⚠️ <strong>This function does multiple things:</strong></p>
<ol>
<li><p>Adds an item to the cart.</p>
</li>
<li><p>Calculates the total price.</p>
</li>
<li><p>Applies a discount if there’s a code.</p>
</li>
<li><p>Logs the transaction.</p>
</li>
</ol>
<p>While this function might look manageable now, it can quickly grow if more tasks are added, making it harder to debug and maintain.</p>
<p>Let’s break this long function into smaller, single-purpose functions:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateCart</span>(<span class="hljs-params">cart, item, discountCode</span>) </span>{
    addItemToCart(cart, item);
    <span class="hljs-keyword">let</span> total = calculateTotal(cart);

    <span class="hljs-keyword">if</span> (discountCode) {
        total = applyDiscount(total, discountCode);
    }

    logTransaction(item, total);
    <span class="hljs-keyword">return</span> total;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addItemToCart</span>(<span class="hljs-params">cart, item</span>) </span>{
    cart.items.push(item);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTotal</span>(<span class="hljs-params">cart</span>) </span>{
    <span class="hljs-keyword">return</span> cart.items.reduce(<span class="hljs-function">(<span class="hljs-params">total, cartItem</span>) =&gt;</span> total + cartItem.price * cartItem.quantity, <span class="hljs-number">0</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">logTransaction</span>(<span class="hljs-params">item, total</span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Item added: <span class="hljs-subst">${item.name}</span>, New total: $<span class="hljs-subst">${total}</span>`</span>);
}
</code></pre>
<h4 id="heading-let-me-explain">🧩 Let me explain:</h4>
<ol>
<li><p><code>addItemToCart</code>: This function is now responsible only for adding an item to the cart. It’s simple, with a clear purpose.</p>
</li>
<li><p><code>calculateTotal</code>: This function calculates the total price of all items in the cart. It’s easier to read and understand, and if you need to update the way totals are calculated, you only have to modify this function.</p>
</li>
<li><p><code>logTransaction</code>: Handles the responsibility of logging details. If you ever need to change what gets logged (for example, adding a timestamp), you can do so in this function without touching the rest of the code.</p>
</li>
<li><p><code>updateCart</code>: The main function now reads more like a summary of the actions being taken: add an item, calculate the total, apply discounts, and log the result. It’s easier to follow and understand at a glance.</p>
</li>
</ol>
<p><strong>📒 Let’s summarize limiting function length:</strong></p>
<ol>
<li><p><strong>🎯 Focus on One Task</strong>: Each function should ideally perform just one task. If a function seems to be doing multiple tasks, consider breaking it up.</p>
</li>
<li><p><strong>🩼 Use Helper Functions</strong>: Helper functions are small, focused functions that assist a main function by performing a specific task. In the example above, <code>addItemToCart</code>, <code>calculateTotal</code>, and <code>logTransaction</code> are helper functions.</p>
</li>
<li><p><strong>🪦 Descriptive Names</strong>: Name your functions based on their tasks (for example, <code>addItemToCart</code>), which helps make the code self-explanatory.</p>
</li>
</ol>
<h2 id="heading-best-practices-for-clean-code">Best Practices for Clean Code</h2>
<p>Now that we’ve covered some important tips, let’s look at some overarching principles that make up the philosophy behind clean code:</p>
<ol>
<li><p><strong>🎏 Simplicity</strong>: Always aim to make your code as simple as possible.</p>
</li>
<li><p><strong>🧂 Consistency</strong>: Keep your code uniform in style and structure.</p>
</li>
<li><p><strong>🌾 Clarity</strong>: Your code should clearly communicate what it does.</p>
</li>
<li><p><strong>⛽ Efficiency</strong>: Write code that’s optimized for performance without sacrificing readability.</p>
</li>
</ol>
<p>These principles make coding less about writing and more about designing solutions. Writing clean code is a skill that grows with practice, so keep learning and improving over time.</p>
<p><strong>🔌 A Note on Dependencies</strong></p>
<p>Instead of hardcoding dependencies directly into your code, use package managers like <a target="_blank" href="https://www.npmjs.com/"><strong>npm</strong></a> (for JavaScript) or <strong>pip</strong> (for Python) to manage them. This way, you can easily update or remove them when needed.</p>
<h2 id="heading-conclusion">Conclusion 🏁</h2>
<p>Writing clean code is like building a strong foundation for a house. It keeps everything in order, making it easy to add new features or fix issues as your project grows.</p>
<p>With these tips, you can start developing habits that will make your code more readable, maintainable, and enjoyable to work on.</p>
<h3 id="heading-recommended-next-steps">Recommended Next Steps 📘</h3>
<p>For a structured guide to becoming a backend developer in six months, you can check out my <a target="_blank" href="https://codewithshahan.gumroad.com/l/pcela">backend developer roadmap</a>. It’s designed to help beginners stay on track with weekly goals, covering the essential skills, tools, and technologies. This roadmap can keep you motivated and make learning more manageable.</p>
<p><strong>You can follow me on</strong> <a target="_blank" href="https://x.com/shahancd"><strong>𝕏</strong></a> <strong>for instant updates.</strong></p>
<p>Hope to see you next time!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Cleaner Code Using Mongoose Schemas ]]>
                </title>
                <description>
                    <![CDATA[ If you are used to building NodeJS applications using the Mongoose ORM, this article is for you. In it, we'll discuss some cool features of Mongoose schemas that'll help you write more organized and maintainable code. To get the most out of this guid... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-cleaner-code-using-mongoose-schemas/</link>
                <guid isPermaLink="false">66db07581905f28bb66717a2</guid>
                
                    <category>
                        <![CDATA[ mongoose ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Object Oriented Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ dry ]]>
                    </category>
                
                    <category>
                        <![CDATA[ APIs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ ِAya Nabil Othman ]]>
                </dc:creator>
                <pubDate>Fri, 06 Sep 2024 13:44:56 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725431278897/86823d79-7b9c-4512-a834-edcdd4e11ac3.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you are used to building NodeJS applications using the Mongoose ORM, this article is for you. In it, we'll discuss some cool features of Mongoose schemas that'll help you write more organized and maintainable code.</p>
<p>To get the most out of this guide, you should have a background in JavaScript, understand how Mongoose works, and know Object-Oriented Programming basics.</p>
<h3 id="heading-heres-what-well-cover">Here's what we'll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-a-mongoose-schema">What is a Mongoose Schema?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-discriminator">Discriminator</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-statics">Statics</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-methods">Methods</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-query-builder">Query Builder</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-hooks">Hooks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ol>
<h2 id="heading-what-is-a-mongoose-schema">W<strong>hat is a Mongoose Schema?</strong></h2>
<p>Mongoose schemas provide a structured way to model data in a MongoDB database, allowing you to define the properties and behavior of the documents. Schemas serve as a blueprint for a document that gets saved in the database. They enables developers to enforce data integrity and work with MongoDB in a more intuitive and organized manner.</p>
<p>Within a MongoDB collection, a schema outlines the fields of the documents, their data types, validation rules, default values, constraints, and more.</p>
<p>Programmatically, a Mongoose schema is a JavaScript object. Actually, it is an instance of a built-in class called <code>Schema</code> inside the <code>mongoose</code> module. For this reason, you can add more methods to its prototype. This will help you implement many features as middleware, methods, statics, and more. You will learn about some of them in this tutorial.</p>
<h3 id="heading-features-youll-learn-how-to-implement"><strong>Features you'll learn how to implement:</strong></h3>
<ul>
<li><p><a class="post-section-overview" href="#discriminator">Discriminator</a></p>
</li>
<li><p><a class="post-section-overview" href="#statics">Statics</a></p>
</li>
<li><p><a class="post-section-overview" href="#methods">Methods</a></p>
</li>
<li><p><a class="post-section-overview" href="#query-builder">Query Builder</a></p>
</li>
<li><p><a class="post-section-overview" href="#hooks">Hooks</a></p>
</li>
</ul>
<h2 id="heading-discriminator">Discriminator</h2>
<p>A discriminator is a feature that enables you to create multiple models (subtypes) that inherit from a base model (parent). This happens by defining a base schema and then extending it with extra fields specific to each subtype or each child schema.</p>
<p>All documents, regardless of their specific model, are stored in the same MongoDB collection. This keeps your data organized in a single collection while allowing for flexible querying and data management. Also, each document includes a special field that indicates its specific model type, allowing Mongoose to distinguish between the different subtypes.</p>
<p><strong>How to use</strong> <code>discriminator</code><strong>:</strong></p>
<ol>
<li><p>Start by defining a base schema, which will have the common fields among the subtypes. After that, create a model from it.</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">import</span> mongoose <span class="hljs-keyword">from</span> <span class="hljs-string">'mongoose'</span>;

 <span class="hljs-keyword">const</span> baseSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
     <span class="hljs-attr">name</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span> },
 }, { <span class="hljs-attr">discriminatorKey</span>: <span class="hljs-string">'kind'</span> }; <span class="hljs-comment">// defaults to '__t');</span>

 <span class="hljs-keyword">const</span> BaseModel = mongoose.model(<span class="hljs-string">'Base'</span>, baseSchema);
</code></pre>
</li>
<li><p>Create the subtypes that extend the base schema by defining the <code>discriminator</code> for each one.</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> catSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
     <span class="hljs-attr">meow</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>, <span class="hljs-attr">default</span>: <span class="hljs-literal">true</span> }
 });
 <span class="hljs-comment">// subtype</span>
 <span class="hljs-keyword">const</span> Cat = BaseModel.discriminator(<span class="hljs-string">'Cat'</span>, catSchema);

 <span class="hljs-keyword">const</span> dogSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
     <span class="hljs-attr">bark</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>, <span class="hljs-attr">default</span>: <span class="hljs-literal">true</span> }
 });
 <span class="hljs-comment">// subtype</span>
 <span class="hljs-keyword">const</span> Dog = BaseModel.discriminator(<span class="hljs-string">'Dog'</span>, dogSchema);
</code></pre>
</li>
<li><p>You can then create documents in the regular way. All the documents will be stored in the same collection, but each has its own type depending on its subtype model.</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> fluffy = <span class="hljs-keyword">await</span> Cat.create({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Fluffy'</span> });
 <span class="hljs-keyword">const</span> rover = <span class="hljs-keyword">await</span> Dog.create({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Rover'</span> });
</code></pre>
</li>
</ol>
<h3 id="heading-discriminator-use-case"><code>discriminator</code> use case:</h3>
<p>Let's say that you're building a multi-user Ecommerce web application which accommodates three main user roles: <em>admins</em>, <em>clients</em>, and <em>sellers</em>. Each of these roles plays a crucial part in the ecosystem of online shopping.</p>
<p>If you try to build a class for each role, you'll find that all the three have common fields and methods. You may decide to create a parent schema (user) and some other children schemas (client, seller, admin) that inherit from it.</p>
<p>You can use the <code>discriminator</code> to achieve this.</p>
<p>In your <code>user.model.js</code> file, add the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> mongoose <span class="hljs-keyword">from</span> <span class="hljs-string">"mongoose"</span>;

<span class="hljs-keyword">const</span> userSchema = mongoose.Schema(
  {
    <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">profilePic</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">birthDate</span>: <span class="hljs-built_in">Date</span>,
    <span class="hljs-attr">accountAcctivated</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>, <span class="hljs-attr">default</span>: <span class="hljs-literal">false</span> },
  },
  {
    <span class="hljs-attr">timestamps</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">discriminatorKey</span>: <span class="hljs-string">"role"</span>,
  }
);

<span class="hljs-keyword">const</span> User = mongoose.model(<span class="hljs-string">"User"</span>, userSchema);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> User;
</code></pre>
<p>Now you have the base model (<code>User</code>) from which other subtypes will inherit. In this parent schema, you define the common fields that all users will share regardless of their roles.</p>
<p>In your <code>client.model.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> mongoose <span class="hljs-keyword">from</span> <span class="hljs-string">"mongoose"</span>;
<span class="hljs-keyword">import</span> User <span class="hljs-keyword">from</span> <span class="hljs-string">"./user.model.js"</span>;

<span class="hljs-keyword">const</span> clientSchema = mongoose.Schema(
  {
    <span class="hljs-attr">products</span>: <span class="hljs-built_in">Array</span>,
    <span class="hljs-attr">address</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">phone</span>: <span class="hljs-built_in">String</span>,
  }
);

<span class="hljs-keyword">const</span> Client = User.discriminator(<span class="hljs-string">"Client"</span>, clientSchema);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Client;
</code></pre>
<p>In your <code>seller.model.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> mongoose <span class="hljs-keyword">from</span> <span class="hljs-string">"mongoose"</span>;
<span class="hljs-keyword">import</span> User <span class="hljs-keyword">from</span> <span class="hljs-string">"./user.model.js"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sellerSchema = mongoose.Schema(
  {
    <span class="hljs-attr">rating</span>: <span class="hljs-built_in">Number</span>,
    <span class="hljs-attr">businessType</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">enum</span>: [<span class="hljs-string">"individual"</span>, <span class="hljs-string">"corporation"</span>] },
  }
);

<span class="hljs-keyword">const</span> Seller = User.discriminator(<span class="hljs-string">"Seller"</span>, sellerSchema);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Seller;
</code></pre>
<p>In your <code>admin.model.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> mongoose <span class="hljs-keyword">from</span> <span class="hljs-string">"mongoose"</span>;
<span class="hljs-keyword">import</span> User <span class="hljs-keyword">from</span> <span class="hljs-string">"./user.model.js"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> adminSchema = mongoose.Schema(
  {
    <span class="hljs-attr">permissions</span>: <span class="hljs-built_in">Array</span>,
    <span class="hljs-attr">assignedTasks</span>: <span class="hljs-built_in">Array</span>,
    <span class="hljs-attr">department</span>: <span class="hljs-built_in">String</span>,
  }
);

<span class="hljs-keyword">const</span> Admin = User.discriminator(<span class="hljs-string">"Admin"</span>, adminSchema);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Admin;
</code></pre>
<p>The subtypes or children will be the <code>Client</code>, <code>Seller</code>, and <code>Admin</code>. In each subtype schema, you should add any extra fields or behaviors specific to this subtype only. By creating the child model using the discriminator, the child model will inherit all the fields and methods of its parent model <code>User</code>.  </p>
<p>So the previous code will create a <code>user</code> collection in the database with each document having a <code>role</code> field either Client, or Seller, or Admin. All documents are now sharing the parent (<code>user</code>) fields, and depending on the <code>role</code> of each document, each has another extra field.</p>
<p>Although all the documents will be saved in one single collection, models are fully separated while coding. What does this mean?</p>
<p>For instance, If you need to retrieve all clients from the <code>User</code> collection, you should write <code>Client.find({})</code>. This statement uses the discriminator key to find all documents whose <code>role</code> is <code>Client</code>. This way, any operations or queries that refer to one of the child models will still be written separately from the parent model.</p>
<p><strong>Note:</strong> Before diving into the next sections, just keep in mind that any statics, methods, query builders, or hooks should be defined before creating the model itself (that is, before <code>const User = mongoose.model("User", userSchema);</code>).</p>
<h2 id="heading-statics">Statics</h2>
<p>Statics are useful for defining functions that operate on the model level. They allow you to define reusable functions for operations related to the entire model. They help encapsulate logic that applies to the model rather than individual documents, making your code cleaner, more organized and maintainable</p>
<p>Methods like <code>find</code>, <code>findOne</code>, <code>findById</code> and others all are methods attached to the model. By using the <code>statics</code> property of Mongoose schemas, you will be able to build your own model method.  </p>
<p>Statics are powerful. By using them, you can encapsulate complex queries that you might want to reuse. Also, you can create statics for operations that modify or aggregate data, such as counting documents or finding documents based on specific criteria.</p>
<h3 id="heading-statics-use-case"><code>statics</code> use case</h3>
<p>Statics are easy to build. You define a static method on your schema using the <code>statics</code> object.</p>
<p>In your <code>user.model.js</code> file, add these static methods, <code>countUsers</code> and <code>findByEmail</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// model method</span>
userSchema.statics.countUsers = <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>.countDocuments({});
};

<span class="hljs-comment">// model method</span>
userSchema.statics.findByEmail = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">email</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.findOne({ email });
};
</code></pre>
<p>Inside any static method, <code>this</code> refers to the <strong>model</strong> itself. In this example, <code>this</code> in <code>this.findOne({ email })</code> refers to the <code>User</code> model.</p>
<p>Example usage:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findByEmail(<span class="hljs-string">"foo@bar.com"</span>);
<span class="hljs-comment">//or</span>
<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">await</span> Client.findByEmail(<span class="hljs-string">"foo@bar.com"</span>);
<span class="hljs-comment">//or</span>
<span class="hljs-keyword">const</span> seller = <span class="hljs-keyword">await</span> Seller.findByEmail(<span class="hljs-string">"foo@bar.com"</span>);
<span class="hljs-comment">//or</span>
<span class="hljs-keyword">const</span> admin = <span class="hljs-keyword">await</span> Admin.findByEmail(<span class="hljs-string">"foo@bar.com"</span>);
</code></pre>
<p>When you call the static method on your model, the method gets called and <code>this</code> is replaced by the model you called the statics on. This line performs a query to find a single document in the MongoDB collection where the <code>email</code> field matches the provided <code>email</code> argument.</p>
<h2 id="heading-methods">Methods</h2>
<p>Methods are functions that you can define on a schema and that can be called on instances of documents created from this schema. They help encapsulate logic within the document itself, making your code cleaner and more modular.</p>
<p>By using instance methods, you can easily interact with and manipulate the data associated with specific documents.</p>
<h3 id="heading-methods-use-case"><code>methods</code> use case</h3>
<p>You can define methods on the schema using the <code>methods</code> object.</p>
<p>In your <code>user.model.js</code> file, add a document method through which you can check the password of a user:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// instance or document method</span>
userSchema.methods.getProfile = <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-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> (<span class="hljs-subst">${<span class="hljs-built_in">this</span>.email}</span>)`</span>;
};

<span class="hljs-comment">// instance or document method</span>
userSchema.methods.checkPassword = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">password</span>) </span>{
    <span class="hljs-keyword">return</span> password === <span class="hljs-built_in">this</span>.password ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;
};
</code></pre>
<p>Inside any document method, <code>this</code> refers to the <strong>document</strong> itself. In this example, <code>this</code> in <code>this.password</code> refers to the <code>user</code> document at which the method will get called on. This means that you can access all the fields of this document. This is so valuable because you can retrieve, modify, and check for anything related to this document.</p>
<p>Example usage:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> client = <span class="hljs-keyword">await</span> Client.findById(...)
client.checkPassword(<span class="hljs-string">"12345"</span>)
<span class="hljs-comment">//or</span>
<span class="hljs-keyword">const</span> seller = <span class="hljs-keyword">await</span> Seller.findById(...)
seller.checkPassword(<span class="hljs-string">"12345"</span>)
<span class="hljs-comment">//or</span>
<span class="hljs-keyword">const</span> admin = <span class="hljs-keyword">await</span> Admin.findById(...)
admin.checkPassword(<span class="hljs-string">"12345"</span>)
</code></pre>
<p>Since methods are instance-level functions, they are called on the documents. <code>await Client.findById(...)</code> will return a document that has all the built-in methods as well as your own predefined methods <code>checkPassword</code> and <code>getProfile</code>. So by calling, for example <code>client.checkPassword("12345")</code>, the <code>this</code> keyword in the <code>checkPassword</code> function definition will get replaced with the <code>client</code> document. This in turn will compare the user password with the password saved earlier in the database.</p>
<h2 id="heading-query-builder">Query Builder</h2>
<p>A query builder in Mongoose is a custom method that you can define on the query object to simplify and encapsulate common query patterns. These query builders allow you to create reusable and readable query logic, making it easier to work with your data.</p>
<p>One of the most valuable usages of query builders is chaining. They can be chained with other query builders that you've built or with standard query methods like find, sort, and so on.</p>
<h3 id="heading-query-builder-use-case">Query builder use case</h3>
<p>You define query builders by adding them to the <code>query</code> property of a Mongoose schema.</p>
<p>In your <code>user.model.js</code> file, add a query helper method that lets you implement pagination.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// query helper</span>
userSchema.query.paginate = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">{ page, limit }</span>) </span>{
    <span class="hljs-comment">// some code</span>
    <span class="hljs-keyword">const</span> skip = limit * (page - <span class="hljs-number">1</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.skip(skip).limit(limit);
};
</code></pre>
<p>To implement pagination, you need two important variables: first, the page number, and second, the number of items you will retrieve per page.</p>
<p>To query the database for a specific count of documents, you will always use the <code>skip</code> and <code>limit</code> built-in query methods in <code>mongoose</code>. <code>skip</code> is used to set a cursor after a certain number of documents, after which the query will get implemented. <code>limit</code> is used to retrieve a specific number of documents.</p>
<p>Inside any query builder method, <code>this</code> refers to the <strong>query</strong> itself. And since query builders are chainable, you can call any of them after each other.</p>
<p>Finally, any query builder method should return a <code>mongoose query object</code>, which is why you must write <code>return this.skip(skip).limit(limit)</code>.</p>
<p>Example usage:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> results = <span class="hljs-keyword">await</span> Client.find().paginate({ <span class="hljs-attr">page</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span> });
<span class="hljs-comment">//or</span>
<span class="hljs-keyword">const</span> results = <span class="hljs-keyword">await</span> Seller.find().paginate({ <span class="hljs-attr">page</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span> });
<span class="hljs-comment">//or</span>
<span class="hljs-keyword">const</span> results = <span class="hljs-keyword">await</span> Admin.find().paginate({ <span class="hljs-attr">page</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span> });
</code></pre>
<p>You can then call it on any query, and <code>await Client.find().paginate({ page: 2, limit: 5 })</code> will invoke the <code>paginate</code> function and replace the <code>this</code> keyword with <code>Client.find()</code> using the query builder.</p>
<p>You can implement pagination with certain conditions, but you'll always call <code>skip</code> and <code>limit</code>. By defining the <code>paginate</code> query builder you won't repeat yourself and you'll be able to encapsulate the logic in one single function.</p>
<h2 id="heading-hooks">Hooks</h2>
<p>Hooks (also known as middleware) are functions that are executed at specific points in the lifecycle of a document. They allow you to add custom behavior before or after certain operations, such as saving, updating, or removing documents.</p>
<p>Types of Hooks</p>
<ul>
<li><p>Pre Hooks: Executed before an operation.</p>
</li>
<li><p>Post Hooks: Executed after an operation.</p>
</li>
</ul>
<h3 id="heading-hooks-use-case">Hooks use case</h3>
<p>In your <code>user.model.js</code> file, add a <code>post</code> save middleware through which you can send an email for account activation once the user document is saved in the database.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// post hook</span>
userSchema.post(<span class="hljs-string">"save"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">doc, next</span>) </span>{
  <span class="hljs-comment">// send email logic</span>
  <span class="hljs-comment">// if succeeded</span>
  <span class="hljs-keyword">return</span> next();
  <span class="hljs-comment">// if failed</span>
  <span class="hljs-keyword">return</span> next(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to send email!"</span>));
});
</code></pre>
<p>The callback function will get invoked once you create a user through <code>model.create()</code> or any time you call <code>save()</code> method on the user document.</p>
<p>In this this example, if you need to avoid sending emails on save, you should write a condition to be sure that this <code>save</code> is for a new user only. You can write something like <code>if (doc.createdAt.getTime() === doc.updatedAt.getTime())</code>.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In this overview of Mongoose features, we've explored four key concepts: discriminators, statics, methods, and hooks.</p>
<p><strong>Discriminators</strong> allow you to create multiple models that share a common schema enabling different document types to be stored in a single collection. This facilitates data management and querying.  </p>
<p><strong>Statics</strong> are model-level methods that provide reusable functionality applicable to the entire model. They encapsulate complex queries and data manipulation logic, helping to keep your codebase clean and maintainable.  </p>
<p><strong>Methods</strong> are instance-level functions that operate on individual document instances. They allow for custom behaviors and data manipulations specific to each document, so you can modify the document’s data in a specific way, such as formatting or calculating values based on its fields.  </p>
<p><strong>Hooks</strong> (or middleware) enable you to run functions at specific points in the document lifecycle, such as before or after saving, updating or deleting a document. This is useful for implementing validation, logging, or any other side effects related to database operations.  </p>
<p>Together, these features enhance the versatility and organization of your Mongoose models, making it easier to build robust and maintainable applications with MongoDB.</p>
<p><a target="_blank" href="https://github.com/Ayanabilothman/mongoose-schema-features">Here</a> can will find a repository where you can learn more about Mongoose schemas and use cases.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Primitive Obsession? ]]>
                </title>
                <description>
                    <![CDATA[ In a statically-typed language like Java, C#, Go, Typescript, or even Dart, how do you represent an email address? Okay, what about a password? A phone number? Zip code? Home address? Alright, what about a unique ID? If your answer to all or most of ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-primitive-obsession/</link>
                <guid isPermaLink="false">66ba189cb80b6ce06c3fdf1b</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Asaboro ]]>
                </dc:creator>
                <pubDate>Tue, 23 Jul 2024 22:03:40 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-23-at-08.25.18.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In a statically-typed language like Java, C#, Go, Typescript, or even Dart, how do you represent an email address? Okay, what about a password? A phone number? Zip code? Home address? Alright, what about a unique ID?</p>
<p>If your answer to all or most of these is a string, then you are suffering from what Software Development experts call "<strong>Primitive Obsession</strong>".</p>
<p>While primitives like <code>int</code>, <code>char</code>, <code>byte</code>, <code>short</code>, <code>long</code>, <code>float</code>, <code>double</code>, <code>boolean</code>, <code>strings</code>, and so on are the basic built-in building blocks of any programming language, Primitive Obsession is when your code relies too much on them to represent otherwise more complex concepts.</p>
<p>Experts say it's a code smell. This is because Primitive Obsession can lead to a range of problems including lack of validation, poor readability, code duplication, and difficulty in refactoring. This article will help you resolve this issue.</p>
<h2 id="heading-what-youll-learn-in-this-article">What You'll Learn in this Article</h2>
<p>This tutorial, while quite short, is designed to help you understand and address the issue of primitive obsession in your code. So when you are done reading, you should be able to:</p>
<ol>
<li><p>Identify what's so bad about Primitive Obsession and associated drawbacks.</p>
</li>
<li><p>Design better software and implement data structures that enhance code correctness, maintainability, and future-proof your software against potential issues.</p>
</li>
<li><p>Improve Data Safety, and Security, and reduce the likelihood of runtime errors and unexpected behavior by using more robust data representations.</p>
</li>
</ol>
<h2 id="heading-prerequisites-what-you-need-to-know">Prerequisites: What You Need to Know</h2>
<ol>
<li><p>Familiarity with OOP principles like classes, objects, encapsulation, inheritance, and polymorphism will be beneficial when designing custom data structures.</p>
</li>
<li><p>Proficiency in statically-typed languages like Java, C#, Go, TypeScript, and Dart where variable types are declared at compile time.</p>
</li>
</ol>
<p>It's fine if you're not familiar with these concepts – there are many resources available online and in textbooks to help you get started. But this tutorial assumes a basic grasp of these foundations and builds upon them to address the issue of primitive obsession.</p>
<h2 id="heading-whats-bad-about-primitive-obsession">What's Bad about Primitive Obsession?</h2>
<p>Primitive obsession is problematic for several reasons:</p>
<ol>
<li><p>Weak type checking</p>
</li>
<li><p>Limited built-in functionality for specific data types</p>
</li>
<li><p>Reduced maintainability and loss of domain knowledge</p>
</li>
</ol>
<p>Let's take a look at each issue in detail:</p>
<h3 id="heading-1-primitives-offer-weak-type-checking">1. Primitives offer weak type checking</h3>
<p>Beyond efficient memory allocation, or wasteful compute time in deciphering what type a value is, one of the benefits of statically type language is that it lets the compiler help you catch potential type mismatches at compile time. This can help prevent runtime errors caused by using the wrong data type.</p>
<p>The compiler would scream at you if you did this:</p>
<pre><code class="lang-dart"><span class="hljs-built_in">String</span> phoneNumber = <span class="hljs-string">"+1-555-229-1234"</span>;
<span class="hljs-built_in">int</span> zipCode = <span class="hljs-number">101257</span>;

zipCode = phoneNumber; <span class="hljs-comment">// throws an error</span>
</code></pre>
<p>What if you did this?</p>
<pre><code class="lang-dart"><span class="hljs-built_in">String</span> phoneNumber = <span class="hljs-string">"+1-555-229-1234"</span>;
<span class="hljs-built_in">String</span> zipCode = <span class="hljs-string">"1000 AP"</span>

zipCode = phoneNumber; <span class="hljs-comment">//works fine</span>
</code></pre>
<p>It will compile and do nothing!</p>
<p>Why?</p>
<p><strong>Because a string will always be a string.</strong></p>
<p>The compiler cannot differentiate whether the string value you pass represents a user password or an email address. Consequently, it cannot prevent you from mistakenly assigning a variable to the wrong field leading to runtime errors and unexpected behaviour.</p>
<h3 id="heading-2-limited-built-in-functionality-for-specific-data-types">2. Limited built-in functionality for specific data types.</h3>
<p>When you rely heavily on primitives, you often need to write additional code to perform tasks such as email address validation or phone number formatting. And that's not a problem really.</p>
<p>The real problem is the repetitive and scattered nature of these implementations. This doesn't just increase the risk of errors but it also makes the code harder to maintain and refactor.</p>
<h3 id="heading-3-reduced-maintainability-and-loss-of-domain-knowledge">3. Reduced Maintainability and Loss of Domain Knowledge</h3>
<p>Scattering business rules and logic across the codebase makes it harder to maintain and evolve the software. When primitives are used extensively, it can be challenging to understand the purpose and constraints of the data they represent.</p>
<p>Encapsulating this logic within dedicated types helps preserve domain knowledge and makes the code more intuitive for future developers.</p>
<p>For instance, you might need to block certain email addresses due to fraud or restrict specific zip codes, areas, or companies. When you use primitives, this important context is not evident, leading to potential errors and increased maintenance burden.</p>
<h2 id="heading-how-to-break-away-from-primitive-obsession">How to Break Away from Primitive Obsession</h2>
<h3 id="heading-1-watch-out-for-variables-with-special-validation-logic">1. Watch out for variables with special validation logic.</h3>
<p>Take Phone Numbers, for example. In Nigeria, where I'm from, all phone numbers are eleven digits long and start with a zero. The second digit is usually a "<em>7</em>" , "<em>8</em>", or "9" which helps identify the telecom operator. Any other number is invalid.</p>
<p>The same can be said for a Website URL. It could very well be represented by a string. But a URL has more information and specific properties compared to a string (for example, the scheme, query parameters, and protocol). And each part has a different validation method.</p>
<h3 id="heading-2-watch-out-for-variables-with-special-comparison-rules">2. Watch out for variables with special comparison rules</h3>
<p>Beyond simple equality checks (==), if you find yourself implementing custom comparison logic for a variable without encapsulating it in a class, it's a red flag.</p>
<p>For instance, comparing email addresses often involves more than a simple equality check. You might need to perform case-insensitive matching, strip out whitespace, or handle variations in formatting to accurately identify matching emails such as + sign in email addresses for people who want to game your ssytem.</p>
<p>daniel@example.com is the same email address as daniel+dev@example.com. Emails sent to the latter will be received on the former.</p>
<h3 id="heading-3-watch-out-for-variables-with-special-formatting-rules">3. Watch out for variables with special formatting rules</h3>
<p>Any variable that requires specific formatting or parsing to extract meaningful information is a candidate for a richer representation.</p>
<p><strong>Currency values</strong> are a good example of this. Different regions use different formatting rules – some use commas and some use decimal points. It's the same case with a date of birth or anything that requires some data.</p>
<p>Identifying and resolving primitive obsession is a continuous process.</p>
<p>You won't be able to catch all instances at once, especially those that are uncommon and unique to your business domain. That's perfectly fine – that's how it should be.</p>
<p>Instead of panicking or giving up, gradually refactor your code to incorporate these changes. This approach is key to making your code future-proof and maintainable.</p>
<h2 id="heading-you-dont-see-it-until-you-are-shown">You Don't See it Until You Are Shown</h2>
<p>Primitive obsession hides in plain sight. And that's a significant issue because, unlike static errors, linters won't flag them and neither will your program crash as a result.</p>
<p>It often takes a mentor, a code review, or an "aha" moment to realize that these repetitive checks and rules scattered throughout your codebase can be centralized into their own dedicated types. This recognition is the first step toward more robust, readable, and maintainable code.</p>
<p>So stay open-minded, engage with others, read code from different sources, and contribute to open-source projects. That's how you learn. Ultimately, it's all about one thing: encapsulation – grouping data and the methods that operate on it in one location for maintainability.</p>
<h2 id="heading-credits-and-resources">Credits and resources:</h2>
<ol>
<li><p><a target="_blank" href="https://medium.com/the-sixt-india-blog/primitive-obsession-code-smell-that-hurt-people-the-most-5cbdd70496e9">A Code Smell that Hurts People the Most</a> by Arpit Jain.</p>
</li>
<li><p><a target="_blank" href="https://refactoring.guru/smells/primitive-obsession">Signs and Symptoms of Primitive Obsession</a> by Refactoring Guru.</p>
</li>
<li><p><a target="_blank" href="https://hackernoon.com/what-is-primitive-obsession-and-how-can-we-fix-it-wh2f33ki">How to Fix Primitive Obsession</a> by Sam Walpole on Hackernoon.</p>
</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Console Logging Tips – How to Debug and Understand Your Code ]]>
                </title>
                <description>
                    <![CDATA[ Console logging is an essential tool for developers to use to debug and understand the behavior of their code.  While most developers are familiar with basic console logging using console.log(), there are many other powerful methods provided by the c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/console-logging-tips/</link>
                <guid isPermaLink="false">66c4c3bf8e05d0e4345147bb</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ console ]]>
                    </category>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joan Ayebola ]]>
                </dc:creator>
                <pubDate>Tue, 20 Feb 2024 18:09:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Ivory-and-Blue-Lavender-Aesthetic-Photo-Collage-Presentation--9-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Console logging is an essential tool for developers to use to debug and understand the behavior of their code. </p>
<p>While most developers are familiar with basic console logging using <code>console.log()</code>, there are many other powerful methods provided by the console object that can make debugging more efficient and effective.</p>
<p>In this comprehensive guide, we will explore various console logging tricks such as <code>console.table</code>, <code>console.group</code>, <code>console.assert</code>, and more. These tricks can help you organize your debugging process, visualize complex data structures, and catch errors early on in your development workflow.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-1-introduction-to-console-logging">Introduction to Console Logging</a></li>
<li><a class="post-section-overview" href="#heading-2-basic-console-logging">Basic Console Logging</a></li>
<li><a class="post-section-overview" href="#heading-3-advanced-console-logging-tricks">Advanced Console Logging Tricks</a><br>– <code>[console.table](#heading-31-consoletable)</code><br>– <a class="post-section-overview" href="#heading-32-consolegroup-and-consolegroupcollapsed"><code>console.group</code>  and <code>console.groupCollapsed</code></a><br>– <code>[console.assert](#heading-33-consoleassert)</code><br>– <a class="post-section-overview" href="#heading-34-consolecount-and-consolecountreset"><code>console.count</code> and <code>console.countReset</code></a><br>– <a class="post-section-overview" href="#heading-35-consoletime-and-consoletimeend"><code>console.time</code> and <code>console.timeEnd</code></a><br>– <code>[console.trace](#heading-36-consoletrace)</code><br>– <code>[console.dir](#heading-37-consoledir)</code><br>– <code>[console.clear](#heading-38-consoleclear)</code></li>
<li><a class="post-section-overview" href="#heading-4-best-practices-for-console-logging">Best Practices for Console Logging</a></li>
<li><a class="post-section-overview" href="#heading-5-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-1-introduction-to-console-logging">1. Introduction to Console Logging</h2>
<p>Console logging is a technique used by developers to output messages, variables, and other information to the browser's console. This is particularly useful for debugging purposes, as it allows developers to inspect the state of their code and track its execution flow.</p>
<p>The <code>console</code> object in JavaScript provides various methods for logging different types of information. While <code>console.log()</code> is the most commonly used method, there are several other methods that can be used to enhance your debugging experience.</p>
<h2 id="heading-2-basic-console-logging">2. Basic Console Logging</h2>
<p>Before we dive into the advanced console logging tricks, let's start by revisiting the basics of console logging using <code>console.log()</code>. This method accepts any number of arguments and outputs them to the console.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> name = <span class="hljs-string">"Femi"</span>;

<span class="hljs-keyword">const</span> age = <span class="hljs-number">30</span>;

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Name:"</span>, name, <span class="hljs-string">"Age:"</span>, age);
</code></pre>
<p>In the above example, we are logging the <code>name</code> and <code>age</code> variables to the console using <code>console.log()</code>. This will output:</p>
<pre><code>Name: Femi Age: <span class="hljs-number">30</span>
</code></pre><p>You can use <code>console.log()</code> to log strings, numbers, booleans, objects, arrays, and more.</p>
<h2 id="heading-3-advanced-console-logging-tricks">3. Advanced Console Logging Tricks</h2>
<h3 id="heading-31-consoletable">3.1 <code>console.table</code></h3>
<p>The <code>console.table()</code> method allows you to display tabular data in the console. It takes an array or an object as input and presents it as a table.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> users = [

{ <span class="hljs-attr">name</span>: <span class="hljs-string">"Chris"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span> },

{ <span class="hljs-attr">name</span>: <span class="hljs-string">"Dennis"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">15</span> },

{ <span class="hljs-attr">name</span>: <span class="hljs-string">"Victor"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">17</span> }

];

<span class="hljs-built_in">console</span>.table(users);
</code></pre>
<p>The above code will output a table in the console:</p>
<pre><code class="lang-markdown"><span class="hljs-section">(index)  |  name  |  age
-------------------------</span>
0    |  Chris  |   25
1    |  Dennis |   15
2    |  Victor |   17
</code></pre>
<p><code>console.table()</code> is particularly useful when dealing with arrays of objects or other tabular data structures.</p>
<h3 id="heading-32-consolegroup-and-consolegroupcollapsed">3.2 <code>console.group</code> and <code>console.groupCollapsed</code></h3>
<p>The <code>console.group()</code> and <code>console.groupCollapsed()</code> methods allow you to group related log messages together in the console. This can help organize your debugging output and make it easier to understand.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Start a new console group named "Group 1"</span>
<span class="hljs-built_in">console</span>.group(<span class="hljs-string">"Group 1"</span>);

<span class="hljs-comment">// Log messages inside "Group 1"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message 1"</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message 2"</span>);

<span class="hljs-comment">// End "Group 1"</span>
<span class="hljs-built_in">console</span>.groupEnd();

<span class="hljs-comment">// Start a new collapsed console group named "Group 2"</span>
<span class="hljs-built_in">console</span>.groupCollapsed(<span class="hljs-string">"Group 2"</span>);

<span class="hljs-comment">// Log messages inside "Group 2"</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message 3"</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message 4"</span>);

<span class="hljs-comment">// End "Group 2"</span>
<span class="hljs-built_in">console</span>.groupEnd();
</code></pre>
<p>In the above example, we create two groups of log messages. The first group is expanded, while the second group is collapsed by default. This helps keep the console output organized and easy to navigate.</p>
<p>If you run this code in a browser's developer console, the output will look something like this:</p>
<pre><code>Group <span class="hljs-number">1</span>
  Message <span class="hljs-number">1</span>
  Message <span class="hljs-number">2</span>
Group <span class="hljs-number">2</span>
  ▶ Message <span class="hljs-number">3</span>
  ▶ Message <span class="hljs-number">4</span>
</code></pre><p>In this example, "Group 1" is expanded by default, showing the messages inside it. On the other hand, "Group 2" is collapsed initially (indicated by the ▶ symbol), and you need to click on it to expand and reveal the messages inside. The collapsing of "Group 2" makes it visually neater in the console, especially when dealing with a large number of log messages.</p>
<h3 id="heading-33-consoleassert">3.3 <code>console.assert</code></h3>
<p>The <code>console.assert()</code> method allows you to assert whether a condition is true or false. If the condition is false, it will log an error message to the console.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> x = <span class="hljs-number">5</span>;

<span class="hljs-comment">// Check if the condition x === 10 is true, if not, log the error message</span>
<span class="hljs-built_in">console</span>.assert(x === <span class="hljs-number">10</span>, <span class="hljs-string">"x is not equal to 10"</span>);
</code></pre>
<p>In this case, the condition being checked is <code>x === 10</code>, which compares the value of the variable <code>x</code> to 10. Since the value of <code>x</code> is 5, the condition is false. As a result, the <code>console.assert</code> method will log the error message to the console.</p>
<p>If you run this code in a browser's developer console, you would see an assertion error in the console output with the specified error message:</p>
<pre><code>Assertion failed: x is not equal to <span class="hljs-number">10</span>
</code></pre><p>This is a helpful way to include runtime checks in your code and log informative messages if certain conditions are not met.</p>
<h3 id="heading-34-consolecount-and-consolecountreset">3.4 <code>console.count</code> and <code>console.countReset</code></h3>
<p>The <code>console.count()</code> method allows you to count the number of times a particular piece of code is executed. You can also reset the count using <code>console.countReset()</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Log and count the number of times "greet" is called</span>
  <span class="hljs-built_in">console</span>.count(<span class="hljs-string">"greet"</span>);

  <span class="hljs-comment">// Return a greeting message</span>
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello!"</span>;
}

<span class="hljs-comment">// Call greet() two times</span>
greet();
greet();

<span class="hljs-comment">// Reset the counter for "greet"</span>
<span class="hljs-built_in">console</span>.countReset(<span class="hljs-string">"greet"</span>);

<span class="hljs-comment">// Call greet() again</span>
greet();
</code></pre>
<p><code>console.count("greet");</code>: This line logs the number of times "greet" is called. The count is initially 1 when <code>greet()</code> is first called and increments with each subsequent call.</p>
<p>If you run this code in a browser's developer console, the output might look like this:</p>
<pre><code>greet: <span class="hljs-number">1</span>
<span class="hljs-attr">greet</span>: <span class="hljs-number">2</span>
<span class="hljs-attr">greet</span>: <span class="hljs-number">1</span>
</code></pre><p>The first two calls to <code>greet</code> increment the count, and the third call, after the reset, starts the count again from 1. The count is specific to the label "greet."</p>
<h3 id="heading-35-consoletime-and-consoletimeend">3.5 <code>console.time</code> and <code>console.timeEnd</code></h3>
<p>The <code>console.time()</code> and <code>console.timeEnd()</code> methods allow you to measure the time taken by a block of code to execute.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.time(<span class="hljs-string">"timer"</span>);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000000</span>; i++) {

<span class="hljs-comment">// Some time-consuming operation</span>

}

<span class="hljs-built_in">console</span>.timeEnd(<span class="hljs-string">"timer"</span>);
</code></pre>
<p>In the above example,</p>
<ul>
<li><code>console.time("timer");</code>: This  starts a timer with the label "timer" when the loop </li>
<li><code>console.timeEnd("timer");</code>: This stops the timer labeled "timer" and logs the elapsed time to the console.</li>
</ul>
<p>If you run this code in a browser's developer console, the output will look like this:</p>
<pre><code>timer: XXms
</code></pre><p>The "XX" will be replaced with the actual time taken by the loop to execute the time-consuming operation. This measurement is useful for profiling and understanding the performance of a specific code block or operation.</p>
<h3 id="heading-36-consoletrace">3.6 <code>console.trace</code></h3>
<p>The <code>console.trace()</code> method outputs a stack trace to the console. This can be helpful for debugging purposes to see the call stack leading to the current execution point.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Call the bar function</span>
  bar();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bar</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Log a trace of the call stack</span>
  <span class="hljs-built_in">console</span>.trace(<span class="hljs-string">"Trace:"</span>);
}

<span class="hljs-comment">// Call the foo function</span>
foo();
</code></pre>
<ul>
<li><code>foo</code> function: Calls the <code>bar</code> function.</li>
<li><code>bar</code> function: Logs a trace of the call stack using <code>console.trace</code>.</li>
<li><code>foo</code> is called: This triggers the call to <code>bar</code>, and the trace is logged.</li>
</ul>
<p>If you run this code in a browser's developer console, the output might look something like this:</p>
<pre><code>Trace:
bar @ (index):<span class="hljs-number">8</span>
foo @ (index):<span class="hljs-number">3</span>
(anonymous) @ (index):<span class="hljs-number">12</span>
</code></pre><p>The output shows the call stack at the time <code>console.trace</code> was called. It includes information about the functions in the stack, such as the function names and their respective locations in the code. In this example, the call stack is displayed in reverse order, with the most recent function call at the top.</p>
<h3 id="heading-37-consoledir">3.7 <code>console.dir</code></h3>
<p>The <code>console.dir()</code> method allows you to display an interactive listing of the properties of a JavaScript object.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Chris"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span> };

<span class="hljs-comment">// Display an interactive listing of the properties of the object</span>
<span class="hljs-built_in">console</span>.dir(obj);
</code></pre>
<p>The <code>console.dir</code> method is commonly used to log an interactive representation of an object to the console. If you run this code in a browser's developer console, the output might look something like this:</p>
<pre><code><span class="hljs-built_in">Object</span>
  <span class="hljs-attr">age</span>: <span class="hljs-number">25</span>
  <span class="hljs-attr">name</span>: <span class="hljs-string">"Chris"</span>
  <span class="hljs-attr">__proto__</span>: <span class="hljs-built_in">Object</span>
</code></pre><p>This output provides a visual representation of the object's properties, including their names and values. It also shows the prototype of the object (<code>__proto__</code>). The <code>console.dir</code> method is particularly useful when dealing with complex objects or nested structures, as it allows you to explore the object's properties in a more interactive way than <code>console.log</code>.</p>
<h3 id="heading-38-consoleclear">3.8 <code>console.clear</code></h3>
<p>The <code>console.clear()</code> method clears the console of all previous log messages.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message 1"</span>);

<span class="hljs-built_in">console</span>.clear();

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message 2"</span>);
</code></pre>
<p>In the above example, <code>console.clear()</code> will clear the console before logging "Message 2".</p>
<h2 id="heading-4-best-practices-for-console-logging">4. Best Practices for Console Logging</h2>
<p>While console logging can be a powerful debugging tool, it's important to use it judiciously and follow best practices:</p>
<ul>
<li><strong>Avoid Excessive Logging</strong>: Too many log messages can clutter the console and make it difficult to find relevant information. Only log what is necessary for debugging.</li>
<li><strong>Use Descriptive Messages</strong>: When logging messages, use descriptive labels to make it clear what each message represents.</li>
<li><strong>Use Console Methods Wisely</strong>: Choose the appropriate console method (<code>log</code>, <code>table</code>, <code>group</code>, and so on) based on the type of data you are logging and how you want it to be displayed.</li>
<li><strong>Remove Debugging Code in Production</strong>: Remember to remove or disable console logging statements in your production code to avoid unnecessary overhead.</li>
</ul>
<h2 id="heading-5-conclusion">5. Conclusion</h2>
<p>Console logging is a powerful tool for debugging JavaScript code. By leveraging advanced console logging tricks such as <code>console.table</code>, <code>console.group</code>, <code>console.assert</code>, and others, you can streamline your debugging process and gain deeper insights into your code's behavior.</p>
<p>In this comprehensive guide, we covered various console logging tricks, along with examples demonstrating how to use them effectively. By incorporating these techniques into your development workflow and following best practices, you can become a more efficient and effective developer.</p>
<p>Experiment with these console logging tricks in your own projects to see how they can help you debug and understand your code better. Happy debugging!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Chrome DevTools – Simple Strategies for Smarter Web Development ]]>
                </title>
                <description>
                    <![CDATA[ As a web developer, there are many tools out there – in addition to your code editor – that can make you more efficient.  It doesn't matter if you're just starting out or have been coding for years. Knowing how to effectively use Developer Tools (Dev... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/chrome-devtools/</link>
                <guid isPermaLink="false">66c5a334215f782a032b1cb7</guid>
                
                    <category>
                        <![CDATA[ Google Chrome ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ devtools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Problem Solving ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ophy Boamah ]]>
                </dc:creator>
                <pubDate>Thu, 15 Feb 2024 16:12:02 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/ChromeDevTools-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a web developer, there are many tools out there – in addition to your code editor – that can make you more efficient. </p>
<p>It doesn't matter if you're just starting out or have been coding for years. Knowing how to effectively use Developer Tools (DevTools for short) can significantly boost your development process. You can edit pages on the fly, quickly spot issues, and deeply understand your site's performance. </p>
<p>All major browsers have their own DevTools that let you examine the code of a webpage, evaluate its metrics, and run some tests alongside. This article will discuss Chrome's DevTools, as it's the industry standard.</p>
<h2 id="heading-table-of-contents">Table of contents:</h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-chrome-devtools">What is Chrome DevTools?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-open-chrome-devtools">How to Open Chrome DevTools</a></li>
<li><a class="post-section-overview" href="#heading-keyboard-shortcuts-for-easy-navigation">Keyboard shortcuts for Easy Navigation</a></li>
<li><a class="post-section-overview" href="#heading-key-chrome-devtools-features">Key Chrome DevTools Features</a></li>
<li><a class="post-section-overview" href="#heading-practical-devtools-use-cases">Practical DevTools Use Cases</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h1 id="heading-what-is-chrome-devtools">What is Chrome DevTools?</h1>
<p>Chrome DevTools is a set of tools that are essential for diagnosing and solving web development challenges, directly within the Google Chrome browser. </p>
<p>It gives you direct access to a website's inner workings - to inspect HTML and CSS, debug JavaScript, analyze performance, and see the immediate impact of your code, all in realtime. </p>
<p>This direct access to a website's inner workings is crucial for diagnosing issues quickly and efficiently, ensuring your web applications are both performant and bug-free.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/DevToolsScreenshots-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>A grid of elements, console, performance and network panels screenshots</em></p>
<h1 id="heading-how-to-open-chrome-devtools">How to Open Chrome DevTools</h1>
<p>To open DevTools in your Chrome browser, you can either:</p>
<ol>
<li>Right-click on any webpage and select inspect from the list of options.</li>
<li>Use the shortcut (command + option + I on Mac or control + shift + I on Windows). </li>
<li>Click the three dot icon next to your profile picture on your Chrome browser, choose 'More Tools' and 'Developer Tools' from the second option box.</li>
</ol>
<p>It usually opens in a split screen interface, either below your current webpage or beside it. Once open, its features line up as tabs at the top of the DevTools window. These tabs include: Elements, Console, Source, Network, Application, Security, Memory, Performance, Audits.</p>
<h2 id="heading-keyboard-shortcuts-for-easy-navigation">Keyboard Shortcuts for Easy Navigation</h2>
<ol>
<li>Use Cmd or Ctrl + Shift + C to open the Elements panel</li>
<li>Use Cmd or Ctrl + Shift + J to open the Console panel</li>
<li>Use Cmd or Ctrl + ] to move forward to the next panel </li>
<li>Use Cmd or Ctrl + [ to move back to the previous panel </li>
</ol>
<h1 id="heading-key-chrome-devtools-features">Key Chrome DevTools Features</h1>
<p>DevTools is packed with features essential for web developers to streamline various aspects of their workflow. Let's look at a few of them in some detail now.</p>
<h2 id="heading-elements-panel">Elements Panel</h2>
<p>This panel is used for inspecting and modifying the HTML and CSS of a webpage in real-time, which is great for debugging layout issues or experimenting with new styles before applying them in your actual code. You also get to see how the DOM (Document Object Model) is structured. </p>
<p>Imagine fine-tuning your website's footer appearance (background color, font size) directly in your browser and seeing the results instantly. </p>
<p>With DevTools open, click on the Elements tab to access it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/elpanel-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot of Chrome DevTools' Elements panel</em></p>
<h2 id="heading-console-panel">Console Panel</h2>
<p>This panel serves as your interactive playground for JavaScript within the browser. Whether you're tracking down an elusive bug with a quick <code>console.log()</code> or experimenting with DOM elements, in the Console panel you can test snippets of JavaScript and view any logs or errors in the currently loaded webpage. </p>
<p>To use it, simply open DevTools and select the "Console" tab or use the shortcut (option + command + J on Mac or contrl + shift + J on Windows).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/clpanel-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot of Chrome DevTools' Console panel</em></p>
<h2 id="heading-network-panel">Network Panel</h2>
<p>This panel gives you an overview of all network activity on your webpage – from tracking every resource that is loaded to how your site communicates with servers. </p>
<p>If you've wondered why your website takes forever to load or why some API requests seem to vanish into thin air, the Network panel is your go-to as it provides insights into the success or failure of API calls. </p>
<p>To access it, open DevTools and navigate to the "Network" tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/netpanel-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot of Chrome DevTools' Network panel</em></p>
<h2 id="heading-performance-panel">Performance Panel</h2>
<p>This panel is used for capturing and analyzing a website's performance metrics. It shows all the activities happening when interacting with a page. </p>
<p>When your web app starts to crawl under heavy usage, the Performance panel can pinpoint where the performance bottlenecks lie so that you can resolve these issues, ensuring your app runs smoothly. </p>
<p>With DevTools open, click on the "Performance" tab to use it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/perfpanel-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot of Chrome DevTools' Performance panel</em></p>
<p>The above are only a handful of the panels available, but they're by far the most popular and must-knows. Using them properly will make your development processes more intuitive and rewarding.</p>
<h1 id="heading-practical-devtools-use-cases">Practical DevTools Use Cases</h1>
<p>In the following interactive examples, I intentionally created the mini project in Codepen <strong>with issues</strong> to simulate real-world debugging scenarios using Chrome DevTools. </p>
<p>I figured it'd be a great way to highlight the practical uses of certain DevTools panels and features in identifying bugs and troubleshooting right in the browser. </p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Chrome browser (<a target="_blank" href="https://support.google.com/chrome/answer/95346?hl=en&amp;co=GENIE.Platform%3DDesktop">Click this link to download</a>)</li>
<li>A basic understanding of HTML, CSS, and JavaScript</li>
<li><a target="_blank" href="https://codepen.io/ophyboamah/full/rNpZZwo">Codepen</a></li>
</ul>
<p></p><p>
  <span>See the Pen <a href="https://codepen.io/ophyboamah/pen/rNpZZwo">
  Modal Window</a> by Ophy Boamah (<a href="https://codepen.io/ophyboamah">@ophyboamah</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p><p></p>


<h2 id="heading-how-to-debug-html-and-css-with-the-elements-panel">How to Debug HTML and CSS with the Elements Panel</h2>
<p>Our mini project contains a modal that, upon clicking, should display a modal window with some important information. But there's a bug preventing this from happening. </p>
<p>This situation sets the stage for a practical demonstration of how you can use the Elements Panel to troubleshoot and resolve styling and structural issues.</p>
<pre><code>&lt;body&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"show-modal"</span>&gt;</span>Click me to learn a secret 🤫<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal hidden"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"close-modal"</span>&gt;</span><span class="hljs-symbol">&amp;times;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hey Ophy here 👋🏾<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      I lead Women Who Code Frontend, a global remote community of 3,000+ women frontend devs and enthusiasts. Find us on beacons.ai/wwcodefrontend
    <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="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"overlay hidden"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"script.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
&lt;/body&gt;
</code></pre><pre><code class="lang-css"><span class="hljs-selector-class">.hidden</span> {
  <span class="hljs-attribute">display</span>: none;
}

<span class="hljs-selector-class">.modal</span> {
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(-<span class="hljs-number">50%</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">70%</span>;

  <span class="hljs-attribute">background-color</span>: white;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">6rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">3rem</span> <span class="hljs-number">5rem</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.3</span>);
  <span class="hljs-attribute">z-index</span>: <span class="hljs-number">10</span>;
}
</code></pre>
<p>In our modal's HTML code above, we've added the class name 'modal hidden' which has a corresponding styling with the CSS property of <code>display:none</code> that is set to hide the modal when the page is loaded initially and only display it when the button is clicked.</p>
<h3 id="heading-step-1-initial-inspection">✅ Step 1 - Initial inspection:</h3>
<p>Attempt to trigger the modal by clicking on the 'Click me to learn a secret' button. Since we've set that up not to work, right-click on the area where the modal should appear and choose "Inspect" to open DevTools' Elements Panel.</p>
<h3 id="heading-step-2-diagnose-visibility-issues">✅ Step 2 - Diagnose visibility issues:</h3>
<p>In the Elements Panel, locate the modal in the DOM to see that the modal is present but not visible. This confirms that the bug is caused within our CSS code <code>display: hidden</code>. </p>
<p>As soon as you click on the modal in the DOM, any corresponding CSS classes will be pulled up within Styles at the bottom section of the Elements panel. You can toggle some properties on and off or type others to see the effects in real-time.</p>
<p>Manually change the class name from <code>modal hidden</code> to <code>modal block</code> to trigger the right properties that'll cause the modal to show.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/modalblock.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot of debugging the modal's HTML, CSS in Elements panel</em></p>
<h3 id="heading-step-3-center-the-modal">✅ Step 3 - Center the modal:</h3>
<p>Now the modal is visible, but it's displayed at the top – which is different from where we'd like it to be (that is, in the center of the page).</p>
<p>To change this, modify the <code>transform</code> property to <code>translate(-50%, -50%)</code> by adding the second <code>-50%</code> and ensure that <code>top: 50%</code>, and <code>left: 50%</code> are correctly set to center the modal on the screen.</p>
<h3 id="heading-step-4-enhance-the-appearance">✅ Step 4 - Enhance the appearance:</h3>
<p>You can go further to refine the modal's appearance by tweaking its <code>background-color</code>, <code>padding</code>, or other stylistic properties directly within the Styles to achieve the desired look and feel.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/ChromeDevTools.gif" alt="Image" width="600" height="400" loading="lazy">
<em>A GIF fixing the modal in Chrome DevTools' Elements panel</em></p>
<h2 id="heading-debug-javascript-with-the-sources-panel">Debug JavaScript with the Sources Panel</h2>
<p>I added a bug in the JavaScript code of our modal mini project to prevent it from opening when the button is clicked. </p>
<p>In the real world, this would cause neither the open nor close commands to trigger any action, which would leave users unable to interact with the content and frustrated as a result. Let's troubleshoot and debug this issue in the Sources Panel.</p>
<p>In the code below, the openModal function is set to remove the indicated classes. However, this doesn't work because we deliberately misspelled <code>hidden</code>. </p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Introducing a bug: Incorrectly spelling 'hidden' as 'hiddn'</span>
<span class="hljs-keyword">const</span> openModal = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  modal.classList.remove(<span class="hljs-string">"hiddn"</span>); <span class="hljs-comment">// Intentional bug</span>
  overlay.classList.remove(<span class="hljs-string">"hidden"</span>);

  <span class="hljs-comment">// Fetch data from a real API and display in the modal</span>
};
</code></pre>
<h3 id="heading-step-1-set-up-breakpoints">✅ Step 1 - Set up breakpoints:</h3>
<p>Open Chrome DevTools and navigate to the Sources Panel. Here, find the JavaScript file that includes the modal functionality (in our example its pen.js). </p>
<p>The openModal function contains the logic for displaying the modal on the screen. This function will include a line where the modal element's class is manipulated to remove a "hidden" class. </p>
<p>Click on the number next to this code line in DevTools. A blue (or sometimes red, depending on the theme) icon appears next to the line number, indicating that a breakpoint has been set. This breakpoint will pause the execution of our JavaScript code as soon as it reaches this line.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/soscreenshot.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot of setting breakpoints the modal's JS in Sources panel</em></p>
<p>Breakpoints pause code execution at critical points, allowing you to inspect the current state of variables and understand the flow of execution. This step is crucial for identifying where the code deviates from expected behaviour.</p>
<h3 id="heading-step-2-examine-the-code-execution-flow">✅ Step 2 - Examine the code execution flow:</h3>
<p>With our breakpoint in place, try to open the modal by clicking on its button. Execution of our JavaScript code now pauses at our breakpoint, which enables us to step through the code line by line. </p>
<p>This is an opportunity to observe variables, function calls, look for anomalies such as misnamed functions, incorrect logic, or uncaught exceptions that could explain why the modal isn't working. </p>
<p>In our case it's because we intentionally misspelled the class name <code>hidden</code> as <code>hiddn</code>. Fix that in the code to get the modal working again.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/ChromeDevTools--2-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>A GIF troubleshooting the modal bug in Chrome DevTools' Elements panel</em></p>
<h2 id="heading-optimize-performance-with-the-network-panel">Optimize Performance with the Network Panel</h2>
<p>Here I've added a fetch function that makes an API call to a live endpoint (<a target="_blank" href="https://jsonplaceholder.typicode.com/posts/1"><code>https://jsonplaceholder.typicode.com/posts/1</code></a>). This is an excellent opportunity to explore the Network Panel's capabilities in diagnosing and understanding network-related problems.</p>
<p>From the code below, you can see that the openModal function doesn't only open the modal but also makes an API call to the <code>jsonplaceholder</code> endpoint to fetch some data. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> openModal = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  fetch(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts/1'</span>)
    .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
    .then(<span class="hljs-function"><span class="hljs-params">json</span> =&gt;</span> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'modal-content'</span>).innerText = json.title)
    .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 loading the content:'</span>, error));
};
</code></pre>
<h3 id="heading-step-1-initiate-the-api-call">✅ Step 1 - Initiate the API call:</h3>
<p> On the modal project UI, click on the 'Click me to learn a secret' button. Though the modal does not visibly activate, because of the fetch logic within the openModal function, an API call will be made.</p>
<h3 id="heading-step-2-network-panel-inspection">✅ Step 2 - Network Panel Inspection:</h3>
<p>Ideally, your Network Panel should be open before clicking the button, but you can also reverse the steps. Detailed insights on your API request such as the request's method, status code, response and the time it took to complete, will be available under headers, preview, response, initiator and timing tabs respectively. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/netscreenshot.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot overview of API request in Network panel</em></p>
<h3 id="heading-step-3-simulating-network-conditions">✅ Step 3 - Simulating Network Conditions:</h3>
<p>Use the Network Panel's throttling feature to mimic various network speeds like offline or slow 3G to see how the API request behaves under constrained conditions. </p>
<p>From this you can compare how different network speeds can affect application performance. This will teach you the importance of optimizing data loading strategies to enhance user experience, especially on slower connections.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/ChromeDevTools--1-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>A GIF observing API requests and responses in Chrome DevTools' Network panel</em></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Bringing Chrome DevTools into your web development routine is not just about fixing bugs. It's about streamlining your workflow, making your sites more accessible, and boosting their performance. </p>
<p>Through our modal window mini-project, we've seen firsthand how DevTools can address a wide array of development challenges, but that’s merely scratching the surface of what it can do. </p>
<p>As you continue to explore its capabilities and familiarize yourself with its features, you'll find it's an invaluable companion on your web development journey – designed to make your development process not just faster, but also more rewarding.</p>
<ul>
<li><a target="_blank" href="https://developer.chrome.com/docs/devtools">The Official Chrome DevTools documentation</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/learn-how-to-use-the-chrome-devtools-to-troubleshoot-websites/">How to use the Chrome DevTools to troubleshoot websites</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use SonarLint to Write Cleaner Code ]]>
                </title>
                <description>
                    <![CDATA[ When you're building a coding project, the better it is, the more fun it'll be to use. And the prouder you'll be of your hard work, right? Also, writing quality and performant code helps your program or website work as expected – which should be ever... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-sonarlint-to-write-cleaner-code/</link>
                <guid isPermaLink="false">66d4609233b83c4378a51822</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ workflow ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Okosa Leonard ]]>
                </dc:creator>
                <pubDate>Thu, 18 Jan 2024 23:58:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/slint.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you're building a coding project, the better it is, the more fun it'll be to use. And the prouder you'll be of your hard work, right?</p>
<p>Also, writing quality and performant code helps your program or website work as expected – which should be every developer's goal.</p>
<p><a target="_blank" href="https://docs.sonarsource.com/sonarcloud/improving/sonarlint/">SonarLint</a> is a tool that helps you make sure your code is top-notch. It's like having a friendly guide who checks your code to see if it's well-written and doesn't have mistakes.</p>
<h2 id="heading-what-is-sonarlint">What is SonarLint?</h2>
<p>SonarLint is an open-source code analysis tool that helps you find and resolve security and code quality problems in your source code as you're writing it. This plugin works with several integrated development environments (IDEs), including well-known ones like IntelliJ IDEA, Eclipse, and Visual Studio.</p>
<p>SonarLint's main purpose is to give you immediate feedback on possible problems with your code, including security flaws, bugs, and other recommended practices for programming. SonarLint analyzes code in the background while you create or change it in your IDE, giving you instant feedback and frequently exposing problems right in the code editor.</p>
<p>SonarLint is a component of the larger SonarQube ecosystem.</p>
<p>In this article, I'll teach you how to use SonarLint to help you write quality code.</p>
<h2 id="heading-why-is-sonarlint-useful">Why is SonarLint Useful?</h2>
<p>Let's imagine that building a website is like constructing a house. You want your house to be safe and well-designed, right? Well, SonarLint is like having a thorough inspector who checks your work as you build, making sure everything is just right.</p>
<p>Here's why SonarLint is important in web development:</p>
<ol>
<li><p><strong>Catch Mistakes Early (Code Quality):</strong> Assuming you were building a staircase, and accidentally put a step in the wrong place, SonarLint is like a smart friend who tells you immediately, "Hey, you might have made a mistake here!" It helps catch small errors in your code before they become big problems.</p>
</li>
<li><p><strong>Follow the Blueprint (Coding Standards):</strong> When building a house, you follow a blueprint to make sure everything fits together. In coding, there are also rules (like a blueprint) on how to write good code. SonarLint helps you stick to these rules, making your code easy to read and work with.</p>
</li>
<li><p><strong>Keep It Secure (Security):</strong> Just like you'd want your house to have good locks on the doors, you'd want your website to be secure. SonarLint checks your code for potential security issues, ensuring there are no "unlocked doors" that could let bad things happen.</p>
</li>
<li><p><strong>Work Together Well (Collaboration):</strong> Imagine that each builder in your team used a different kind of tool. It would be chaos! SonarLint helps your team work together smoothly by making sure everyone follows the same coding standards. This way, everyone can understand and contribute to the project easily.</p>
</li>
<li><p><strong>Save Time and Effort (Efficiency):</strong> Fixing mistakes after the whole house is built would take a lot of time and effort. SonarLint helps you fix issues as you go, saving you from returning and redoing things. It's like having a helpful friend who stops you from making mistakes in the first place.</p>
</li>
<li><p><strong>Learn and Improve (Education):</strong> SonarLint does not only point out mistakes but also explains why they might be a problem. It's like having a coding teacher who helps you understand how to write better code. This way, you learn and become a better developer over time.</p>
</li>
</ol>
<p>So, in the world of web development, SonarLint is your coding buddy, and it makes sure your JavaScript "house" is strong, secure, and well-organized from the ground up. It's a valuable tool in your workflow and helps you create high-quality websites that everyone can enjoy.</p>
<p>But you still may be wondering why you need this tool. You have a debugger already installed in your IDE and it can already track the errors in your environment.</p>
<p>Well, integrating SonarLint complements your debugger by focusing on code quality and security during development.</p>
<p>While a debugger helps to find and fix runtime issues, SonarLint analyzes code in real time, identifies bugs and potential vulnerabilities, and enforces coding standards.</p>
<p>You can also customize and configure coding rules based on your project's specific requirements and coding standards.</p>
<p>This proactive approach enhances overall code quality and ensures cleaner, more maintainable code before it reaches the debugging stage. This leads to fewer errors and smoother development workflows.</p>
<p>Before we get into the details of how to set up and use SonarLint, let's look at what makes code high-quality.</p>
<h2 id="heading-code-quality-metrics">Code Quality Metrics</h2>
<p>Be the best cookbook author! When writing code there are specific guidelines you must follow.</p>
<p>Just like when you're cooking up a new recipe or want to follow a traditional one, you should make sure anyone who reads it can follow along, and that the recipe you wrote down results in a good dish.</p>
<p>In the same sense, when writing code, it's always important to make your code readable so that other developers can understand it easily and so your code works as it's supposed to. Code quality metrics are like measuring how well you followed the recipe.</p>
<p>Here's a breakdown:</p>
<p><strong>Readability (Clarity):</strong> This is similar to making sure your recipe instructions are clear. The code should be easy for others (or future you) to understand.</p>
<p><strong>Maintainability (Ease of Changes):</strong> If you had to change ingredients in your recipe (code), it should be easy to switch things without chaos.</p>
<p><strong>Performance (Speed):</strong> As you'd want your meal ready quickly, efficient code is expected to run fast. Code quality metrics check how fast your code is executed.</p>
<p><strong>Reliability (Consistency):</strong> A good recipe always tastes the same. Similarly, reliable code consistently produces the correct results.</p>
<p><strong>Security (Safety):</strong> Just like checking if ingredients are safe to eat, code quality metrics look for potential dangers in your code that could be exploited.</p>
<p>These should be your goals when writing quality code. And SonarLint can help you accomplish them.</p>
<h2 id="heading-how-to-set-up-sonarlint-and-integrate-with-your-ide">How to Set Up SonarLint and Integrate with Your IDE</h2>
<p>An IDE (Integrated Development Environment) is a software application that helps developers write and debug code more effectively. IDEs include a code editor and compiler or interpreter.</p>
<p>In this article, you'll see how to install SonarLint using VS Code extensions.</p>
<h3 id="heading-how-to-install-sonarlint-with-vs-code">How to Install SonarLint with VS Code</h3>
<p>First, install VS Code or open the application if you've already installed it.</p>
<p>Next, head over to the Extensions tab on VS Code and download the SonarLint extension.</p>
<p>To use the SonarLint extension for JavaScript, TypeScript, or CSS, you should have a minimum version of <code>14.17.0</code> of Node.js installed on your system (especially if you want to use <a target="_blank" href="https://docs.sonarsource.com/sonarlint/vs-code/team-features/connected-mode/">Connected Mode</a> with Sonar Cloud).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/sonar.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Install SonarLint in VS Code</em></p>
<p>Now that you've installed SonarLint, running an analysis on your code should be easy and it should start immediately after you open a new file.</p>
<p>This means SonarLint will start working and catching errors in your code as you write them on your IDE. Now let's look at an example in the next section.</p>
<h3 id="heading-how-to-use-sonarlint-in-your-ide">How to Use SonarLint in Your IDE</h3>
<p>Now let's look at how you can get the best out of SonarLint on your IDE. SonarLint is also a wonderful teacher, helping you better understand how to write clean code and giving you more information about why you have an error.</p>
<p>So instead of scouring the web to figure out what's wrong with your code, SonarLint explains why it has given you an error.</p>
<p>Here's an example of how to use it.</p>
<p>To be able to see the interface where we'll be working, open your terminal on VS Code – you can use Ctrl + backtick (`) to do this. I'm currently working on a project in React.js, and I didn't notice that I have duplicate border property names in my CSS class. Luckily, SonarLint caught this issue.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/sonarlint.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>A CSS error caught by SonarLint</em></p>
<p>If you click on the light bulb, you'll see an option to fix the code by deactivating the CSS rule or to be blunt removing the extra border which I have in my CSS class in this instance. There's also another option for opening a description rule so you can understand why you're getting that error.</p>
<p>So SonarLint gives you two options:</p>
<ol>
<li><p>It offers an option that gives you the ability and resources to understand why you have that error with the "Open description of rule".</p>
</li>
<li><p>It offers a solution to the error of the code which it has found.</p>
</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/sonarlint-another.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Options offered by SonarLint to help fix and understand this problem</em></p>
<p>If you click on the open description rule, SonarLint opens another tab in VS Code to help you understand why it has thrown that error and how you can write cleaner/better code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/sonarlint-teacher.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Tab opened by SonarLint in VSCode to help understand the error</em></p>
<p>As you can see, SonarLint is an excellent teacher and your best buddy as you continue to build and work on your IDE.</p>
<p>Another great thing about SonarLint is that it works with multiple programming languages. So whatever programming language you're using, chances are that SonarLint can handle it.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>SonarLint is like having a coding buddy that helps you become a better programmer. As you write code, it's like having a teacher right there with you, pointing out ways to improve.</p>
<p>Imagine having a super-smart friend who does not just spot mistakes but also explains why they're wrong and shows you how to fix them.</p>
<p>Before your code gets to the testing stage, SonarLint checks for mistakes and makes sure your program runs smoothly. It's like having a superpower to catch issues early, saving you time and effort.</p>
<p>But that's not all! SonarLint is also like a security guard for your code. It watches out for any potential weak points that could let bad things happen. By learning from SonarLint, you can write better code and become more aware of keeping your code safe and secure.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Clean Code – Tips and Best Practices (Full Handbook) ]]>
                </title>
                <description>
                    <![CDATA[ Hi everyone! In this handbook we're going to talk about writing "clean" code. It's a topic that used to confuse me a bit when I was starting out as a programmer, and I find that it has many nuances and possible interpretations. So in this article we'... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-clean-code/</link>
                <guid isPermaLink="false">66d45f073dce891ac3a967f6</guid>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ German Cocca ]]>
                </dc:creator>
                <pubDate>Mon, 15 May 2023 14:43:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/pexels-ken-tomita-389819.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi everyone! In this handbook we're going to talk about writing "clean" code. It's a topic that used to confuse me a bit when I was starting out as a programmer, and I find that it has many nuances and possible interpretations.</p>
<p>So in this article we'll talk about what the term "clean code" means, why it's important, how can we assess whether a codebase is clean or not. You'll also learn some best practices and conventions you can follow to make your code cleaner.</p>
<p>Let's go!</p>
<h1 id="heading-table-of-contents">Table of Contents</h1>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-does-it-mean-to-write-clean-code-and-why-should-i-care">What does it mean to write "clean code" and why should I care?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-can-i-assess-whether-a-codebase-is-clean-or-not">How can I assess whether a codebase is clean or not?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tips-and-conventions-to-write-cleaner-code">Tips and conventions to write cleaner code</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-effectiveness-efficiency-and-simplicity">Effectiveness, efficiency and simplicity</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-format-and-syntax">Format and syntax</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-naming">Naming</a></p>
</li>
<li><p><a class="post-section-overview" href="#conciseness-versus-clarity">Conciseness versus clarity</a></p>
</li>
<li><p><a class="post-section-overview" href="#re-usability">Re-usability</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-clear-flow-of-execution">Clear flow of execution</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-single-responsibility-principle">Single responsibility principle</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-having-a-single-source-of-truth">Having a "single source of truth"</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-only-expose-and-consume-data-you-need">Only expose and consume information you need</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-modularization">Modularization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-folder-structures">Folder structures</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-documentation">Documentation</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping up</a></p>
</li>
</ul>
<h1 id="heading-what-does-it-mean-to-write-clean-code-and-why-should-i-care">What Does it Mean to Write "Clean Code" and Why Should I Care?</h1>
<p>Clean code is a term used to describe computer code that is easy to read, understand, and maintain. Clean code is written in a way that makes it simple, concise, and expressive. It follows a set of conventions, standards, and practices that make it easy to read and follow.</p>
<p>Clean code is free from complexity, redundancy, and other code smells and anti-patterns that can make it difficult to maintain, debug, and modify.</p>
<p>I can't overstate the importance of clean code. When code is easy to read and understand, it makes it easier for developers to work on the codebase. This can lead to increased productivity and reduced errors.</p>
<p>Also, when code is easy to maintain, it ensures that the codebase can be improved and updated over time. This is especially important for long-term projects where code must be maintained and updated for years to come.</p>
<h1 id="heading-how-can-i-assess-whether-a-codebase-is-clean-or-not">How Can I Assess Whether a Codebase is Clean or Not?</h1>
<p>You can assess clean code in a variety of ways. Good documentation, consistent formatting, and a well-organized codebase are all indicators of clean code.</p>
<p>Code reviews can also help to identify potential issues and ensure that code follows best practices and conventions.</p>
<p>Testing is also an important aspect of clean code. It helps to ensure that code is functioning as expected and can catch errors early.</p>
<p>There are several tools, practices, and conventions you can implement to ensure a clean codebase. By implementing these tools and practices, developers can create a codebase that is easy to read, understand, and maintain.</p>
<p>It's also important to remember that there's an inevitable amount of subjectivity related to this topic, and there are a number of different opinions and tips out there. What might look clean and awesome for one person or one project might not be so for another person or another project.</p>
<p>But still there are a few general conventions we can follow to achieve cleaner code, so let's jump into that now.</p>
<h1 id="heading-tips-and-conventions-to-write-cleaner-code">Tips and Conventions to Write Cleaner Code</h1>
<h2 id="heading-effectiveness-efficiency-and-simplicity">Effectiveness, Efficiency and Simplicity</h2>
<p>Whenever I need to think about how to implement a new feature into an already existing codebase, or how to tackle the solution of a specific problem, I always prioritize this three simple things.</p>
<h3 id="heading-effectiveness">Effectiveness</h3>
<p>First, our code should be <strong>effective</strong>, meaning it should solve the problem it's supposed to solve. Of course this is the most basic expectation we could have for our code, but if our implementation doesn't actually work, it's worthless to think about any other thing.</p>
<h3 id="heading-efficiency">Efficiency</h3>
<p>Second, once we know our code solves the problem, we should check if it does so <strong>efficiently</strong>. Does the program run using a reasonable amount of resources in terms of time and space? Can it run faster and with less space?</p>
<p>Algorithmic complexity is something you should be aware of in order to evaluate this. If you're not familiar with it, you can check <a target="_blank" href="https://www.freecodecamp.org/news/introduction-to-algorithms-with-javascript-examples/#algorithmic-complexity">this article I wrote</a>.</p>
<p>To expand upon efficiency, here are two examples of a function that calculates the sum of all numbers in an array.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Inefficient Example</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sumArrayInefficient</span>(<span class="hljs-params">array</span>) </span>{
  <span class="hljs-keyword">let</span> sum = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; array.length; i++) {
    sum += array[i];
  }
  <span class="hljs-keyword">return</span> sum;
}
</code></pre>
<p>This implementation of the <code>sumArrayInefficient</code> function iterates over the array using a <code>for</code> loop and adds each element to the <code>sum</code> variable. This is a valid solution, but it is not very efficient because it requires iterating over the entire array, regardless of its length.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Efficient example</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sumArrayEfficient</span>(<span class="hljs-params">array</span>) </span>{
  <span class="hljs-keyword">return</span> array.reduce(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b, <span class="hljs-number">0</span>);
}
</code></pre>
<p>This implementation of the <code>sumArrayEfficient</code> function uses the <code>reduce</code> method to sum the elements of the array. The <code>reduce</code> method applies a function to each element of the array and accumulates the result. In this case, the function simply adds each element to the accumulator, which starts at 0.</p>
<p>This is a more efficient solution because it only requires a single iteration over the array and performs the summing operation on each element as it goes.</p>
<h3 id="heading-simplicity">Simplicity</h3>
<p>And last comes <strong>simplicity</strong>. This is the toughest one to evaluate because its subjective, it depends on the person who reads the code. But some guidelines we can follow are:</p>
<ol>
<li><p>Can you easily understand what the program does at each line?</p>
</li>
<li><p>Do functions and variables have names that clearly represent their responsibilities?</p>
</li>
<li><p>Is the code indented correctly and spaced with the same format all along the codebase?</p>
</li>
<li><p>Is there any documentation available for the code? Are comments used to explain complex parts of the program?</p>
</li>
<li><p>How quick can you identify in which part of the codebase are certain features of the program? Can you delete/add new features without the need of modifying many other parts of the code?</p>
</li>
<li><p>Does the code follow a modular approach, with different features separated in components?</p>
</li>
<li><p>Is code reused when possible?</p>
</li>
<li><p>Are the same architecture, design, and implementation decisions followed equally all along the codebase?</p>
</li>
</ol>
<p>By following and prioritizing these three concepts of effectiveness, efficiency, and simplicity, we can always have a guideline to follow when thinking about how to implement a solution. Now let's expand upon some of the guidelines that can help us simplify our code.</p>
<h2 id="heading-format-and-syntax">Format and Syntax</h2>
<p>Using consistent formatting and syntax throughout a codebase is an important aspect of writing clean code. This is because consistent formatting and syntax make the code more readable and easier to understand.</p>
<p>When code is consistent, developers can easily identify patterns and understand how the code works, which makes it easier to debug, maintain, and update the codebase over time. Consistency also helps to reduce errors, as it ensures that all developers are following the same standards and conventions.</p>
<p>Some of the things we should think about regarding format and syntax are:</p>
<ul>
<li><strong>Indentation and spacing</strong></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// bad indentation and spacing</span>
<span class="hljs-keyword">const</span> myFunc=<span class="hljs-function">(<span class="hljs-params">number1,number2</span>)=&gt;</span>{
<span class="hljs-keyword">const</span> result=number1+number2;
<span class="hljs-keyword">return</span> result;
}

<span class="hljs-comment">// good indentation and spacing</span>
<span class="hljs-keyword">const</span> myFunc = <span class="hljs-function">(<span class="hljs-params">number1, number2</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> result = number1 + number2
    <span class="hljs-keyword">return</span> result
}
</code></pre>
<p>Here we have an example of a same function, one done with no indentation and spacing, and the other properly spaced and indented. We can see that the second one is clearly easier to read.</p>
<ul>
<li><strong>Consistent syntax</strong></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Arrow function, no colons, no return</span>
<span class="hljs-keyword">const</span> multiplyByTwo = <span class="hljs-function"><span class="hljs-params">number</span> =&gt;</span> number * <span class="hljs-number">2</span>

<span class="hljs-comment">// Function, colons, return</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiplyByThree</span>(<span class="hljs-params">number</span>) </span>{
    <span class="hljs-keyword">return</span> number * <span class="hljs-number">3</span>;
}
</code></pre>
<p>Again, here we have very similar functions implemented with different syntax. The first one is an arrow function, with no colons and no return, while the other is a common function that uses colons and a return.</p>
<p>Both work and are just fine, but we should aim to always use the same syntax for similar operations, as it becomes more even and readable along the codebase.</p>
<p>Linterns and code formatters are great tools we can use in our projects to automatize the syntax and formatting conventions in our codebase. If you're not familiar with this tools, <a target="_blank" href="https://www.freecodecamp.org/news/using-prettier-and-jslint/">check out this other article of mine</a>.</p>
<ul>
<li><strong>Consistent case conventions</strong></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// camelCase</span>
<span class="hljs-keyword">const</span> myName = <span class="hljs-string">'John'</span>
<span class="hljs-comment">// PascalCase</span>
<span class="hljs-keyword">const</span> MyName = <span class="hljs-string">'John'</span>
<span class="hljs-comment">// snake_case</span>
<span class="hljs-keyword">const</span> my_name = <span class="hljs-string">'John'</span>
</code></pre>
<p>Same goes for the case convention we choose to follow. All of these work, but we should aim to consistently use the same one all through our project.</p>
<h2 id="heading-naming">Naming</h2>
<p>Naming variables and functions clearly and descriptively is an important aspect of writing clean code. It helps to improve the readability and maintainability of the codebase. When names are well-chosen, other developers can quickly understand what the variable or function is doing, and how it is related to the rest of the code.</p>
<p>Here are two examples in JavaScript that demonstrate the importance of clear and descriptive naming:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1: Poor Naming</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ab</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">let</span> x = <span class="hljs-number">10</span>;
  <span class="hljs-keyword">let</span> y = a + b + x;
  <span class="hljs-built_in">console</span>.log(y);
}

ab(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
</code></pre>
<p>In this example, we have a function that takes two parameters, adds them to a hardcoded value of 10, and logs the result to the console. The function name and variable names are poorly chosen and don't give any indication of what the function does or what the variables represent.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1: Good Naming</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTotalWithTax</span>(<span class="hljs-params">basePrice, taxRate</span>) </span>{
  <span class="hljs-keyword">const</span> BASE_TAX = <span class="hljs-number">10</span>;
  <span class="hljs-keyword">const</span> totalWithTax = basePrice + (basePrice * (taxRate / <span class="hljs-number">100</span>)) + BASE_TAX;
  <span class="hljs-built_in">console</span>.log(totalWithTax);
}

calculateTotalWithTax(<span class="hljs-number">50</span>, <span class="hljs-number">20</span>);
</code></pre>
<p>In this example, we have a function that calculates the total price of a product including tax. The function name and variable names are well-chosen and give a clear indication of what the function does and what the variables represent.</p>
<p>This makes the code easier to read and understand, especially for other developers who may be working with the codebase in the future.</p>
<h2 id="heading-conciseness-vs-clarity">Conciseness vs Clarity</h2>
<p>When it comes to writing clean code, it's important to strike a balance between conciseness and clarity. While it's important to keep code concise to improve its readability and maintainability, it's equally important to ensure that the code is clear and easy to understand. Writing overly concise code can lead to confusion and errors, and can make the code difficult to work with for other developers.</p>
<p>Here are two examples that demonstrate the importance of conciseness and clarity:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1: Concise function</span>
<span class="hljs-keyword">const</span> countVowels = <span class="hljs-function"><span class="hljs-params">s</span> =&gt;</span> (s.match(<span class="hljs-regexp">/[aeiou]/gi</span>) || []).length;
<span class="hljs-built_in">console</span>.log(countVowels(<span class="hljs-string">"hello world"</span>));
</code></pre>
<p>This example uses a concise arrow function and regex to count the number of vowels in a given string. While the code is very short and easy to write, it may not be immediately clear to other developers how the regex pattern works, especially if they are not familiar with regex syntax.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 2: More verbose and clearer function</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">countVowels</span>(<span class="hljs-params">s</span>) </span>{
  <span class="hljs-keyword">const</span> vowelRegex = <span class="hljs-regexp">/[aeiou]/gi</span>;
  <span class="hljs-keyword">const</span> matches = s.match(vowelRegex) || [];
  <span class="hljs-keyword">return</span> matches.length;
}

<span class="hljs-built_in">console</span>.log(countVowels(<span class="hljs-string">"hello world"</span>));
</code></pre>
<p>This example uses a traditional function and regex to count the number of vowels in a given string, but does so in a way that is clear and easy to understand. The function name and variable names are descriptive, and the regex pattern is stored in a variable with a clear name. This makes it easy to see what the function is doing and how it works.</p>
<p>It's important to strike a balance between conciseness and clarity when writing code. While concise code can improve readability and maintainability, it's important to ensure that the code is still clear and easy to understand for other developers who may be working with the codebase in the future.</p>
<p>By using descriptive function and variable names, and making use of clear and readable code formatting and comments, it's possible to write clean and concise code that is easy to understand and work with.</p>
<h2 id="heading-reusability">Reusability</h2>
<p>Code reusability is a fundamental concept in software engineering that refers to the ability of code to be used multiple times without modification.</p>
<p>The importance of code reusability lies in the fact that it can greatly improve the efficiency and productivity of software development by reducing the amount of code that needs to be written and tested.</p>
<p>By reusing existing code, developers can save time and effort, improve code quality and consistency, and minimize the risk of introducing bugs and errors. Reusable code also allows for more modular and scalable software architectures, making it easier to maintain and update codebases over time.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1: No re-usability</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateCircleArea</span>(<span class="hljs-params">radius</span>) </span>{
  <span class="hljs-keyword">const</span> PI = <span class="hljs-number">3.14</span>;
  <span class="hljs-keyword">return</span> PI * radius * radius;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateRectangleArea</span>(<span class="hljs-params">length, width</span>) </span>{
  <span class="hljs-keyword">return</span> length * width;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTriangleArea</span>(<span class="hljs-params">base, height</span>) </span>{
  <span class="hljs-keyword">return</span> (base * height) / <span class="hljs-number">2</span>;
}

<span class="hljs-keyword">const</span> circleArea = calculateCircleArea(<span class="hljs-number">5</span>);
<span class="hljs-keyword">const</span> rectangleArea = calculateRectangleArea(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>);
<span class="hljs-keyword">const</span> triangleArea = calculateTriangleArea(<span class="hljs-number">3</span>, <span class="hljs-number">7</span>);

<span class="hljs-built_in">console</span>.log(circleArea, rectangleArea, triangleArea);
</code></pre>
<p>This example defines three functions that calculate the area of a circle, rectangle, and triangle, respectively. Each function performs a specific task, but none of them are reusable for other similar tasks.</p>
<p>Additionally, the use of a hard-coded PI value can lead to errors if the value needs to be changed in the future. The code is inefficient since it repeats the same logic multiple times.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 2: Implementing re-usability</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateArea</span>(<span class="hljs-params">shape, ...args</span>) </span>{
  <span class="hljs-keyword">if</span> (shape === <span class="hljs-string">'circle'</span>) {
    <span class="hljs-keyword">const</span> [radius] = args;
    <span class="hljs-keyword">const</span> PI = <span class="hljs-number">3.14</span>;
    <span class="hljs-keyword">return</span> PI * radius * radius;
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (shape === <span class="hljs-string">'rectangle'</span>) {
    <span class="hljs-keyword">const</span> [length, width] = args;
    <span class="hljs-keyword">return</span> length * width;
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (shape === <span class="hljs-string">'triangle'</span>) {
    <span class="hljs-keyword">const</span> [base, height] = args;
    <span class="hljs-keyword">return</span> (base * height) / <span class="hljs-number">2</span>;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Shape "<span class="hljs-subst">${shape}</span>" not supported.`</span>);
  }
}

<span class="hljs-keyword">const</span> circleArea = calculateArea(<span class="hljs-string">'circle'</span>, <span class="hljs-number">5</span>);
<span class="hljs-keyword">const</span> rectangleArea = calculateArea(<span class="hljs-string">'rectangle'</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>);
<span class="hljs-keyword">const</span> triangleArea = calculateArea(<span class="hljs-string">'triangle'</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>);

<span class="hljs-built_in">console</span>.log(circleArea, rectangleArea, triangleArea);
</code></pre>
<p>This example defines a single function <code>calculateArea</code> that takes a <code>shape</code> argument and a variable number of arguments. Based on the <code>shape</code> argument, the function performs the appropriate calculation and returns the result.</p>
<p>This approach is much more efficient since it eliminates the need to repeat code for similar tasks. It is also more flexible and extensible, as additional shapes can easily be added in the future.</p>
<h2 id="heading-clear-flow-of-execution">Clear Flow of Execution</h2>
<p>Having a clear flow of execution is essential for writing clean code because it makes the code easier to read, understand, and maintain. Code that follows a clear and logical structure is less prone to errors, easier to modify and extend, and more efficient in terms of time and resources.</p>
<p>On the other hand, spaghetti code is a term used to describe code that is convoluted and difficult to follow, often characterized by long, tangled, and unorganized code blocks. Spaghetti code can be a result of poor design decisions, excessive coupling, or lack of proper documentation and commenting.</p>
<p>Here are two examples of JavaScript code that perform the same task, one with a clear flow of execution, and the other with spaghetti code:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1: Clear flow of execution</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateDiscount</span>(<span class="hljs-params">price, discountPercentage</span>) </span>{
  <span class="hljs-keyword">const</span> discountAmount = price * (discountPercentage / <span class="hljs-number">100</span>);
  <span class="hljs-keyword">const</span> discountedPrice = price - discountAmount;
  <span class="hljs-keyword">return</span> discountedPrice;
}

<span class="hljs-keyword">const</span> originalPrice = <span class="hljs-number">100</span>;
<span class="hljs-keyword">const</span> discountPercentage = <span class="hljs-number">20</span>;
<span class="hljs-keyword">const</span> finalPrice = calculateDiscount(originalPrice, discountPercentage);

<span class="hljs-built_in">console</span>.log(finalPrice);

<span class="hljs-comment">// Example 2: Spaghetti code</span>
<span class="hljs-keyword">const</span> originalPrice = <span class="hljs-number">100</span>;
<span class="hljs-keyword">const</span> discountPercentage = <span class="hljs-number">20</span>;

<span class="hljs-keyword">let</span> discountedPrice;
<span class="hljs-keyword">let</span> discountAmount;
<span class="hljs-keyword">if</span> (originalPrice &amp;&amp; discountPercentage) {
  discountAmount = originalPrice * (discountPercentage / <span class="hljs-number">100</span>);
  discountedPrice = originalPrice - discountAmount;
}

<span class="hljs-keyword">if</span> (discountedPrice) {
  <span class="hljs-built_in">console</span>.log(discountedPrice);
}
</code></pre>
<p>As we can see, example 1 follows a clear and logical structure, with a function that takes in the necessary parameters and returns the calculated result. On the other hand, example 2 is much more convoluted, with variables declared outside of any function and multiple if statements used to check if the code block has executed successfully.</p>
<h2 id="heading-single-responsibility-principle">Single Responsibility Principle</h2>
<p>The Single Responsibility Principle (SRP) is a principle in software development that states that each class or module should have only one reason to change, or in other words, each entity in our codebase should have a single responsibility.</p>
<p>This principle helps to create code that is easy to understand, maintain, and extend.</p>
<p>By applying SRP, we can create code that is easier to test, reuse, and refactor, since each module only handles a single responsibility. This makes it less likely to have side effects or dependencies that can make the code harder to work with.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 1: Withouth SRP</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processOrder</span>(<span class="hljs-params">order</span>) </span>{
  <span class="hljs-comment">// validate order</span>
  <span class="hljs-keyword">if</span> (order.items.length === <span class="hljs-number">0</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Error: Order has no items"</span>);
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-comment">// calculate total</span>
  <span class="hljs-keyword">let</span> total = <span class="hljs-number">0</span>;
  order.items.forEach(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> {
    total += item.price * item.quantity;
  });

  <span class="hljs-comment">// apply discounts</span>
  <span class="hljs-keyword">if</span> (order.customer === <span class="hljs-string">"vip"</span>) {
    total *= <span class="hljs-number">0.9</span>;
  }

  <span class="hljs-comment">// save order</span>
  <span class="hljs-keyword">const</span> db = <span class="hljs-keyword">new</span> Database();
  db.connect();
  db.saveOrder(order, total);
}
</code></pre>
<p>In this example, the <code>processOrder</code> function handles several responsibilities: it validates the order, calculates the total, applies discounts, and saves the order to a database. This makes the function long and hard to understand, and any changes to one responsibility may affect the others, making it harder to maintain.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example 2: With SRP</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderProcessor</span> </span>{
  <span class="hljs-keyword">constructor</span>(order) {
    <span class="hljs-built_in">this</span>.order = order;
  }

  validate() {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.order.items.length === <span class="hljs-number">0</span>) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Error: Order has no items"</span>);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  calculateTotal() {
    <span class="hljs-keyword">let</span> total = <span class="hljs-number">0</span>;
    <span class="hljs-built_in">this</span>.order.items.forEach(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> {
      total += item.price * item.quantity;
    });
    <span class="hljs-keyword">return</span> total;
  }

  applyDiscounts(total) {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.order.customer === <span class="hljs-string">"vip"</span>) {
      total *= <span class="hljs-number">0.9</span>;
    }
    <span class="hljs-keyword">return</span> total;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderSaver</span> </span>{
  <span class="hljs-keyword">constructor</span>(order, total) {
    <span class="hljs-built_in">this</span>.order = order;
    <span class="hljs-built_in">this</span>.total = total;
  }

  save() {
    <span class="hljs-keyword">const</span> db = <span class="hljs-keyword">new</span> Database();
    db.connect();
    db.saveOrder(<span class="hljs-built_in">this</span>.order, <span class="hljs-built_in">this</span>.total);
  }
}

<span class="hljs-keyword">const</span> order = <span class="hljs-keyword">new</span> Order();
<span class="hljs-keyword">const</span> processor = <span class="hljs-keyword">new</span> OrderProcessor(order);

<span class="hljs-keyword">if</span> (processor.validate()) {
  <span class="hljs-keyword">const</span> total = processor.calculateTotal();
  <span class="hljs-keyword">const</span> totalWithDiscounts = processor.applyDiscounts(total);
  <span class="hljs-keyword">const</span> saver = <span class="hljs-keyword">new</span> OrderSaver(order, totalWithDiscounts);
  saver.save();
}
</code></pre>
<p>In this example, the <code>processOrder</code> function has been split into two classes that follow the SRP: <code>OrderProcessor</code> and <code>OrderSaver</code>.</p>
<p>The <code>OrderProcessor</code> class handles the responsibilities of validating the order, calculating the total, and applying discounts, while the <code>OrderSaver</code> class handles the responsibility of saving the order to the database.</p>
<p>This makes the code easier to understand, test, and maintain, since each class has a clear responsibility and can be modified or replaced without affecting the others.</p>
<h2 id="heading-having-a-single-source-of-truth">Having a "Single Source of Truth"</h2>
<p>Having a "single source of truth" means that there is only one place where a particular piece of data or configuration is stored in the codebase, and any other references to it in the code refer back to that one source. This is important because it ensures that the data is consistent and avoids duplication and inconsistency.</p>
<p>Here's an example to illustrate the concept. Let's say we have an application that needs to display the current weather conditions in a city. We could implement this feature in two different ways:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Option 1: No "single source of truth"</span>

<span class="hljs-comment">// file 1: weatherAPI.js</span>
<span class="hljs-keyword">const</span> apiKey = <span class="hljs-string">'12345abcde'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCurrentWeather</span>(<span class="hljs-params">city</span>) </span>{
  <span class="hljs-keyword">return</span> fetch(<span class="hljs-string">`https://api.weather.com/conditions/v1/<span class="hljs-subst">${city}</span>?apiKey=<span class="hljs-subst">${apiKey}</span>`</span>)
    .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json());
}

<span class="hljs-comment">// file 2: weatherComponent.js</span>
<span class="hljs-keyword">const</span> apiKey = <span class="hljs-string">'12345abcde'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayCurrentWeather</span>(<span class="hljs-params">city</span>) </span>{
  getCurrentWeather(city)
    .then(<span class="hljs-function"><span class="hljs-params">weatherData</span> =&gt;</span> {
      <span class="hljs-comment">// display weatherData on the UI</span>
    });
}
</code></pre>
<p>In this option, the API key is duplicated in two different files, making it harder to maintain and update. If we ever need to change the API key, we have to remember to update it in both places.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Option 2: "Single source of truth"</span>

<span class="hljs-comment">// file 1: weatherAPI.js</span>
<span class="hljs-keyword">const</span> apiKey = <span class="hljs-string">'12345abcde'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCurrentWeather</span>(<span class="hljs-params">city</span>) </span>{
  <span class="hljs-keyword">return</span> fetch(<span class="hljs-string">`https://api.weather.com/conditions/v1/<span class="hljs-subst">${city}</span>?apiKey=<span class="hljs-subst">${apiKey}</span>`</span>)
    .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json());
}

<span class="hljs-keyword">export</span> { getCurrentWeather, apiKey };


<span class="hljs-comment">// file 2: weatherComponent.js</span>
<span class="hljs-keyword">import</span> { getCurrentWeather } <span class="hljs-keyword">from</span> <span class="hljs-string">'./weatherAPI'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayCurrentWeather</span>(<span class="hljs-params">city</span>) </span>{
  getCurrentWeather(city)
    .then(<span class="hljs-function"><span class="hljs-params">weatherData</span> =&gt;</span> {
      <span class="hljs-comment">// display weatherData on the UI</span>
    });
}
</code></pre>
<p>In this option, the API key is stored in one place (in the <code>weatherAPI.js</code> file) and exported for other modules to use. This ensures that there is only one source of truth for the API key and avoids duplication and inconsistency.</p>
<p>If we ever need to update the API key, we can do it in one place and all other modules that use it will automatically get the updated value.</p>
<h2 id="heading-only-expose-and-consume-data-you-need">Only Expose and Consume Data You Need</h2>
<p>One important principle of writing clean code is to only expose and consume the information that is necessary for a particular task. This helps to reduce complexity, increase efficiency, and avoid errors that can arise from using unnecessary data.</p>
<p>When data that is not needed is exposed or consumed, it can lead to performance issues and make the code more difficult to understand and maintain.</p>
<p>Suppose you have an object with multiple properties, but you only need to use a few of them. One way to do this would be to reference the object and the specific properties every time you need them. But this can become verbose and error-prone, especially if the object is deeply nested. A cleaner and more efficient solution would be to use object destructuring to only expose and consume the information you need.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Original object</span>
<span class="hljs-keyword">const</span> user = {
  <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span>,
  <span class="hljs-attr">email</span>: <span class="hljs-string">'alice@example.com'</span>,
  <span class="hljs-attr">age</span>: <span class="hljs-number">25</span>,
  <span class="hljs-attr">address</span>: {
    <span class="hljs-attr">street</span>: <span class="hljs-string">'123 Main St'</span>,
    <span class="hljs-attr">city</span>: <span class="hljs-string">'Anytown'</span>,
    <span class="hljs-attr">state</span>: <span class="hljs-string">'CA'</span>,
    <span class="hljs-attr">zip</span>: <span class="hljs-string">'12345'</span>
  }
};

<span class="hljs-comment">// Only expose and consume the name and email properties</span>
<span class="hljs-keyword">const</span> { name, email } = user;

<span class="hljs-built_in">console</span>.log(name); <span class="hljs-comment">// 'Alice'</span>
<span class="hljs-built_in">console</span>.log(email); <span class="hljs-comment">// 'alice@example.com'</span>
</code></pre>
<h2 id="heading-modularization">Modularization</h2>
<p>Modularization is an essential concept in writing clean code. It refers to the practice of breaking down large, complex code into smaller, more manageable modules or functions. This makes the code easier to understand, test, and maintain.</p>
<p>Using modularization provides several benefits such as:</p>
<ol>
<li><p>Re-usability: Modules can be reused in different parts of the application or in other applications, saving time and effort in development.</p>
</li>
<li><p>Encapsulation: Modules allow you to hide the internal details of a function or object, exposing only the essential interface to the outside world. This helps to reduce coupling between different parts of the code and improve overall code quality.</p>
</li>
<li><p>Scalability: By breaking down large code into smaller, modular pieces, you can easily add or remove functionality without affecting the entire codebase.</p>
</li>
</ol>
<p>Here is an example in JavaScript of a piece of code that performs a simple task, one not using modularization and the other implementing modularization.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Without modularization</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculatePrice</span>(<span class="hljs-params">quantity, price, tax</span>) </span>{
  <span class="hljs-keyword">let</span> subtotal = quantity * price;
  <span class="hljs-keyword">let</span> total = subtotal + (subtotal * tax);
  <span class="hljs-keyword">return</span> total;
}

<span class="hljs-comment">// Without modularization</span>
<span class="hljs-keyword">let</span> quantity = <span class="hljs-built_in">parseInt</span>(prompt(<span class="hljs-string">"Enter quantity: "</span>));
<span class="hljs-keyword">let</span> price = <span class="hljs-built_in">parseFloat</span>(prompt(<span class="hljs-string">"Enter price: "</span>));
<span class="hljs-keyword">let</span> tax = <span class="hljs-built_in">parseFloat</span>(prompt(<span class="hljs-string">"Enter tax rate: "</span>));

<span class="hljs-keyword">let</span> total = calculatePrice(quantity, price, tax);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Total: $"</span> + total.toFixed(<span class="hljs-number">2</span>));
</code></pre>
<p>In the above example, the <code>calculatePrice</code> function is used to calculate the total price of an item given its quantity, price, and tax rate. However, this function is not modularized and is tightly coupled with the user input and output logic. This can make it difficult to test and maintain.</p>
<p>Now, let's see an example of the same code using modularization:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// With modularization</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateSubtotal</span>(<span class="hljs-params">quantity, price</span>) </span>{
  <span class="hljs-keyword">return</span> quantity * price;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateTotal</span>(<span class="hljs-params">subtotal, tax</span>) </span>{
  <span class="hljs-keyword">return</span> subtotal + (subtotal * tax);
}

<span class="hljs-comment">// With modularization</span>
<span class="hljs-keyword">let</span> quantity = <span class="hljs-built_in">parseInt</span>(prompt(<span class="hljs-string">"Enter quantity: "</span>));
<span class="hljs-keyword">let</span> price = <span class="hljs-built_in">parseFloat</span>(prompt(<span class="hljs-string">"Enter price: "</span>));
<span class="hljs-keyword">let</span> tax = <span class="hljs-built_in">parseFloat</span>(prompt(<span class="hljs-string">"Enter tax rate: "</span>));

<span class="hljs-keyword">let</span> subtotal = calculateSubtotal(quantity, price);
<span class="hljs-keyword">let</span> total = calculateTotal(subtotal, tax);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Total: $"</span> + total.toFixed(<span class="hljs-number">2</span>));
</code></pre>
<p>In the above example, the <code>calculatePrice</code> function has been broken down into two smaller functions: <code>calculateSubtotal</code> and <code>calculateTotal</code>. These functions are now modularized and are responsible for calculating the subtotal and total, respectively. This makes the code easier to understand, test, and maintain, and also makes it more reusable in other parts of the application.</p>
<p>Modularization can also refer to the practice of dividing single files of code into many smaller files that are later on compiled back on to a single (or fewer files). This practice has the same benefits we just talked about.</p>
<p>If you'd like to know how to implement this in JavaScript using modules, <a target="_blank" href="https://www.freecodecamp.org/news/modules-in-javascript/">check out this other article of mine</a>.</p>
<h2 id="heading-folder-structures">Folder Structures</h2>
<p>Choosing a good folder structure is an essential part of writing clean code. A well-organized project structure helps developers find and modify code easily, reduces code complexity, and improves project scalability and maintainability.</p>
<p>On the other hand, a poor folder structure can make it challenging to understand the project's architecture, navigate the codebase, and lead to confusion and errors.</p>
<p>Here are examples of a good and a bad folder structure using a React project as an example:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Bad folder structure</span>
my-app/
├── App.js
├── index.js
├── components/
│   ├── Button.js
│   ├── Card.js
│   └── Navbar.js
├── containers/
│   ├── Home.js
│   ├── Login.js
│   └── Profile.js
├── pages/
│   ├── Home.js
│   ├── Login.js
│   └── Profile.js
└── utilities/
    ├── api.js
    └── helpers.js
</code></pre>
<p>In this example, the project structure is organized around file types, such as components, containers, and pages.</p>
<p>But this approach can lead to confusion and duplication, as it's not clear which files belong where. For example, the <code>Home</code> component is present in both the <code>containers</code> and <code>pages</code> folders. It can also make it challenging to find and modify code, as developers may need to navigate multiple folders to find the code they need.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Good folder structure</span>
my-app/
├── src/
│   ├── components/
│   │   ├── Button/
│   │   │   ├── Button.js
│   │   │   ├── Button.module.css
│   │   │   └── index.js
│   │   ├── Card/
│   │   │   ├── Card.js
│   │   │   ├── Card.module.css
│   │   │   └── index.js
│   │   └── Navbar/
│   │       ├── Navbar.js
│   │       ├── Navbar.module.css
│   │       └── index.js
│   ├── pages/
│   │   ├── Home/
│   │   │   ├── Home.js
│   │   │   ├── Home.module.css
│   │   │   └── index.js
│   │   ├── Login/
│   │   │   ├── Login.js
│   │   │   ├── Login.module.css
│   │   │   └── index.js
│   │   └── Profile/
│   │       ├── Profile.js
│   │       ├── Profile.module.css
│   │       └── index.js
│   ├── utils/
│   │   ├── api.js
│   │   └── helpers.js
│   ├── App.js
│   └── index.js
└── public/
    ├── index.html
    └── favicon.ico
</code></pre>
<p>In this example, the project structure is organized around features, such as components, pages, and utils. Each feature has its own folder, which contains all the files related to that feature.</p>
<p>This approach makes it easy to find and modify code, as all the files related to a feature are located in the same folder. It also reduces code duplication and complexity, as features are separated, and their related files are organized together.</p>
<p>Overall, a good folder structure should be organized around features, not file types, and should make it easy to find and modify code. A clear and logical structure can make a project easier to maintain, understand and scale, while a confusing and inconsistent structure can lead to errors and confusion.</p>
<p>If you're interested in learning more about this, <a target="_blank" href="https://www.freecodecamp.org/news/an-introduction-to-software-architecture-patterns/#different-folder-structures-to-know">in this article I wrote about software architecture</a> I expanded upon the topic of folder structures and well-known patterns you can follow.</p>
<h2 id="heading-documentation">Documentation</h2>
<p>Documentation is an essential part of writing clean code. Proper documentation not only helps the developer who wrote the code understand it better in the future but also makes it easier for other developers to read and understand the codebase. When code is well-documented, it can save time and effort in debugging and maintaining the code.</p>
<p>Documenting is specially important in cases in which simple and easy to understand solutions can't be implemented, cases when the business logic is quite complex, and cases in which people who are not familiar with the codebase have to interact with it.</p>
<p>One way to document code is by using comments. Comments can provide context and explain what the code is doing. But it's important to use comments wisely, only commenting where necessary and avoiding redundant or unnecessary ones.</p>
<p>Another way to document code is by using inline documentation. Inline documentation is embedded in the code itself and can be used to explain what a specific function or piece of code does. Inline documentation is often used in combination with tools like <a target="_blank" href="https://jsdoc.app/">JSDoc</a>, which provides a standard for documenting code in JavaScript.</p>
<p>Tools like Typescript can also provide automatic documentation for our codebase, which is hugely helpful.</p>
<p>If you'd like to know more about Typescript, I wrote <a target="_blank" href="https://www.freecodecamp.org/news/an-introduction-to-typescript/#otherfunctionalitiesoftypescript">a beginner friendly guide a while ago</a>.</p>
<p>And Lastly, tools like Swagger and Postman can be used to document APIs, providing a way to easily understand how to interact with them</p>
<p>If you're interested in knowing how to fully implement, test, consume and document APIs, I recently wrote two guides for <a target="_blank" href="https://www.freecodecamp.org/news/build-consume-and-document-a-rest-api/">REST APIs</a> and <a target="_blank" href="https://www.freecodecamp.org/news/building-consuming-and-documenting-a-graphql-api/">GraphQL APIs</a>.</p>
<h1 id="heading-wrapping-up"><strong>Wrap</strong>ping <strong>Up</strong></h1>
<p>Well everyone, as always, I hope you enjoyed the article and learned something new.</p>
<p>If you want, you can also follow me on <a target="_blank" href="https://www.linkedin.com/in/germancocca/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/CoccaGerman">Twitter</a>. See you in the next one!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/giphy.gif" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Linters and Code Formatters in Your Projects ]]>
                </title>
                <description>
                    <![CDATA[ Hi everyone! In this article we're going to take a look at two very useful tools we can use to make our lives easier when writing code: linting tools and code formatters. We're going to talk about what these tools are, how they work, why are they use... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/using-prettier-and-jslint/</link>
                <guid isPermaLink="false">66d45f27052ad259f07e4ad8</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ eslint ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Prettier ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ German Cocca ]]>
                </dc:creator>
                <pubDate>Mon, 10 Apr 2023 22:02:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/alysa-bajenaru-88IV5AtWjB8-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi everyone! In this article we're going to take a look at two very useful tools we can use to make our lives easier when writing code: linting tools and code formatters.</p>
<p>We're going to talk about what these tools are, how they work, why are they useful, and finally see how we can implement them in a basic React project.</p>
<p>Let's go!</p>
<h1 id="heading-table-of-contents">Table of Contents</h1>
<ul>
<li><p><a class="post-section-overview" href="#heading-about-linting-tools">About linting tools</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-are-linting-tools">What are Linting Tools?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-are-linting-tools-useful">Why are Linting Tools Useful?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-main-linting-tools-in-the-market">Main Linting Tools in the Market</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-about-code-formatters">About code formatters</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-are-code-formatters">What are Code Formatters?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-are-code-formatters-useful">Why are Code Formatters Useful?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-main-code-formatters-available">Main Code Formatters Available</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-eslint-and-prettier">How to Implement ESLint and Prettier</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-install-eslint">How to Install ESLint</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-prettier">How to Install Prettier</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping up</a></p>
</li>
</ul>
<h1 id="heading-about-linting-tools">About Linting Tools</h1>
<p>In the world of web development, linting tools have become an essential part of the developer's toolkit.</p>
<p>Linting tools are used to analyze source code for potential errors or stylistic issues, making it easier to maintain code quality and consistency across a project.</p>
<h2 id="heading-what-are-linting-tools">What are Linting Tools?</h2>
<p>Linting tools are automated tools that analyze source code to detect potential errors, security vulnerabilities, or coding style issues.</p>
<p>They are designed to help developers catch mistakes before they become a problem, and to promote best practices in coding.</p>
<p>The term "lint" comes from the name of the first lint tool, which was developed in the early 1970s by a team of Bell Labs researchers led by Stephen C. Johnson.</p>
<p>The original lint tool was designed to analyze C source code for potential errors and stylistic issues.</p>
<p>Since then, linting tools have evolved to work with a variety of programming languages, including JavaScript, Python, and Ruby.</p>
<h2 id="heading-why-are-linting-tools-useful">Why are Linting Tools Useful?</h2>
<p>Linting tools are useful for a number of reasons. Firstly, they help you catch errors early in the development process, when they are easier and cheaper to fix.</p>
<p>Secondly, they can help promote coding standards and best practices within a development team, ensuring that code is consistent and maintainable.</p>
<p>Finally, they can help you identify potential security vulnerabilities in your code, reducing the risk of a breach.</p>
<h2 id="heading-main-linting-tools-in-the-market">Main Linting Tools in the Market</h2>
<p>There are several linting tools available in the market today. Here are some of the most popular ones:</p>
<ol>
<li><p><strong>ESLint:</strong> <a target="_blank" href="https://eslint.org/">ESLint</a> is a widely used and highly configurable linter for JavaScript and TypeScript. It can be extended using plugins and supports various rule sets, making it a flexible tool for enforcing coding standards and preventing errors.</p>
</li>
<li><p><strong>JSHint:</strong> <a target="_blank" href="https://jshint.com/">JSHint</a> is a popular linter that has been around since 2010. It offers a simple configuration and a wide range of built-in rules to help developers avoid common pitfalls and improve code quality.</p>
</li>
<li><p><strong>JSLint:</strong> <a target="_blank" href="https://www.jslint.com/">JSLint</a> was one of the first linters to be developed for JavaScript, and it still sees some use today. It is known for its strictness and for enforcing a particular style of code, which can be helpful for maintaining consistency across a team.</p>
</li>
<li><p><strong>StandardJS:</strong> <a target="_blank" href="https://standardjs.com/">StandardJS</a> is a popular linter that aims to provide a "batteries included" approach to JavaScript linting. It has a minimal configuration and includes a set of opinionated rules designed to promote clean, readable code.</p>
</li>
</ol>
<p>And we should also talk about <strong>Typescript</strong>. When using <a target="_blank" href="https://www.typescriptlang.org/">TypeScript</a>, the TypeScript compiler itself acts as a linter. It checks the syntax of TypeScript code and provides warnings and errors when there are issues. This built-in linter can catch common mistakes and issues such as misspelled variable names, invalid method calls, and syntax errors.</p>
<p>The TypeScript compiler can be run using the <code>tsc</code> command in a terminal. When the <code>--noEmit</code> flag is used, the TypeScript compiler will only perform a syntax check without compiling the code to JavaScript. This allows the compiler to act as a linter and provide feedback on code quality without actually generating any output.</p>
<p>You can also configure the TypeScript compiler using a <code>tsconfig.json</code> file to specify various options, including the strictness of the checking. This can help catch even more potential issues and ensure that the code follows best practice</p>
<p>If you're not familiar with TypeScript, I recommend you <a target="_blank" href="https://www.freecodecamp.org/news/an-introduction-to-typescript/">this article I wrote a while ago</a>.</p>
<h1 id="heading-about-code-formatters">About Code Formatters</h1>
<p>In modern web development, code formatters have become an essential tool for developers. These tools automate the process of code formatting, making it easier to write and read code.</p>
<h2 id="heading-what-are-code-formatters">What are Code Formatters?</h2>
<p>Code formatters are automated tools that help you format source code automatically. The main purpose of code formatters is to standardize the formatting of code across a project or team, making it easier to read and understand code.</p>
<p>With code formatters, developers no longer need to spend time formatting code manually, which can save a lot of time and effort.</p>
<p>Code formatting tools have been around for decades. One of the earliest tools was the "indent" program, which was used to format C code in the early 1970s. But these early tools were limited and didn't have the same level of functionality as modern code formatters.</p>
<p>In the early 2000s, tools like "astyle" and "uncrustify" were developed, which introduced more advanced formatting capabilities.</p>
<h2 id="heading-why-are-code-formatters-useful">Why are Code Formatters Useful?</h2>
<p>Code formatters are useful for a variety of reasons. First and foremost, they help to standardize code formatting, which makes it easier to read and understand code. This is particularly important when working on large projects with multiple developers, where everyone needs to be able to read and understand each other's code.</p>
<p>Code formatters also help to ensure that code is consistent across a project or team, which can help to prevent errors and improve code quality. They also make it easier to maintain code over time, as the code is formatted consistently and is easier to read and understand.</p>
<h2 id="heading-main-code-formatters-available">Main Code Formatters Available</h2>
<p>There are several code formatting tools available in the market today. Here are some of the most popular ones:</p>
<ol>
<li><p><strong>Prettier:</strong> <a target="_blank" href="https://prettier.io/">Prettier</a> is a popular code formatter for JavaScript, TypeScript, and CSS. It's highly configurable and can be used in a variety of different environments, including editors, build tools, and code quality checkers.</p>
</li>
<li><p><strong>ESLint:</strong> While primarily known as a linting tool, <a target="_blank" href="https://eslint.org/">ESLint</a> can also be used as a code formatter. It has a <code>--fix</code> flag that can automatically format your code based on rules you define.</p>
</li>
<li><p><strong>Beautify:</strong> Beautify is a code formatter for JavaScript, HTML, and CSS that can be used in a variety of editors and IDEs. It allows you to customize your formatting options and has support for a wide range of languages.</p>
</li>
</ol>
<h1 id="heading-how-to-implement-eslint-and-prettier">How to Implement ESLint and Prettier</h1>
<p>Cool, so now let's see a linter and code formatter in action! We're going to implement the two most popular tools (ESLint and Prettier) in a simple React project to get an idea of how these things work.</p>
<p>First let's create our project by running this in our command line: <code>npm create vite@latest linternsAndFormatters --template react</code></p>
<p>Then <code>cd</code> into your project and run <code>npm install</code> so our dependencies get installed.</p>
<p>Now that we have our project up and running, we'll start by installing <strong>ESLint.</strong></p>
<h2 id="heading-how-to-install-eslint">How to Install ESLint</h2>
<p>To install ESLint, we can just run <code>npm init @eslint/config</code> in our console. This will fire a series of prompts asking how we want to use ESLint in our project and building the corresponding config. Your console might end up looking something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-72.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Installing ESLint</em></p>
<p>After all this, we'll see a new file called <code>.eslintrc.cjs</code> in the root of our project. Here's where ESLint's config lives and where we can customize the linter to our preferences. The initial config given the options I selected is the following:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {
    <span class="hljs-string">"env"</span>: {
        <span class="hljs-string">"browser"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-string">"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">"overrides"</span>: [
    ],
    <span class="hljs-string">"parserOptions"</span>: {
        <span class="hljs-string">"ecmaVersion"</span>: <span class="hljs-string">"latest"</span>,
        <span class="hljs-string">"sourceType"</span>: <span class="hljs-string">"module"</span>
    },
    <span class="hljs-string">"plugins"</span>: [
        <span class="hljs-string">"react"</span>
    ],
    <span class="hljs-string">"rules"</span>: {
    }
}
</code></pre>
<p>To see our linter in action, let's add the following script in our <code>package.json</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"lint"</span>: <span class="hljs-string">"eslint --fix . --ext .js,.jsx"</span>
</code></pre>
<p>This script executes the <code>eslint</code> command with the <code>--fix</code> option to automatically fix linting errors and warnings. The command is executed on all files with the <code>.js</code> or <code>.jsx</code> extension located in the root directory of the project, as specified by the <code>.</code> argument.</p>
<p>Now let's modify our <code>app.jsx</code> file to have 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">import</span> <span class="hljs-string">'./App.css'</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">const</span> emptyVariable = <span class="hljs-string">''</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Vite + React<span class="hljs-tag">&lt;/<span class="hljs-name">h1</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>Then run <code>npm run lint</code> and voilà! Your linter is screaming with red highlighted text that you have an unused variable in your code! =D</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-73.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-install-prettier">How to Install Prettier</h2>
<p>Cool, now let's hop on to our code formatter.</p>
<p>We're going to install it by running <code>npm install --save-dev --save-exact prettier</code>.</p>
<p>Then we're going to create and empty config file by running <code>echo {}&gt; .prettierrc.json</code>.</p>
<p>Since we're here, add the following options to your newly created config file:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"singleQuote"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-string">"jsxSingleQuote"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-string">"semi"</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<p>What this does is assure single quotes are used whenever possible and semicolons are nowhere to be found (because, god, who likes semicolons...).</p>
<p>As we did with our linter, let's add the following script in our <code>package.json</code> file:</p>
<pre><code class="lang-javascript">    <span class="hljs-string">"format"</span>: <span class="hljs-string">"prettier --write ."</span>
</code></pre>
<p>The script runs the Prettier code formatter on all the files in the project directory and its sub-directories. When run with the <code>--write</code> option, it modifies the files in place, changing them to conform to Prettier's rules for indentation, line length, and other formatting options. The <code>.</code> argument specifies that all files in the project directory and its sub directories should be formatted.</p>
<p>Lastly, let's "uglify" the first line of our <code>app.jsx</code> file like this:</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>;
</code></pre>
<p>Run <code>npm run format</code> and you should see it corrected right in front of you:</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>
</code></pre>
<p>You can breath easy now, those ugly semicolons won't come back to haunt you. ;)</p>
<p>As we've seen, the set up of these two tools isn't that complex, and they truly help to make our everyday jobs easier. ESLint will help us catch bugs and unnecessary/redundant code, and Prettier will help us standardize code format all across our codebase.</p>
<p>Another tip is that if you have a CI/CD pipeline in place, it's a good idea to implement the linting and formatting scripts as part of your workflow. This will help you ensure that every deployment is both automatically linted and formatted.</p>
<p>If you're not familiar with CI/CD or setting up a pipeline, I recently wrote <a target="_blank" href="https://www.freecodecamp.org/news/what-is-ci-cd/">an article about that</a>. ;)</p>
<h1 id="heading-wrapping-up">Wrapping up</h1>
<p>Linters and code formatters are powerful tools that can greatly benefit web developers.</p>
<p>Linters help you catch potential bugs and issues before they become serious problems, and encourage you to write more maintainable and readable code.</p>
<p>Code formatters help you enforce a consistent code style and format, saving time and reducing the chances of human error.</p>
<p>By using these tools in your web development workflow, you can improve your productivity and the quality of your code.</p>
<p>As always, I hope you enjoyed the article and learned something new.</p>
<p>If you want, you can also follow me on <a target="_blank" href="https://www.linkedin.com/in/germancocca/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/CoccaGerman">Twitter</a>. See you in the next one!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/4M2n.gif" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Alternatives to Prettier – Popular Code Linting and Formatting Tools ]]>
                </title>
                <description>
                    <![CDATA[ Many programmers hate code formatting because it is tedious and time-consuming. You can spend hours making sure everything is perfect and well-indented.  This is why code formatters are so useful. A code formatter is a tool that formats code accordin... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/alternatives-to-prettier/</link>
                <guid isPermaLink="false">66d0395a386d35c4e3bb3c39</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ eslint ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Prettier ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kamaldeen Lawal ]]>
                </dc:creator>
                <pubDate>Wed, 15 Mar 2023 17:43:50 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/Alternatives-to-Prettier.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Many programmers hate code formatting because it is tedious and time-consuming. You can spend hours making sure everything is perfect and well-indented. </p>
<p>This is why code formatters are so useful.</p>
<p>A code formatter is a tool that formats code according to certain standards. It makes it so you don't have to worry as much about code formatting. Instead, you can focus on writing good code. This save time and also reduces your stress.</p>
<p>In this guide, we will talk about the Prettier code formatter. We will also talk about alternatives to Prettier like JsFmt, StandardJS, EsLint + EditorConfig, and Beautifier. Hopefully you’ll take away something that you can use to improve your code formatting.</p>
<h2 id="heading-brief-overview-of-prettier">Brief Overview of Prettier</h2>
<p><a target="_blank" href="https://prettier.io/">Prettier</a> is a popular code formatter that can handle complex code structures and format your code in a readable way.</p>
<p>It operates on the principle of no configuration required and it's designed to produce readable, consistent code. </p>
<p>Prettier is an opinionated tool that encourages programmers to follow its formatting rules. It also parses the code and reprints it uniformly.</p>
<h2 id="heading-why-explore-alternatives-to-prettier">Why Explore Alternatives to Prettier?</h2>
<p>There are many advantages of using Prettier. But like every other tool, exploring alternatives is sometimes a good idea. Here are some of the reasons for exploring alternatives to Prettier:</p>
<ol>
<li><strong>Inflexible style guides</strong>: Prettier adopts a strict set of formatting rules, and does not allow for much customization. Some programmers want a tool with a lot of configurations available.</li>
<li><strong>Speed</strong>: Although Prettier is fast, you may need a tool that provides faster and better performance in large codebases or real-time formatting.</li>
<li><strong>Language support</strong>: Prettier may not support (or might offer inadequate support) for the language you use.</li>
<li><strong>More features</strong>: While Prettier is open source, you might prefer a paid code formatter that has more features and better integration with other tools.</li>
</ol>
<p>In the guide, we will talk about four alternatives to Prettier. They are:</p>
<ul>
<li>JsFmt</li>
<li>StandardJS</li>
<li>ESLint+EditorConfig</li>
<li>JS Beautifier</li>
</ul>
<h2 id="heading-jsfmt-overview">JsFmt Overview</h2>
<p><a target="_blank" href="https://rdio.github.io/jsfmt/">JsFmt</a> is a code formatter that uses esformatter as a formatting tool. It automatically reformats JavaScript code according to a set of predefined rules. It is available specifically to re-write, format, search, and validate JavaScript code.</p>
<p>To install JsFmt, run this command:</p>
<pre><code>npm install -g jsfmt
</code></pre><p>A .jsfmtrc file, which can either be a JSON or INI formatted file, can overwrite any of the esformatter formatting options.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"indent"</span>: <span class="hljs-number">4</span>,
  <span class="hljs-attr">"line_ending"</span>: <span class="hljs-string">"unix"</span>,
  <span class="hljs-attr">"quote"</span>: <span class="hljs-string">"single"</span>
}
</code></pre>
<p>In this example, we specified the spaces for indentation to be four, we chose line-ending to be unix, and we picked single as the quote style for strings.</p>
<p>You can use the jsfmt rewrite method to change values in your JavaScript code. Here's an example of how to do that:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> x = <span class="hljs-number">5</span>;
<span class="hljs-keyword">const</span> y = <span class="hljs-number">10</span>;
<span class="hljs-keyword">const</span> z = x + y;
<span class="hljs-built_in">console</span>.log(z);

<span class="hljs-comment">//  The output will change to the below code after writing:  npx jsfmt --rewrite '5 -&gt; 20' reduce.js</span>

<span class="hljs-keyword">const</span> x = <span class="hljs-number">20</span>;
<span class="hljs-keyword">const</span> y = <span class="hljs-number">10</span>;
<span class="hljs-keyword">const</span> z = x + y;
<span class="hljs-built_in">console</span>.log(z);
</code></pre>
<p>To learn more about JsFmt, you can read its documentation <a target="_blank" href="https://github.com/rdio/jsfmt">here</a>.</p>
<h3 id="heading-features-of-jsfmt">Features of JsFmt</h3>
<ol>
<li>Formating: JsFmt can format code according to a set of predefined rules.</li>
<li>Integrations: you can integrate JsFmt with popular code editors like Visual Studio Code, Sublime Text, and Atom, making it easy to format your code directly in your editor.</li>
<li>Command-line interface: JsFmt allows you to format your code as part of your build process or development workflow in the command line.</li>
</ol>
<h3 id="heading-jsfmt-formatting-rules">JsFmt Formatting Rules</h3>
<p>Some of the formatting rules adopted by JsFmt are as follows</p>
<ol>
<li>Set indent: With the <code>--indent</code> option, JsFmt indents your code with two spaces per level.</li>
<li>Quotes: In JsFmt, single quotes are the default for strings, but you can change this with the <code>--double-quote</code> option.</li>
<li>Wrapping: you can use <code>--linene-width</code> to change the default wrap lines setting in JsFmt.</li>
<li>Semicolons: JsFmt adds semicolons at the end of each statement by default. You can disable this using the <code>--no-semi</code> option.</li>
</ol>
<h3 id="heading-pros-of-jsfmt">Pros of JsFmt</h3>
<ol>
<li>Formatting, searching, and re-writing of JavaScript.</li>
<li>Customizable: JsFmt's flexibility makes it a popular choice for many development teams. It is a highly customizable tool that you can configure to match the specific requirements of a project.</li>
</ol>
<h3 id="heading-con-of-jsfmt">Con of JsFmt</h3>
<ol>
<li>Lack of flexibility: despite the fact that it's customizeable, certain parts of JsFmt may not always be configurable to match the needs of your project.</li>
</ol>
<h2 id="heading-standardjs-overview">StandardJS Overview</h2>
<p><a target="_blank" href="https://standardjs.com/">StandardJS</a> is an open-source, no configuration linter, formatter, and JavaScript style guide. It checks the code for probable errors with the linter. It also formats code automatically, and helps you write code that is easy to read and understand.</p>
<p>It is the most popular option, coming in at 27,905 stars on GitHub clean code linter. It is also a powerful tool for ensuring the quality and consistency of your JavaScript code.</p>
<p>You can either install it globally or locally on your machine. To install globally, use the first command, while the second command is for installing locally. Note that to install it, you must have Node and npm installed on your computer.</p>
<p>To install globally: <code>$ npm install standard --global</code></p>
<p>To install locally: <code>$ npm install standard --save-dev</code></p>
<p>Alternatively, you can add StandardJS to the package JSON.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"my-cool-package"</span>,
  <span class="hljs-attr">"devDependencies"</span>: {
    <span class="hljs-attr">"standard"</span>: <span class="hljs-string">"*"</span>
  },
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"standard &amp;&amp; node my-tests.js"</span>
  }
}
</code></pre>
<p>The styles are checked automatically when you run the command:</p>
<pre><code>npm test
</code></pre><p>To illustrate how it works, check the JavaScript code below:</p>
<pre><code class="lang-javascript!">let number = 10;
if (number == 10) {
  alert("yes");
} else {
  alert("no");
}

// The Output after running the npm test in the terminal

&gt; test
&gt; standard &amp;&amp; node my-tests.js

standard: Use JavaScript Standard Style (https://standardjs.com)
  C:\Users\hp\Desktop\pretier\Js\script.js:5:5: Parsing error: Unexpected token else (null)
</code></pre>
<p>StandardJS shows that the code has a parsing error.</p>
<p>To fix most issues, run the following code:</p>
<pre><code>standard --fix
</code></pre><h3 id="heading-features-of-standardjs">Features of StandardJS</h3>
<ol>
<li>Community: A community of contributors guides the development of StandardJS by providing bug fixes and new features.</li>
<li>Linting: StandardJS linting catches style issues and programmer errors early.</li>
<li>Automatic code formatting: StandardJS get rid of messy and inconsistent code.</li>
<li>Command line integration: It has a command-line interface for running linter checks and auto-formatting code.</li>
</ol>
<h3 id="heading-standardjs-formatting-rules">StandardJS Formatting Rules</h3>
<p>Some of the widely used StandardJS formatting rules are listed below:</p>
<ol>
<li>Indentation: StandardJS enforces a consistent indentation level of 2 spaces by default. To strictly implement this, you need to add the <code>--fix</code> option.</li>
<li>Line wrap: StandardJS doesn't enforce the rule of line length, but it recommends keeping lines shorter than 80 characters. Use <code>$ myfile.js | standard --stdin</code> to manually check the file length.</li>
<li>Semicolons: StandardJS recommends using semicolons for clarity and to avoid potential issues. But the tool doesn't enforce this. To enforce the use of semicolons, use this:</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"extends"</span>: <span class="hljs-string">"standard"</span>
}
</code></pre>
<ol>
<li>Spaces around operators: StandardJS recommends using spaces around operators, such as + and -, but it doesn't enforce this rule.</li>
</ol>
<h3 id="heading-pros-of-standardjs">Pros of StandardJS</h3>
<ol>
<li>Zero configuration: No decisions to make. StandardJS is the easiest way to enforce code quality in your project.</li>
<li>Easy installation: StandardJS is easy to install, and you can use it with most editors and IDEs.</li>
<li>Enhances Productivity: StandardJS saves developers time and increases productivity by formatting code according to its rules.</li>
<li>Wide support: Most editors and IDEs support StandardJS using plugins and integrations.</li>
<li>Consistency: StandardJS promote consistency across projects by enforcing a strict set of coding rules.</li>
</ol>
<h3 id="heading-cons-of-standardjs">Cons of StandardJS</h3>
<ol>
<li>Opinionated: Some developers may find the tool too opinionated. If that's the case, you might prefer to use other linting tools that allow for more customization.</li>
<li>Limited flexibility: StandardJS enforces a strict set of rules and conventions, which some developers may feel restricted by and prefer a more customizable approach.</li>
</ol>
<h2 id="heading-eslint-editconfig-overview">ESLint + EditConfig Overview</h2>
<p><a target="_blank" href="https://eslint.org/">ESlint</a> provides configurable rules that you can tailor according to your specific project needs. It is one of the most popular JavaScript linter that analyzes programming errors, bugs, and suspicious constructs.</p>
<p>You can extend its functionality by adding plugins, which can provide custom parsers and extra rules.</p>
<p>You'll need Node installed on your before installing ESLint. To install it, use the command below:</p>
<pre><code>npm init @eslint/config
</code></pre><p>Alternatively, you can create this manually on your machine:</p>
<pre><code>npm install --save-dev eslint
</code></pre><p>For both installations, you need to have installed a package.json file. If not, run this command</p>
<pre><code>npx eslint --init
</code></pre><p>The command will ask a series of questions about your project, coding style, and preferences to generate your configuration file.</p>
<p>You can run ESLint on any of your directories or files with this command:</p>
<pre><code>npx eslint yourfile.js
</code></pre><p>Rules can be turned off and you can run the toolonly with basic syntax validation, as ESLint is configurable and flexible to your use case.</p>
<p>Once you have generated the configuration file, you can customize according to your needs. The configuration file is a JavaScript file that exports an object with the configuration settings.</p>
<p>For example, you can specify the rules you want, plugins to use, and environments for your code:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"rules"</span>: {
    <span class="hljs-attr">"semi"</span>: [<span class="hljs-string">"error"</span>, <span class="hljs-string">"always"</span>],
    <span class="hljs-attr">"quotes"</span>: [<span class="hljs-string">"error"</span>, <span class="hljs-string">"double"</span>],
    <span class="hljs-attr">"indent"</span>: [<span class="hljs-string">"error"</span>, <span class="hljs-number">4</span>]
  }
}
</code></pre>
<p>The semi, quotes, and indent are the names of the rules in ESLint, while the error level of the rule is the first value. There are only three outputs for the first values. They are:</p>
<ul>
<li>"off" or 0 - turn the rule off</li>
<li>"warn" or 1 - turn the rule on as a warning (doesn’t affect exit code)</li>
<li>"error" or 2 - turn the rule on as an error (exit code will be 1).</li>
</ul>
<pre><code class="lang-json">{
  <span class="hljs-attr">"env"</span>: {
    <span class="hljs-attr">"browser"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"es2021"</span>: <span class="hljs-literal">true</span>
  },
  <span class="hljs-attr">"extends"</span>: <span class="hljs-string">"eslint: recommended"</span>,
  <span class="hljs-attr">"overrides"</span>: [],
  <span class="hljs-attr">"parserOptions"</span>: {
    <span class="hljs-attr">"ecmaVersion"</span>: <span class="hljs-string">"latest"</span>
  },
  <span class="hljs-attr">"rules"</span>: {
    <span class="hljs-attr">"indent"</span>: [<span class="hljs-string">"error"</span>, <span class="hljs-number">4</span>],
    <span class="hljs-attr">"quotes"</span>: [<span class="hljs-string">"error"</span>, <span class="hljs-string">"single"</span>],
    <span class="hljs-attr">"semi"</span>: [<span class="hljs-string">"error"</span>, <span class="hljs-string">"never"</span>]
  }
}
</code></pre>
<p>In this example, you specify that your code should run in a browser environment. Enable ECMAScript 2018 syntax, and follow the ESLint rules. You've also enabled three specific rules: indent, quotes, and semi.</p>
<p>The indent rule determines that an alert error will be thrown if indentation is more than 4 spaces. Likewise if you use double-quotes instead of single, there will be an error. You also specified not to use semi-colons.</p>
<p>To fix most of the issues in ESLint, use this command:</p>
<pre><code>npx eslint yourfile.js --fix
</code></pre><p>Here's an example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">6</span>, <span class="hljs-number">78</span>, <span class="hljs-number">8</span>];
<span class="hljs-keyword">let</span> peoples = [<span class="hljs-string">"shola"</span>, <span class="hljs-string">"kamal"</span>];
<span class="hljs-built_in">console</span>.log(peoples);

<span class="hljs-comment">// The output</span>

 error  <span class="hljs-string">'numbers'</span> is assigned a value but never used  no-unused-vars
   error  Extra semicolon                               semi

✖ <span class="hljs-number">2</span> problems (<span class="hljs-number">2</span> errors, <span class="hljs-number">0</span> warnings)
  <span class="hljs-number">1</span> error and <span class="hljs-number">0</span> warnings potentially fixable <span class="hljs-keyword">with</span> the <span class="hljs-string">`--fix`</span> option.
</code></pre>
<h3 id="heading-editorconfig-overview">EditorConfig Overview</h3>
<p><a target="_blank" href="https://editorconfig.org/#file-format-details">EditorConfig</a> is an open-source file format. It provides standard ways of defining and maintaining coding styles in a project.</p>
<p>It maintains consistent coding styles which is especially useful when you have many developers working on the same project across various editors and IDEs. The tool consists of a collection of text editor plugins that enable editors to read the file format and adhere to defined styles.</p>
<p>You'll need to create a file named .editorconfig in the directory. EditorConfig plugins will look for the file in the directory of the opened file and on every parent directory.</p>
<p>Files are read from top to bottom, and a search for .editorconfig files will stop if the root file path is reached.</p>
<p>Creating an EditorConfig file is straightforward. Open a new file, and save it with .editorconfig as shown below.</p>
<p><img src="https://i.imgur.com/SHEafBl.png" alt="editorconfig file" width="237" height="34" loading="lazy"></p>
<p>Inside the .editorconfig file, the following wildcard patterns are used:</p>
<pre><code class="lang-javascript">root = <span class="hljs-literal">true</span>

[*]

indent_size = <span class="hljs-number">4</span>
indent_style = space
end_of_line = lf
insert_final_newline = <span class="hljs-literal">true</span>

 <span class="hljs-comment">// Set root to true: A search for .editorconfig files will stop if the root file path is reached or an EditorConfig file with root=true is found.</span>

 <span class="hljs-comment">//[*]: Except for path selectors, it matches any string of characters.</span>

 <span class="hljs-comment">//indent_size: Indent size is set to 4. </span>
 <span class="hljs-comment">//Indent_style: set to space</span>
 <span class="hljs-comment">//end_of_line: Set to lf</span>
<span class="hljs-comment">//insert_final_newline: Set to true</span>
</code></pre>
<p>To know more about the wildcards pattern, visit the <a target="_blank" href="https://editorconfig.org/#file-format-details">EditorConfig docs</a>.</p>
<p>Using ESLint and EditorConfig together can help to spot potential issues early. It also ensures that your code is consistent, maintainable, and of high quality.</p>
<p>The combination of ESLint and EDitorConfig saves you time on code maintenance and debugging.</p>
<h3 id="heading-features-of-eslint">Features of ESLint</h3>
<ol>
<li>Configurable: ESLint allows you to customize and add your own rules to the configuration file.</li>
<li>Support ECMAScript: ESLint ensures your code is compatible with the latest language features.</li>
<li>Supports many file formats: ESLint can analyze JavaScript code in a variety of file formats, including but not limited to .js, .jsx, and .vue.</li>
<li>Integration: ESLint integrates seamlessly with Webpack and Gulp, which are popular build tools.</li>
</ol>
<h3 id="heading-eslint-formatting-rules">ESLint Formatting Rules</h3>
<p>Some of the popular formatting rules in ESLint are listed below:</p>
<ol>
<li>Indentation: ESLint by default expects a four-space per level indent. But you can customize this using the popular <code>--fix</code> option.</li>
<li>Semicolons: ESLint enforces the use of semicolons at the end of each statement. This rule is set to "always" by default. Use the popular <code>--fix</code> option to reset it to "never".</li>
<li>Line wrap: Use the <code>max-len</code> rule to change the maximum line length from the default 80 to your preferred  value.</li>
<li>Quotes: The quotes rule can be changed from the default value of "single" to "double" using the <code>--fix</code> option.</li>
</ol>
<h3 id="heading-pros-of-eslint">Pros of ESLint</h3>
<ol>
<li>Saves time: ESLint saves time by reducing the amount of time spent on manual code reviews and debugging.</li>
<li>Active Community: ESLint has a wide and active community base that contributes to the development of the tool and its ecosystem.</li>
<li>Code analyzer: ESLint analyze your code to quickly find problems.</li>
<li>Consistency: ESLint helps in maintaining clean and readable code by enforcing a consistent coding style.</li>
</ol>
<h3 id="heading-cons-of-eslint">Cons of ESLint</h3>
<ol>
<li>Rule conflicts: With a large set of rules, ESLint rules can sometimes conflict with one another, resulting in more configuration and fine-tuning.</li>
<li>Steeper learning curve: ESLint has a pretty steep learning curve, as it has many rules and learning how to configure them can take time.</li>
<li>False positives: ESLint can sometimes flag code as problematic code even when it is correct, which can be frustrating for developers.</li>
</ol>
<h2 id="heading-overview-of-js-beautifier">Overview of JS Beautifier</h2>
<p><a target="_blank" href="https://beautifier.io/">JavaScript Beautifier</a>, also known as js-beautify, is an open-source, cross-platform command-line tool. It is a beautifier for re-formating and re-indenting bookmarklets, ugly JavaScript, and it partly deobfuscates scripts.</p>
<p>You can install JS beautifier both locally and globally.</p>
<p>Run <code>npm -g install js-beautify</code> to install globally, and <code>npm install js-beautify</code> to install locally.</p>
<p>You can configure it through the command line option.</p>
<p>After local installation, you can import and call the appropriate beautifier methods for JS, CSS, or HTML. An example of how to call the methods goes like this: beautify (<code>code</code>, <code>options</code>).</p>
<p>While <code>code</code> is the string of code to be beautified, <code>options</code> is an object with the settings you would like used to beautify the code. See the example below for a JavaScript script file:</p>
<pre><code>npx beautify(<span class="hljs-string">"script.js"</span>,{<span class="hljs-attr">indent_size</span>:<span class="hljs-number">4</span>})
</code></pre><p>You can also configure it through a configuration file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"indent_size"</span>: <span class="hljs-number">4</span>,
  <span class="hljs-attr">"indent_char"</span>: <span class="hljs-string">" "</span>,
  <span class="hljs-attr">"indent_with_tabs"</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">"brace_style"</span>: <span class="hljs-string">"collapse"</span>
}
</code></pre>
<p>Create a file <code>.jsbeautifyrc</code> in the root directory of your project. This option will override the default option of JS beautifier. You can also use Beautifier on your web browser. Learn more about <a target="_blank" href="https://www.npmjs.com/package/js-beautify">JSbeautifer from its docs here</a>.</p>
<h3 id="heading-feature-of-js-beautifier">Feature of JS Beautifier</h3>
<ol>
<li>Formatting: You can customize JS Beautifier to fit your personal preferences and coding style because it offers varieties of formatting options, such as indentation size and braces style.</li>
<li>Online version: You can beautify JavaScript using JS Beautifier in your web browser, just as you can on the command line.</li>
</ol>
<h3 id="heading-js-beautifier-formatting-rules">JS Beautifier Formatting Rules</h3>
<ol>
<li>Indentation: The default identation in JS Beautifier is 4 spaces, but you can change it to 2 or 8 spaces, or use tabs instead. Use the <code>indent_size</code> option to specify the number of spaces to use for indentation.</li>
<li>Semicolons: You can change your semicolon settings in JS Beautifier with the <code>semicolon</code> option. You change this by alternating the value of the semicolon option between "true" or "false".</li>
<li>Line wrap: Use the <code>max_char</code> option to limit each line to 80 characters. You can set the value of the max_char to 80 or any other preferred  number.</li>
</ol>
<h3 id="heading-pros-of-js-beautifier">Pros of JS Beautifier</h3>
<ol>
<li>Time-saving: JS Beautifier saves time. It automates the many steps of formatting and organizing code.</li>
<li>Online presence: JS Beautifier's online presence is a game changer, as a lot of non-developers will be able to use it.</li>
<li>Detects errors: JS Beautifier helps catch small errors that can be difficult to spot otherwise.</li>
<li>Integration: JS Beautifier's compatibility with varieties of code editors and IDEs makes it a versatile tool.</li>
</ol>
<h3 id="heading-cons-of-js-beautifier">Cons of JS Beautifier</h3>
<ol>
<li>Complexity: Despite having an online version, JS Beautifier is somewhat complex for beginners.</li>
<li>Potential for over-formatting: In some cases, JS Beautifier may make the code harder to read because of over-formatting.</li>
</ol>
<h2 id="heading-results-from-all-the-formatting-tools">Results from all the Formatting Tools</h2>
<p>We'll use the code sample below to test how these four popular tools format code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">7</span>]

          <span class="hljs-keyword">let</span> peoples = [<span class="hljs-string">'kamal'</span>, <span class="hljs-string">'lawal'</span>, <span class="hljs-string">"shola"</span>, <span class="hljs-string">"olaide"</span>];
</code></pre>
<p>As you can see, this code isn't properly formatted. So let's try the tools to see how they help.</p>
<h3 id="heading-formatting-example-with-jsfmt">Formatting example with JsFmt</h3>
<p>Using the above code as a sample, the command <code>npx jsfmt --write "Your file"</code> will format the code to this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">7</span>]

<span class="hljs-keyword">let</span> peoples = [<span class="hljs-string">'kamal'</span>, <span class="hljs-string">'lawal'</span>, <span class="hljs-string">"shola"</span>, <span class="hljs-string">"olaide"</span>];
</code></pre>
<p>As you can see, there is a noticeable change in the code, and you can configure this to your desired taste.</p>
<h3 id="heading-formatting-example-with-standardjs">Formatting example with StandardJS</h3>
<p>By running the popular <code>npx standard--fix</code> command from the terminal, you will have the following result.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">7</span>]

<span class="hljs-keyword">const</span> peoples = [<span class="hljs-string">'kamal'</span>, <span class="hljs-string">'lawal'</span>, <span class="hljs-string">'shola'</span>, <span class="hljs-string">'olaide'</span>]
</code></pre>
<p>Notice the code was properly formatted, most especially the elements with double quotes within the <code>peoples</code> array.</p>
<h3 id="heading-formatting-example-with-eslint">Formatting example with ESLint</h3>
<p>Using the same code as above, the <code>npx eslint "Your file name --fix"</code> command will quickly format to this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">7</span>]

<span class="hljs-keyword">let</span> peoples = [<span class="hljs-string">'kamal'</span>,<span class="hljs-string">'lawal'</span>,<span class="hljs-string">'shola'</span>,<span class="hljs-string">'olaide'</span>]
</code></pre>
<p>You can also change the configuration of the tool, by changing the elements of the <code>peoples</code> array so they're inside double quotes:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">7</span>]

<span class="hljs-keyword">let</span> peoples = [<span class="hljs-string">"kamal"</span>,<span class="hljs-string">"lawal"</span>,<span class="hljs-string">"shola"</span>,<span class="hljs-string">"olaide"</span>];
</code></pre>
<p>You can do this by going to the .eslintrc file and manipulating the rules like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"quotes"</span>: [<span class="hljs-string">"error"</span>, <span class="hljs-string">"double"</span>],
  <span class="hljs-attr">"semi"</span>: [<span class="hljs-string">"off"</span>, <span class="hljs-string">"always"</span>]
}
</code></pre>
<h3 id="heading-formatting-example-with-js-beautifier">Formatting example with JS Beautifier</h3>
<p>Here's the result from JS Beautifier for the same code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">7</span>]
<span class="hljs-keyword">let</span> peoples = [<span class="hljs-string">'kamal'</span>, <span class="hljs-string">'lawal'</span>, <span class="hljs-string">"shola"</span>, <span class="hljs-string">"olaide"</span>];
</code></pre>
<p>You can configure it more from your JSON file if you wish.</p>
<p>Now you've seen these formatters in action!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this guide, we talked about some alternatives to using Prettier. We discussed Jsfmt, ESlint, StandardJS, and JS Beautifier, as well as their features, pros, and cons.</p>
<p>I hope you are now more equipped to choose the right linter/formatter for your coding projects.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Simpler JavaScript Code ]]>
                </title>
                <description>
                    <![CDATA[ As developers, writing clean and maintainable code is the goal. But sometimes, this is hard to achieve when we have a large and bulky codebase that can become complex and difficult to manage. One way to avoid this is to simplify your code. This can h... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/simplify-javascript-code/</link>
                <guid isPermaLink="false">66bf4b6ae4e2e43b8a15cb29</guid>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temitope Oyedele ]]>
                </dc:creator>
                <pubDate>Fri, 10 Mar 2023 18:57:42 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/10-Ways-to-Simplify-Your-Javascript-Code--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As developers, writing clean and maintainable code is the goal. But sometimes, this is hard to achieve when we have a large and bulky codebase that can become complex and difficult to manage.</p>
<p>One way to avoid this is to simplify your code. This can help improve its readability, efficiency, and maintainability.</p>
<p>This article will discuss ten ways to simplify your JavaScript code, making it more readable and maintainable. Let’s jump right in!</p>
<h2 id="heading-use-arrow-functions">Use Arrow Functions</h2>
<p>Using Arrow functions is a shorthand way for creating functions in JavaScript. They simplify your code by reducing the boilerplate needed to define a function.</p>
<p>For example, instead of using the function keyword to define a function like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greeings</span>(<span class="hljs-params">name</span>)</span>{ 
<span class="hljs-built_in">console</span>.log(Hello, ${name}!);
}
</code></pre>
<p>You can use an arrow function like this</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> greeting = <span class="hljs-function"><span class="hljs-params">name</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>);
</code></pre>
<p>Apart from arrow functions having a shorter syntax, they can make your code more concise, easier to read, and less error-prone. This makes it a better choice than using the function keyword</p>
<h2 id="heading-use-descriptive-variable-names">Use Descriptive Variable Names</h2>
<p>Using descriptive variable names can make your code more readable and easier to understand. This is much better than using single-letter variable names or abbreviations, as it may not be immediately clear to someone else reading your code what those variables mean.</p>
<p>For example, instead of using:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> x = <span class="hljs-number">10</span>;
</code></pre>
<p>Use this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numberOfItems = <span class="hljs-number">10</span>;
</code></pre>
<p><code>numberOfItems</code> is much more descriptive than <code>x</code> and will help you (or other developers looking at your code) understand what it's doing.</p>
<h2 id="heading-use-functional-programming">Use Functional Programming</h2>
<p>Functional programming prioritizes the use of pure functions and immutable data structures. Using functional programming techniques can help simplify your code greatly and reduce the risk of bugs and side effects.</p>
<p>For example, instead of modifying an array in place:</p>
<pre><code><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
numbers.push(<span class="hljs-number">4</span>);
</code></pre><p>You can use the spread operator to create a new array:</p>
<pre><code><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> newNumbers = [...numbers, <span class="hljs-number">4</span>];
</code></pre><p>Using the spread operator helps you prevent unexpected side effects and makes your code more predictable. </p>
<p>When you modify the function in place, you change the original array or object, If another part of your code is relying on that array or object, then it can lead to bugs and unexpected behavior. </p>
<p>On the other hand, using the spread operator creates a new array or object, leaving the original intact. This makes your code more predictable and easier to reason about.</p>
<h2 id="heading-avoid-nesting-code">Avoid Nesting Code</h2>
<p>Nesting code can make it difficult to read and understand. A better way is to try to flatten your code as much as possible. You can do this by using early returns, ternary operators, and function composition.</p>
<p>For example, instead of nesting if statements:</p>
<pre><code><span class="hljs-keyword">if</span> (condition1) {
  <span class="hljs-keyword">if</span> (condition2) {
    <span class="hljs-comment">// code</span>
  }
}
</code></pre><p>Use early returns:</p>
<pre><code><span class="hljs-keyword">if</span> (condition1) {
  <span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">if</span> (condition2) {
  <span class="hljs-keyword">return</span>;
}
<span class="hljs-comment">// code</span>
</code></pre><p>Using early returns here makes our code is more readable and easier to understand because it breaks down each condition into a separate if statement, and returns early if any condition fails.</p>
<p>Early returns can also increase the efficiency of your code by preventing unnecessary computations.</p>
<h2 id="heading-use-default-parameters">Use Default Parameters</h2>
<p>Using default parameters allows you to specify a default value for a function parameter. This can simplify your code by reducing the number of conditional statements you need to write.</p>
<p>For example, instead of using conditional logic to set a default value:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name</span>) </span>{
  <span class="hljs-keyword">if</span> (!name) {
    name = <span class="hljs-string">'World'</span>;
  }
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>);
}
</code></pre><p>You can use a default parameter:</p>
<pre><code>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name = <span class="hljs-string">'World'</span></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>);
}
</code></pre><p>Using a default parameter provides you with a simple way to set default values. But not only that, it makes your code more flexible, less error prone, and also makes your code easier to understand.</p>
<h2 id="heading-use-destructuring">Use Destructuring</h2>
<p>Destructuring allows you to extract values from arrays and objects and assign them to variables. Doing this can make your code more concise and easier to read.</p>
<p>For example, instead of accessing object properties directly like this:</p>
<pre><code><span class="hljs-keyword">const</span> person = { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> };
<span class="hljs-keyword">const</span> name = person.name;
<span class="hljs-keyword">const</span> age = person.age;
</code></pre><p>You can use destructuring:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { name, age } = { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> };
</code></pre>
<p>Using destructuring would be much better than accessing object properties as it helps you quickly understand the purpose of the code, especially when working with complex data structures. It also helps reduce the amount of code you need to write, provides flexibility, results in cleaner code, and also helps avoid naming conflicts</p>
<h2 id="heading-use-promises">Use Promises</h2>
<p>Promises allow you to write asynchronous code in a more readable and predictable way. They simplify your code by avoiding the need for callbacks and enabling you to chain asynchronous operations together.</p>
<p>For example, instead of nesting callbacks:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserData</span>(<span class="hljs-params">userId, callback</span>) </span>{
  getUser(userId, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">user</span>) </span>{
    getPosts(user, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">posts</span>) </span>{
      getComments(posts, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">comments</span>) </span>{
        callback(comments);
      });
    });
  });
}
</code></pre><p>You can use promises like this:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserData</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-keyword">return</span> getUser(userId)
    .then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> getPosts(user))
    .then(<span class="hljs-function"><span class="hljs-params">posts</span> =&gt;</span> getComments(posts));
}
</code></pre><p>Using promises instead of nesting callbacks can makes the code more concise and easier to read, especially when working with complex asynchronous operations.</p>
<h2 id="heading-use-array-methods">Use Array Methods</h2>
<p>JavaScript has many built-in methods for manipulating arrays, such as <code>map</code>, <code>filter</code>, <code>reduce</code>, and <code>forEach</code>. Using these methods can make your code more concise and easier to read.</p>
<p>For example, instead of using a for loop to iterate over an array:</p>
<pre><code><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; numbers.length; i++) {
  <span class="hljs-built_in">console</span>.log(numbers[i]);
}
</code></pre><p>You can use the <code>forEach</code> method:</p>
<pre><code><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
numbers.forEach(<span class="hljs-function"><span class="hljs-params">number</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(number));
</code></pre><p>Using array methods over traditional for loops can make your code more concise, readable, and modular, while also providing better error handling and supporting functional programming techniques.</p>
<h2 id="heading-use-object-methods">Use Object Methods</h2>
<p>JavaScript objects provide a variety of built-in methods, such as <code>Object.keys</code>, <code>Object.values</code>, and <code>Object.entries</code>. These methods can make your code simpler by reducing the need for loops and conditionals.</p>
<p>For example, instead of using a for loop to iterate over an object:</p>
<pre><code><span class="hljs-keyword">const</span> person = { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> };
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> key <span class="hljs-keyword">in</span> person) {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${key}</span>: <span class="hljs-subst">${person[key]}</span>`</span>);
}
</code></pre><p>You can use the <code>Object.entries</code> method:</p>
<pre><code><span class="hljs-keyword">const</span> person = { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> };
<span class="hljs-built_in">Object</span>.entries(person).forEach(<span class="hljs-function">(<span class="hljs-params">[key, value]</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${key}</span>: <span class="hljs-subst">${value}</span>`</span>));
</code></pre><p>Just like the array methods, using object methods can make your code more concise, readable, and modular.</p>
<h2 id="heading-use-libraries-and-frameworks">Use Libraries and Frameworks</h2>
<p>JavaScript has a wide variety of modules and frameworks that may help you create simpler code with less boilerplate. </p>
<p>Examples include React for building user interfaces, Lodash for functional programming, and Moment.js for working with dates and times.</p>
<p>You might consider using a framework/library when:</p>
<ul>
<li>When you want to build a complex application with functionalities that can be achieved with a library or framework.</li>
<li>When you have a tight timeline and need to deliver your project quickly.</li>
<li>When you want to improve your code's quality and reduce maintenance costs over time.</li>
</ul>
<p>On the other hand, you may also want to avoid using a framework/library when:</p>
<ul>
<li>When your project requirements are simple and require no external tools.</li>
<li>When you want to have control over your code and avoid dependencies on external tools.</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Simplifying your code can make it more readable and maintainable. By following these tips, you can write code that is easier to understand and more efficient. </p>
<p>What other tips would you suggest? Don't forget to share if you found this helpful.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
