Today I Learned

A collection of concise write-ups on small things I learn day to day across various languages and technologies.

2023-06-15
Frontend
Optimizing React Renders
3 min
intermediate

Today I learned about using React.memo, useCallback, and useMemo to prevent unnecessary re-renders in React applications.

const MemoizedComponent = React.memo(function MyComponent(props) {
    // Only re-renders if props change
  });
  
  const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);
ReactPerformanceOptimization
2023-06-10
Frontend
CSS Container Queries
2 min
intermediate

Container queries allow you to apply styles to an element based on the size of the element's container rather than the viewport size.

.container {
    container-type: inline-size;
  }
  
  @container (min-width: 400px) {
    .card {
      display: grid;
      grid-template-columns: 2fr 1fr;
    }
  }
CSSResponsive Design
2023-06-05
Backend
PostgreSQL JSONB Indexing
4 min
advanced

Learned how to create GIN indexes on JSONB columns in PostgreSQL for faster querying of JSON data.

-- Create a GIN index on a JSONB column
  CREATE INDEX idx_data ON table_name USING GIN (data_column);
  
  -- Query using the index
  SELECT * FROM table_name WHERE data_column @> '{"key": "value"}'::jsonb;
PostgreSQLDatabasePerformance
2023-05-28
DevOps
Docker Multi-Stage Builds
5 min
intermediate

Using multi-stage builds in Docker can significantly reduce the final image size by only including necessary artifacts from build stages.

# Build stage
  FROM node:16 AS build
  WORKDIR /app
  COPY package*.json ./
  RUN npm install
  COPY . .
  RUN npm run build
  
  # Production stage
  FROM nginx:alpine
  COPY --from=build /app/dist /usr/share/nginx/html
  EXPOSE 80
  CMD ["nginx", "-g", "daemon off;"]
DockerContainersCI/CD
2023-05-20
Soft Skills
Active Listening Techniques
3 min
beginner

Practiced the HEAR technique (Halt, Engage, Anticipate, Replay) for better communication with team members during sprint planning.

CommunicationTeam Collaboration
2023-05-15
Tips & Tricks
VS Code Productivity Shortcuts
2 min
beginner

Discovered that Ctrl+Shift+L selects all occurrences of the current selection, making bulk edits much faster.

// Some useful VS Code shortcuts:
  // Ctrl+Shift+L - Select all occurrences of current selection
  // Alt+Click - Insert cursor
  // Ctrl+D - Select next occurrence of current selection
  // Ctrl+/ - Toggle line comment
IDEProductivity
2023-05-10
DevOps
AWS S3 Bucket Policies
4 min
beginner

Learned how to configure S3 bucket policies to control access to objects while maintaining security best practices.

{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "PublicReadForGetBucketObjects",
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::example-bucket/*",
        "Condition": {
          "IpAddress": {
            "aws:SourceIp": "203.0.113.0/24"
          }
        }
      }
    ]
  }
AWSS3Security+1
2023-04-25
DevOps
Terraform State Management
5 min
intermediate

Discovered best practices for managing Terraform state files in a team environment using remote backends.

# Configure the backend
  terraform {
    backend "s3" {
      bucket         = "terraform-state-prod"
      key            = "network/terraform.tfstate"
      region         = "us-west-2"
      dynamodb_table = "terraform-locks"
      encrypt        = true
    }
  }
TerraformIaCDevOps+1
2023-04-15
DevOps
AWS Lambda Cold Starts
6 min
advanced

Investigated and implemented strategies to minimize cold start latency in serverless applications using AWS Lambda.

// Optimize imports by moving them inside the handler when possible
  exports.handler = async (event) => {
    // Only load heavy dependencies when needed
    const heavyDependency = event.needsHeavyProcessing 
      ? require('heavy-library') 
      : null;
      
    // Function logic here
    
    return { statusCode: 200, body: 'Success' };
  };
AWSLambdaServerless+1
2023-04-05
DevOps
Infrastructure as Code with AWS CDK
7 min
advanced

Explored AWS Cloud Development Kit (CDK) for defining cloud infrastructure using familiar programming languages instead of YAML or JSON.

import * as cdk from 'aws-cdk-lib';
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
  import * as ecs from 'aws-cdk-lib/aws-ecs';
  import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
  
  export class MicroserviceStack extends cdk.Stack {
    constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
      super(scope, id, props);
  
      // Create VPC and Fargate Cluster
      const vpc = new ec2.Vpc(this, 'ServiceVPC', { maxAzs: 2 });
      const cluster = new ecs.Cluster(this, 'Cluster', { vpc });
      
      // Define the Fargate Service
      const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef');
      taskDefinition.addContainer('AppContainer', {
        image: ecs.ContainerImage.fromRegistry('my-app:latest'),
        memoryLimitMiB: 512,
        cpu: 256,
        portMappings: [{ containerPort: 80 }]
      });
      
      // Create the service
      const service = new ecs.FargateService(this, 'Service', {
        cluster,
        taskDefinition,
        desiredCount: 2
      });
      
      // Set up load balancing
      const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { vpc, internetFacing: true });
      const listener = lb.addListener('Listener', { port: 80 });
      listener.addTargets('Target', {
        port: 80,
        targets: [service]
      });
      
      // Output the load balancer URL
      new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: lb.loadBalancerDnsName });
    }
  }
AWSCDKIaC+1
2023-03-20
DevOps
Kubernetes Pod Resource Limits
6 min
advanced

Learned how to properly configure CPU and memory limits for Kubernetes pods to optimize cluster resource utilization.

apiVersion: v1
  kind: Pod
  metadata:
    name: frontend
  spec:
    containers:
    - name: app
      image: app:1.0.0
      resources:
        requests:
          memory: "128Mi"
          cpu: "100m"
        limits:
          memory: "256Mi"
          # Note: No CPU limit to avoid throttling
      ports:
      - containerPort: 80
KubernetesContainer OrchestrationResource Management
2023-03-10
DevOps
Getting Started with Docker Compose
4 min
beginner

Learned how to use Docker Compose to define and run multi-container applications with a single configuration file.

version: '3.8'
  
  services:
    frontend:
      build: ./frontend
      ports:
        - "3000:3000"
      depends_on:
        - backend
      environment:
        - API_URL=http://backend:8000
  
    backend:
      build: ./backend
      ports:
        - "8000:8000"
      depends_on:
        - database
      environment:
        - DB_HOST=database
        - DB_USER=postgres
        - DB_PASSWORD=example
        - DB_NAME=myapp
  
    database:
      image: postgres:13
      volumes:
        - db-data:/var/lib/postgresql/data
      environment:
        - POSTGRES_USER=postgres
        - POSTGRES_PASSWORD=example
        - POSTGRES_DB=myapp
  
  volumes:
    db-data:
DockerDocker ComposeContainers
2023-02-10
Soft Skills
Kinh nghiệm làm việc với Legacy Code
8 min
intermediate

Những bài học thực tế khi phải bảo trì và nâng cấp hệ thống legacy code lớn trong môi trường doanh nghiệp.

// Ví dụ về Adapter Pattern để tách biệt code mới và cũ
  // Interface mới
  interface ModernPaymentProcessor {
    processPayment(amount: number, currency: string): Promise<PaymentResult>;
  }
  
  // Adapter cho legacy code
  class LegacyPaymentAdapter implements ModernPaymentProcessor {
    private legacyProcessor = new LegacyPaymentSystem();
    
    async processPayment(amount: number, currency: string): Promise<PaymentResult> {
      // Chuyển đổi tham số cho hệ thống cũ
      const legacyAmount = this.convertToLegacyFormat(amount, currency);
      
      // Gọi hệ thống cũ
      const result = this.legacyProcessor.makePayment(legacyAmount);
      
      // Chuyển đổi kết quả sang định dạng mới
      return this.convertToModernResult(result);
    }
    
    private convertToLegacyFormat(amount: number, currency: string): string {
      // Logic chuyển đổi
      return `${amount}|${currency}`;
    }
    
    private convertToModernResult(legacyResult: any): PaymentResult {
      // Logic chuyển đổi kết quả
      return {
        success: legacyResult.status === "OK",
        transactionId: legacyResult.id,
        timestamp: new Date()
      };
    }
  }
Legacy CodeRefactoringBảo trì phần mềm