NODE-202 Sprint Summary

Modified on Tue, 24 Sep, 2024 at 5:11 PM

TABLE OF CONTENTS



RBAC

What is RBAC?

  • What is it?
    RBAC is a method of restricting access based on the roles of individual users within an organization. Permissions are assigned to roles, and roles are assigned to users.

  • Where is it used?
    Commonly used in applications where users have varying levels of permissions (e.g., admin, editor, viewer) in enterprise-level systems, web applications, and databases.

  • How is it used?
    RBAC implementation involves defining roles, permissions, and assigning them to users. It is used to ensure that only authorized users perform certain actions.

  • Takeaways/Best Practices:
    Define roles clearly, keep roles distinct from permissions, implement the principle of least privilege.

Code Example:

const checkRole = (role) => (req, res, next) => {
  if (req.user.role !== role) {
    return res.status(403).json({ message: 'Access denied' });
  }
  next();
};

How to implement RBAC in MERN applications?

  • What is it?
    Adding role-based permissions to a MERN stack application.

  • Where is it used?
    Full-stack applications where different types of users need different levels of access to resources (e.g., admin dashboards, content moderation tools).

  • How is it used?
    Use middleware to enforce access rules based on roles in your Express server, integrate role-based control in React for hiding or showing components.

  • Takeaways/Best Practices:
    Use JWT tokens with role claims, design a flexible system for easy role changes.

Code Example:

const jwt = require('jsonwebtoken');
const authMiddleware = (req, res, next) => {
  const token = req.header('Authorization');
  if (!token) return res.status(401).json({ message: 'No token, authorization denied' });
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    res.status(401).json({ message: 'Token is not valid' });
  }
};


Testing

Test-Driven Development (TDD)

  • What is it?
    TDD is a software development process where tests are written before writing the actual code.

  • Where is it used?
    In projects requiring high test coverage, reliable refactoring, or where automated testing is prioritized.

  • How is it used?
    Write a test, run the test (which fails), then write the code to pass the test, and finally refactor the code while keeping the test passing.

  • Takeaways/Best Practices:
    Keep tests small and focused, use a red-green-refactor cycle, and make sure tests are deterministic.

Unit Tests Using Jest

  • What is it?
    Jest is a JavaScript testing framework that allows for unit testing by mocking modules and writing assertions.

  • Where is it used?
    Used in JavaScript/Node.js applications to verify individual functions, components, or services.

  • How is it used?
    Write test cases using test() or it() functions, utilize Jest’s mocking capabilities to isolate code.

  • Takeaways/Best Practices:
    Ensure you mock dependencies properly, focus on one piece of logic per test, and maintain clear descriptions in test cases.

Code Example (Basic Jest Test):

test('should return a list of users', async () => {
  const res = await request(app).get('/api/users');
  expect(res.statusCode).toEqual(200);
  expect(res.body).toHaveProperty('users');
});


Mocking API Calls Using Jest

  • What is it?
    Jest allows you to mock API calls to isolate the code being tested from external dependencies.

  • Where is it used?
    In applications where external APIs are used, ensuring tests are not dependent on network calls.

  • How is it used?
    Use Jest’s jest.mock() to mock Axios or Fetch calls.

  • Takeaways/Best Practices:
    Ensure you mock all network interactions, verify that API response handling is tested properly.

Code Example:

jest.mock('axios');
test('should fetch users', async () => {
  axios.get.mockResolvedValue({ data: [{ id: 1, name: 'John Doe' }] });
  const users = await getUsers();
  expect(users).toEqual([{ id: 1, name: 'John Doe' }]);
});


SQL

SQL AND, OR, NOT

  • What is it?
    Logical operators used in SQL queries for filtering data.

  • Where is it used?
    Used in SQL WHERE clauses to combine multiple conditions.

  • How is it used?
    AND requires all conditions to be true, OR allows any condition to be true, NOT negates a condition.

  • Takeaways/Best Practices:
    Use parentheses to clarify logic when mixing AND/OR, avoid overly complex queries.

Code Example:

SELECT * FROM Customers 
WHERE Country = 'USA' AND (City = 'New York' OR City = 'Los Angeles');


SQL BETWEEN

  • What is it?
    SQL operator used to filter values within a given range.

  • Where is it used?
    In SELECT, UPDATE, or DELETE queries to specify ranges of values.

  • How is it used?
    Use the BETWEEN keyword to select values that fall between two given values.

  • Takeaways/Best Practices:
    Ensure that the range boundaries are correctly set and consider performance for large datasets.

Code Example (SQL):

SELECT * FROM Orders WHERE OrderDate BETWEEN '2023-01-01' AND '2023-12-31';

SQL IS NULL, LIKE with %, []

  • What is it?
    SQL IS NULL checks for null values, LIKE is used for pattern matching.

  • Where is it used?
    IS NULL is used in WHERE clauses to check for empty fields, LIKE is used for wildcard searching.

  • How is it used?
    Use LIKE with % for wildcard searches, use IS NULL for null checking.

  • Takeaways/Best Practices:
    Always handle null values correctly, and be cautious with wildcard searches to avoid performance issues.

Code Example (SQL):

SELECT * FROM Customers WHERE City LIKE 'S%';
SELECT * FROM Customers WHERE Address IS NULL;

SQL EXISTS, ANY, ALL

  • What is it?
    EXISTS checks for the existence of records, ANY and ALL compare a value to a set of values.

  • Where is it used?
    Used in subqueries for conditional logic.

  • How is it used?
    EXISTS returns true if a subquery returns any records, ANY compares values in a subquery, ALL compares all values.

  • Takeaways/Best Practices:
    EXISTS is often more efficient than COUNT for subquery checks, use ALL sparingly.

Code Example (SQL):

SELECT * FROM Customers 
WHERE EXISTS (
SELECT * 
FROM Orders 
WHERE Customers.CustomerID = Orders.CustomerID
);


SQL MIN, MAX

  • What is it?
    SQL MIN and MAX functions are used to retrieve the smallest and largest values in a column, respectively.

  • Where is it used?
    These functions are commonly used in reports or analytics to find extremes, such as the lowest or highest values in a dataset.

  • How is it used?
    Use MIN() and MAX() in SELECT queries to find minimum and maximum values.

  • Takeaways/Best Practices:
    Ensure the data types are numeric or date for valid comparisons, and combine with GROUP BY for aggregated results.

Code Example:

SELECT MIN(Salary) AS LowestSalary, MAX(Salary) AS HighestSalary 
FROM Employees;


SQL COUNT, SUM, AVG, COUNT with DISTINCT

  • What is it?
    COUNT counts the rows, SUM adds numeric values, AVG calculates the average, and COUNT with DISTINCT counts unique values.

  • Where is it used?
    Used in reports and analytics where you need totals, averages, or unique counts.

  • How is it used?
    Use COUNT to return row numbers, SUM for totals, and AVG for averages. Use DISTINCT with COUNT for unique counts.

  • Takeaways/Best Practices:
    Handle NULL values carefully as they affect COUNT and AVG, and use DISTINCT for counting unique rows.

Code Example:

SELECT COUNT(DISTINCT EmployeeID), SUM(Salary), AVG(Salary) 
FROM Employees;


SQL HAVING vs WHERE

  • What is it?
    WHERE filters rows before aggregation, and HAVING filters groups after aggregation.

  • Where is it used?
    WHERE is used for initial filtering of data, while HAVING is used when you need to filter after using GROUP BY.

  • How is it used?
    Use WHERE for simple filtering of rows and HAVING for conditions applied after GROUP BY.

  • Takeaways/Best Practices:
    Always use HAVING with aggregate functions like COUNT, SUM, etc., and use WHERE for filtering individual rows.

Code Example:

SELECT Department, COUNT(EmployeeID) 
FROM Employees 
WHERE Salary > 30000 
GROUP BY Department 
HAVING COUNT(EmployeeID) > 5;

SQL CASE

  • What is it?
    CASE is used for conditional logic within SQL, similar to if-else statements.

  • Where is it used?
    Used to create new columns based on conditions or to transform data based on criteria.

  • How is it used?
    Use CASE to create conditional columns, returning values based on conditions.

  • Takeaways/Best Practices:
    Include an ELSE clause to handle unexpected values and use CASE sparingly to avoid complicating queries.

Code Example:

SELECT EmployeeID, Salary, 
CASE 
WHEN Salary > 50000 THEN 'High' 
ELSE 'Low' 
END AS SalaryRange 
FROM Employees;

SQL INNER JOIN

  • What is it?
    INNER JOIN returns rows when there is a match in both tables.

  • Where is it used?
    Used to retrieve related data from two or more tables.

  • How is it used?
    Use INNER JOIN in the FROM or SELECT statement to combine matching rows from related tables.

  • Takeaways/Best Practices:
    Ensure proper join conditions to avoid duplicate or missing data.

Code Example:

SELECT Employees.Name, Departments.DepartmentName 
FROM Employees 
INNER JOIN Departments ON Employees.DepartmentID = Departments.DepartmentID;

SQL LEFT OUTER JOIN

  • What is it?
    LEFT JOIN returns all rows from the left table, and matching rows from the right table. Non-matching rows from the right table will contain NULL values.

  • Where is it used?
    Used to retain all rows from the left table, regardless of matches in the right table.

  • How is it used?
    Use LEFT JOIN to include unmatched rows from the left table.

  • Takeaways/Best Practices:
    Handle NULL values carefully in the result set.

Code Example:

SELECT Employees.Name, Departments.DepartmentName 
FROM Employees 
LEFT JOIN Departments ON Employees.DepartmentID = Departments.DepartmentID;

SQL RIGHT OUTER JOIN

  • What is it?
    RIGHT JOIN returns all rows from the right table, and matching rows from the left table. Non-matching rows from the left table will contain NULL values.

  • Where is it used?
    Used to retain all rows from the right table, regardless of matches in the left table.

  • How is it used?
    Use RIGHT JOIN to include unmatched rows from the right table.

  • Takeaways/Best Practices:
    Understand when to use RIGHT JOIN versus LEFT JOIN based on your data needs.

Code Example:

SELECT Employees.Name, Departments.DepartmentName 
FROM Employees 
RIGHT JOIN Departments ON Employees.DepartmentID = Departments.DepartmentID;

SQL FULL OUTER JOIN

  • What is it?
    FULL OUTER JOIN returns all rows from both tables. Non-matching rows will contain NULLs for the missing side.

  • Where is it used?
    Used when you need to retain all records from both tables, even if there are no matches.

  • How is it used?
    Use FULL JOIN to return records from both tables, filling in NULLs for non-matching rows.

  • Takeaways/Best Practices:
    Be mindful of the large number of NULLs that can be returned with a FULL OUTER JOIN.

Code Example:

SELECT Employees.Name, Departments.DepartmentName 
FROM Employees 
FULL JOIN Departments ON Employees.DepartmentID = Departments.DepartmentID;

SQL COALESCE

  • What is it?
    COALESCE returns the first non-NULL expression in a list.

  • Where is it used?
    Used in SQL queries to handle NULL values by providing a default value.

  • How is it used?
    Use COALESCE to return the first non-null value in a list of expressions.

  • Takeaways/Best Practices:
    Use COALESCE when handling potential NULL values in result sets.

Code Example:

SELECT EmployeeID, COALESCE(PhoneNumber, 'No Phone Number') AS ContactInfo 
FROM Employees;

SQL SELF JOIN

  • What is it?
    A SELF JOIN is when a table is joined with itself to compare rows within the same table.

  • Where is it used?
    Used in hierarchical queries or when comparing rows within a single table.

  • How is it used?
    Use aliases to join the same table to itself.

  • Takeaways/Best Practices:
    Be cautious with table aliasing to avoid confusion.

Code Example:

SELECT A.EmployeeID, B.ManagerID 
FROM Employees A 
INNER JOIN Employees B ON A.ManagerID = B.EmployeeID;

Common Table Expressions (CTEs) in SQL

  • What is it?
    CTEs are temporary result sets defined in a query and referenced within the query itself.

  • Where is it used?
    CTEs are useful for breaking down complex queries into simpler parts.

  • How is it used?
    Use the WITH clause to define a CTE, which can then be used in the main query.

  • Takeaways/Best Practices:
    CTEs improve readability and reusability of code in complex queries.

Code Example:

WITH EmployeeCTE AS (
    SELECT EmployeeID, Salary 
    FROM Employees
)
SELECT * FROM EmployeeCTE WHERE Salary > 50000;

Connecting the Frontend and Backend

  • What is it?
    Connecting the frontend (React) and backend (Node.js/Express) in a MERN stack application involves creating seamless communication between the two using HTTP requests, typically through APIs.

  • Where is it used?
    It is a core aspect of full-stack development, used in MERN applications to allow the frontend to retrieve or send data to the backend, enabling dynamic, data-driven interfaces.

  • How is it used?
    The frontend (React) sends HTTP requests to the backend (Node.js/Express) through API endpoints (e.g., RESTful APIs). The backend processes the request (e.g., CRUD operations on a database like MongoDB) and returns a response. This communication is usually facilitated using tools like Axios or Fetch on the frontend.
    Steps:

    1. Backend (Express): Set up API routes using Express to handle requests. These routes perform tasks like reading or writing to the MongoDB database.

    2. Frontend (React): Use Axios or Fetch to send HTTP requests (GET, POST, PUT, DELETE) to the API endpoints and update the UI based on the response.

    3. CORS (Cross-Origin Resource Sharing): Ensure that the backend server allows requests from the frontend by configuring CORS middleware.

    4. Environment Variables: Use environment variables to store the API endpoint and other sensitive data securely.

  • Takeaways/Best Practices:
    Use environment variables for sensitive configuration (like API URLs), set up proper error handling on both the client and server side, and ensure that your application is secure by protecting API routes with authentication and validation (e.g., JWT).

Code Example:

Backend (Node.js/Express):

const express = require('express');
const app = express();
const mongoose = require('mongoose');
const cors = require('cors');
app.use(cors());  // Allow requests from frontend
app.use(express.json());
// Example route
app.get('/api/data', (req, res) => {
  res.json({ message: 'Data fetched from backend' });
});
// Start server
app.listen(5000, () => console.log('Server running on port 5000'));


Frontend (React with Axios):

import React, { useEffect, useState } from 'react';
import axios from 'axios';
const App = () => {
  const [data, setData] = useState('');
  useEffect(() => {
    // Fetch data from backend
    axios.get('http://localhost:5000/api/data')
      .then(response => {
        setData(response.data.message);
      })
      .catch(error => {
        console.error("There was an error fetching data!", error);
      });
  }, []);
  return (
    <div>
      <h1>Backend Data:</h1>
      <p>{data}</p>
    </div>
  );
};
export default App;


Microservices

Monoliths vs Microservices

  • What is it?
    A comparison between two architectural styles: monolithic (single unit) and microservices (collection of loosely coupled services).

  • Where is it used?
    Monoliths are traditional applications, microservices are commonly used in large-scale, distributed systems.

  • How is it used?
    Monoliths package everything into a single deployable unit, whereas microservices are developed and deployed independently.

  • Takeaways/Best Practices:
    Use monoliths for small applications, favor microservices for scalability and flexibility, but manage the complexity carefully.

Communication in Microservices: Sync and Async

  • What is it?
    Two types of communication patterns in microservices architecture: synchronous (real-time requests) and asynchronous (message-driven).

  • Where is it used?
    Sync communication is used when immediate feedback is required, async communication is used when tasks can be processed in the background.

  • How is it used?
    Synchronous uses REST APIs or gRPC, while asynchronous uses message brokers like Kafka or RabbitMQ.

  • Takeaways/Best Practices:
    Use sync for simple operations, async for decoupling services and handling large volumes of tasks.

Transactions in Microservices

  • What is it?
    Transactions in microservices ensure consistency across distributed services. Distributed transactions can be implemented using Saga or two-phase commit protocols.

  • Where is it used?
    Used in systems with multiple microservices interacting in a business process that requires consistent data.

  • How is it used?
    Implement Saga pattern for distributed transactions or use two-phase commits in simpler systems.

  • Takeaways/Best Practices:
    Manage distributed transactions carefully to avoid performance issues and consistency problems.

API Gateway

  • What is it?
    An API Gateway is a single entry point for clients to interact with multiple microservices. It manages request routing, security, and rate-limiting.

  • Where is it used?
    Used in microservices architectures to decouple services and centralize communication.

  • How is it used?
    Configure API Gateway to forward client requests to appropriate microservices and handle security or rate-limiting.

  • Takeaways/Best Practices:
    Use API Gateway for centralized authentication, authorization, and routing to simplify service management.

Backend for Frontend (BFF)

  • What is it?
    BFF is a design pattern where each frontend interface has a corresponding backend service optimized for its needs.

  • Where is it used?
    Commonly used in applications where multiple frontend interfaces (e.g., mobile, web) require different data structures or APIs.

  • How is it used?
    Build separate backends to serve each frontend, ensuring that each service is optimized for its interface.

  • Takeaways/Best Practices:
    BFF helps optimize performance for different frontends, but it can lead to duplication in backend services.

Aggregator Composite Service

  • What is it?
    Aggregator services collect and aggregate data from multiple microservices into a single response.

  • Where is it used?
    Used in microservices to gather and combine data from different services, often for a single API response.

  • How is it used?
    An aggregator service calls multiple microservices, compiles their responses, and sends them to the client.

  • Takeaways/Best Practices:
    Use aggregation to simplify client-side data handling and reduce API call complexity.

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article