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.