SOLID
S → Single Responsibility Principle (SRP)
Ek class/function ka sirf ek hi kaam hona chahiye!
wrong: Ek hi class 2 kaam kar rahi (DB + Email). 😬
class User {
saveUserToDB(user) { /* save logic */ }
sendEmail(user) { /* email logic */ }
}
correct : sb alag alag
class User {
constructor(name) {
this.name = name;
}
}
class UserDB {
save(user) { console.log(`Saving ${user.name} to DB`); }
}
class EmailService {
sendEmail(user) { console.log(`Sending email to ${user.name}`); }
}
O → Open/Closed Principle (OCP)
Code extend karo, par modify mat karo!
wrong
function calculateArea(shape) {
if (shape.type === 'circle') return Math.PI * shape.radius ** 2;
if (shape.type === 'square') return shape.side * shape.side;
}
correct
class Shape {
area() {}
}
class Circle extends Shape {
constructor(radius) { super(); this.radius = radius; }
area() { return Math.PI * this.radius ** 2; }
}
class Square extends Shape {
constructor(side) { super(); this.side = side; }
area() { return this.side * this.side; }
}
const shapes = [new Circle(5), new Square(4)];
shapes.forEach(shape => console.log(shape.area()));
L → Liskov Substitution Principle (LSP)
Child class ko parent ki jagah use karo bina tod-phod ke!
wrong
class Bird { fly() { console.log('Flying'); } }
class Parrot extends Bird {} // ✅ Works fine
class Ostrich extends Bird { fly() { throw 'Cannot fly'; } } // ❌ Breaks LSP
correct
class Bird {}
class FlyingBird extends Bird { fly() { console.log('Flying'); } }
class Ostrich extends Bird { walk() { console.log('Walking'); } }
I → Interface Segregation Principle (ISP)
Client ko sirf wahi interface dena jo chahiye!
wrong
class Printer {
print() {}
scan() {}
fax() {}
}
class OldPrinter extends Printer {
print() {}
scan() { throw 'Not supported'; }
fax() { throw 'Not supported'; }
}
// OldPrinter sirf print karna chahta hai, par scan() aur fax() bhi implement karni pad rahi hai—even when it's useless! 😤
correct
class Printer {
print() {}
}
class Scanner {
scan() {}
}
class BasicPrinter extends Printer {
print() { console.log('Printing...'); }
}
D → Dependency Inversion Principle (DIP)
High-level module should not depend on low-level module directly! High-level modules should not depend on low-level modules directly. Dono abstractions pe depend karein!
wrong
class MySQLDatabase {
save(data) { console.log('Saved in MySQL'); }
}
class UserService {
constructor() {
this.db = new MySQLDatabase(); // tightly coupled, Direct dependency!
}
}
/* 👉 Yeh tight coupling hai!
UserService sirf MySQLDatabase ke saath kaam karega.
Future mein agar MongoDB chahiye ho toh poora code todna padega! 😫
*/
correct
// 1. Abstraction
class Database {
save(data) {}
}
// 2. Low-level implementations
class MySQLDatabase extends Database {
save(data) { console.log('MySQL mein save:', data); }
}
class MongoDB extends Database {
save(data) { console.log('MongoDB mein save:', data); }
}
// 3. High-level module depends on abstraction, not concrete
class UserService {
constructor(database) {
this.db = database; // loose coupling!
}
saveUser(user) {
this.db.save(user);
}
}
// Usage
const mysqlDB = new MySQLDatabase();
const userService1 = new UserService(mysqlDB);
userService1.saveUser({ name: 'Shadab' });
const mongoDB = new MongoDB();
const userService2 = new UserService(mongoDB);
userService2.saveUser({ name: 'Shadab' });