Part 5: SOLID Principles and Design Patterns - Production-Ready Code
Introduction
SOLID Principles
S - Single Responsibility Principle (SRP)
Problem: Multiple Responsibilities
// Bad - User class does too much
class User {
constructor(
public id: string,
public username: string,
public email: string,
public password: string
) {}
// Responsibility 1: User data management
updateEmail(email: string): void {
this.email = email;
}
// Responsibility 2: Password hashing
hashPassword(): void {
this.password = crypto.createHash('sha256').update(this.password).digest('hex');
}
// Responsibility 3: Database operations
save(): void {
console.log(`Saving user ${this.id} to database`);
// db.query('INSERT INTO users...');
}
// Responsibility 4: Email notifications
sendWelcomeEmail(): void {
console.log(`Sending welcome email to ${this.email}`);
// emailService.send(...);
}
// Responsibility 5: Validation
validate(): boolean {
return this.username.length >= 3 && this.email.includes('@');
}
}Solution: Separate Responsibilities
O - Open/Closed Principle (OCP)
Problem: Modifying Existing Code
Solution: Extend Through Abstraction
L - Liskov Substitution Principle (LSP)
Problem: Broken Substitution
Solution: Proper Abstraction
I - Interface Segregation Principle (ISP)
Problem: Fat Interface
Solution: Segregated Interfaces
D - Dependency Inversion Principle (DIP)
Problem: High-level Depends on Low-level
Solution: Depend on Abstraction
Essential Design Patterns
Factory Pattern
Singleton Pattern
Observer Pattern
Repository Pattern
Decorator Pattern
Best Practices
1. Apply SOLID from the Start
2. Choose Right Pattern for Problem
3. Keep It Simple
4. Test-Driven Design
5. Refactor Continuously
Conclusion
Next Steps
Resources
PreviousPart 4: Interfaces and Composition - Contracts and FlexibilityNextFunctional Programming 101
Last updated