Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Angular Component

July 31, 2019

Standard Design Principles

These are the foundational design principles every developer should internalize. They complement the SOLID Principles (covered in a dedicated post) and apply across languages and frameworks.

1. DRY (Don’t Repeat Yourself)

Every piece of knowledge should have a single, authoritative representation in your codebase. When you duplicate logic, you create multiple places that must change together — and they inevitably drift apart.

What to extract:

  • Repeated values become constants
  • Repeated logic becomes a shared method
  • Repeated patterns become a base class or utility

Warning: Don’t merge unrelated code just because it looks similar. Two functions that happen to share structure but serve different domains should stay separate. Premature abstraction is worse than duplication.

# BAD: duplicated discount logic
def get_member_price(price):
    return price * 0.9

def get_employee_price(price):
    return price * 0.9  # same now, but will diverge later? Keep separate.

# GOOD: truly shared logic extracted
def apply_discount(price, rate):
    return price * (1 - rate)

member_price = apply_discount(100, 0.10)
employee_price = apply_discount(100, 0.15)

2. Encapsulation

Hide internal state behind a well-defined interface. Make fields private, expose only what callers need, and keep mutation controlled. This protects invariants and lets you refactor internals without breaking consumers.

public class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    public double getBalance() {
        return balance;
    }

    public void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("Amount must be positive");
        balance += amount;
    }

    public void withdraw(double amount) {
        if (amount > balance) throw new IllegalStateException("Insufficient funds");
        balance -= amount;
    }
}

Callers can’t set balance to a negative value directly. The class enforces its own rules. This is the core value of encapsulation — protecting invariants, not just hiding fields.

3. Composition Over Inheritance

Inheritance creates tight coupling. A subclass is permanently bound to its parent’s implementation, and deep hierarchies become fragile. Composition lets you assemble behavior from smaller, independent components.

Prefer composition when:

  • You need behavior from multiple sources (most languages allow only single inheritance)
  • The relationship is “has-a” rather than “is-a”
  • You want to swap behavior at runtime
# Composition: build behavior from small, focused components
class Engine:
    def start(self):
        return "Engine running"

class GPS:
    def navigate(self, destination):
        return f"Navigating to {destination}"

class Car:
    def __init__(self):
        self.engine = Engine()
        self.gps = GPS()

    def drive(self, destination):
        return f"{self.engine.start()} | {self.gps.navigate(destination)}"

car = Car()
print(car.drive("New York"))
# Engine running | Navigating to New York

Swapping Engine for ElectricEngine requires no inheritance changes — just inject a different object.

4. Program to Interfaces, Not Implementations

Depend on abstractions. When your code references a concrete class, you can’t substitute alternatives without modifying callers. When it references an interface, any conforming implementation works.

// BAD: coupled to ArrayList
ArrayList<String> names = new ArrayList<>();

// GOOD: depends on the List interface
List<String> names = new ArrayList<>();

// This applies to method signatures too:
public void processOrders(List<Order> orders) {
    // works with ArrayList, LinkedList, or any List implementation
}

This principle scales from variable declarations to entire service layers. In Spring, you inject OrderService (interface), not OrderServiceImpl.

5. Delegation

A class shouldn’t do work that belongs to another class. If an object needs functionality that isn’t its core concern, delegate to a specialist. This keeps classes focused and testable.

// OrderController delegates to OrderService — it doesn't contain business logic
@RestController
public class OrderController {
    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }

    @PostMapping("/orders")
    public ResponseEntity<Order> create(@RequestBody OrderRequest request) {
        return ResponseEntity.ok(orderService.createOrder(request));
    }
}

Controllers delegate to services. Services delegate to repositories. Each layer owns one concern. If you see a controller making JDBC calls, that’s a delegation failure.

Summary

These five principles — DRY, Encapsulation, Composition over Inheritance, Programming to Interfaces, and Delegation — form the day-to-day habits of effective developers. Combined with the SOLID Principles, they give you a strong foundation for writing clean, maintainable code in any language.

July 31, 2019

Singleton Pattern

Introduction

The Singleton pattern ensures a class has only one instance and provides a global point of access to it. It is one of the most widely used — and misused — design patterns in software engineering. When applied correctly, it solves real problems around shared resource management, such as configuration settings, connection pools, and logging systems.

The Problem

Imagine your application needs a centralized configuration manager that reads settings from a file or environment variables. If every part of your codebase creates its own instance, you end up with duplicated I/O, inconsistent state, and wasted memory. Worse, if one module changes a setting in its copy, other modules never see the update. You need a single, shared source of truth.

The Solution

The Singleton pattern solves this by restricting instantiation to a single object. The class itself controls its own creation, stores the instance privately, and exposes it through a static access method. Every caller gets the same instance, guaranteeing consistent state across the entire application.

Key Principle

Controlled access to a sole instance. The class owns its lifecycle — no external code can create or destroy additional instances. This gives you a single coordination point without relying on global variables.

Java Example

This example implements a thread-safe ConfigurationManager that loads application settings once and provides them everywhere.

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class ConfigurationManager {

    // volatile ensures visibility across threads
    private static volatile ConfigurationManager instance;

    private final Properties properties;

    // Private constructor prevents external instantiation
    private ConfigurationManager() {
        properties = new Properties();
        try (FileInputStream fis = new FileInputStream("app.properties")) {
            properties.load(fis);
            System.out.println("Configuration loaded from app.properties");
        } catch (IOException e) {
            System.err.println("Failed to load config: " + e.getMessage());
            // Load defaults
            properties.setProperty("db.host", "localhost");
            properties.setProperty("db.port", "5432");
            properties.setProperty("app.name", "MyApplication");
        }
    }

    // Double-checked locking for thread safety
    public static ConfigurationManager getInstance() {
        if (instance == null) {
            synchronized (ConfigurationManager.class) {
                if (instance == null) {
                    instance = new ConfigurationManager();
                }
            }
        }
        return instance;
    }

    public String get(String key) {
        return properties.getProperty(key);
    }

    public String get(String key, String defaultValue) {
        return properties.getProperty(key, defaultValue);
    }

    public int getInt(String key, int defaultValue) {
        String value = properties.getProperty(key);
        if (value == null) return defaultValue;
        try {
            return Integer.parseInt(value.trim());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }
}

// Usage
public class Application {
    public static void main(String[] args) {
        ConfigurationManager config = ConfigurationManager.getInstance();

        String dbHost = config.get("db.host", "localhost");
        int dbPort = config.getInt("db.port", 5432);
        String appName = config.get("app.name", "DefaultApp");

        System.out.println("App: " + appName);
        System.out.println("DB: " + dbHost + ":" + dbPort);

        // Same instance everywhere
        ConfigurationManager sameConfig = ConfigurationManager.getInstance();
        System.out.println("Same instance: " + (config == sameConfig)); // true
    }
}

Python Example

The same configuration manager scenario in Python, using a class-level instance with thread safety.

import threading
import json
import os


class ConfigurationManager:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls):
        if cls._instance is None:
            with cls._lock:
                # Double-checked locking
                if cls._instance is None:
                    cls._instance = super().__new__(cls)
                    cls._instance._initialized = False
        return cls._instance

    def __init__(self):
        if self._initialized:
            return
        self._initialized = True
        self._config = {}
        self._load_config()

    def _load_config(self):
        config_path = "config.json"
        if os.path.exists(config_path):
            with open(config_path, "r") as f:
                self._config = json.load(f)
                print("Configuration loaded from config.json")
        else:
            # Load defaults
            self._config = {
                "db.host": "localhost",
                "db.port": 5432,
                "app.name": "MyApplication",
            }
            print("Loaded default configuration")

    def get(self, key, default=None):
        return self._config.get(key, default)

    def get_int(self, key, default=0):
        value = self._config.get(key)
        if value is None:
            return default
        try:
            return int(value)
        except (ValueError, TypeError):
            return default


# Usage
if __name__ == "__main__":
    config = ConfigurationManager()

    db_host = config.get("db.host", "localhost")
    db_port = config.get_int("db.port", 5432)
    app_name = config.get("app.name", "DefaultApp")

    print(f"App: {app_name}")
    print(f"DB: {db_host}:{db_port}")

    # Same instance everywhere
    same_config = ConfigurationManager()
    print(f"Same instance: {config is same_config}")  # True

When to Use

  • Configuration management — when your application needs a single source of truth for settings loaded from files, environment variables, or remote config services.
  • Connection pooling — managing a shared pool of database or HTTP connections where multiple instances would waste resources or cause connection limits to be exceeded.
  • Logging — a centralized logger that all modules write to, ensuring consistent log formatting, output destinations, and thread-safe writes.
  • Caching layers — an in-memory cache (like an LRU cache) that must be shared across the application to avoid duplicate data and stale entries.

Real-World Usage

  • Java RuntimeRuntime.getRuntime() returns the single Runtime instance for the JVM.
  • Spring Framework — Spring beans are singletons by default. The IoC container manages one instance per bean definition.
  • Python logging modulelogging.getLogger(name) returns the same logger instance for a given name across the entire application.
  • Android SharedPreferences — the preferences instance is cached and shared across components to avoid redundant disk reads.
  • Database drivers — connection managers in libraries like HikariCP and SQLAlchemy use singleton-like patterns to manage connection pools.
July 31, 2019

MongoDB – Type of Applications

Good fit
heavy read

Bad fit
Ad hoc queries
Updates
Joins

Social Applications
Social applications can go from 0 users to a million users in a very short time. The best DB fit for these kinds of applications is the DB that can easily scale horizontally which is where MongoDB comes into the picture.

Online Advertisement
Ads can be saved and updated from all kinds of sources. Data is not really related to each other but there is a lot of them.

Data Archive
Archiving a lot of data that may or may not be retrieved often can be done with a NoSQL DB like MongoDB.

July 30, 2019

MongoDB – Why nosql or mongodb?

Performance
MongoDB tends to be faster than relational DB when it comes to retrieving data. NoSQL database scales horizontally and is designed to scale to hundreds of millions and even billions of users doing updates as well as reads

Relational DB tends to be faster on ad hoc queries, updates, and joins. But applications can be designed and developed in a way to avoid these use cases. For example: to update you can use primary keys to update.

Differences
NoSQL scales horizontally (add more servers) but SQL Relational DB scales vertically (add more memories).

SQL relational DB must know columns and data types of the data to store. NoSQL DB does not have to know columns and data types. A row in a SQL relational DB contains all columns even if they are empty. A row in a NoSQL DB may or may not have all columns.

Advantages
Big data.

Schema changes are problematic and time-consuming in the world of SQL. NoSQL is great when business requirements are not stable and keep changing. You don’t have to modify or alter table and column definitions which is a painful process.

Scalability.

Disadvantages

https://medium.com/@jon.perera/sql-vs-nosql-a-beginners-guide-f80991f76a4b
https://www.mongodb.com/scale/nosql-databases-pros-and-cons
July 30, 2019