Key Software Design Principles

KISS (Keep It Simple, Stupid)

Favor the simplest solution that works. Avoid unnecessary complexity.

Python Example (Over-engineered vs Simple):

# Anti-KISS: Unnecessary abstraction
class AdderFactory:
    def create_adder(self):
        return lambda x, y: x + y

factory = AdderFactory()
result = factory.create_adder()(2, 3)  # 5

# KISS: Direct and clear
result = 2 + 3  # 5

DRY (Don't Repeat Yourself)

Eliminate duplication by extracting common code into reusable functions/classes.

Python Example:

# Not DRY: Repeated validation
def validate_user_age(age):
    if age < 0 or age > 150:
        raise ValueError("Invalid age")

def validate_employee_age(age):
    if age < 0 or age > 150:
        raise ValueError("Invalid age")

# DRY: Single source
def validate_age(age):
    if age < 0 or age > 150:
        raise ValueError("Invalid age")

validate_user_age = validate_employee_age = validate_age

YAGNI (You Ain't Gonna Need It)

Do not add functionality until it is actually required.

Python Example:

# YAGNI violation: Adding XML export "just in case"
def export_user_data(user, format="json"):
    if format == "json":
        return json.dumps(user)
    elif format == "xml":  # Never used
        return to_xml(user)  # Extra code

# YAGNI compliant
def export_user_data(user):
    return json.dumps(user)  # Only what's needed now

Separation of Concerns (SoC)

Divide a program into distinct sections, each addressing a separate concern (e.g., UI, business logic, data access).

Python Example:

# Violates SoC: Everything mixed
class UserController:
    def create_user(self, name, email):
        # Validation + DB + Email all in one
        if "@" not in email:
            return "Invalid email"
        db.execute("INSERT INTO users ...")
        send_email(email, "Welcome!")

# SoC: Separate layers
class UserValidator:
    def is_valid_email(self, email): ...

class UserRepository:
    def save(self, user): ...

class EmailService:
    def send_welcome(self, email): ...

class UserService:
    def create(self, name, email):
        if not UserValidator().is_valid_email(email):
            raise ValueError
        UserRepository().save(user)
        EmailService().send_welcome(email)

Law of Demeter (LoD – Principle of Least Knowledge)

A module should only talk to its immediate friends; avoid chaining calls through objects.

Python Example:

# Violates LoD: Deep chaining
wallet = user.get_wallet()
balance = wallet.get_balance()
currency = balance.get_currency()

# Follows LoD: Only direct friends
balance = user.get_balance()  # User knows how to get its balance
currency = balance.currency   # Balance exposes its own data

These principles guide building clean, maintainable code. Apply them consistently for long-term benefits.