এই পর্বে যা শিখবেন
- সংজ্ঞা, ছবি, উদাহরণ আর trade-off দিয়ে যেকোনো ফুল-স্ট্যাক প্রশ্নের লিখিত উত্তর সাজানো, নম্বর আর সময় মেপে
- React-এর state, effect, reconciliation আর state-এর জায়গা নিয়ে ছোট টীকা থেকে ১০ নম্বরের উত্তর লেখা
- CSR, SSR, SSG, ISR, hydration, Server Component, REST, status code, pagination আর idempotency গুছিয়ে ব্যাখ্যা করা
- ORM, N+1, transaction, session, JWT, permission, real-time, background job, test আর deployment-এর মডেল উত্তর
- ভাইভায় তিন বাক্যে উত্তর দেওয়া, পরের প্রশ্ন আগে থেকে আন্দাজ করা, আর AI-এর লেখা উত্তর যাচাই করা
১ · ভালো উত্তর লেখার কৌশল — কাঠামো, ছবি, উদাহরণ, trade-off
একই জিনিস জেনে দুজন আলাদা নম্বর পান। একজন লেখেন “SSR মানে server-side rendering, এতে SEO ভালো হয়”, তারপর থামেন। অন্যজন লেখেন HTML কোথায় আর কখন তৈরি হয়, একটি ছোট সময়রেখা আঁকেন, বাজারঘরের কোন পাতায় কোনটি দেবেন বলেন, আর শেষে বলেন SSR-এর দাম কী। দ্বিতীয়জনের খাতায় পরীক্ষক প্রতিটি নম্বরের জায়গা খুঁজে পান। দর্জির দোকানের মাপের খাতার মতো ভাবুন: বুক, কোমর, হাতা আলাদা ঘরে লেখা থাকলে কারিগরকে কিছু খুঁজতে হয় না।
- সংজ্ঞা: এক–দুই বাক্য, মূল শর্তসহ। “Idempotent মানে একাধিকবারের প্রভাব একবারের সমান”, শুধু “বারবার পাঠানো যায়” নয়।
- ছবি বা ছক: Request-এর পথ, component tree, login-এর ধাপ, test pyramid, deploy pipeline. “পার্থক্য লিখুন” প্রশ্নে একই মাপকাঠির টেবিল।
- উদাহরণ: একটি কাল্পনিক অনলাইন দোকান, বাজারঘর, ধরে লিখুন: পণ্যের পাতা, কার্ট, checkout, admin. সংখ্যা থাকলে সূত্র → মান → একক → মানে।
- Trade-off ও সীমা: কৌশলটি কী কেনে আর কী দাম দেয়। ফুল-স্ট্যাকের প্রায় প্রতিটি প্রশ্নের উত্তরেই “নির্ভর করে”, তাই কিসের ওপর নির্ভর করে, সেটিই গভীরতা দেখায়।
- সিদ্ধান্ত: “বাজারঘরের কার্টে আমি এটি নেব, কারণ …” ধরনের একটি বাক্য। পরীক্ষক বুঝতে পারেন আপনি শুধু মুখস্থ করেননি, বেছে নিতে পারেন।
নম্বর-ভাগের একটি অনুশীলনী ছক
| প্রশ্নের ধরন | সংজ্ঞা | ছবি বা ছক | উদাহরণ বা কোড | Trade-off ও সিদ্ধান্ত |
|---|---|---|---|---|
| ৪ নম্বর (সংক্ষিপ্ত টীকা) | ১–২ | ঐচ্ছিক | ১ | ১ |
| ৫ নম্বর (পার্থক্য বা ছোট ব্যাখ্যা) | ১ | ২ (টেবিল) | ১ | ১ |
| ১০ নম্বর (দীর্ঘ বা নকশা) | ২ | ৩ | ২ | ৩ |
এই ভাগ কোনো নির্দিষ্ট পরীক্ষার নিয়ম নয়, শুধু নিজের উত্তর মাপার একটি সহজ ছক। আপনার পরীক্ষার নির্দেশনা আলাদা হলে সেটিই মানুন। প্রতিটি মডেল উত্তরের “নম্বর কোথায়” সারি প্রশ্নের বিষয় দেখে সাজানো, তাই এই ছক থেকে একটু আলাদা হতে পারে।
প্রশ্নের ক্রিয়াপদ কী চায়
| প্রশ্নে লেখা | যা দিতেই হবে |
|---|---|
| সংজ্ঞা দিন / কী? | শর্তসহ এক বাক্য, কেন লাগে, একটি উদাহরণ |
| পার্থক্য লিখুন / বনাম | একই মাপকাঠির অন্তত চার সারির টেবিল, শেষে “কখন কোনটি” |
| ধাপে ধাপে ব্যাখ্যা করুন | নম্বর দেওয়া ধাপ: কে পাঠায়, কে যাচাই করে, কোথায় জমা হয়, ব্যর্থ হলে কী হয় |
| ছবিসহ ব্যাখ্যা করুন | লেবেল করা বাক্স আর তীর; প্রতিটি তীরে কী যাচ্ছে (HTML, JSON, cookie, SQL) |
| নকশা করুন | চাহিদা → অংশগুলো → ডেটার পথ → ব্যর্থতার পথ → কী ইচ্ছে করে বাদ দিলেন |
| কোডের আউটপুট লিখুন | আউটপুট, তারপর কেন: কোন snapshot, কোন ক্রম, কোন cache |
| সংক্ষিপ্ত টীকা লিখুন | ৪–৬ লাইন: কী, কেন, একটি উদাহরণ, একটি সীমা |
কোড আর ছবি — কতটুকু লিখবেন
খাতায় পুরো component বা পুরো Express app লেখার দরকার নেই। দরকার ৪–৮ লাইনের সেই অংশটি, যেখানে ধারণাটি থাকে: setCount(c => c + 1), WHERE (created_at, id) < (?, ?), UPDATE … WHERE stock >= 1. ছবিতে তিন থেকে ছয়টি বাক্সই যথেষ্ট, কিন্তু প্রতিটি তীরে লেবেল চাই। লেবেলহীন তীর পরীক্ষকের কাছে প্রায় ফাঁকা জায়গা। আর framework-এর version বদলায়, তাই API-র নাম লিখলে version-ও লিখুন: “Next.js 16-এ params একটি Promise”.
সময় ভাগ
নিয়মটি সরল: মোট মিনিট ÷ মোট নম্বর। ধরা যাক ১৮০ মিনিটে ৯০ নম্বর। তাহলে প্রতি নম্বরে দুই মিনিট, ১০ নম্বরের প্রশ্নে কুড়ি মিনিট। দীর্ঘ প্রশ্নে প্রথম দুই মিনিট মার্জিনে পাঁচ শব্দের খসড়া করুন। আটকে গেলে কাঠামো লিখে এগিয়ে যান, কারণ পদ্ধতিরও নম্বর থাকে।
নিচের stepper-এ ঙ-০১ প্রশ্নের (session বনাম JWT) ১০ নম্বরের উত্তর ধাপে ধাপে গড়া হয়েছে।
| যোগ হলো | |
| খাতায় যা লিখলেন | |
| জমা নম্বর | |
| খরচ হওয়া সময় |
- পরিকল্পনা। পাঁচ শব্দের খসড়ায় দুই মিনিট গেল। নম্বর এখনো শূন্য, কিন্তু কোনো অংশ বাদ পড়বে না।
- সংজ্ঞা — ২ নম্বর। “অবস্থা কোথায় থাকে” কথাটি প্রথম বাক্যেই এল: session-এ server-এ, JWT-তে token-এর ভেতরে। মোট ৫ মিনিট।
- ছবি — আরও ২ নম্বর। দুই পথের পাশাপাশি সিঁড়ি, প্রতিটি তীরে কী যাচ্ছে লেখা। মোট ৪ নম্বর, ৯ মিনিট।
- ছক — আরও ৩ নম্বর। এটিই সবচেয়ে বড় অংশ, তাই সবচেয়ে বেশি সময় পেল। মোট ৭ নম্বর, ১৫ মিনিট।
- Trade-off ও সিদ্ধান্ত — শেষ ৩ নম্বর। কোনটি কোথায় মানায়, refresh token কেন ঘোরে, আর বাজারঘরের সিদ্ধান্ত। কুড়ি মিনিটে পুরো দশ নম্বর।
যে পার্থক্যগুলো বারবার ঘুরে আসে
এ ধরনের জোড়া প্রশ্ন বিশ্ববিদ্যালয়ের web engineering কোর্সে, চাকরির লিখিত পরীক্ষায় আর ইন্টারভিউতে প্রায়ই আসে। প্রথমে এগুলো নিজে টেবিলে লিখতে পারেন কি না দেখুন, তারপর ঠিকানা ধরে মিলিয়ে নিন।
| পার্থক্য | প্রশ্ন | পার্থক্য | প্রশ্ন |
|---|---|---|---|
| State, props | ক-০১ | Session, JWT | ঙ-০১ |
| CSR, SSR, SSG, ISR | খ-০১ | Authentication, authorization | ঙ-০২ |
| Server, Client Component | খ-০৩ | XSS, CSRF, CORS | ঙ-০৩ |
| Safe, idempotent; PUT, PATCH | গ-০১ | Polling, SSE, WebSocket | চ-০১ |
| 401, 403, 404, 409, 422 | গ-০২ | Unit, integration, E2E | ছ-০১ |
| Offset, cursor | গ-০৩ | Mock, stub, fake | ছ-০২ |
| ORM, query builder, raw SQL | ঘ-০১ | VPS, PaaS, serverless | ঝ-০১ |
কোন মডিউলের প্রশ্ন কোথায়
| বিষয় | কোর্সের পর্ব | লিখিত | ভাইভা |
|---|---|---|---|
| React আর state | ৭–২৩ | অংশ ২ (ক-০১–ক-০৪) | ভ-০১–ভ-০৫ |
| Rendering আর Next.js | ৩, ৫১–৫৯ | অংশ ৩ (খ-০১–খ-০৩) | ভ-০৬–ভ-০৯ |
| Backend আর API নকশা | ২৪–৩৭ | অংশ ৪ (গ-০১–গ-০৩) | ভ-১০–ভ-১৩ |
| Database আর ORM | ৩৮–৪৪ | অংশ ৫ (ঘ-০১–ঘ-০৩) | ভ-১৪–ভ-১৭ |
| Auth আর নিরাপত্তা | ৪৫–৫০ | অংশ ৬ (ঙ-০১–ঙ-০৩) | ভ-১৮–ভ-২১ |
| Real-time আর background কাজ | ৬০–৬৫ | অংশ ৭ (চ-০১, চ-০২) | ভ-২২–ভ-২৩ |
| Testing | ৭২–৭৭ | অংশ ৮ (ছ-০১–ছ-০৩) | ভ-২৪–ভ-২৬ |
| Deployment, operations, stack বাছাই | ৭৮–৮৮ | অংশ ৯ (জ-০১, জ-০২, ঝ-০১) | ভ-২৭–ভ-৩০ |
এই পাতার কোনো প্রশ্ন কোনো নির্দিষ্ট পরীক্ষা, বিশ্ববিদ্যালয়, প্রতিষ্ঠান বা কোম্পানির ইন্টারভিউ থেকে নেওয়া নয়; এ ধরনের প্রশ্ন বিশ্ববিদ্যালয়, চাকরি আর ইন্টারভিউর পরীক্ষায় প্রায়ই আসে। “বাজারঘর” একটি কাল্পনিক দোকান। যেখানে কোনো সংখ্যা কোর্সের পর্বের run থেকে এসেছে, সেখানে সেটি একটি local run-এর ফল, সাধারণ নিয়ম নয়। হিসাবের পুরো অনুশীলন পর্ব ৮৯-এ, MCQ পর্ব ৯০-এ, আর কোডিং ও ডিবাগিংয়ের ইন্টারভিউ প্রশ্ন পর্ব ৯২ ও ৯৩-এ।
২ · অংশ ক — React আর state (মডিউল ২, ৩)
রিভিশন: পর্ব ১০ (state, snapshot), পর্ব ১৩ (effect), পর্ব ১৪ (hook-এর নিয়ম), পর্ব ১৫ (reconciliation), পর্ব ১৬–পর্ব ১৯ (state-এর জায়গা, Context, store, server state).
ক-০১সংক্ষিপ্ত টীকা: React-এ state আর props. একটি click handler-এ পরপর তিনবার setCount(count + 1) লিখলে count কত বাড়ে, আর setCount(c => c + 1) তিনবার লিখলে কত? — ৪ নম্বর (সহজ)
সংজ্ঞা: Props হলো parent থেকে আসা মান; child শুধু পড়ে, বদলায় না। State হলো component-এর নিজের মনে রাখা মান, যা বদলালে React আবার render করে। বাড়ির উদাহরণে props হলো বাবা-মায়ের দেওয়া টিফিনের টাকা, state হলো নিজের খাতায় লেখা হিসাব।
মূল কথা: প্রতিটি render একটি snapshot. ওই render-এ count একটি স্থির সংখ্যা। setCount(count + 1) তিনবার লিখলে তিনটিই “০ + ১” চায়, তাই count বাড়ে মাত্র ১। Updater function c => c + 1 আগের সারির ফল নিয়ে হিসাব করে, তাই বাড়ে ৩। আর একই event-এর সব আপডেট React একসাথে batching করে, তাই render হয় একবারই।
নিচের live React block-টি পর্দা খুলতেই একবার চলে। দুটি state, একটিতে সরাসরি মান, অন্যটিতে updater.
<div id="root"></div>
<script src="../course-kit/vendor/react-lab.js"></script>
<script type="text/jsx">
function Cart() {
const [a, setA] = useState(0);
const [b, setB] = useState(0);
useEffect(() => {
setA(a + 1); setA(a + 1); setA(a + 1); // all three read a = 0
setB(x => x + 1); setB(x => x + 1); setB(x => x + 1); // each reads the last result
}, []);
useEffect(() => { console.log(`render: a=${a}, b=${b}`); });
return <p>a = {a}, b = {b}</p>;
}
createRoot(document.getElementById('root')).render(<Cart />);
</script>আউটপুট:
render: a=0, b=0
render: a=1, b=3
প্রথম লাইন প্রথম render-এর। ছয়টি আপডেট মিলে একটি মাত্র নতুন render ঘটাল (দ্বিতীয় লাইন)। a বাড়ল ১, কারণ তিনটি ডাকই একই snapshot-এর a = 0 দেখেছে; b বাড়ল ৩, কারণ প্রতিটি updater আগেরটির ফল পেয়েছে। খাতায় শুধু শেষ লাইন আর এই দুই কারণ লিখলেই পুরো নম্বর।
সীমা: Props বদলায় না মানে child বদলাতে পারে না; parent নতুন props দিলে child নতুন মান পায়। আর state সরাসরি বদলানো (items.push(x)) চলে না: reference একই থাকে বলে React বদল দেখে না।
নম্বর কোথায়: দুই সংজ্ঞা (১), snapshot-এর ব্যাখ্যা (১), দুই উত্তর ১ ও ৩ (১), batching বা immutable update-এর সীমা (১)। পর্ব ১০ · পর্ব ৯
যেখানে নম্বর কাটে: “state async, তাই দেরিতে বদলায়” লিখে থামা, snapshot না বলা; তিনবারের ক্ষেত্রে ৩ লেখা; props আর state-কে শুধু “বাইরের, ভেতরের” বলে উদাহরণ না দেওয়া।
ক-০২Virtual DOM আর reconciliation কী? React-এর diff কেন O(n)? List-এ key কেন লাগে, আর index-কে key করলে কোথায় ভাঙে? — ৫ নম্বর (মাঝারি)
সংজ্ঞা: Virtual DOM হলো UI-এর একটি হালকা বর্ণনা, সাধারণ JavaScript object-এর গাছ। Reconciliation হলো পুরোনো আর নতুন গাছ মিলিয়ে ঠিক কোন DOM বদল দরকার, তা বের করা। এটি আসল DOM-এর চেয়ে “দ্রুত” নয়; এর লাভ হলো আপনি UI বর্ণনা করেন, DOM-এ হাত দেওয়ার হিসাব React করে।
O(n) কেন: দুটি গাছের সাধারণ সর্বনিম্ন তফাত বের করার অ্যালগরিদম প্রায় O(n³). React দুটি অনুমান নেয়: (১) element-এর ধরন আলাদা হলে পুরো subtree নতুন, ভেতরে মেলানো হয় না; (২) list-এ key বলে দেয় কোন সারি কোনটি। এতে প্রতিটি node মোটামুটি একবার দেখা হয়। ১,০০০ node-এ প্রায় ১০০ কোটির বদলে প্রায় ১,০০০টি তুলনা।
| key | ক্রম বদলালে বা মাঝে যোগ করলে | কখন চলে |
|---|---|---|
| Database-এর id | সারি তার state আর DOM নিয়ে সরে যায় | প্রায় সবসময় এটিই |
| Array index | Index একই থাকে, তাই input-এর লেখা ভুল পণ্যের পাশে থাকে | শুধু স্থির, state ছাড়া list |
Math.random() | প্রতি render-এ নতুন, সব সারি ধ্বংস হয়ে নতুন তৈরি | কখনো নয় |
উদাহরণ: বাজারঘরের কার্টে প্রতিটি সারিতে পরিমাণের input আছে। ওপরে একটি নতুন পণ্য যোগ হলে index key-তে React ভাবে সারি ০ এখনো সারি ০, তাই আগের সারির টাইপ করা “৩” নতুন পণ্যের পাশে চলে আসে।
সীমা: Re-render মানেই DOM বদল নয়। React function আবার চালাতে পারে, অথচ diff শেষে DOM-এ একটিও পরিবর্তন না-ও হতে পারে। Fiber-এ render ধাপ থামানো যায়, commit ধাপ যায় না।
নম্বর কোথায়: দুই সংজ্ঞা (১), দুই অনুমান ও O(n) (২), key-এর কাজ ও index-এর সমস্যা উদাহরণসহ (১), একটি সীমা (১)। পর্ব ১৫ · পর্ব ১১
যেখানে নম্বর কাটে: “Virtual DOM আসল DOM-এর চেয়ে দ্রুত” লেখা; key-কে শুধু warning থামানোর জিনিস বলা; ধরন বদলালে state হারায়, এ কথা বাদ দেওয়া।
ক-০৩useEffect-এর dependency array-এর তিন রূপ লিখুন। Cleanup কখন চলে? একটি search box-এ effect দিয়ে data আনলে race condition কীভাবে হয় আর কীভাবে ঠেকাবেন? — ৫ নম্বর (মাঝারি)
সংজ্ঞা: Effect হলো component-কে বাইরের জগতের সাথে মিলিয়ে রাখার কোড: timer, event listener, socket, network. React-এর ভেতরের হিসাবের জন্য effect নয়।
| লেখা | কখন চলে |
|---|---|
| Array নেই | প্রতিটি commit-এর পরে |
[] | শুধু প্রথম mount-এ |
[q] | প্রথমবার, আর q বদলালে (Object.is দিয়ে তুলনা) |
Cleanup: শুধু unmount-এ নয়। Dependency বদলে effect আবার চলার আগেও চলে, পুরোনো মান নিয়ে। Development-এ StrictMode ইচ্ছা করে setup → cleanup → setup চালায়, যাতে cleanup-এর অভাব ধরা পড়ে।
Race condition: ক্রেতা “চা” লিখলেন, তারপর “চাল”। দুটি অনুরোধ গেল। “চা”-র উত্তর দেরিতে এলে সেটি “চাল”-এর ফলের ওপরে বসে যায়। ঠেকানোর দুই পথ: cleanup-এ ignore = true করে পুরোনো উত্তর ফেলে দেওয়া, অথবা AbortController দিয়ে পুরোনো অনুরোধ বাতিল।
useEffect(() => {
const ctrl = new AbortController();
fetch(`/api/products?q=${encodeURIComponent(q)}`, { signal: ctrl.signal })
.then(r => r.json()).then(setItems).catch(() => {});
return () => ctrl.abort(); // runs before the next q, and on unmount
}, [q]);Trade-off: বড় অ্যাপে এই কাজ TanStack Query-র মতো library করে (cache, retry, dedupe), কারণ প্রতিটি effect-এ loading, error আর বাতিল হাতে লেখা ভুলপ্রবণ। আর যা render-এ হিসাব করা যায় (filter করা list, কার্টের মোট), তার জন্য effect লাগেই না।
নম্বর কোথায়: তিন রূপ (১.৫), cleanup কখন (১), race-এর বর্ণনা (১), প্রতিকার কোডসহ (১), trade-off (০.৫)। পর্ব ১৩ · পর্ব ১৯
যেখানে নম্বর কাটে: []-কে “কখনো চলে না” লেখা; cleanup শুধু unmount-এ বলা; dependency বাদ দিতে lint চাপা দেওয়ার পরামর্শ।
ক-০৪একটি বড় React অ্যাপে state কোথায় রাখবেন? State-এর জাতগুলো লিখুন, colocation আর derived state ব্যাখ্যা করুন, আর Context, একটি global store (Zustand বা Redux Toolkit) আর server-state library-র (TanStack Query) মধ্যে কখন কোনটি, একটি অনলাইন দোকানের উদাহরণে দেখান। — ১০ নম্বর (কঠিন)
সংজ্ঞা: State-এর জায়গা ঠিক করা মানে প্রতিটি মানের একজন মালিক ঠিক করা। জাত চিনলেই জায়গা প্রায় ঠিক হয়ে যায়। মূল দুটি নীতি: colocation (যার দরকার তার যত কাছে সম্ভব) আর single source of truth (এক তথ্য, এক ঠিকানা)।
| জাত | বাজারঘরের উদাহরণ | জায়গা |
|---|---|---|
| UI state | মেনু খোলা, modal | সেই component-এর useState |
| Form state | Checkout-এর ঠিকানা | Form-এর ভেতরে, বা React Hook Form |
| URL state | Category, sort, পাতা | Search params, যাতে refresh, Back আর শেয়ার কাজ করে |
| Client global | কার্ট, theme | Context + reducer, বা Zustand বা Redux Toolkit |
| Server state | পণ্যের তালিকা, অর্ডার | TanStack Query-র cache; আসল কপি server-এ |
Derived state: যা হিসাব করা যায়, তা জমা নয়। কার্টের মোট দাম আলাদা state-এ রাখলে একদিন সারি বদলাবে, মোট বদলাবে না। Render-এর সময় হিসাব করুন; ভারী হলে useMemo.
তিন হাতিয়ারের তুলনা:
| মাপকাঠি | Context | Global store | TanStack Query |
|---|---|---|---|
| কাজ | মান নিচে পৌঁছানো; নিজে state রাখে না | React-এর বাইরে state, selector দিয়ে পড়া | Server-এর ডেটার cache, refetch, invalidate |
| মান বদলালে কে render | প্রতিটি consumer, memo থাকলেও | শুধু যার selector-এর মান বদলেছে | শুধু সেই query key-এর observer |
| মানায় | কম বদলায় এমন মান: theme, ভাষা, লগইন করা ব্যবহারকারী | ঘন বদলায়, অনেক জায়গায় পড়া হয়: কার্ট | যা server-এর মালিকানায়: পণ্য, অর্ডার |
| দাম | বড় context-এ অকারণ render | নতুন dependency, নিয়ম শেখা | Cache-এর ধারণা (staleTime, gcTime) বোঝা |
উদাহরণের সংখ্যা: পর্ব ১৭-এর একটি মাপা run-এ একটি বড় ভাগ করা context ভেঙে ছোট করায় ২১০টি render নেমে এল ১০টিতে। পর্ব ১৮-এর এক local build-এ একই কার্টের জন্য Zustand যোগ করল ০.৪০ kB আর Redux Toolkit ৮.২৫ kB (gzip), render সংখ্যা সমান। এগুলো একটি run-এর ফল, সাধারণ নিয়ম নয়।
Trade-off: Redux নেবেন কি না, এ নিয়ে সমাজে মতভেদ আছে। Redux Toolkit কঠোর পথ, DevTools আর সব পরিবর্তনের খাতা দেয়, যা বড় দলে কাজে লাগে; Zustand ছোট আর কম আনুষ্ঠানিক। অনেক অ্যাপে server state query library-তে আর বাকিটা local থাকলে global store লাগেই না। আর token বা গোপন তথ্য কখনো localStorage-এ নয়।
সিদ্ধান্ত: বাজারঘরে filter URL-এ, পণ্য ও অর্ডার TanStack Query-তে, কার্ট একটি ছোট store-এ, theme আর ভাষা Context-এ, আর বাকি সব যার দরকার তার কাছে।
নম্বর কোথায়: পাঁচ জাত উদাহরণসহ (২), colocation ও derived state (২), তিন হাতিয়ারের তুলনা (৩), trade-off ও মতভেদ (২), সিদ্ধান্ত (১)। পর্ব ১৬ · পর্ব ১৭ · পর্ব ১৮ · পর্ব ১৯
যেখানে নম্বর কাটে: “Context মানে Redux-এর বদলি” লেখা; server-এর ডেটাকে client store-এ কপি করে রাখা; সব state এক global store-এ ঢালার পরামর্শ; URL-কে state হিসেবে না ভাবা।
৩ · অংশ খ — Rendering আর Next.js (মডিউল ১, ৮)
রিভিশন: পর্ব ৩ (rendering-এর মানচিত্র), পর্ব ৫১ (App Router), পর্ব ৫২ (Server ও Client Component), পর্ব ৫৩ (cache), পর্ব ৫৪ (Server Action), পর্ব ৫৫ (SSR, SSG, ISR, PPR), পর্ব ৫৬ (hydration).
খ-০১CSR, SSR, SSG আর ISR-এর পার্থক্য লিখুন, একটি ছবিসহ। একটি অনলাইন দোকানের হোম, পণ্যের পাতা, কার্ট আর admin ড্যাশবোর্ডে কোনটি দেবেন, কেন? — ১০ নম্বর (মাঝারি)
সংজ্ঞা: পুরো বিষয়টি দুই প্রশ্নে: HTML কোথায় তৈরি হয়, আর কখন। CSR-এ browser-এ, JavaScript আসার পরে। SSR-এ server-এ, প্রতিটি অনুরোধে। SSG-এ build-এর সময়, একবার। ISR-এ build-এ, তারপর নির্দিষ্ট সময় পরে বা দরকারমতো পেছনে নতুন করে। বিরিয়ানির দোকানের মতো: SSG সকালের ডেকচি, SSR অর্ডারমতো আলাদা রান্না, ISR ঠান্ডা হলে নতুন ডেকচি চড়ানো, কিন্তু ততক্ষণ পুরোনোটিই পরিবেশন।
HTML কোথায় আর কখন তৈরি হয়
Where and when the HTML is made, for each strategy
তুলনার ছক (SSR বনাম SSG বনাম ISR, সাথে CSR):
| মাপকাঠি | CSR | SSR | SSG | ISR |
|---|---|---|---|---|
| HTML কখন | Browser-এ, JS চলার পরে | প্রতিটি অনুরোধে | Build-এ একবার | Build-এ, পরে পেছনে নতুন |
| ডেটার সতেজতা | প্রতিবার নতুন (client fetch) | প্রতিবার নতুন | Build-এর সময়ের | Window পর্যন্ত পুরোনো হতে পারে |
| প্রথম দেখা | দেরিতে, JS-এর পরে | HTML আসতেই | দ্রুততম, CDN থেকে | দ্রুত, CDN বা cache থেকে |
| Server-এর খরচ | শুধু API | প্রতি অনুরোধে render | প্রায় শূন্য | মাঝে মাঝে নতুন render |
| SEO ও শেয়ারের preview | দুর্বল হতে পারে | ভালো | ভালো | ভালো |
| ব্যক্তিগত ডেটা | চলে | চলে, cache private | না | না, ভাগ করা cache |
উদাহরণ: ISR-এ revalidate = 60 মানে প্রতি মিনিটে নতুন পাতা নয়। ৬০ সেকেন্ড পেরোনোর পরের প্রথম অনুরোধ পুরোনো পাতা পায় আর পেছনে নতুন তৈরি শুরু করে। নিচের simulator সেটি একটি নকল ঘড়িতে দেখায়।
// ISR with revalidate = 60 s, on a simulated clock (seconds).
const REVALIDATE = 60;
let price = 500; // price in the database
let page = { price, builtAt: 0 }; // the cached HTML, built at t=0
let regenerating = null;
function request(t) {
if (regenerating && t >= regenerating.doneAt) { // background rebuild finished
page = { price: regenerating.price, builtAt: regenerating.doneAt };
regenerating = null;
}
const age = t - page.builtAt;
let status = 'HIT';
if (age > REVALIDATE) {
status = 'STALE'; // serve old page, rebuild in background
if (!regenerating) regenerating = { price, doneAt: t + 1 };
}
console.log(`t=${String(t).padStart(3)}s ${status.padEnd(5)} price=${page.price}`);
}
request(10);
price = 450; // admin changes the price at t=20
request(30);
request(70); // first request after the window
request(75);আউটপুট:
t= 10s HIT price=500
t= 30s HIT price=500
t= 70s STALE price=500
t= 75s HIT price=450
দাম ২০ সেকেন্ডে বদলেছে, কিন্তু ৩০ সেকেন্ডে এখনো পুরোনো দাম, কারণ window শেষ হয়নি। ৭০ সেকেন্ডের অনুরোধ STALE পেল, পুরোনো দামসহ, আর পেছনের নতুন তৈরি শুরু করল। ৭৫ সেকেন্ডে নতুন দাম। পর্ব ৫৫-এর সত্যিকারের Next.js run-এও ঠিক এই ক্রম দেখা গেছে। দাম সঙ্গে সঙ্গে দেখাতে হলে tag ধরে on-demand revalidation লাগে।
সিদ্ধান্ত ও trade-off: হোম আর পণ্যের পাতা static বা ISR (দ্রুত, SEO, দাম কিছুক্ষণ পুরোনো হলে ক্ষতি কম, আর দাম বদলালে tag ধরে নতুন); কার্ট আর অ্যাকাউন্ট প্রতি অনুরোধে (ব্যক্তিগত, কখনো ভাগ করা cache-এ নয়); admin ড্যাশবোর্ড CSR বা dynamic (SEO লাগে না, লগইনের পেছনে)। Next.js 16-এ একই পাতায় static shell আর dynamic অংশ মেশানো যায় (partial prerendering), আর next build-এর route table-এর চিহ্ন (○ static, ● generateStaticParams, ƒ dynamic, ◐ partial) সিদ্ধান্তের লিখিত প্রমাণ। SSR-এর দাম: প্রতিটি অনুরোধে server-এর CPU, আর ধীর query মানে ধীর TTFB.
নম্বর কোথায়: চার সংজ্ঞা (২), ছবি (২), ছক (৩), চার পাতার সিদ্ধান্ত কারণসহ (২), একটি trade-off (১)। পর্ব ৩ · পর্ব ৫৫
যেখানে নম্বর কাটে: SPA আর CSR-কে এক বলা (SPA পাতা বদলানোর ধরন, CSR HTML তৈরির জায়গা); ISR-কে “প্রতি মিনিটে rebuild” লেখা; কার্টের পাতা CDN-এর ভাগ করা cache-এ রাখা; পুরো সাইটে একটিই কৌশল ধরে নেওয়া।
খ-০২Hydration কী? Hydration mismatch-এর তিনটি কারণ আর তার প্রতিকার লিখুন। Hydration-এর খরচ কমানোর দুটি উপায় বলুন। — ৫ নম্বর (মাঝারি)
সংজ্ঞা: Hydration হলো server-এর পাঠানো HTML-এ browser-এ একই component আবার চালিয়ে DOM মেলানো আর event handler জুড়ে পাতা সচল করা। React-এ এর দরজা hydrateRoot. ততক্ষণ পাতা দেখা যায়, কিন্তু চাপ দিলে কাজ করে না। পর্ব ৫৬-এর এক local run-এ (CPU ৬ গুণ ধীর) পাতা দেখা গেছে 520 ms-এ, প্রথম সফল ক্লিক 1418 ms-এ।
| কারণ | কেন দুই রকম হয় | প্রতিকার |
|---|---|---|
Date.now(), Math.random() | Server আর browser-এ আলাদা মুহূর্ত, আলাদা সংখ্যা | মান server থেকে prop হিসেবে দিন, বা mount-এর পরে effect-এ |
typeof window-এর শাখা | Server-এ window নেই, তাই ভিন্ন markup | দুই দিকে একই render, browser-এর অংশ useEffect বা useSyncExternalStore-এ |
| Locale বা time zone | Server UTC-তে, ক্রেতা ঢাকায় | Intl-এ timeZone: 'Asia/Dhaka' আর locale স্পষ্ট করে দেওয়া |
এ ছাড়া ভুল HTML nesting (<p>-এর ভেতরে <div>) আর browser extension-ও কারণ। suppressHydrationWarning একটি element-এর এক স্তরের warning চুপ করায়, সমস্যা সারায় না।
খরচ কমানো: (১) Server Component-এ যা interactive নয় তা রাখা, যাতে কম JavaScript hydrate হয়; (২) Suspense দিয়ে ভাগ করা selective hydration, যেখানে যে অংশে ক্লিক হয় সেটি অগ্রাধিকার পায়। অন্য framework-এ islands বা resumability আরও এগিয়ে যায়।
নম্বর কোথায়: সংজ্ঞা (১), তিন কারণ ও প্রতিকার (৩), খরচ কমানোর দুই উপায় (১)। পর্ব ৫৬ · পর্ব ৫২
যেখানে নম্বর কাটে: Hydration-কে “HTML আবার ডাউনলোড” বলা; mismatch-এর সমাধান হিসেবে শুধু suppressHydrationWarning লেখা; ssr: false-এর দাম (SEO আর প্রথম দেখা) না বলা।
খ-০৩Next.js App Router-এ Server Component আর Client Component-এর পার্থক্য লিখুন। "use client" ঠিক কী করে? Server Action কেন একটি “খোলা দরজা”? — ৫ নম্বর (কঠিন)
| মাপকাঠি | Server Component | Client Component |
|---|---|---|
| কোথায় চলে | শুধু server-এ; কোড browser-এ যায় না | Server-এ HTML-এর জন্য একবার, তারপর browser-এ |
| যা পারে | async, সরাসরি database, secret পড়া | useState, useEffect, onClick, browser API |
| Default | App Router-এ সবকিছু শুরুতে server | ফাইলের মাথায় "use client" লিখলে |
| Bundle-এ প্রভাব | কিছু যোগ হয় না | নিজে আর তার সব import |
"use client": এটি একটি সীমানা, প্রতিটি component-এর লেবেল নয়। যে ফাইলে বসে, সেটি আর তার সব import client bundle-এ যায়। সীমানা পেরোয় শুধু serializable props: সাধারণ object, array, Date, JSX; সাধারণ function নয়। পর্ব ৫২-এর মাপে review-এর markdown library server-এ থাকায় পাতার নিজস্ব JS ছিল 692 byte; একটি "use client" লাইনে তা হলো 230,210 byte. Server Component আর SSR এক নয়: SSR বলে HTML কোথায় তৈরি, Server Component বলে কোড browser-এ যায় কি না। Client Component-ও SSR হয়।
Server Action: "use server" লেখা async function, যা browser থেকে একটি POST-এ ডাকা হয়। UI-তে বোতাম লুকালেও যে কেউ action ID দিয়ে সরাসরি POST পাঠাতে পারেন। তাই login, অনুমতি আর ownership-এর যাচাই action-এর ভেতরেই লাগে, পাতার যাচাই যথেষ্ট নয়; ইনপুট Zod দিয়ে, আর rate limit নিজের দায়িত্ব। Framework Origin মেলানো আর body-র সীমার মতো কিছু পাহারা দেয়, সব নয়।
নম্বর কোথায়: তুলনার ছক (২), "use client"-এর সীমানা ও serializable props (১.৫), Server Action-এর ঝুঁকি ও প্রতিকার (১.৫)। পর্ব ৫২ · পর্ব ৫৪
যেখানে নম্বর কাটে: প্রতিটি component-এ "use client" লাগবে বলা; Server Component-কে SSR-এর আরেক নাম বলা; Server Action-কে “server-এ চলে, তাই নিরাপদ” লেখা।
৪ · অংশ গ — Backend আর API নকশা (মডিউল ৪, ৫)
রিভিশন: পর্ব ২ (অনুরোধের যাত্রা), পর্ব ২৬ (middleware), পর্ব ২৭ (যাচাই), পর্ব ২৮ (error), পর্ব ৩২ (REST), পর্ব ৩৩ (status code, idempotency), পর্ব ৩৪ (pagination), পর্ব ৩৫ (versioning).
গ-০১REST API-তে resource কীভাবে নকশা করবেন? Safe আর idempotent method-এর পার্থক্য লিখুন, আর PUT ও PATCH-এর তফাত একটি উদাহরণে দেখান। — ৫ নম্বর (সহজ)
সংজ্ঞা: REST একটি স্থাপত্যের ধরন, protocol নয়; Roy Fielding-এর ২০০০ সালের dissertation থেকে নাম। মূল নিয়ম: URL-এ বিশেষ্য (resource), method-এ ক্রিয়া। POST /createOrder নয়, POST /api/orders; নাম বহুবচন, ছোট হাতের, শব্দের মাঝে hyphen.
| Method | Safe | Idempotent | বাজারঘরে |
|---|---|---|---|
| GET | হ্যাঁ | হ্যাঁ | GET /api/products/7 |
| PUT | না | হ্যাঁ | পুরো ঠিকানা বদল |
| PATCH | না | নিশ্চয়তা নেই | শুধু দাম বদল |
| DELETE | না | হ্যাঁ | কার্ট থেকে সারি মোছা |
| POST | না | না | নতুন অর্ডার, 201 আর Location |
পার্থক্য: Safe মানে server-এর অবস্থা বদলায় না। Idempotent মানে একাধিকবারের প্রভাব একবারের সমান। তাই DELETE idempotent, কিন্তু safe নয়। আর idempotent মানে উত্তর একই নয়: দ্বিতীয় DELETE 404 দিতে পারে, প্রভাব একই।
PUT বনাম PATCH: পণ্য {"name":"চাল","price":8200,"tags":["ধান","মিনিকেট"]}. PUT-এ {"name":"চাল","price":8000} পাঠালে পুরোটা বদলে tags হারায়। JSON Merge Patch-এ PATCH {"price":8000} শুধু দাম বদলায়; null দিলে key মুছে যায়, আর array পুরোটাই বদলে যায়।
নম্বর কোথায়: resource-এর নিয়ম (১), safe ও idempotent ছক (২), PUT বনাম PATCH উদাহরণ (১), একটি সীমা (১)। পর্ব ৩২
যেখানে নম্বর কাটে: REST-কে protocol বলা; idempotent মানে “একই উত্তর” লেখা; টাকাকে float-এ রাখা (ক্ষুদ্রতম এককে পূর্ণসংখ্যা, যেমন পয়সা, নিরাপদ)।
গ-০২400, 401, 403, 404, 409 আর 422-এর পার্থক্য লিখুন। একটি ভালো error body-তে কী থাকে? Network-এ উত্তর হারিয়ে client POST আবার পাঠালে কী হয়, আর Idempotency-Key কীভাবে বাঁচায়? — ৫ নম্বর (মাঝারি)
| Code | মানে | বাজারঘরে |
|---|---|---|
| 400 | Request পড়াই গেল না | ভাঙা JSON |
| 401 | পরিচয় পাইনি | Cookie বা token নেই |
| 403 | পরিচয় আছে, অনুমতি নেই | Customer admin পাতায় |
| 404 | নেই, বা অস্তিত্ব গোপন | অন্যের অর্ডার |
| 409 | বর্তমান অবস্থার সাথে সংঘাত | স্টক নেই, একই email আগে আছে |
| 422 | পড়া গেছে, নিয়ম ভেঙেছে | পরিমাণ −২ |
Error body: RFC 9457-এর Problem Details (application/problem+json): যন্ত্রের জন্য স্থির code বা type, মানুষের জন্য বার্তা, ঘরভিত্তিক ভুল, আর একটি trace id. Stack trace, SQL আর ফাইলের path শুধু log-এ।
দুবার POST: POST idempotent নয়। অর্ডার তৈরি হলো, উত্তর হারাল, client আবার পাঠাল: দুটি অর্ডার, দুবার টাকা। Idempotency-Key-এ client একটি এলোমেলো key দেয়; server প্রথমবারের উত্তর জমায় আর একই key-তে সেটিই আবার দেয়।
const http = require('node:http');
const orders = [], seenKeys = new Map(); // "database" + key -> saved reply
const server = http.createServer((req, res) => {
const key = req.headers['idempotency-key'];
if (key && seenKeys.has(key)) { // same key again: replay
res.writeHead(201, { 'Idempotent-Replayed': 'true' });
return res.end(seenKeys.get(key));
}
orders.push({ id: orders.length + 1, paisa: 70000 });
const body = JSON.stringify(orders.at(-1));
if (key) seenKeys.set(key, body);
res.writeHead(201).end(body);
});
async function buyTwice(key) { // the first reply is "lost", client retries
orders.length = 0; seenKeys.clear();
const headers = key ? { 'Idempotency-Key': key } : {};
for (let i = 0; i < 2; i++) await fetch(url, { method: 'POST', headers });
const total = orders.reduce((s, o) => s + o.paisa, 0) / 100;
console.log(`${key ? 'with key ' : 'without key'}: orders=${orders.length}, charged=${total} taka`);
}
let url;
server.listen(0, '127.0.0.1', async () => {
url = `http://127.0.0.1:${server.address().port}/api/orders`;
await buyTwice(null);
await buyTwice('k-7f3a');
server.close();
});আউটপুট:
without key: orders=2, charged=1400 taka
with key : orders=1, charged=700 taka
Key ছাড়া একই ৳৭০০-এর অর্ডার দুবার, ৳১,৪০০ কাটা। Key-সহ দ্বিতীয় অনুরোধ জমানো উত্তর পেল, নতুন অর্ডার হলো না। এটি শেখানোর জন্য ছোট নকল; আসল server-এ key আর উত্তর database-এ রাখতে হয়, আর একসাথে আসা দুটি একই key-এর অনুরোধ সামলাতে key দাবি করাটা atomic হতে হয় (পর্ব ৩৩)।
নম্বর কোথায়: ছয় code-এর ছক (২), error body (১), দুবার POST-এর সমস্যা (১), key-এর সমাধান ও সীমা (১)। পর্ব ৩৩ · পর্ব ২৭
যেখানে নম্বর কাটে: 401-কে “অনুমতি নেই” লেখা; সব ভুলে 500 বা 200-এর ভেতরে "error"; client-কে stack trace দেখানো; retry-কে সব method-এ নিরাপদ ধরা।
গ-০৩Offset আর cursor (keyset) pagination-এর পার্থক্য লিখুন। গভীর পাতায় offset কেন ধীর? তালিকা বদলালে কোথায় ভুল হয়? একটি নিরাপদ cursor query লিখুন, আর sort-এর নাম client থেকে এলে SQL injection কীভাবে ঠেকাবেন। — ১০ নম্বর (কঠিন)
সংজ্ঞা: Offset pagination বলে “প্রথম N সারি বাদ দিয়ে পরের ২০টি”: LIMIT 20 OFFSET 40. Keyset বা cursor pagination বলে “আগের পাতার শেষ সারির পরের ২০টি”: শেষ সারির মান মনে রেখে WHERE-এ তুলনা। প্রথমটি বইয়ের পৃষ্ঠা নম্বর, দ্বিতীয়টি বইয়ের ভেতরে রাখা বুকমার্ক।
| মাপকাঠি | Offset | Cursor (keyset) |
|---|---|---|
| Query | LIMIT 20 OFFSET k | WHERE (created_at, id) < (?, ?) LIMIT 21 |
| গভীর পাতার খরচ | বাদ দেওয়া সব সারি পড়ে, খরচ k-এর সমানুপাতিক | Index-এ সোজা নামে, গভীরতায় প্রায় স্থির |
| সারি যোগ বা মুছলে | সারি দুবার আসে বা হারায় | স্থির, কারণ মান ধরে তুলনা |
| “পাতা ৪৭-এ যাও” | সহজ | সরাসরি পারে না, শুধু আগে-পরে |
| মোট সংখ্যা | প্রায়ই COUNT(*) সাথে | দরকার নেই; limit + 1 এনে hasMore |
| মানায় | ছোট admin তালিকা, পাতা নম্বর লাগে | Infinite scroll, feed, বড় টেবিল, API |
কেন ধীর: OFFSET 999980-এ database প্রায় ১০ লাখ সারি পেরিয়ে তবে ২০টি দেয়। পর্ব ৩৪-এর PostgreSQL run-এ keyset query index-এর মাত্র কয়েকটি page পড়েছে, offset পড়েছে হাজার হাজার। একটি run-এ সব গভীরতায় cursor-এর সময় প্রায় একই থেকেছে।
তালিকা বদলালে: ক্রেতা পাতা ১ (৯, ৮, ৭) দেখার পরে ওপরে নতুন পণ্য ১০ এল। এখন offset 3 থেকে পাতা ২ শুরু হয় ৭ দিয়ে, তাই ৭ দুবার। একটি পণ্য মুছলে উল্টো, একটি সারি চোখের আড়ালে হারায়। Cursor “৭-এর পরের গুলো” চায়, তাই দুটি ক্ষেত্রেই ঠিক থাকে।
SELECT id, name, price, created_at
FROM products
WHERE (created_at, id) < ($1, $2) -- last row of the previous page
ORDER BY created_at DESC, id DESC -- id is the tie-breaker
LIMIT 21; -- limit + 1 tells hasMoreতিনটি খুঁটিনাটি: (১) Tie-breaker: শুধু created_at-এ সমান মানের সারি হারায়, তাই শেষে অনন্য id. (২) (created_at DESC, id DESC)-এ একটি composite index. (৩) Cursor-টি opaque রাখুন (base64url, চাইলে HMAC সই), যাতে client ভেতরের গঠনে নির্ভর না করে।
Sort-এ injection: ORDER BY-এ placeholder চলে না, কারণ placeholder মান বসায়, কলামের নাম নয়। তাই client-এর পাঠানো ?sort=price_asc একটি allowlist map থেকে নিজের লেখা SQL টুকরোয় বদলান: { price_asc: 'price ASC, id ASC', newest: 'created_at DESC, id DESC' }. Map-এ না থাকলে 400 বা 422. Client-এর লেখা কখনো SQL-এ জোড়া নয়, আর limit-এর একটি ওপরের সীমা (যেমন ১০০)।
সিদ্ধান্ত: বাজারঘরের পণ্যের তালিকা আর অর্ডারের ইতিহাসে cursor; admin-এর ছোট রিপোর্টে, যেখানে পাতা নম্বর লাগে, offset.
নম্বর কোথায়: দুই সংজ্ঞা (১), তুলনার ছক (৩), ধীর হওয়ার কারণ (১), তালিকা বদলের উদাহরণ (১), cursor query ও তিন খুঁটিনাটি (২), sort-এর allowlist (১), সিদ্ধান্ত (১)। পর্ব ৩৪ · DBMS ও SQL কোর্স
যেখানে নম্বর কাটে: Tie-breaker বাদ; hasMore-এর জন্য প্রতিবার COUNT(*); cursor-এ পাতা নম্বর রাখা; sort কলামের নাম সরাসরি SQL-এ জোড়া।
৫ · অংশ ঘ — Database আর ORM (মডিউল ৬)
রিভিশন: পর্ব ৩৮ (ORM), পর্ব ৩৯ (Prisma), পর্ব ৪০ (migration), পর্ব ৪১ (সম্পর্ক), পর্ব ৪২ (N+1), পর্ব ৪৩ (transaction), পর্ব ৪৪ (cache).
ঘ-০১Raw SQL, query builder আর ORM-এর পার্থক্য লিখুন। Parameterized query কেন SQL injection ঠেকায়? Serverless-এ connection pool নিয়ে কী সমস্যা হয়? — ৫ নম্বর (মাঝারি)
| মাপকাঠি | Raw SQL (driver) | Query builder | ORM |
|---|---|---|---|
| আপনি লেখেন | SQL নিজে | কোডে SQL-এর গঠন | Object আর সম্পর্কের ভাষায় চাওয়া |
| উদাহরণ | pg | Kysely, Drizzle | Prisma, Django ORM, Eloquent |
| নিয়ন্ত্রণ | সবচেয়ে বেশি | বেশি | কম, কিন্তু কাজ দ্রুত |
| ঝুঁকি | String জোড়ার ভুল | মাঝারি | লুকানো N+1, অদেখা SQL |
শেষে সবাই SQL-ই পাঠায়। পর্ব ৩৮-এর একই query-তে pg, Kysely আর Drizzle একটি JOIN পাঠাল, আর Prisma 7.10.1 পাঠাল দুটি query; log না দেখলে এটি জানা যায় না। কোনটি সেরা, এ নিয়ে মতভেদ আছে; সৎ উত্তর হলো বেশিরভাগ কাজে ORM, কঠিন report-এ নিরাপদ raw SQL.
Parameterized query: SQL-এর গঠন আর মান আলাদা যায়, তাই মান কখনো আদেশ হতে পারে না। পর্ব ৩৮-এর আসল PostgreSQL-এ string জোড়া দেওয়া query-তে ০-এর জায়গায় ৮টি সারি ফিরেছে। Prisma-তে $queryRaw-এর tagged template নিরাপদ, $queryRawUnsafe-এ জোড়া দেওয়া নয়।
Pool আর serverless: সংযোগ বানানো দামি, তাই connection pool. কিন্তু serverless-এ প্রতিটি কপির নিজের pool: ২৫টি কপি × ৫টি সংযোগ = ১২৫টি চাওয়া, PostgreSQL-এর সীমা ১০০ হলে ভাঙে (পর্ব ৩৮-এর একটি local run-এ ২৬টি query ব্যর্থ)। প্রতিকার: কপি-প্রতি pool ছোট আর সামনে একটি pooler.
নম্বর কোথায়: তিন স্তরের ছক (২), parameterized query-র কারণ (১.৫), pool-এর হিসাব ও প্রতিকার (১.৫)। পর্ব ৩৮ · DBMS · ORM ও migration
যেখানে নম্বর কাটে: “ORM থাকলে injection হয় না” লেখা; escape করাকে parameterized query-র সমান বলা; pool-এর গুণফল না দেখানো।
ঘ-০২N+1 সমস্যা কী? ২০টি অর্ডারের একটি পাতায় প্রতিটি অর্ডারের ক্রেতা আর পণ্যের সারি আনতে loop-এ মোট কতটি query যায়? প্রতি round trip ৪০ ms ধরলে সময় কত? কীভাবে কমাবেন আর কীভাবে ধরবেন? — ৫ নম্বর (মাঝারি)
সংজ্ঞা: N+1 মানে তালিকার জন্য ১টি query, তারপর loop-এ প্রতিটি সারির জন্য আরও query. মোট = ১ + (সম্পর্কের সংখ্যা) × N.
হিসাব: ১ + ২ × ২০ = ৪১টি query; ৪১ × ৪০ ms = ১,৬৪০ ms শুধু round trip-এ। দুটি IN (…) query-তে batch করলে ৩টি, ১২০ ms. নিচের ছোট নকল ORM সংখ্যাটি গুনে দেখায়।
// A tiny fake ORM that counts SQL round trips. RTT is an assumed 40 ms.
const RTT = 40;
const orders = Array.from({ length: 20 }, (_, i) => ({ id: i + 1, userId: (i % 5) + 1 }));
let sql = 0;
const db = {
orders() { sql++; return orders; },
userById(id) { sql++; return { id }; },
itemsByOrder(id) { sql++; return [{ orderId: id }]; },
usersIn(ids) { sql++; return ids.map((id) => ({ id })); },
itemsIn(ids) { sql++; return ids.map((id) => ({ orderId: id })); },
};
function lazyLoop() {
sql = 0;
for (const o of db.orders()) { db.userById(o.userId); db.itemsByOrder(o.id); }
return sql;
}
function batched() {
sql = 0;
const list = db.orders();
db.usersIn([...new Set(list.map((o) => o.userId))]);
db.itemsIn(list.map((o) => o.id));
return sql;
}
for (const [name, fn] of [['loop (N+1)', lazyLoop], ['batched IN', batched]]) {
const n = fn();
console.log(`${name}: ${n} queries, about ${n * RTT} ms in round trips`);
}আউটপুট:
loop (N+1): 41 queries, about 1640 ms in round trips
batched IN: 3 queries, about 120 ms in round trips
৪১ থেকে ৩: সময়ের প্রায় পুরোটাই round trip, query-র নিজের কাজ নয়। এখানে ৪০ ms একটি ধরে নেওয়া মান। পর্ব ৪২-এর সত্যিকারের Prisma run-এ include একই পাতা ৩টি query-তে আর join strategy ১টিতে নামিয়েছে, আর ৪০ ms RTT-তে loop লেগেছে ১,৬৭৩ ms, join ৪২ ms.
ধরবেন কীভাবে: Query log বা প্রতি request-এ SQL গোনা (Prisma-র query event আর AsyncLocalStorage), আর test-এ একটি query budget, যেমন “এই endpoint ৫টির বেশি query নয়”; এটি সময়ের test-এর চেয়ে স্থির। আর foreign key-তে PostgreSQL নিজে index দেয় না, EXPLAIN ANALYZE দেখে যোগ করতে হয়। select দিয়ে শুধু দরকারি কলাম আনলে JSON-ও ছোট হয়।
নম্বর কোথায়: সংজ্ঞা ও সূত্র (১), ৪১ আর ১,৬৪০ ms (১), প্রতিকার include বা batch (১.৫), ধরার উপায় (১), index-এর কথা (০.৫)। পর্ব ৪২ · পর্ব ৩৬ (GraphQL-এ DataLoader)
যেখানে নম্বর কাটে: সূত্রে সম্পর্কের সংখ্যা ভুলে ২১ লেখা; “এক বড় query সবসময় দ্রুত” বলা; শুধু cache দিয়ে ঢাকার পরামর্শ।
ঘ-০৩একটি দোকানে শেষ একটি পণ্য ২০ জন একসাথে কিনতে চাইলেন। “আগে স্টক পড়া, তারপর কমানো” ধরনের কোড কেন oversell করে? Transaction-এর ভেতরে নিলেও কেন বাঁচে না? তিনটি সমাধান তুলনা করুন, আর payment gateway-কে transaction-এর ভেতরে কেন রাখবেন না। — ১০ নম্বর (কঠিন)
সংজ্ঞা: Race condition মানে ফল নির্ভর করে কাজগুলো কোন ক্রমে মিলল তার ওপর। “পড়া → যাচাই → লেখা”, এই তিন ধাপের মাঝে অন্য অনুরোধ ঢুকে পড়ে: ২০ জনই stock = 1 পড়েন, ২০ জনই যাচাই পার হন। এটি lost update-এর ধরন।
Transaction কেন যথেষ্ট নয়: PostgreSQL-এর default isolation Read Committed. এতে পড়া মান আটকানো থাকে না। পর্ব ৪৩-এর সত্যিকারের PostgreSQL-এ transaction ছাড়া কোড এক run-এ ১৩ থেকে ২০টি অর্ডার নিল; একই কোড $transaction-এর ভেতরে নিয়েও প্রতিবার ১০টি অর্ডার, আর স্টক দেখাল ০, যেন সব ঠিক।
| পথ | কীভাবে | লাভ | দাম |
|---|---|---|---|
| শর্তসাপেক্ষ atomic update | UPDATE products SET stock = stock - 1 WHERE id = $1 AND stock >= 1; বদলানো সারি ০ হলে “স্টক নেই” | সবচেয়ে সরল, এক statement | শুধু এক সারির শর্তে চলে |
| Pessimistic lock | SELECT … FOR UPDATE, তারপর লেখা | জটিল নিয়ম লেখা যায় | অপেক্ষা, deadlock-এর ঝুঁকি; সব জায়গায় একই ক্রমে lock |
| Optimistic (version column) | WHERE version = $v; না মিললে retry | সংঘাত কম হলে দ্রুত | ভিড়ে অনেক retry |
এ ছাড়া Serializable isolation আর serialization failure-এ retry (Prisma-তে P2034), বা unique constraint দিয়ে database-কেই শেষ পাহারাদার বানানো।
Gateway বাইরে কেন: Transaction যতক্ষণ খোলা, ততক্ষণ lock আর সংযোগ আটকে থাকে। Payment gateway কয়েক সেকেন্ড নিতে পারে বা ঝুলে যেতে পারে; ভেতরে রাখলে সবাই অপেক্ষায়। তাই পথটি ভাগ করা: স্টক ধরে রাখা (ছোট transaction) → অর্ডার PENDING → gateway-তে টাকা → webhook এলে confirm, ব্যর্থ বা মেয়াদ শেষে release. আর database আর অন্য service-এ একসাথে লেখা (dual write) ঠেকাতে outbox: event একই transaction-এ টেবিলে, পরে relay পাঠায়।
সিদ্ধান্ত: বাজারঘরের checkout-এ শর্তসাপেক্ষ update (Prisma-তে updateMany, তারপর count দেখা), ছোট transaction, আর race-এর test আসল database-এ, কারণ memory-র নকল store এই ভুল দেখায় না।
নম্বর কোথায়: race-এর ব্যাখ্যা (২), Read Committed-এর সীমা (২), তিন পথের ছক (৩), gateway বাইরে ও outbox (২), সিদ্ধান্ত (১)। পর্ব ৪৩ · পর্ব ৬৫ · পর্ব ৭৫
যেখানে নম্বর কাটে: “Transaction দিলেই race শেষ” লেখা; app-এর memory-তে mutex দিয়ে সমাধান (একাধিক server-এ কাজ করে না); gateway-র ডাক transaction-এর ভেতরে রাখা।
৬ · অংশ ঙ — Authentication আর নিরাপত্তা (মডিউল ৭)
রিভিশন: পর্ব ৪৫ (session), পর্ব ৪৬ (JWT), পর্ব ৪৭ (OAuth), পর্ব ৪৮ (permission), পর্ব ৪৯ (account), পর্ব ৫০ (নিরাপত্তা তালিকা). তত্ত্বের জন্য Cybersecurity · session ও token.
ঙ-০১Session-ভিত্তিক আর JWT-ভিত্তিক login-এর পার্থক্য লিখুন, ছবিসহ। Refresh token কেন লাগে আর কেন প্রতিবার বদলায়? একটি সাধারণ web দোকান আর একটি মোবাইল অ্যাপের জন্য আপনি কী বাছবেন? — ১০ নম্বর (মাঝারি)
সংজ্ঞা: Session-এ cookie-তে থাকে শুধু একটি এলোমেলো id; কে login করেছেন, তা থাকে server-এর store-এ (database বা Redis). হোটেলের রিসেপশনের মতো: আপনার হাতে শুধু রুমের চাবি, খাতা রিসেপশনে। JWT-এ server কিছু দাবি (user id, role, মেয়াদ) স্বাক্ষর করে client-কে দেয়; client প্রতিবার পাঠায়, server স্বাক্ষর যাচাই করে, store দেখে না। এটি সই করা পরিচয়পত্র, খাতা লাগে না।
দুই পথে login-এর পরের অনুরোধ
Session looks up a store; JWT verifies a signature
তুলনার ছক (session বনাম JWT):
| মাপকাঠি | Session | JWT |
|---|---|---|
| অবস্থা কোথায় | Server-এর store-এ | Token-এর ভেতরে, client-এর কাছে |
| বাতিল (logout, ban) | সঙ্গে সঙ্গে: store-এর row মুছলেই | মেয়াদ পর্যন্ত চলে; ছোট মেয়াদ, denylist বা version লাগে |
| প্রতি অনুরোধে খরচ | একটি store lookup | স্বাক্ষর যাচাই, lookup নেই |
| গোপনীয়তা | Cookie-তে শুধু id | Payload শুধু encoded, যে কেউ পড়তে পারে |
| CSRF | Cookie নিজে যায়, তাই SameSite আর CSRF token লাগে | Header-এ পাঠালে CSRF কম; cookie-তে রাখলে একই সমস্যা |
| XSS-এ | HttpOnly cookie script পড়তে পারে না | localStorage-এ রাখলে script পড়ে নিতে পারে |
| মানায় | একই domain-এর web app | আলাদা API, মোবাইল অ্যাপ, অনেক service |
Refresh token: Access token ছোট মেয়াদের (কয়েক মিনিট), যাতে চুরি হলেও ক্ষতি সীমিত। বারবার login এড়াতে লম্বা মেয়াদের refresh token, যা server-এর database-এ থাকে (শুধু hash), তাই বাতিলের একটি জায়গা থাকে। প্রতিবার ব্যবহারে নতুন refresh token দেওয়া হয় (rotation); পুরোনোটি আবার এলে বোঝা যায় কেউ চুরি করেছে, তখন পুরো family বাতিল। React-এ একসাথে অনেক 401 এলে refresh একবারই (single-flight), নইলে নিজের ব্যবহারকারীকেই logout করে দেয়।
নিরাপদ অভ্যাস দুই পথেই: Login-এ session id বদলানো (session fixation ঠেকাতে), HttpOnly; Secure; SameSite cookie, password-এর ধীর hash (argon2 বা bcrypt-এর মতো), আর JWT-তে verifier নিজের নিয়মে চলে: algorithms, issuer, audience কোডে স্থির।
সিদ্ধান্ত: বাজারঘরের web অ্যাপে session (সহজ, সঙ্গে সঙ্গে logout). মোবাইল অ্যাপ বা আলাদা API-তে ছোট access token আর ঘোরানো refresh token. “JWT আধুনিক, তাই ভালো” কোনো যুক্তি নয়।
নম্বর কোথায়: দুই সংজ্ঞা (২), ছবি (২), ছক (৩), refresh ও rotation-এর কারণ আর সিদ্ধান্ত (৩)। পর্ব ৪৫ · পর্ব ৪৬
যেখানে নম্বর কাটে: “JWT encrypted” লেখা; JWT-তে logout-কে সহজ বলা; logout-এ শুধু cookie মোছা (store-এর row থেকে যায়); token localStorage-এ রাখার পরামর্শ বিনা সতর্কতায়।
ঙ-০২Authentication আর authorization-এর পার্থক্য লিখুন। শুধু role যাচাই কেন যথেষ্ট নয়? IDOR কী, আর কীভাবে ঠেকাবেন? Frontend-এ বোতাম লুকানো কেন নিরাপত্তা নয়? — ৫ নম্বর (সহজ)
সংজ্ঞা: Authentication: আপনি কে (না পারলে 401). Authorization: এই কাজটি আপনার জন্য অনুমোদিত কি না (না হলে 403). তৃতীয় প্রশ্ন, প্রায়ই ভুলে যাওয়া: এই নির্দিষ্ট জিনিসটি আপনার কি না।
Role যথেষ্ট নয়: RBAC বলে “customer অর্ডার দেখতে পারেন”। কিন্তু দুজন customer-এর role একই, অর্ডার আলাদা। URL-এ /api/orders/1042 বদলে 1043 করে অন্যের অর্ডার পড়া গেলে, সেটি IDOR.
// owner comes from the session, never from the request body
const order = await prisma.order.findFirst({
where: { id: orderId, userId: session.userId },
});
if (!order) throw new NotFound(); // 404 hides that the order existsপ্রতিকার: আনার পরে যাচাই নয়, আনার সময়েই সীমা: WHERE id = ? AND userId = ?. অন্যের জিনিসে 404 দিলে অস্তিত্বও গোপন থাকে। আর একটি test matrix (ভূমিকা × কাজ × মালিকানা) দিয়ে প্রমাণ।
Frontend: React-এ admin বোতাম লুকানো শুধু UX. API সরাসরি curl বা DevTools দিয়ে ডাকা যায়, তাই আসল সিদ্ধান্ত server-এ, প্রতিটি route, Server Action আর WebSocket event-এ।
নম্বর কোথায়: দুই সংজ্ঞা ও status (১.৫), IDOR উদাহরণ (১.৫), query-তে owner শর্ত (১), frontend-এর সীমা (১)। পর্ব ৪৮ · Cybersecurity কোর্স
যেখানে নম্বর কাটে: 401 আর 403 উল্টে লেখা; owner id request body থেকে নেওয়া; শুধু middleware-এ role দেখে থামা।
ঙ-০৩XSS, CSRF আর CORS-এর পার্থক্য লিখুন। React কি XSS পুরোপুরি ঠেকায়? CORS কি server-কে রক্ষা করে? প্রতিটির একটি প্রতিরক্ষা দিন। — ৫ নম্বর (মাঝারি)
| মাপকাঠি | XSS | CSRF | CORS |
|---|---|---|---|
| কী | আক্রমণ: অন্যের script আপনার পাতায় চলে | আক্রমণ: অন্য সাইট browser-এর cookie দিয়ে আপনার server-এ অনুরোধ পাঠায় | আক্রমণ নয়: browser-এর একটি অনুমতির নিয়ম |
| কে প্রয়োগ করে | — | — | Browser; server শুধু header দিয়ে জানায় |
| প্রতিরক্ষা | Output escape, DOMPurify, CSP | SameSite cookie, CSRF token, Fetch Metadata | নির্দিষ্ট origin-এর allowlist, credentials সাবধানে |
React আর XSS: JSX-এর লেখা React নিজে escape করে, তাই সাধারণ লেখায় script চলে না। কিন্তু dangerouslySetInnerHTML, javascript: URL আর সরাসরি DOM-এর কাজ আলাদা। সেখানে sanitize (DOMPurify) আর দ্বিতীয় দেয়াল হিসেবে CSP, আগে Report-Only.
CORS আর server: না। CORS browser-কে বলে অন্য origin-এর JavaScript উত্তর পড়তে পারবে কি না; অনুরোধ server-এ পৌঁছায়ই। curl যেকোনো origin থেকে ডেটা পায়। তাই authentication আর authorization আলাদা লাগবেই। পর্ব ৫০-এর ল্যাবে একই site-এর অন্য origin থেকে আসা POST SameSite=Lax পেরিয়ে গেছে; ঠেকিয়েছে CSRF token আর Fetch Metadata.
নম্বর কোথায়: তিনটির ছক (২), React-এর সীমা (১), CORS-এর সীমা (১), প্রতিটির প্রতিরক্ষা (১)। পর্ব ৫০ · Cybersecurity · CSRF · XSS ও CSP
যেখানে নম্বর কাটে: CORS-কে নিরাপত্তার দেয়াল বলা; Access-Control-Allow-Origin: *-এর সাথে credentials; “React থাকলে XSS নেই”; আক্রমণের payload বিস্তারে লেখা (দরকার নেই, নম্বরও আনে না)।
৭ · অংশ চ — Real-time আর background কাজ (মডিউল ৯)
রিভিশন: পর্ব ৬০ (WebSocket), পর্ব ৬১ (SSE, polling), পর্ব ৬২ (queue, retry, cron), পর্ব ৬৩ (email), পর্ব ৬৫ (payment, webhook).
চ-০১Short polling, long polling, SSE আর WebSocket-এর পার্থক্য লিখুন। একটি দোকানের “অর্ডারের অবস্থা” আর “ক্রেতা-বিক্রেতার chat”-এ কোনটি নেবেন? দুই server-এ চালালে chat কেন ভাঙে? — ৫ নম্বর (মাঝারি)
| পথ | কীভাবে | দিক | দাম |
|---|---|---|---|
| Short polling | নির্দিষ্ট সময় পরপর নতুন অনুরোধ | Client জিজ্ঞেস করে | অনেক খালি অনুরোধ, গড়ে অর্ধেক interval দেরি |
| Long polling | Server খবর না আসা পর্যন্ত উত্তর আটকে রাখে | Client জিজ্ঞেস করে | প্রতিটি খবরের পরে নতুন সংযোগ |
| SSE | একটি খোলা HTTP উত্তরে text/event-stream | Server → client | এক দিকের; proxy-র buffering সামলাতে হয় |
| WebSocket | HTTP GET-এ Upgrade, উত্তরে 101, তারপর frame | দুই দিকে | আলাদা protocol; scale-এ adapter আর heartbeat |
বাছাই: অর্ডারের অবস্থা শুধু server থেকে আসে, মাঝে মাঝে বদলায়: SSE (browser নিজেই reconnect করে আর Last-Event-ID পাঠায়), বা খুব কম ভিড়ে polling. Chat-এ দুই দিকেই ঘন বার্তা: WebSocket (যেমন Socket.IO-র room). পর্ব ৬১-এর এক local run-এ ২০ সেকেন্ডে polling ১০টি অনুরোধ পাঠিয়েছে, SSE একটি সংযোগ।
দুই server-এ: Room থাকে এক process-এর memory-তে। Server A-তে যুক্ত ক্রেতা server B-র বার্তা পান না। প্রতিকার: Redis-এর মতো adapter দিয়ে broadcast সব process-এ ছড়ানো; Socket.IO-র polling চালু থাকলে load balancer-এ sticky session. আর প্রতিটি room-এ ঢোকার আগে মালিকানা যাচাই, সংযোগের সময় session যাচাই।
নম্বর কোথায়: চার পথের ছক (২), দুই ক্ষেত্রে বাছাই কারণসহ (১.৫), scale-এর সমস্যা ও প্রতিকার (১.৫)। পর্ব ৬০ · পর্ব ৬১
যেখানে নম্বর কাটে: সব real-time-এ WebSocket বলা; Socket.IO আর WebSocket-কে এক protocol বলা; serverless-এ দীর্ঘ খোলা সংযোগের সমস্যা না জানা।
চ-০২Background job কেন লাগে? At-least-once delivery মানে কী, আর handler-কে কেন idempotent হতে হয়? Exponential backoff-এ jitter কেন? Payment-এর webhook-এ একই খবর দুবার এলে কী করবেন? — ৫ নম্বর (মাঝারি)
কেন: Invoice বানানো, email, ছবি ছোট করার মতো ধীর বা অনিশ্চিত কাজ ক্রেতার উত্তর থেকে আলাদা করতে, আর ব্যর্থ হলে retry করতে। পর্ব ৬২-এর একটি run-এ invoice আর email একই request-এ থাকায় p50 ছিল ৫১৫ ms; queue-তে job রেখে উত্তর দিলে ০.৭ ms. আর fire-and-forget-এ process মরলে কাজ হারায় (ওই run-এ ৫টি email-এর ১টি পৌঁছেছে)।
At-least-once: Worker মাঝপথে মরলে queue job আবার দেয়, তাই একই job একাধিকবার আসতে পারে। Handler idempotent না হলে ক্রেতা দুটি email পান। প্রতিকার: job id বা event id-তে unique constraint, “আগে হয়েছে কি না” দেখে কাজ। যে ভুল সারবে না (ভুল ঠিকানা), তার জন্য retry নয়, dead letter queue.
Jitter: একসাথে ব্যর্থ হওয়া হাজার job যদি সবাই ঠিক ১, ২, ৪, ৮ সেকেন্ডে ফেরে, তবে প্রতিবার একসাথে আঘাত করে। Jitter অপেক্ষাকে একটি পরিসরে ছড়িয়ে দেয়। নিচে seed দেওয়া এলোমেলো সংখ্যায় “full jitter”: প্রতিটি অপেক্ষা ০ থেকে সীমার মধ্যে।
// Retry delays for 3 failed jobs: plain exponential vs "full jitter".
// Seeded PRNG (mulberry32) so the output is the same on every run.
function mulberry32(seed) {
return function () {
seed |= 0; seed = (seed + 0x6d2b79f5) | 0;
let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
const rand = mulberry32(42);
const BASE = 1000; // 1 s
const plain = (n) => BASE * 2 ** n; // 1 s, 2 s, 4 s, 8 s
const jitter = (n) => Math.round(rand() * plain(n));
for (const job of ['job-A', 'job-B', 'job-C']) {
const p = [0, 1, 2, 3].map(plain).join(' ');
const j = [0, 1, 2, 3].map(jitter).join(' ');
console.log(`${job} plain: ${p} | jitter: ${j}`);
}আউটপুট (ms):
job-A plain: 1000 2000 4000 8000 | jitter: 601 897 3410 5358
job-B plain: 1000 2000 4000 8000 | jitter: 175 1053 1093 4998
job-C plain: 1000 2000 4000 8000 | jitter: 865 945 1000 7056
Plain-এ তিনটি job প্রতিবার একই মুহূর্তে ফেরে, তাই ধীর সেবার ওপর ঢেউয়ের মতো চাপ পড়ে। Jitter-এ প্রথম চেষ্টাগুলো ১৭৫, ৬০১ আর ৮৬৫ ms-এ ছড়িয়ে গেল। সীমা তবু দ্বিগুণ হচ্ছে, তাই মোট চাপও কমছে।
Webhook দুবার: Gateway নিশ্চিত হতে না পারলে একই event আবার পাঠায়। আগে raw body-র HMAC যাচাই, তারপর event id একটি unique column-এ লেখা; duplicate হলে 200 দিন, কিন্তু কিছুই দুবার করবেন না। Return URL শুধু দেখায়, সিদ্ধান্ত নেয় না; সত্যের উৎস server-to-server খবর আর gateway-র validation API, paisa-য় পরিমাণ মিলিয়ে।
নম্বর কোথায়: কেন job (১), at-least-once ও idempotency (১.৫), backoff ও jitter (১), webhook-এর duplicate (১.৫)। পর্ব ৬২ · পর্ব ৬৫
যেখানে নম্বর কাটে: “Queue থাকলে প্রতিটি job ঠিক একবার চলে” লেখা; সব ভুলে অসীম retry; দুই server-এ cron চালিয়ে একই report দুবার পাঠানো (ভাগ করা lock বা queue-র scheduler লাগে)।
৮ · অংশ ছ — Testing (মডিউল ১১)
রিভিশন: পর্ব ৭২ (কৌশল), পর্ব ৭৩ (Vitest), পর্ব ৭৪ (Testing Library), পর্ব ৭৫ (Supertest), পর্ব ৭৬ (Playwright), পর্ব ৭৭ (mock, MSW). Test-এর সাধারণ তত্ত্ব Software Engineering কোর্সে।
ছ-০১Unit, integration আর end-to-end test-এর পার্থক্য লিখুন। Test pyramid আর testing trophy কী বলে? একটি অনলাইন দোকানে কোন স্তরে কী test করবেন, আর কোনটি আগে? — ১০ নম্বর (মাঝারি)
সংজ্ঞা: Unit test একটি ছোট অংশ (function, reducer) আলাদা করে দেখে। Integration test কয়েকটি আসল অংশ একসাথে দেখে, যেমন HTTP থেকে database পর্যন্ত একটি API. E2E test আসল browser-এ পুরো system ব্যবহারকারীর মতো চালায়। যত ওপরে, তত বাস্তব, তত ধীর আর দামি।
Pyramid আর trophy — অনুপাতের দুই পরামর্শ
Test pyramid vs testing trophy
তুলনার ছক (unit বনাম integration বনাম E2E):
| মাপকাঠি | Unit | Integration (API) | E2E |
|---|---|---|---|
| কী জোড়া থাকে | একটি function বা component | HTTP → route → service → আসল database | Browser → frontend → API → database |
| Tool (এই কোর্সে) | Vitest 5.1, Testing Library | Supertest, test PostgreSQL | Playwright 1.64 |
| গতি | Millisecond; পর্ব ৭৩-এর ২৯টি test এক run-এ ১৫৯ ms | সেকেন্ড; পর্ব ৭৫-এর ২০টি এক run-এ ৩.০৪ s | প্রতিটি কয়েক সেকেন্ড |
| যা ধরে | হিসাবের ভুল, সীমানার মান | SQL, constraint, অনুমতি, race | পুরো পথের জোড়া, UI-র বাস্তব আচরণ |
| যা ধরে না | অংশের মাঝের জোড়া | Browser-এর আচরণ | কোন স্তরে ভুল, সহজে বলে না |
| অস্থিরতা | খুব কম | কম, ডেটা আলাদা রাখলে | বেশি; web-first assertion লাগে |
বাজারঘরের পরিকল্পনা: আকার নয়, ঝুঁকি আগে। (১) Unit: দাম, কুপন, পয়সার হিসাব, reducer. (২) Integration: checkout API-তে স্টক কমা, অন্যের অর্ডারে 404, ভুল স্বাক্ষরের webhook-এ 401, একই webhook দুবার। (৩) E2E: খোঁজা → কার্ট → checkout → অর্ডার নিশ্চিত, একটি বা দুটি মূল পথ, মোবাইলের মাপেও। Footer-এর রং সবার শেষে।
Trade-off: Pyramid আর trophy নিয়ে মতভেদ আছে। খাঁটি হিসাবের library-তে pyramid মানায়; database-নির্ভর web অ্যাপে integration বেশি আস্থা দেয়। আর coverage মেঝে, ছাদ নয়: ১০০% coverage-এর কোডেও সীমানার বাগ থাকতে পারে।
নম্বর কোথায়: তিন সংজ্ঞা (২), ছবি (২), ছক (৩), দোকানের পরিকল্পনা (২), trade-off (১)। পর্ব ৭২ · পর্ব ৭৫ · পর্ব ৭৬
যেখানে নম্বর কাটে: Integration-কে “দুটি unit test একসাথে” বলা; E2E দিয়েই সব test করার পরামর্শ; নিজের database mock করে API test-কে integration বলা।
ছ-০২Mock, stub আর fake-এর পার্থক্য লিখুন। কী নকল করবেন আর কী আসল রাখবেন? Flaky test কী, তার তিনটি সাধারণ কারণ আর প্রতিকার লিখুন। — ৫ নম্বর (মাঝারি)
| নকল | কাজ | উদাহরণ |
|---|---|---|
| Stub | তৈরি উত্তর দেয় | Courier API সবসময় “৳৬০” বলে |
| Mock | ডাকার ধরন যাচাই করে | SMS function ঠিক একবার, এই নম্বরে ডাকা হলো কি না |
| Fake | সহজ কিন্তু কাজ করা বাস্তবায়ন | Memory-তে একটি repository |
কী নকল: যা আপনার নয়, ধীর বা খরচের: payment gateway, SMS, email. নিজের database আর repository আসল রাখুন, নইলে SQL, schema আর constraint কখনো চলে না, আর ভুল কলামের নামেও test সবুজ। MSW network-এর সীমানায় নকল করে, তাই আপনার কোড অপরিবর্তিত থাকে।
Flaky test: কোড না বদলেও কখনো পাস, কখনো ফেল। কারণ প্রায় সবসময় নির্দিষ্ট:
- অপেক্ষা:
waitForTimeout(500)বা await ছাড়া async. পর্ব ৭৬-এর ল্যাবে এমন test দশবারে ছয়বার ফেল, web-first assertion দশে দশ পাস। - সময় আর ডেটা: আসল ঘড়ি, time zone, seed ছাড়া এলোমেলো ডেটা। প্রতিকার fake timer আর seed.
- ভাগ করা অবস্থা: একই database সারিতে সমান্তরাল test, test-এর ক্রমের ওপর নির্ভরতা। প্রতিকার প্রতি test-এ নিজের ডেটা (factory), truncate বা worker-প্রতি database.
খুঁজুন বারবার চালিয়ে (৫০ বারে ৪ বার ফেলের মতো সংখ্যা), সারান কারণ ধরে। Retry দিয়ে ঢাকলে আসল বাগও লুকায়।
নম্বর কোথায়: তিন নকলের ছক (১.৫), কী নকল কী আসল (১), flaky-র সংজ্ঞা (০.৫), তিন কারণ ও প্রতিকার (২)। পর্ব ৭৭ · পর্ব ৭৬
যেখানে নম্বর কাটে: সব নকলকে “mock” বলা; flaky-র প্রতিকার হিসেবে শুধু retry; নিজের service-এর ভেতরের function-ও mock করা, ফলে test কোডের ভেতরের ক্রমে বাঁধা পড়ে।
ছ-০৩সংক্ষিপ্ত টীকা: code coverage আর mutation testing. একটি project-এ ২৬টি mutant-এর ২৪টি test ধরেছে; mutation score কত, আর এটি coverage থেকে কী বেশি বলে? — ৪ নম্বর (সহজ)
Code coverage: Test চলার সময় কোডের কত অংশ (লাইন, branch) চলেছে। এটি বলে কোথায় test পৌঁছায়নি, কিন্তু চলা লাইনের ফল যাচাই হয়েছে কি না বলে না; assertion ছাড়া test-ও coverage বাড়ায়।
Mutation testing: Tool কোডে ছোট ভুল ঢোকায় (>= বদলে >, + বদলে -), প্রতিটিকে mutant বলে, তারপর test চালায়। কোনো test ফেল করলে mutant “killed”.
হিসাব: Mutation score = killed ÷ মোট = ২৪ ÷ ২৬ ≈ ৯২.৩%. বাকি ২টি mutant মানে দুটি জায়গায় কোড বদলালেও কোনো test টের পায় না, প্রায়ই সীমানার মান (যেমন ঠিক ৳৫০০-এ ছাড়)। পর্ব ৭২-এ ১০০% coverage-এর কোডেও এমন বাগ ধরা পড়েছে।
নম্বর কোথায়: দুই সংজ্ঞা (২), হিসাব (১), পার্থক্যের মানে (১)। পর্ব ৭২ · পর্ব ৭৩
যেখানে নম্বর কাটে: “১০০% coverage মানে বাগ নেই” লেখা; score-এ survived দিয়ে ভাগ করা; mutation-কে নিরাপত্তার mutation (XSS) ভাবা।
৯ · অংশ জ ও ঝ — Deployment, operations আর stack বাছাই (মডিউল ১২, ১৩)
রিভিশন: পর্ব ৭৮ (env, secret), পর্ব ৭৯ (build), পর্ব ৮০ (Docker), পর্ব ৮১ (CI/CD), পর্ব ৮২ (কোথায় চালাবেন), পর্ব ৮৩ (monitoring), পর্ব ৮৪ (performance), পর্ব ৮৫ (stack), পর্ব ৮৭ (scaling). Operations-এর গভীরতা Cloud ও DevOps কোর্সে।
জ-০১একটি Next.js + Express + PostgreSQL অ্যাপকে নিরাপদে production-এ নেওয়ার পথ বর্ণনা করুন: environment ও secret, Docker image, CI/CD pipeline-এর ধাপ, database migration কখন চলবে, আর rollback. একটি ছবি দিন। — ১০ নম্বর (কঠিন)
মূল নীতি: একই কোড, ভিন্ন config. Local, preview, staging, production-এ কোড এক থাকে; বদলায় environment variable, database আর secret. আর build once, deploy many: staging-এ যে build পরীক্ষা হলো, ঠিক সেটিই production-এ।
Pull request থেকে production
Cheap checks first, one migration before traffic
Environment ও secret: Secret Git-এ নয়; .gitignore প্রথম বেড়া, scanner দ্বিতীয়। একবার commit হলে ফাইল মুছে লাভ নেই, key বাতিল করে নতুন বানাতে হয়। Next.js-এ NEXT_PUBLIC_ মানে “browser-এ যাবে”, আর মানটি next build-এর সময় JavaScript-এ বসে যায়; পরে env বদলালে bundle বদলায় না। Staging কখনো production database ছোঁবে না।
Docker: প্রতিটি process-এর একটি container (web, api, worker). Multi-stage build: build-এর যন্ত্রপাতি চূড়ান্ত image-এ নয়। পর্ব ৮০-এর ল্যাবে একই Next.js অ্যাপ এক ধাপে 2.65GB, output: 'standalone'-সহ তিন ধাপে 407MB, non-root user, ভেতরে .env নেই। আগে package*.json কপি করে npm ci, পরে সোর্স, যাতে layer cache কাজে লাগে। SIGTERM-এ graceful shutdown.
CI/CD: প্রতিটি pull request-এ npm ci (lockfile হুবহু), lint, type check, unit ও component test, PostgreSQL-সহ integration test, build, Playwright. Action পিন করুন পূর্ণ commit SHA-তে; fork-এর PR secret পায় না।
Migration: prisma migrate deploy একটি আলাদা job-এ, একবার, traffic-এর আগে; প্রতিটি container চালুর সময় নয়, আর কখনো migrate dev নয়। Breaking বদল expand-contract-এ: আগে নতুন কলাম যোগ, দুই version একসাথে চলে, পরের release-এ পুরোনো মোছা। পর্ব ৮১-এর ল্যাবে আগেভাগে contract করায় পুরোনো version সত্যিই P2022 দিয়ে ভেঙেছে।
Rollback: আগের SHA-র image আবার deploy. Database সাধারণত পেছনে নেওয়া হয় না; expand-only migration থাকলে পুরোনো কোড নতুন schema-তে চলে, দরকারে roll forward.
নম্বর কোথায়: নীতি ও env-secret (২), ছবি (২), Docker (২), pipeline-এর ক্রম (১.৫), migration ও expand-contract (১.৫), rollback (১)। পর্ব ৭৮ · পর্ব ৮০ · পর্ব ৮১
যেখানে নম্বর কাটে: Production-এ migrate dev; প্রতিটি deploy-এ নতুন build; secret-কে NEXT_PUBLIC_ দিয়ে পাঠানো; rollback-এ database restore-কে প্রথম পদক্ষেপ বলা।
জ-০২Production-এ একটি অ্যাপ monitor করবেন কীভাবে? চারটি golden signal লিখুন। ৯৯.৯% মাসিক SLO-তে ৩০ দিনে কত মিনিট downtime চলে? Alert কেন লক্ষণে, কারণে নয়? Core Web Vitals-এর তিনটি মাপ আর ভালোর সীমা লিখুন। — ৫ নম্বর (মাঝারি)
Golden signals: latency, traffic, errors, saturation. এর সাথে error tracking (stack trace, release, source map), structured log আর request id, আর বাইরে থেকে uptime check.
Error budget: ৩০ দিন × ২৪ ঘণ্টা × ৬০ মিনিট = ৪৩,২০০ মিনিট। ০.১% = ৪৩.২ মিনিট. Burn rate ১৪.৪ মানে budget স্বাভাবিকের ১৪.৪ গুণ দ্রুত পুড়ছে: এক ঘণ্টায় ৩০ দিনের budget-এর ২%.
লক্ষণে alert: ক্রেতার ক্ষতি হলো লক্ষণ (checkout-এ error বাড়া, p99 latency বেড়ে যাওয়া)। CPU ৮০% একটি কারণ, যা ক্ষতি ছাড়াও ঘটে। কারণে page করলে রাতে অকারণ ঘুম ভাঙে, আর দল alert-কে উপেক্ষা করতে শেখে। কারণগুলো dashboard বা ticket-এ।
| মাপ | কী মাপে | ভালো (p75) |
|---|---|---|
| LCP | মূল জিনিস কত তাড়াতাড়ি দেখা গেল | ≤ ২.৫ s |
| INP | ক্লিকের পরে কত তাড়াতাড়ি সাড়া | ≤ ২০০ ms |
| CLS | লেখা কতটা লাফাল | ≤ ০.১ |
রায় হয় আসল ক্রেতাদের ৭৫তম percentile ধরে (field data); Lighthouse-এর lab data ভুল খোঁজার জন্য।
নম্বর কোথায়: golden signals ও অন্য উপাদান (১), budget-এর হিসাব (১.৫), লক্ষণ বনাম কারণ (১), Web Vitals (১.৫)। পর্ব ৮৩ · পর্ব ৮৪
যেখানে নম্বর কাটে: ৯৯.৯%-কে ৪.৩২ ঘণ্টা লেখা (সেটি ৯৯.৪%-এর কাছাকাছি); Lighthouse score-কে আসল ক্রেতার রায় বলা; source map প্রকাশ্যে দেওয়া।
ঝ-০১একটি নতুন প্রকল্পের জন্য ফুল-স্ট্যাক stack কীভাবে বাছবেন? একটি ওজন দেওয়া সিদ্ধান্তের ছক বানান (ওজন ৪০/৩০/৩০; A-র স্কোর ৫/২/৪, B-র ৩/৫/৪), ফল ব্যাখ্যা করুন। VPS, PaaS আর serverless-এর trade-off লিখুন, আর সিদ্ধান্ত কীভাবে লিখে রাখবেন। — ১০ নম্বর (কঠিন)
মূল কথা: “সেরা stack” বলে কিছু নেই; আছে “এই দল, এই পণ্য, এই বাজেটের জন্য ভালো stack”. ভালো উত্তর শুরু হয় পাল্টা প্রশ্নে: দল কোন ভাষা জানে, SEO কতটা জরুরি, real-time লাগবে কি না, hosting কী, সময় কত, কে রক্ষণাবেক্ষণ করবেন।
ধাপ: (১) আগে কঠিন শর্ত: শুধু PHP চলে এমন shared hosting হলে Node server-এর stack স্কোর পাওয়ার আগেই বাদ। (২) তারপর ওজন, স্কোরের আগে লিখে রাখা। (৩) স্কোর, ধরে নেওয়া বলে স্বীকার করা। (৪) সংবেদনশীলতা: কতটা ওজন বদলালে বিজয়ী বদলায়।
| মাপকাঠি (ওজন) | A | B |
|---|---|---|
| দলের দক্ষতা (০.৪০) | ৫ → ২.০০ | ৩ → ১.২০ |
| Real-time ও scale (০.৩০) | ২ → ০.৬০ | ৫ → ১.৫০ |
| Hosting ও খরচ (০.৩০) | ৪ → ১.২০ | ৪ → ১.২০ |
| মোট | ৩.৮০ | ৩.৯০ |
ব্যাখ্যা: B জেতে, কিন্তু ব্যবধান মাত্র ০.১০. দলের দক্ষতার ওজন ০.৪০ থেকে ০.৪৫ করলে (আর real-time ০.২৫) A = ২.২৫ + ০.৫০ + ১.২০ = ৩.৯৫, B = ১.৩৫ + ১.২৫ + ১.২০ = ৩.৮০; বিজয়ী বদলে গেল। তাই এমন ছকে সিদ্ধান্ত দুর্বল, আর আসল আলোচনা হওয়া উচিত “real-time কতটা জরুরি” নিয়ে।
| মাপকাঠি | VPS | PaaS | Serverless |
|---|---|---|---|
| নিয়ন্ত্রণ | সবচেয়ে বেশি (root) | মাঝারি | কম |
| আপনার কাজ | OS, patch, reverse proxy, process manager | Config আর deploy | শুধু কোড |
| যা কঠিন | রক্ষণাবেক্ষণ, নিরাপত্তা | বড় হলে খরচ, lock-in | দীর্ঘ WebSocket, লম্বা job, database-এ সংযোগের বন্যা, cold start |
| মানায় | স্থির ভার, দক্ষ দল | ছোট দল, দ্রুত শুরু | অনিয়মিত ভার, ছোট stateless কাজ |
VPS-এ zero-downtime-এর একটি উদাহরণ: পর্ব ৮২-এর একটি local run-এ pm2 reload চলাকালীন ২৩,৭৪৫টি অনুরোধের একটিও ব্যর্থ হয়নি, restart-এ ৩৮৩টি পেয়েছে 502. কোনো নির্দিষ্ট vendor নয়, অংশ ধরে সিদ্ধান্ত: static ফাইল CDN-এ, Next.js আর API একটি process-এ, worker আলাদা, PostgreSQL managed সেবায়, এগুলো উদাহরণ মাত্র।
লিখে রাখা: এক পাতার ADR: শিরোনাম, অবস্থা, প্রেক্ষাপট, সিদ্ধান্ত, পরিণাম। পুরোনো ADR বদলানো হয় না, নতুন ADR দিয়ে প্রতিস্থাপিত হয়। আর Dan McKinley-র “innovation token” ধারণা: একটি দল অল্প কয়েকটি নতুন জিনিসই সামলাতে পারে, বাকি সব পরিচিত, যেমন একটি modular monolith আর PostgreSQL.
নম্বর কোথায়: পাল্টা প্রশ্ন ও কঠিন শর্ত (২), ছক ও হিসাব (২), সংবেদনশীলতা (২), hosting-এর trade-off (২), ADR ও innovation token (২)। পর্ব ৮৫ · পর্ব ৮২ · পর্ব ৮৭
যেখানে নম্বর কাটে: একটি stack-কে সবসময় সেরা বলা; ওজন স্কোর দেখার পরে বসানো; ০.১০ ব্যবধানকে নিশ্চিত জয় বলা; প্রথম দিনেই microservices; কোনো vendor-এর দাম তথ্য হিসেবে লেখা।
১০ · ভাইভা — কৌশল, ৩০টি ছোট প্রশ্ন, সাধারণ ভুল আর AI
ভাইভায় পরীক্ষক আপনার উত্তর শুনেই পরের প্রশ্ন বানান। লিখিত পরীক্ষায় আপনি পথ ঠিক করেন, ভাইভায় পথ ঠিক করে আপনার শেষ বাক্য। তাই প্রথম উত্তর এমনভাবে দিন, যাতে পরের প্রশ্ন আপনার চেনা পথে আসে।
তিন বাক্যের কাঠামো
“useMemo কী?” — “এটি একটি hook, যা আগের হিসাবের ফল জমা রাখে, যতক্ষণ dependency বদলায় না (কী)। যেমন হাজার পণ্যের filter প্রতিটি টাইপে আবার না চালানো (কীভাবে)। তবে এর নিজেরও খরচ আছে, আর আগে মেপে দেখা উচিত; React Compiler এখন অনেকটা নিজে করে (সীমা)।” তৃতীয় বাক্যটিই পরের প্রশ্নের দরজা খোলে: “React Compiler কী করে?”
ভাইভার পাঁচটি অভ্যাস
- থেমে শুরু করুন: দুই সেকেন্ড ভাবা দোষের নয়। “একটু ভেবে বলি” বলাও ঠিক আছে।
- ধারণা আগে, tool পরে: আগে “server state হলো server-এর ডেটার cache”, তারপর “যেমন TanStack Query”. Tool-এর নাম ভুল হলেও ধারণা থাকে।
- বাজারঘরের উদাহরণ মুখে রাখুন: কার্ট, শেষ ইলিশ, দাম বদল, দুবার টাকা কাটা। একটি পরিচিত উদাহরণে অনেক প্রশ্নের উত্তর দেওয়া যায়।
- Version বলুন: “React 19-এ provider সরাসরি
<Ctx value>”, “Next.js 16-এmiddleware.ts-এর নামproxy.ts”. Framework বদলায়, আর পরীক্ষক এটি শুনতে চান। - না জানলে সৎভাবে: “পুরো নিশ্চিত নই” বলে যা জানেন সেখান থেকে যুক্তি দিন। API-র নাম, option বা সংখ্যা বানাবেন না।
একটি নমুনা ভাইভা — পরের প্রশ্ন কীভাবে গভীরে নামে
একটি কাল্পনিক ভাইভা, SSR দিয়ে শুরু। প্রতিটি উত্তরের শেষ কথা থেকেই পরের প্রশ্ন আসে।
| পরীক্ষক | |
| প্রার্থী (মূল কথা) | |
| কেন ভালো উত্তর | |
| জোড়া পর্ব |
- শুরু। সংজ্ঞা দিয়েই নিজে থেকে সীমা বললেন: দেখা যায়, কিন্তু চাপ দিলে কাজ করে না। পরীক্ষক সেই সূত্রে hydration-এ গেলেন।
- ধাপ আর দাম। “আবার চালায়, মেলায়, জোড়ে” তিনটি ক্রিয়া, আর মাঝের মৃত সময়ের কথা। গভীরতা এখানেই বোঝা যায়।
- কারণ আগে। সরাসরি
suppressHydrationWarningনা বলে আগে কারণের তালিকা দিলেন। পরীক্ষক এটিই শুনতে চান। - পার্থক্য স্পষ্ট। Server Component আর SSR এক নয়, প্রার্থী তা গুলিয়ে ফেলেননি। কম JavaScript-এর লাভটি বললেন।
- সিদ্ধান্ত। “নির্ভর করে” বলে থামেননি; কার্ট ব্যক্তিগত, তাই প্রতি অনুরোধে।
- প্রমাণ। দাবি নয়, যাচাইয়ের পথ: build-এর চিহ্ন আর response header. ভাইভার সবচেয়ে ভালো শেষ এটিই।
৩০টি ছোট প্রশ্ন — মুখে বলার উত্তর আর সম্ভাব্য পরের প্রশ্ন
জোরে উত্তর বলুন, তারপর প্রশ্নে চেপে মেলান। প্রতিটিতে ৩০ সেকেন্ডের বেশি নয়। তারপর “পরের প্রশ্ন”-এর উত্তরও মুখে বলুন; সেটিই আসল অনুশীলন।
React আর state (পর্ব ৭–২৩)
ভ-০১Hook কেন শর্ত বা loop-এর ভেতরে ডাকা যায় না? (সহজ)
React প্রতিটি hook চেনে ডাকার ক্রম দিয়ে, নাম দিয়ে নয়। শর্তে একটি hook বাদ পড়লে পরের সবগুলো ভুল ঘরের মান পায়। পর্ব ১৪
পরের প্রশ্ন: Custom hook কি state ভাগ করে? — না, logic ভাগ করে; প্রতিটি ডাকের state আলাদা।
ভ-০২useRef আর useState-এর পার্থক্য? (সহজ)
দুটিই render-এর মাঝে মান রাখে, কিন্তু ref বদলালে render হয় না, state বদলালে হয়। Ref DOM ধরতে বা timer id রাখতে। পর্ব ১৪
পরের প্রশ্ন: Render-এর সময় ref পড়া ঠিক কি না? — না, event বা effect-এ পড়ুন; render pure থাকা উচিত।
ভ-০৩memo করা component তবু কেন re-render হলো? (মাঝারি)
ভ-০৪Server state আর client state আলাদা কেন? (মাঝারি)
Server state-এর আসল মালিক server; অন্যরা বদলাতে পারে, তাই browser-এর কপি পুরোনো হতে পারে। এটি একটি cache, তাই refetch, invalidate আর staleTime লাগে। পর্ব ১৯
পরের প্রশ্ন: staleTime আর gcTime? — প্রথমটি কতক্ষণ ডেটা বিশ্বাস করা যায় (default 0), দ্বিতীয়টি অব্যবহৃত ঘর কতক্ষণ থাকে (default ৫ মিনিট)।
ভ-০৫Optimistic update কী, আর ব্যর্থ হলে? (মাঝারি)
Server-এর উত্তরের আগেই UI বদলানো, যেন কাজ হয়ে গেছে। আগে চলমান query বাতিল আর snapshot রাখা; ব্যর্থ হলে snapshot ফেরানো; শেষে invalidate করে server-এর সাথে মেলানো। পর্ব ১৯
পরের প্রশ্ন: কোথায় দেবেন না? — টাকা কাটা বা স্টক কমার মতো জায়গায়, যেখানে ভুল দেখানোর দাম বেশি।
Rendering আর Next.js (পর্ব ৩, ৫১–৫৯)
ভ-০৬SPA আর CSR কি একই? (সহজ)
না। SPA বলে পাতা বদলানোর ধরন (পুরো পাতা reload ছাড়া), CSR বলে HTML কোথায় তৈরি। SSR দিয়েও SPA-র মতো navigation হয়। পর্ব ৩
পরের প্রশ্ন: তাহলে Next.js কী? — প্রথম পাতা server থেকে HTML, পরের navigation client-side; পাতা ধরে কৌশল।
ভ-০৭Next.js App Router-এ layout আর template-এর পার্থক্য? (মাঝারি)
Layout navigation-এ টিকে থাকে আর state রাখে; template প্রতিবার নতুন mount হয়, state মুছে যায়। পর্ব ৫১
পরের প্রশ্ন: Next.js 16-এ params কীভাবে পড়বেন? — এটি Promise: server-এ await params, client-এ use(params) বা useParams()।
ভ-০৮Request waterfall কী, কীভাবে ভাঙবেন? (মাঝারি)
স্বাধীন await একটির পর একটি চলা, তাই মোট সময় যোগফল। Promise.all-এ একসাথে শুরু করলে মোট সময় সবচেয়ে ধীরটির কাছে নামে। পর্ব ৫৩
পরের প্রশ্ন: Streaming কি মোট সময় কমায়? — না; প্রথম দেখার অংশ আগে আসে, ধীরতম query-র সময় থেকেই যায়।
ভ-০৯Next.js 16-এ middleware কোথায় গেল, আর তাতে অনুমতি যাচাই যথেষ্ট কি? (কঠিন)
ফাইলের নাম এখন proxy.ts, পুরোনো middleware.ts deprecated. এটি হালকা প্রাথমিক যাচাই; আসল অনুমতি যাচাই route handler, Server Action বা data layer-এ। পর্ব ৫৭
পরের প্রশ্ন: Route handler-এর GET কি default-এ cache হয়? — না, Next.js 15 থেকে dynamic; cache চাইলে স্পষ্ট করে বলতে হয়।
Backend আর API (পর্ব ২৪–৩৭)
ভ-১০Node.js এক thread-এ চলে, তবু এত request কীভাবে সামলায়? (সহজ)
JavaScript এক thread-এ, কিন্তু অপেক্ষার কাজ (network, disk) যায় OS আর libuv-এ; thread আটকে থাকে না। তাই I/O-ভারী কাজে ভালো, CPU-ভারী কাজে নয়। পর্ব ২৪
পরের প্রশ্ন: Event loop আটকালে কী হয়? — সবার অনুরোধ ধীর; পর্ব ২৪-এর মাপে ১০ ms-এর sync কাজ হার প্রায় ৭৬ হাজার থেকে প্রায় ৯৯ request/s-এ নামিয়েছে।
ভ-১১Express-এ middleware-এর ক্রম কেন গুরুত্বপূর্ণ? (সহজ)
Middleware পরপর চলে। express.json() route-এর পরে বসালে req.body undefined; error middleware (চার argument) সব route-এর পরে। আর next() না ডাকলে, উত্তরও না দিলে, request ঝুলে থাকে। পর্ব ২৬
পরের প্রশ্ন: Express 5-এ async error? — Handler-এর ফেরত দেওয়া rejected promise নিজে error middleware-এ যায়; timer-এর ভেতরের throw যায় না।
ভ-১২TypeScript থাকলে runtime-এ Zod দিয়ে যাচাই কেন? (মাঝারি)
Type compile-এর পরে মুছে যায়; বাইরের ডেটা আসে চলার সময়ে। Schema দেখে গড়ন (না মিললে 422 বা 400), আর স্টকের মতো অবস্থা দেখে service (409). পর্ব ২৭
পরের প্রশ্ন: Mass assignment কীভাবে ঠেকাবেন? — Allowlist schema, অজানা key বাদ, আর repository-তে ঘর নাম ধরে লেখা।
ভ-১৩GraphQL-এ error হলেও status 200 কেন? (মাঝারি)
এক উত্তরে কিছু field সফল আর কিছু ব্যর্থ হতে পারে, তাই ভুল থাকে উত্তরের errors তালিকায়, পাশে আংশিক data. শুধু HTTP status দেখে monitoring করলে এই ভুল চোখে পড়ে না। পর্ব ৩৬
পরের প্রশ্ন: GraphQL-এ N+1 কেন স্বাভাবিক? — Resolver field ধরে চলে; DataLoader একই tick-এর id জমিয়ে batch করে।
Database আর ORM (পর্ব ৩৮–৪৪)
ভ-১৪migrate dev আর migrate deploy-এর পার্থক্য? (সহজ)
dev নিজের কম্পিউটারে নতুন migration ফাইল বানায়, দরকারে reset চাইতে পারে; deploy শুধু আগে থেকে থাকা ফাইল চালায়, production-এ এটিই। পর্ব ৪০
পরের প্রশ্ন: চলমান অ্যাপে কলামের নাম বদলাবেন কীভাবে? — Expand-contract: নতুন কলাম, sync ও backfill, পড়া বদল, তারপর পুরোনো মোছা।
ভ-১৫অর্ডারের সারিতে পণ্যের দাম আবার কেন রাখবেন? (সহজ)
অর্ডার হলো ইতিহাস; পণ্যের দাম পরে বদলায়। কেনার সময়ের দাম, নাম আর ঠিকানা কপি না রাখলে পুরোনো রসিদ বদলে যায়। পর্ব ৪১
পরের প্রশ্ন: PostgreSQL কি foreign key-তে index বানায়? — না, শুধু primary key আর unique-এ; foreign key-তে হাতে যোগ করতে হয়।
ভ-১৬Cache-aside-এ পণ্যের দাম বদলালে কী করবেন? (মাঝারি)
Database-এ commit-এর পরে cache-এর key মুছে দেওয়া (DEL), নতুন মান বসানো নয়; সাথে একটি TTL. পরের পড়া database থেকে নতুন মান এনে আবার রাখে। পর্ব ৪৪
পরের প্রশ্ন: Cache stampede কী? — জনপ্রিয় key মুছতেই অনেক অনুরোধ একসাথে database-এ; lock বা single-flight আর TTL-এ jitter দিয়ে ঠেকানো।
ভ-১৭Redis বন্ধ হয়ে গেলে সাইট কী করবে? (কঠিন)
Fail open: cache-কে miss ধরে database-এ যাওয়া, ছোট timeout-সহ। পর্ব ৪৪-এর এক run-এ default client-এ প্রতিটি অনুরোধ প্রায় ১০ সেকেন্ড আটকে ছিল, নিজের deadline দিলে ৯০ ms. পর্ব ৪৪
পরের প্রশ্ন: তাহলে database কি ভেঙে পড়বে না? — পড়তে পারে; তাই database-এর ভার সীমিত রাখা, যেমন সংযোগের সীমা বা জরুরি পাতাকে অগ্রাধিকার।
Auth আর নিরাপত্তা (পর্ব ৪৫–৫০)
ভ-১৮Logout-এ cookie মুছলেই কি যথেষ্ট? (সহজ)
না। Cookie মুছলে শুধু browser ভোলে; কেউ কপি করে রাখলে সেটি চলতেই থাকে। Session-এ store-এর row মুছতে হয়। পর্ব ৪৫
পরের প্রশ্ন: JWT-তে logout? — Access token মেয়াদ পর্যন্ত চলে; ছোট মেয়াদ, refresh token বাতিল, দরকারে denylist.
ভ-১৯JWT কি encrypted? (সহজ)
সাধারণ JWT স্বাক্ষর করা, encrypted নয়; payload শুধু base64url, যে কেউ পড়তে পারে। তাই ভেতরে গোপন কিছু নয়। পর্ব ৪৬
পরের প্রশ্ন: Verifier কী কী স্থির রাখে? — algorithms, issuer, audience, কোডে; token-এর header-এর কথায় নয়।
ভ-২০Social login-এ ব্যবহারকারী চিনবেন email দিয়ে, না অন্য কিছু দিয়ে? (মাঝারি)
Email বদলায়; স্থায়ী পরিচয় provider-এর sub (issuer সহ)। Account টেবিলে provider আর providerAccountId একসাথে unique. পর্ব ৪৭
পরের প্রশ্ন: state আর PKCE-র পার্থক্য? — state উত্তরটিকে browser-এর সাথে বাঁধে, PKCE code-কে login শুরুর সাথে বাঁধে।
ভ-২১Password reset-এ “এই email নেই” বলা কেন ভুল? (মাঝারি)
এতে কোন email-এর account আছে, বোঝা যায় (user enumeration). একই লেখা, একই status, এমনকি একই সময়ের উত্তর; খবর যাবে মেইলে। পর্ব ৪৯
পরের প্রশ্ন: Reset token database-এ কীভাবে? — এলোমেলো, শুধু hash রাখা, একবারই চলে, মেয়াদ বাঁধা।
Real-time আর background কাজ (পর্ব ৬০–৬৫)
ভ-২২WebSocket handshake-এর status code কত? (সহজ)
101 Switching Protocols, একটি HTTP GET-এ Upgrade: websocket-এর উত্তরে; তারপর একই TCP সংযোগে frame. পর্ব ৬০
পরের প্রশ্ন: মৃত সংযোগ ধরবেন কীভাবে? — Heartbeat: নিয়মিত ping, সময়ে pong না এলে বন্ধ।
ভ-২৩দুই server-এ cron চালালে কী হয়? (মাঝারি)
প্রতিটি কাজ দুবার চলে, কারণ cron একটি সময়ের নিয়ম, lock নয়। ভাগ করা lock বা queue-র scheduler লাগে, আর time zone স্পষ্ট (Asia/Dhaka). পর্ব ৬২
পরের প্রশ্ন: Time zone না দিলে? — Server UTC-তে হলে সকাল ৯টার রিপোর্ট ঢাকায় বিকেল ৩টায় যায়।
Testing (পর্ব ৭২–৭৭)
ভ-২৪getByRole কেন getByTestId-এর আগে? (সহজ)
ব্যবহারকারী আর screen reader বোতামকে role আর নামে চেনেন, test id দেখেন না। Role দিয়ে খুঁজলে accessibility-ও যাচাই হয়। পর্ব ৭৪
পরের প্রশ্ন: getBy, queryBy, findBy? — না পেলে ভুল, null, আর অপেক্ষা করা Promise.
ভ-২৫Playwright-এ প্রতিটি test-এ login না করে কীভাবে? (মাঝারি)
একটি setup project একবার login করে cookie storageState ফাইলে রাখে; বাকি test সেখান থেকে শুরু করে। পর্ব ৭৬
পরের প্রশ্ন: Strict mode violation কী? — Locator একাধিক element পেলে Playwright থেমে যায়; filter বা chaining দিয়ে একটিতে নামাতে হয়।
ভ-২৬Supertest-এ app থেকে listen কেন আলাদা রাখেন? (মাঝারি)
createApp() শুধু app ফেরত দেয়; Supertest নিজে খালি port-এ চালায় আর শেষে বন্ধ করে, তাই port-এর সংঘর্ষ হয় না। পর্ব ৭৫
পরের প্রশ্ন: Test-এর ডেটা আলাদা রাখার তিন পথ? — প্রতি test-এর আগে truncate, transaction শেষে rollback, worker-প্রতি database.
Deployment, operations আর stack (পর্ব ৭৮–৮৮)
ভ-২৭CI-তে npm install নয়, npm ci কেন? (সহজ)
npm ci lockfile-এর হুবহু version বসায়, না মিললে থামে, lockfile বদলায় না। তাই প্রতিটি run একই dependency পায়। পর্ব ৮১
পরের প্রশ্ন: GitHub Action কেন commit SHA-তে পিন করবেন? — Tag সরানো যায়; SHA বিষয়বস্তুর hash, বদলায় না।
ভ-২৮Container-এর exit code 137 আর 143-এর মানে? (মাঝারি)
১৩৭ মানে SIGKILL (সময়সীমা পেরোনো বা memory শেষ), ১৪৩ মানে SIGTERM পেয়ে থামা। Node PID 1 হলে handler ছাড়া SIGTERM উপেক্ষা করে, তারপর SIGKILL. পর্ব ৮০
পরের প্রশ্ন: Graceful shutdown-এ কী করেন? — নতুন সংযোগ বন্ধ, চলমান কাজ শেষ, resource বন্ধ, একটি সর্বোচ্চ সময়সীমাসহ exit.
ভ-২৯নামে hash থাকা JS ফাইল আর HTML-এ কোন Cache-Control? (মাঝারি)
ভ-৩০কয়েকটি app server চালালে login কেন হারায়? (মাঝারি)
Session process-এর memory-তে থাকলে পরের অনুরোধ অন্য server-এ গেলে সে চেনে না। সমাধান Redis বা database-এ ভাগ করা session store. পর্ব ৮৭
পরের প্রশ্ন: Read replica-র পরিচিত ভুল? — লেখার পরপরই replica থেকে পড়লে নিজের লেখা না দেখা; সেই মুহূর্তে primary থেকে পড়া।
যেসব ভুলে নম্বর কাটে
| ভুল | কেন নম্বর কাটে | প্রতিকার |
|---|---|---|
| Tool-এর নামে পুরো উত্তর (“Redux দিয়ে করব”) | ধারণা বোঝা যায় না | আগে নীতি (state-এর মালিক কে), তারপর tool |
| “পার্থক্য” প্রশ্নে অনুচ্ছেদ | মাপকাঠি মেলানো যায় না | একই সারির টেবিল, শেষে “কখন কোনটি” |
| Trade-off ছাড়া সিদ্ধান্ত | মনে হয় মুখস্থ | কী কেনে, কী দাম দেয়, কোন শর্তে বদলাবে |
পুরোনো API (pages router-এর getServerSideProps নতুন App Router প্রশ্নে, v4-এর cacheTime) | Version-এর জ্ঞান নেই মনে হয় | Version লিখুন, নতুন নাম লিখুন |
| নিরাপত্তা শুধু frontend-এ | আসল পাহারা server-এ | Route, action আর query-তে যাচাই |
| ছবিতে তীর বা লেবেল নেই | পথই আসল উত্তর | প্রতিটি তীরে কী যাচ্ছে লিখুন |
| সংখ্যা বানানো (“৯০% দ্রুত”) | একটি ভুল পুরো উত্তরে সন্দেহ আনে | সূত্র দেখান, বা “এক run-এ” বলে উৎস দিন |
| Idempotent, safe, atomic গুলিয়ে ফেলা | সংজ্ঞাই নম্বরের ভিত্তি | প্রতিটির এক বাক্যের সংজ্ঞা মুখস্থ নয়, উদাহরণসহ বুঝে |
AI-কে কড়া পরীক্ষক বানান
AI দিয়ে প্রশ্ন বানানো আর নিজের উত্তর যাচাই করানো যায়। কিন্তু ফুল-স্ট্যাকের উত্তরে AI প্রায়ই পুরোনো framework API দেয় (Next.js-এর pages router, React-এর বাদ পড়া ধরন, TanStack Query v4-এর নাম), এমন package বা option বানায় যা নেই, এমন কোড লেখে যা চলে কিন্তু secret ফাঁস করে বা authorization বাদ দেয়, অদরকারি dependency যোগ করে, আর ভুল চাপা দেয় (খালি catch). তাই তাকে পরীক্ষক বানান, উত্তরদাতা নয়, আর তার প্রতিটি দাবি নিজের version-এর official docs-এ মিলিয়ে নিন।
AI-এর উত্তর যাচাইয়ের চেকলিস্ট
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি ১০ নম্বরের লিখিত উত্তরের অংশগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- মার্জিনে পাঁচ শব্দের খসড়া
- এক–দুই বাক্যের সংজ্ঞা
- লেবেলসহ ছবি বা তুলনার ছক
- একটি অনলাইন দোকানের উদাহরণ বা হিসাব
- Trade-off: কী কেনে, কী দাম দেয়
- এক লাইনের সিদ্ধান্ত
(সহজ) একটি React component-এ count-এর মান ৪। একটি click handler-এ পরপর তিনবার setCount(count + 1) লেখা আছে। ক্লিকের পরের render-এ count কত?
- ৫
- ৭
- ৪
- ৬
(মাঝারি) একটি অনলাইন দোকানের Next.js অ্যাপে “আমার কার্ট” পাতা লগইন করা ব্যবহারকারীর নিজের পণ্য দেখায়। কোন rendering আর cache সবচেয়ে ঠিক?
- SSG, build-এর সময় একবার
- ISR,
revalidate = 60, CDN-এ ভাগ করা cache - প্রতি অনুরোধে dynamic render, Cache-Control
privateবাno-store - Static HTML,
max-age=31536000, immutable
(মাঝারি) পণ্যের id নতুন থেকে পুরোনো ক্রমে: ৯, ৮, ৭, ৬, ৫, ৪, ৩, ২, ১। পাতায় ৩টি করে, offset pagination. পাতা ১ (৯, ৮, ৭) পড়ার পরে ওপরে নতুন পণ্য ১০ যোগ হলো। এখন OFFSET 3 LIMIT 3 কী দেবে?
- ৬, ৫, ৪
- ৭, ৬, ৫
- ৮, ৭, ৬
- ৪, ৩, ২
(মাঝারি) একজন লগইন করা customer GET /api/orders/1043 পাঠালেন, কিন্তু অর্ডারটি অন্য customer-এর। অর্ডারের অস্তিত্বও গোপন রাখতে হবে। কোনটি সবচেয়ে ভালো?
- 401 Unauthorized
- 200, অর্ডারটি দেখানো, কারণ role “customer”
- 403 Forbidden
- Query-তে
WHERE id = ? AND userId = ?, না পেলে 404
(সহজ) একটি পাতায় ২০টি অর্ডার দেখানো হয়। প্রতিটি অর্ডারের ক্রেতা আর পণ্যের সারি loop-এর ভেতরে আলাদা query দিয়ে আনা হয়, আর তালিকার জন্য একটি query. মোট কতটি query যায়?
- ২১
- ৪০
- ৪১
- ৩
(মাঝারি) একটি সেবার মাসিক SLO ৯৯.৯%, মাস ধরা হয় ৩০ দিন। এক মাসে সর্বোচ্চ কত মিনিট downtime চলে (error budget)?
- ৪.৩২ মিনিট
- ৪৩.২ মিনিট
- ৮.৭৬ ঘণ্টা
- ৪৩২ মিনিট
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব শব্দ এখানে একসাথে:
মনে রাখুন
- কাঠামোই নম্বর: সংজ্ঞা → ছবি বা ছক → বাজারঘরের উদাহরণ → trade-off → সিদ্ধান্ত; “পার্থক্য” প্রশ্নে একই সারির টেবিল।
- চারটি জোড়া মুখস্থ নয়, বুঝে: SSR, SSG, ISR (HTML কোথায়, কখন); session, JWT (অবস্থা কোথায়, বাতিল কীভাবে); offset, cursor (জায়গা বনাম মান); unit, integration, E2E (কতটা জোড়া, কতটা দামি)।
- নিরাপত্তা server-এ: query-তে owner শর্ত, Server Action-এর ভেতরে যাচাই, CORS দেয়াল নয়, logout মানে store থেকে মোছা।
- টাকা আর স্টকে নিশ্চয়তা: Idempotency-Key, শর্তসাপেক্ষ atomic update, unique event id, আর at-least-once ধরে idempotent handler.
- ভাইভায় তিন বাক্য: কী → কীভাবে → সীমা; version বলুন, না জানলে সৎভাবে বলুন, আর API বা সংখ্যা বানাবেন না।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৯২ · React আর frontend ইন্টারভিউ — ধারণা, কোড আর ডিবাগিংপরবর্তী পর্বReact আর frontend ইন্টারভিউ: ধারণা, live coding আর ডিবাগিং।
- ফুল-স্ট্যাক ওয়েব ফ্রেমওয়ার্ক · কোর্স হোমরোডম্যাপসব ৯৩টি পর্বের তালিকা; পরের পর্ব ৯২ · React আর frontend ইন্টারভিউ।
- পর্ব ৮৮ · ক্যাপস্টোনরিভিশনবাজারঘর শুরু থেকে শেষ; প্রায় প্রতিটি লিখিত প্রশ্নের উদাহরণ এখানে একসাথে।
- পর্ব ৫৫ · SSR, SSG, ISR আর partial prerenderingপেছনে ফিরেখ-০১-এর পুরো ব্যাখ্যা, সত্যিকারের build-এর route table সহ।
- System Design · লিখিত ও মৌখিক প্রশ্নপাশের ট্র্যাকScaling, cache আর API নকশার বড় মাপের প্রশ্ন।
- DBMS ও SQL · লিখিত ও মৌখিক প্রশ্নপাশের ট্র্যাকIndex, transaction আর isolation-এর তত্ত্বের প্রশ্ন।
- Cybersecurity · লিখিত ও মৌখিক প্রশ্নগভীরে যানXSS, CSRF, session আর token-এর রক্ষকের চোখে প্রশ্ন।
- Cloud ও DevOps · লিখিত ও মৌখিক প্রশ্নগভীরে যানDocker, CI/CD আর monitoring-এর লিখিত প্রশ্ন, একই কাঠামোয়।