Every single scalable architecture relies on these 5 principles. Interviewers will actively look for violations of SOLID in your machine coding rounds.
1. SRP (Single Responsibility Principle)
A class should have one, and ONLY one, reason to change. God classes that mix business logic, database saving, and UI formatting are immediate red flags.
typescript
// ❌ BAD: God Class (Multiple reasons to change)
class EmployeeManager {
calculatePay(empId: string): number { /* logic here */ return 0; }
saveToDatabase(emp: any): void { /* DB logic here */ }
generateReportForm(empId: string): string { /* UI/Format logic here */ return ""; }
}
// ✅ GOOD: Split into distinct responsibilities
class PayCalculator { calculatePay(empId: string): number { return 0; } }
class EmployeeRepository { saveToDatabase(emp: any): void {} }
class EmployeeReportGenerator { generateReportForm(empId: string): string { return ""; } }2. OCP (Open-Closed Principle)
Software entities should be **Open for Extension, but Closed for Modification**. If you need to add a new feature, you write NEW code instead of changing OLD code.
typescript
// ❌ BAD: You must modify this class to add 'Crypto'
class PaymentProcessor {
processPayment(type: string, amount: number) {
if (type === "CreditCard") { /* ... */ }
else if (type === "PayPal") { /* ... */ }
}
}
// ✅ GOOD: Use an Interface (Strategy Pattern)
interface IPaymentStrategy { process(amount: number): boolean; }
class CreditCardStrategy implements IPaymentStrategy { process(amount: number) { return true; } }
class PayPalStrategy implements IPaymentStrategy { process(amount: number) { return true; } }
class CryptoStrategy implements IPaymentStrategy { process(amount: number) { return true; } } // Added without touching old code!
class PaymentManager {
processPayment(strategy: IPaymentStrategy, amount: number) {
strategy.process(amount);
}
}3. LSP (Liskov Substitution Principle)
A subclass should be replaceable by its parent class without breaking the application. Don't force behaviors that aren't true.
typescript
// ❌ BAD: Ostrich is a Bird, but throws an exception on fly()
class Bird { fly(): void {} }
class Ostrich extends Bird {
fly(): void { throw new Error("I can't fly!"); }
// ^ This breaks code that expects all Birds to fly safely
}
// ✅ GOOD: Reconstruct the hierarchy based on capabilities
class Bird {}
class FlyingBird extends Bird { fly(): void {} }
class FlightlessBird extends Bird { run(): void {} }
class Sparrow extends FlyingBird {}
class Ostrich extends FlightlessBird {}4. ISP (Interface Segregation Principle)
Clients shouldn't be forced to depend on interfaces they do not use. Break fat interfaces into smaller, more granular ones.
typescript
// ❌ BAD: Fat Interface
interface IWorker {
work(): void;
eat(): void; // Robots don't eat!
}
// ✅ GOOD: Segregated Interfaces
interface IWorkable { work(): void; }
interface IFeedable { eat(): void; }
class HumanWorker implements IWorkable, IFeedable {
work() {} eat() {}
}
class RobotWorker implements IWorkable {
work() {} // No longer forced to implement eat()
}5. DIP (Dependency Inversion Principle)
High-level modules should not depend on low-level modules. Both should depend on abstractions.
typescript
// ❌ BAD: High-level NotificationService depends tightly on EmailService
class EmailService { send(msg: string) {} }
class NotificationService {
private emailService = new EmailService(); // Tightly coupled!
notify(msg: string) { this.emailService.send(msg); }
}
// ✅ GOOD: Both depend on the IMessageSender abstraction
interface IMessageSender { send(msg: string): void; }
class EmailService implements IMessageSender { send(msg: string) {} }
class SMSService implements IMessageSender { send(msg: string) {} }
class NotificationService {
private sender: IMessageSender;
// Injected dependency! We can pass SMS, Email, or Mock.
constructor(sender: IMessageSender) { this.sender = sender; }
notify(msg: string) { this.sender.send(msg); }
}Take the Phase Interview
Solidify your knowledge. We will ask you 5 random highly-technical questions from the Phase 2: SOLID Principles bucket. A Staff Engineer AI will strictly evaluate your answers.