Part 01 · Low Level Design
How to Solve an LLD Interview
বারবার ব্যবহার করা যায় এমন ৪৫ মিনিটের plan: প্রশ্ন পরিষ্কার করা, entity খোঁজা, class আঁকা, মূল অংশটা code করা, তারপর 'যদি এটা যোগ করি…' ধরনের follow-up পুরো code না ভেঙে সামলানো।
⏱ 1-2 ঘণ্টা · Station 13 / 80
চল্লিশ মিনিট code, offer শূন্য
দুইজন candidate একই প্রশ্ন পেলো: "আমাদের office এর জন্য একটা meeting room booking system design করো।"
ফারহান সাথে সাথেই type করা শুরু করলো। ৩৫ মিনিটে তার ২০০ লাইন: নয়টা method ওয়ালা একটা RoomManager, একটা BookingFactory, একটা IRoomRepository। তারপর interviewer জিজ্ঞেস করলেন, "একই room একই সময়ে কি দুইজন book করতে পারবে?" ফারহান জানে না; booking কীভাবে কাজ করে, সে কখনো জিজ্ঞেসই করেনি। বাকি interview গেল নতুন করে বানাতে।
মিতু পাঁচ মিনিট প্রশ্ন করলো, দুই মিনিটে তিনটা class এর list বানালো, আর ছোট একটা diagram আঁকলো। সে Book আর Cancel code করলো, overlap এর rule এক জায়গায় রেখে। দুইজন একসাথে book করার প্রশ্নে সে Book দেখিয়ে বললো: "check আর লেখা এখানে একটা critical section এ যাবে"।
দুজনেই OOP জানে। approach ছিল শুধু একজনের। LLD part এর এই শেষ chapter সেই approach, শুরু থেকে শেষ পর্যন্ত একটা problem এ লাগিয়ে।
সমস্যা: LLD round এ যেখানে ভুল হয়
| চেনা ভুল | Interviewer যা দেখেন |
|---|---|
| প্রশ্ন না করে code শুরু | ভুল problem solve হচ্ছে; প্রথম follow-up এই আটকে যায় |
| ৪৫ মিনিটের প্রশ্নে দশটা class | দরকারের বেশি engineering; মূল অংশ শেষ করার সময় থাকে না |
| Rule গুলো কয়েকটা class এ ছড়ানো | কোনো পরিষ্কার মালিক নেই; প্রতিটা "যদি" মানে নতুন করে লেখা |
| চুপচাপ code করা | তুমি কী ভাবছো বোঝার উপায় নেই; সাহায্য করার সুযোগও নেই |
| Pattern এর নাম নেওয়া, কারণ ছাড়া | "Factory" কারণ শুনতে senior লাগে, কোনো রকমভেদ আছে বলে না |
Client এর সামনে বাড়ি বানানোর কথা ভাবো
ভালো একজন builder client "একটা বাড়ি" বলার সাথে সাথে ঢালাই শুরু করে না। আগে জানে: কয়জন থাকবে, কয় তলা, budget কত (clarify)। তারপর কোন কোন ঘর আর কোনটা কীসের জন্য (entity)। তারপর floor plan (class diagram)। তারপর মূল কাঠামো বানানো (মূল অংশ code করা)। আর শেষে client জিজ্ঞেস করেন "একটা বারান্দা যোগ করা যায়?", builder দেয়াল না ভেঙে দেখিয়ে দেয় কোথায় হবে (extension)।
তবে একটা জায়গায় মেলে না। Builder এর হাতে কয়েক সপ্তাহ থাকে; তোমার হাতে ৪৫ মিনিট, আর একজন মানুষ যিনি শুধু ফল না, তুমি কীভাবে ভাবছো সেটাও মাপছেন। নিজের সিদ্ধান্ত গুলো মুখে বলে বলে এগোনোও কাজের অংশ।
প্রশ্ন হলো 'একটা meeting room booking system design করো'। তোমার প্রথম দুই মিনিট কী হওয়া উচিত?
পাঁচ ধাপের approach
- Clarify (০–৫ মিনিট)। জিজ্ঞেস করো কারা ব্যবহার করবে (employee, admin), মূল কাজ কী (book, cancel, দেখা), rule কী (capacity, overlap, সর্বোচ্চ সময়), আর একসাথে কতজন। কী কী scope এর বাইরে মুখে বলে দাও (payment, notification, বারবার হওয়া meeting, যদি না চাওয়া হয়)।
- Entity (৫–১২ মিনিট)। Noun গুলো সম্ভাব্য class; রাখো শুধু যাদের state বা আচরণ আছে। প্রত্যেককে এক লাইনের একটা কাজ দাও: Room: নাম আর capacity। Booking: room, সময়ের range, কে। Scheduler: book আর cancel এর rule এর মালিক।
- Class diagram আর মূল method (১২–২০ মিনিট)। Box আর সম্পর্ক আঁকো (chapter 3)। Public method গুলোর নাম দাও:
Book(people, start, end, who),Cancel(who, start)। ঠিক করো কোন rule কার: overlap checkBookingএর, "সবচেয়ে ছোট খালি room"Schedulerএর। - মূল flow code করো (২০–৩৮ মিনিট)। স্বাভাবিক রাস্তা আর প্রধান failure গুলো পরিষ্কার করে লেখো। Rule গুলো তাদের ঘরে রাখো। কাজে লাগলে enum আর value object ব্যবহার করো। Storage রাখো memory তে একটা slice বা map হিসেবে।
- Extension আর follow-up (৩৮–৪৫ মিনিট)। "যদি…" প্রশ্ন আসবেই: concurrency, নতুন rule, নতুন type। উত্তর দাও change টা কোথায় যাবে সেটা দেখিয়ে। তোমার design এ যদি ছোট, এক জায়গার change লাগে, তাহলে তুমি ঠিক সেটাই দেখালে যার জন্য LLD।
- পুরো সময়টা: মুখে ভাবো। যে trade-off নিচ্ছো সেটা বলো ("room গুলো capacity ধরে sort রাখবো, তাহলে প্রথম খালি যে room টায় আঁটে সেটাই সবচেয়ে ভালো")। Interviewer শুধু code না, কথা বলা আর বিচারবুদ্ধিও নম্বর দেন।
Meeting room এর প্রশ্ন, ধাপে ধাপে
প্রশ্ন থেকে চলা Book() পর্যন্ত
ধাপ 1/5 Rule গুলো পাকা করো
Room এর capacity আছে। Booking পুরো ঘণ্টায়, half-open [start, end)। একই room এ দুইটা booking overlap করতে পারবে না। যে room এ আঁটে তার মধ্যে সবচেয়ে ছোটটা। Scope এর বাইরে: বারবার হওয়া meeting, notification।
- rooms
- Jamuna 2, Padma 6, Meghna 10
Whiteboard এ রাখার মতো একটা checklist
Whiteboard এর এক কোণায় এই পাঁচটা শব্দ লিখে রাখো, আর এগোতে এগোতে tick দাও:
Clarify → Entity → Class → Code → যদি।
আর যে rule ই খুঁজে পাও, তার পাশে লিখে রাখো কোন class এর মালিক। কোনো মালিকের নাম বলতে না পারলে বুঝবে একটা entity বাদ পড়েছে, বা দায়িত্ব গুলো জট পাকিয়ে আছে।
নিজে বলো: ভালো চাল না খারাপ চাল?
Interview তে, এটা কি ভালো চাল?
scope: single bookings only
Code এ meeting room scheduler
approach এর ফল: তিনটা ছোট type, প্রতিটা rule এক জায়গায়, পরিষ্কার error, আর এমন একটা গল্প যেটা প্রতিটা রাস্তা চালিয়ে দেখে।
package main
import (
"errors"
"fmt"
)
// Entities from the requirements: Room, Booking, and the Scheduler that owns the rules.
type Room struct {
Name string
Capacity int
}
// Booking holds a half-open time range [Start, End) in whole hours.
type Booking struct {
Room *Room
Start, End int
Who string
}
func (b Booking) Overlaps(start, end int) bool { return b.Start < end && start < b.End }
var (
ErrNoRoomFits = errors.New("no room for that many people")
ErrAllBusy = errors.New("all rooms that fit are busy")
ErrBadTime = errors.New("end must be after start")
)
type Scheduler struct {
rooms []*Room // kept smallest first, so the first free fit is the best fit
bookings []Booking
}
func (s *Scheduler) free(r *Room, start, end int) bool {
for _, b := range s.bookings {
if b.Room == r && b.Overlaps(start, end) {
return false
}
}
return true
}
// Book picks the smallest free room that fits. One method owns the whole rule.
func (s *Scheduler) Book(people, start, end int, who string) (*Room, error) {
if end <= start {
return nil, ErrBadTime
}
fits := false
for _, r := range s.rooms {
if r.Capacity < people {
continue
}
fits = true
if s.free(r, start, end) {
s.bookings = append(s.bookings, Booking{r, start, end, who})
return r, nil
}
}
if !fits {
return nil, ErrNoRoomFits
}
return nil, ErrAllBusy
}
func (s *Scheduler) Cancel(who string, start int) bool {
for i, b := range s.bookings {
if b.Who == who && b.Start == start {
s.bookings = append(s.bookings[:i], s.bookings[i+1:]...)
return true
}
}
return false
}
func main() {
s := &Scheduler{rooms: []*Room{{"Jamuna", 2}, {"Padma", 6}, {"Meghna", 10}}}
try := func(people, start, end int, who string) {
label := fmt.Sprintf("book %2d people %d-%d %-6s", people, start, end, who)
if r, err := s.Book(people, start, end, who); err != nil {
fmt.Printf("%s -> refused: %v\n", label, err)
} else {
fmt.Printf("%s -> %s (%d seats)\n", label, r.Name, r.Capacity)
}
}
try(4, 10, 11, "Nadia")
try(4, 10, 11, "Rahim")
try(12, 10, 11, "Tania")
try(4, 10, 11, "Sabbir")
try(4, 11, 12, "Sabbir")
try(2, 12, 11, "Karim")
if s.Cancel("Nadia", 10) {
fmt.Printf("%-27s -> Padma is free again\n", "cancel Nadia 10-11")
}
try(3, 10, 11, "Karim")
}from __future__ import annotations
from dataclasses import dataclass
# Entities from the requirements: Room, Booking, and the Scheduler that owns the rules.
@dataclass(frozen=True)
class Room:
name: str
capacity: int
@dataclass(frozen=True)
class Booking:
"""A half-open time range [start, end) in whole hours."""
room: Room
start: int
end: int
who: str
def overlaps(self, start: int, end: int) -> bool:
return self.start < end and start < self.end
class BookingError(Exception):
pass
class Scheduler:
def __init__(self, rooms: list[Room]):
self.rooms = sorted(rooms, key=lambda r: r.capacity) # smallest first: first free fit is best
self.bookings: list[Booking] = []
def _free(self, room: Room, start: int, end: int) -> bool:
return not any(b.room == room and b.overlaps(start, end) for b in self.bookings)
def book(self, people: int, start: int, end: int, who: str) -> Room:
"""Picks the smallest free room that fits. One method owns the whole rule."""
if end <= start:
raise BookingError("end must be after start")
fitting = [r for r in self.rooms if r.capacity >= people]
if not fitting:
raise BookingError("no room for that many people")
for room in fitting:
if self._free(room, start, end):
self.bookings.append(Booking(room, start, end, who))
return room
raise BookingError("all rooms that fit are busy")
def cancel(self, who: str, start: int) -> bool:
for b in self.bookings:
if b.who == who and b.start == start:
self.bookings.remove(b)
return True
return False
s = Scheduler([Room("Jamuna", 2), Room("Padma", 6), Room("Meghna", 10)])
def attempt(people: int, start: int, end: int, who: str) -> None:
label = f"book {people:2d} people {start}-{end} {who:<6}"
try:
r = s.book(people, start, end, who)
print(f"{label} -> {r.name} ({r.capacity} seats)")
except BookingError as e:
print(f"{label} -> refused: {e}")
attempt(4, 10, 11, "Nadia")
attempt(4, 10, 11, "Rahim")
attempt(12, 10, 11, "Tania")
attempt(4, 10, 11, "Sabbir")
attempt(4, 11, 12, "Sabbir")
attempt(2, 12, 11, "Karim")
if s.cancel("Nadia", 10):
print(f"{'cancel Nadia 10-11':<27} -> Padma is free again")
attempt(3, 10, 11, "Karim")// Entities from the requirements: Room, Booking, and the Scheduler that owns the rules.
interface Room {
readonly name: string;
readonly capacity: number;
}
// A half-open time range [start, end) in whole hours.
interface Booking {
readonly room: Room;
readonly start: number;
readonly end: number;
readonly who: string;
}
const overlaps = (b: Booking, start: number, end: number) => b.start < end && start < b.end;
class Scheduler {
readonly rooms: Room[];
bookings: Booking[] = [];
constructor(rooms: Room[]) {
this.rooms = [...rooms].sort((a, b) => a.capacity - b.capacity); // smallest first: first free fit is best
}
private free(room: Room, start: number, end: number): boolean {
return !this.bookings.some((b) => b.room === room && overlaps(b, start, end));
}
// Picks the smallest free room that fits. One method owns the whole rule.
book(people: number, start: number, end: number, who: string): Room {
if (end <= start) throw new Error("end must be after start");
const fitting = this.rooms.filter((r) => r.capacity >= people);
if (fitting.length === 0) throw new Error("no room for that many people");
const room = fitting.find((r) => this.free(r, start, end));
if (!room) throw new Error("all rooms that fit are busy");
this.bookings.push({ room, start, end, who });
return room;
}
cancel(who: string, start: number): boolean {
const i = this.bookings.findIndex((b) => b.who === who && b.start === start);
if (i < 0) return false;
this.bookings.splice(i, 1);
return true;
}
}
const s = new Scheduler([
{ name: "Jamuna", capacity: 2 },
{ name: "Padma", capacity: 6 },
{ name: "Meghna", capacity: 10 },
]);
function attempt(people: number, start: number, end: number, who: string): void {
const label = `book ${String(people).padStart(2)} people ${start}-${end} ${who.padEnd(6)}`;
try {
const r = s.book(people, start, end, who);
console.log(`${label} -> ${r.name} (${r.capacity} seats)`);
} catch (e) {
console.log(`${label} -> refused: ${(e as Error).message}`);
}
}
attempt(4, 10, 11, "Nadia");
attempt(4, 10, 11, "Rahim");
attempt(12, 10, 11, "Tania");
attempt(4, 10, 11, "Sabbir");
attempt(4, 11, 12, "Sabbir");
attempt(2, 12, 11, "Karim");
if (s.cancel("Nadia", 10)) console.log(`${"cancel Nadia 10-11".padEnd(27)} -> Padma is free again`);
attempt(3, 10, 11, "Karim");// Entities from the requirements: Room, Booking, and the Scheduler that owns the rules.
struct Room { name: &'static str, capacity: u32 }
// A half-open time range [start, end) in whole hours. `room` is an index into Scheduler.rooms.
struct Booking { room: usize, start: u32, end: u32, who: String }
impl Booking {
fn overlaps(&self, start: u32, end: u32) -> bool { self.start < end && start < self.end }
}
struct Scheduler { rooms: Vec<Room>, bookings: Vec<Booking> } // rooms kept smallest first
impl Scheduler {
fn free(&self, room: usize, start: u32, end: u32) -> bool {
!self.bookings.iter().any(|b| b.room == room && b.overlaps(start, end))
}
// Picks the smallest free room that fits. One method owns the whole rule.
fn book(&mut self, people: u32, start: u32, end: u32, who: &str) -> Result<&Room, &'static str> {
if end <= start { return Err("end must be after start"); }
let fitting: Vec<usize> = (0..self.rooms.len()).filter(|&i| self.rooms[i].capacity >= people).collect();
if fitting.is_empty() { return Err("no room for that many people"); }
let room = fitting.into_iter().find(|&i| self.free(i, start, end)).ok_or("all rooms that fit are busy")?;
self.bookings.push(Booking { room, start, end, who: who.to_string() });
Ok(&self.rooms[room])
}
fn cancel(&mut self, who: &str, start: u32) -> bool {
match self.bookings.iter().position(|b| b.who == who && b.start == start) {
Some(i) => { self.bookings.remove(i); true }
None => false,
}
}
}
fn main() {
let mut s = Scheduler {
rooms: vec![Room { name: "Jamuna", capacity: 2 }, Room { name: "Padma", capacity: 6 }, Room { name: "Meghna", capacity: 10 }],
bookings: vec![],
};
let attempt = |s: &mut Scheduler, people: u32, start: u32, end: u32, who: &str| {
let label = format!("book {people:2} people {start}-{end} {who:<6}");
match s.book(people, start, end, who) {
Ok(r) => println!("{label} -> {} ({} seats)", r.name, r.capacity),
Err(e) => println!("{label} -> refused: {e}"),
}
};
attempt(&mut s, 4, 10, 11, "Nadia");
attempt(&mut s, 4, 10, 11, "Rahim");
attempt(&mut s, 12, 10, 11, "Tania");
attempt(&mut s, 4, 10, 11, "Sabbir");
attempt(&mut s, 4, 11, 12, "Sabbir");
attempt(&mut s, 2, 12, 11, "Karim");
if s.cancel("Nadia", 10) { println!("{:<27} -> Padma is free again", "cancel Nadia 10-11"); }
attempt(&mut s, 3, 10, 11, "Karim");
}import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Main {
// Entities from the requirements: Room, Booking, and the Scheduler that owns the rules.
record Room(String name, int capacity) {}
// A half-open time range [start, end) in whole hours.
record Booking(Room room, int start, int end, String who) {
boolean overlaps(int s, int e) { return start < e && s < end; }
}
static final class BookingException extends Exception {
private static final long serialVersionUID = 1L;
BookingException(String msg) { super(msg); }
}
static final class Scheduler {
private final List<Room> rooms;
private final List<Booking> bookings = new ArrayList<>();
Scheduler(List<Room> rooms) {
this.rooms = rooms.stream().sorted(Comparator.comparingInt(Room::capacity)).toList(); // smallest first
}
private boolean free(Room r, int start, int end) {
return bookings.stream().noneMatch(b -> b.room().equals(r) && b.overlaps(start, end));
}
// Picks the smallest free room that fits. One method owns the whole rule.
Room book(int people, int start, int end, String who) throws BookingException {
if (end <= start) throw new BookingException("end must be after start");
List<Room> fitting = rooms.stream().filter(r -> r.capacity() >= people).toList();
if (fitting.isEmpty()) throw new BookingException("no room for that many people");
for (Room r : fitting) {
if (free(r, start, end)) {
bookings.add(new Booking(r, start, end, who));
return r;
}
}
throw new BookingException("all rooms that fit are busy");
}
boolean cancel(String who, int start) {
return bookings.removeIf(b -> b.who().equals(who) && b.start() == start);
}
}
static Scheduler s = new Scheduler(List.of(new Room("Jamuna", 2), new Room("Padma", 6), new Room("Meghna", 10)));
static void attempt(int people, int start, int end, String who) {
String label = String.format("book %2d people %d-%d %-6s", people, start, end, who);
try {
Room r = s.book(people, start, end, who);
System.out.printf("%s -> %s (%d seats)%n", label, r.name(), r.capacity());
} catch (BookingException e) {
System.out.printf("%s -> refused: %s%n", label, e.getMessage());
}
}
public static void main(String[] args) {
attempt(4, 10, 11, "Nadia");
attempt(4, 10, 11, "Rahim");
attempt(12, 10, 11, "Tania");
attempt(4, 10, 11, "Sabbir");
attempt(4, 11, 12, "Sabbir");
attempt(2, 12, 11, "Karim");
if (s.cancel("Nadia", 10)) System.out.printf("%-27s -> Padma is free again%n", "cancel Nadia 10-11");
attempt(3, 10, 11, "Karim");
}
}#include <algorithm>
#include <cstdio>
#include <stdexcept>
#include <string>
#include <vector>
// Entities from the requirements: Room, Booking, and the Scheduler that owns the rules.
struct Room {
std::string name;
int capacity;
};
// A half-open time range [start, end) in whole hours. `room` indexes Scheduler::rooms_.
struct Booking {
size_t room;
int start, end;
std::string who;
bool overlaps(int s, int e) const { return start < e && s < end; }
};
struct BookingError : std::runtime_error {
using std::runtime_error::runtime_error;
};
class Scheduler {
public:
explicit Scheduler(std::vector<Room> rooms) : rooms_(std::move(rooms)) {
std::sort(rooms_.begin(), rooms_.end(), [](const Room& a, const Room& b) { return a.capacity < b.capacity; });
}
// Picks the smallest free room that fits. One method owns the whole rule.
const Room& book(int people, int start, int end, const std::string& who) {
if (end <= start) throw BookingError("end must be after start");
bool fits = false;
for (size_t i = 0; i < rooms_.size(); i++) {
if (rooms_[i].capacity < people) continue;
fits = true;
if (free(i, start, end)) {
bookings_.push_back({i, start, end, who});
return rooms_[i];
}
}
throw BookingError(fits ? "all rooms that fit are busy" : "no room for that many people");
}
bool cancel(const std::string& who, int start) {
auto it = std::find_if(bookings_.begin(), bookings_.end(),
[&](const Booking& b) { return b.who == who && b.start == start; });
if (it == bookings_.end()) return false;
bookings_.erase(it);
return true;
}
private:
bool free(size_t room, int start, int end) const {
return std::none_of(bookings_.begin(), bookings_.end(),
[&](const Booking& b) { return b.room == room && b.overlaps(start, end); });
}
std::vector<Room> rooms_; // smallest first: the first free fit is the best fit
std::vector<Booking> bookings_;
};
int main() {
Scheduler s({{"Jamuna", 2}, {"Padma", 6}, {"Meghna", 10}});
auto attempt = [&](int people, int start, int end, const std::string& who) {
char label[64];
std::snprintf(label, sizeof label, "book %2d people %d-%d %-6s", people, start, end, who.c_str());
try {
const Room& r = s.book(people, start, end, who);
std::printf("%s -> %s (%d seats)\n", label, r.name.c_str(), r.capacity);
} catch (const BookingError& e) {
std::printf("%s -> refused: %s\n", label, e.what());
}
};
attempt(4, 10, 11, "Nadia");
attempt(4, 10, 11, "Rahim");
attempt(12, 10, 11, "Tania");
attempt(4, 10, 11, "Sabbir");
attempt(4, 11, 12, "Sabbir");
attempt(2, 12, 11, "Karim");
if (s.cancel("Nadia", 10)) std::printf("%-27s -> Padma is free again\n", "cancel Nadia 10-11");
attempt(3, 10, 11, "Karim");
}ছয়টাই হুবহু এটা print করে:
book 4 people 10-11 Nadia -> Padma (6 seats)
book 4 people 10-11 Rahim -> Meghna (10 seats)
book 12 people 10-11 Tania -> refused: no room for that many people
book 4 people 10-11 Sabbir -> refused: all rooms that fit are busy
book 4 people 11-12 Sabbir -> Padma (6 seats)
book 2 people 12-11 Karim -> refused: end must be after start
cancel Nadia 10-11 -> Padma is free again
book 3 people 10-11 Karim -> Padma (6 seats)
Output টা পড়ি:
- নাদিয়া (৪ জন): Jamuna তে আঁটে ২ জন, তাই যেটায় আঁটে তার মধ্যে সবচেয়ে ছোট Padma (৬)।
- রহিম (৪ জন, একই ঘণ্টা): ১০-১১ টায় Padma ব্যস্ত, তাই পরেরটা Meghna।
- তানিয়া (১২ জন): কোনো room এ ১২ টা seat নেই: "ব্যস্ত" থেকে আলাদা একটা error, তাই user বোঝে কী বদলাতে হবে।
- সাব্বির (৪ জন, ১০-১১): যে room গুলোয় আঁটে সব ব্যস্ত। ১১-১২ তে সে Padma পায়, কারণ [10, 11) আর [11, 12) overlap করে না।
- করিম (১২-১১): কোনো room দেখার আগেই ফিরিয়ে দেওয়া: শেষ হতে হবে শুরুর পরে।
- Cancel, তারপর করিম (৩ জন): ১০-১১ তে Padma আবার খালি, আর ৩ জনের জন্য সেটাই সবচেয়ে ছোট room।
- Language ভেদে কী আলাদা: Python, TypeScript, Java আর C++ constructor এ room গুলো capacity ধরে sort করে; Go আর Rust version আশা করে room গুলো ছোট থেকে বড় ক্রমেই দেওয়া হবে, এতে code ছোট থাকে (interview তে এটা মুখে বলে দিও)। Rust প্রতিটা booking এ room এর index রাখে, যাতে scheduler দুইটা list এরই মালিক হয়ে বাছাই করা room এর reference ফেরত দিতে পারে। Java র
removeIfদিয়েCancelএক লাইনে হয়ে যায়।
আসল interview room এ
- পাঁচটা ধাপ timer ধরে practice করো। approach তখনই কাজ করে যখন এটা অভ্যাস হয়ে যায়। LLD Problems part থেকে দুই তিনটা problem ৪৫ মিনিটের alarm দিয়ে করো।
- Requirement গুলো board এ ছোট একটা list হিসেবে লেখো। এটা interviewer এর সাথে তোমার চুক্তি, আর follow-up আসলে তোমার reference।
- Problem এর সহজ নাম গুলোই ব্যবহার করো।
ResourceEntityআরAllocationManagerএর চেয়েRoom,Booking,Schedulerভালো। - আগে সবচেয়ে সহজ data structure নাও (একটা slice, একটা map), আর scale জরুরি হলে ভালোটার কথা বলো ("হাজার হাজার booking হলে প্রতিটা room এর জন্য একটা interval tree")।
- Follow-up এর জন্য ৫–৭ মিনিট রাখো। ৪২ মিনিটেও code করতে থাকলে থামো, আর design টা গুছিয়ে বলো; পরিষ্কার design সহ অর্ধেক লেখা method, কেউ বোঝে না এমন শেষ করা code এর চেয়ে ভালো।
- "এটা আমি দেখে নিতাম" বলা ঠিক আছে। ফাঁকা জায়গা স্বীকার করে যুক্তি দেওয়া ভান করার চেয়ে ভালো।
যে ভুল গুলো round হারায়
ভুলটা বাছো
minute 0: type Room struct {একটু থেমে ভাবো
৪০ মিনিটে interviewer জিজ্ঞেস করলেন: "এবার বারবার হওয়া meeting support করো: প্রতি রবিবার ১০-১১, ৪ সপ্তাহ।" Code নতুন করে না লিখে তুমি কী বলবে?
উত্তর দেখো
একটা Recurrence value object যোগ করো (শুরুর তারিখ, সপ্তাহের দিন, কয়বার), আর এমন একটা method যেটা এটাকে সাধারণ booking এ ভেঙে দেয়। Book থাকে overlap check করার একমাত্র জায়গা: একটা বারবার হওয়া meeting book করা মানে ভাঙা প্রতিটা booking check করা, আর হয় সবগুলো book করা নয়তো একটাও না (তাই scheduler এগুলো একটা lock এর ভেতরে book করে, কোনো একটার সাথে সংঘর্ষ হলে সব ফিরিয়ে নেয়)। আগের class গুলো প্রায় বদলায়ই না, আর এটাই আসল কথা: rule এর আগে থেকেই একটা ঘর ছিল, তাই নতুন feature সেটাই আবার ব্যবহার করে।
ছোট্ট quiz
১. LLD interview approach এর পাঁচটা ধাপ কী কী?
উত্তর
Requirement আর scope পরিষ্কার করা, এক লাইনের কাজ সহ entity এর list, class diagram আর মূল method আঁকা, মূল flow code করা, তারপর extension আর follow-up সামলানো।
২. কী কী scope এর বাইরে, সেটা কেন বলে দেওয়া উচিত?
উত্তর
এতে interviewer এর সাথে একটা চুক্তি হয়, problem টা ৪৫ মিনিটে শেষ করার মতো ছোট থাকে, আর দেখা যায় তুমি অগ্রাধিকার ঠিক করতে পারো।
৩. কোন rule এর মালিক কোন class, সেটা কীভাবে ঠিক করবে?
উত্তর
Rule যে data র উপর নির্ভর করে তার সাথে রাখো। একটা object এর data লাগলে (দুইটা সময়ের range এর overlap) সেটা ওই object এ যায়; অনেকের লাগলে (সবচেয়ে ছোট খালি room) সেটা যায় সেই object এ যে সবগুলো ধরে রাখে।
৪. ৪২ মিনিটেও code করতে থাকলে কী করবে?
উত্তর
থামো, design আর বাকি ধাপ গুলো গুছিয়ে বলো, আর follow-up এর জন্য সময় রাখো। অর্ধেক লেখা method সহ পরিষ্কার একটা design, তাড়াহুড়োর code এর চেয়ে বেশি নম্বর পায়।
তোমার challenge: equipment
Office এ projector এলো। কিছু room এ একটা করে আছে।
Roomএ একটাHasProjectorfield দাও; Padma আর Meghna তে আছে, Jamuna তে নেই।Bookএ একটাneedsProjectorparameter যোগ করো। এটা true হলে শুধু projector ওয়ালা room গুলোই "আঁটে" ধরা হবে।- শেষে নুসরাতের জন্য projector সহ ১৪-১৫ টায় ২ জনের booking করো।
চালানোর আগে আন্দাজ করো নুসরাত কোন room পাবে।
হয়েছে বুঝবে যখন নতুন শেষ লাইন হবে book 2 people 14-15 Nusrat -> Padma (6 seats) (Jamuna তে ২ জন আঁটে, কিন্তু projector নেই), আগের সব লাইন একই থাকবে (ওগুলো সব false পাঠায়), আর projector এর check থাকবে শুধু Book এর ভেতরে।
এক কথায়
Clarify, entity এর list, class এর sketch, মূল অংশ code, তারপর যদি এর প্রশ্ন, মুখে বলে বলে, এই ক্রমে। প্রতিটা rule কে একজন মালিক দাও, যাতে প্রতিটা follow-up ছোট, এক জায়গার change হয়, আর মিনিট গুলো খরচ করো মূল flow তে, কেউ চায়নি এমন pattern এ না।
Station stamp
Chapter শেষ করো
পড়া শেষ হলে Complete চাপো, progress save হবে। XP শুধু Pro তে — Pro থাকলে এই chapter এ +10 XP পেতে।
Pro নিয়ে XP পাও →