মূল বিষয়বস্তুতে যান
Clean Code Mastery

Inline Temp: একবারই ব্যবহার করা রাফ নোটটা ছুঁড়ে ফেলো

Inline Temp রিফ্যাক্টরিং শেখো একটা মজার রাফ পেপারের গল্প দিয়ে — TypeScript আর C# উদাহরণ, নিরাপদ ধাপ, IDE shortcut, আর কখন variable inline করা উচিত না সেটাসহ।

21 মিনিট আপডেট: June 11, 2026beginner
refactoringinline tempinline variabletemporary variablesclean codecomposing methods

📝 রাফ পেপারের গল্প

পরীক্ষার হল। সুমাইয়া, ক্লাস ৮, রোল নম্বর ২৩, গণিত পরীক্ষা দিচ্ছে। ৪ নম্বর প্রশ্ন: "রহিম ৫টা কলম কিনল, প্রতিটার দাম ১০ টাকা। মোট কত?"

সুমাইয়া রাফ পেপার নেয়। লেখে:

Total = 5 x 10 = 50

তারপর উত্তরপত্রে লেখে: "মোট ৫০ টাকা।"

শেষ। রাফ নোট কাজ করে দিয়েছে। সুমাইয়া এটা ঠিক একবার ব্যবহার করেছে — উত্তরে ৫০ কপি করতে। এখন এই রাফ নোটের কী হবে?

সে সেটা ফেলে দেবে। অথবা এড়িয়ে যাবে। কেউ রাফ পেপার উত্তরপত্রের সাথে staple করে না।

কিন্তু ধরো সুমাইয়া সত্যিই staple করে দিল। উত্তরপত্রে লেখা: "ম্যাডাম, Total-এর মান দেখতে Rough Note 1 দেখুন। উত্তর হলো Total টাকা।" নাসরিন ম্যাডামকে এখন রাফ পেজে যেতে হবে, Total লাইন খুঁজতে হবে, ৫০ পড়তে হবে, মাথায় ধরে রাখতে হবে, উত্তরপত্রে ফিরতে হবে, তারপর Total-এর জায়গায় ৫০ বসাতে হবে। একটা প্রশ্নের জন্য — একটু বিরক্তিকর। কিন্তু নাসরিন ম্যাডাম প্রতিদিন চল্লিশটা খাতা দেখেন। প্রতিটা উত্তরে এই লাফ মারলে তিনি মাথাব্যথা নিয়ে বাড়ি যাবেন।

এখন অস্বস্তিকর সত্যটা শোনো: কোডে আমরা সবসময় এই কাজটাই করি। একটা ছোট temporary variable বানাই, স্পষ্ট নাম দিই, ঠিক পরের লাইনে একবার ব্যবহার করি, তারপর সেটা চিরকাল রেখে দিই। প্রতিটা পাঠককে নাসরিন ম্যাডামের মতো লাফাতে হয়: variable পড়ো, মান মনে রাখো, পরের লাইনে যাও, দুটো জোড়া লাগাও। একটা লাফ সস্তা। বড় project-এ হাজারটা লাফ পড়াকে ধীর আর ক্লান্তিকর করে — আর পড়াটাই programmer-রা দিনের বেশিরভাগ সময় করে।

চিত্র ১: সুমাইয়ার পরীক্ষার দিন — রাফ নোট একটা মুহূর্তের জন্য কাজের, কিন্তু পরে চিরকালের বোঝা।

আজকের refactoring হলো সেই ঝাড়ু যেটা এই রাফ নোটগুলো সরায়। এর নাম Inline Temp। এটা পুরো catalog-এর সবচেয়ে ছোট, সবচেয়ে সহজ refactoring — নিরাপদ ছোট-ছোট ধাপে কোড পরিবর্তনের অভ্যাস শেখার জন্য একদম সেরা জায়গা।

🤔 Inline Temp কী?

Inline Temp — Martin Fowler-এর বই Refactoring-এর দ্বিতীয় সংস্করণে এটাকে Inline Variable বলা হয়েছে — একটা খুব ছোট, খুব সহজ refactoring। এক নিঃশ্বাসে পুরো ধারণাটা:

তোমার একটা temporary variable আছে যেটা একটা সহজ expression থেকে একবার assign হয়, আর নামটা কিছুই যোগ করে না। ভেরিয়েবলের প্রতিটা ব্যবহার সেই expression দিয়ে replace করো, তারপর variable-টা মুছে দাও।

এটুকুই। "Temp" মানে হলো temporary variable — একটা local variable যেটা শুধু একটা method-এর ভেতরেই থাকে। "Inline" মানে expression-টাকে সরাসরি সেখানে ঠেলে দেওয়া যেখানে variable-টা ব্যবহার হতো। ঠিক যেভাবে সুমাইয়া রাফ কাজটা সরাসরি উত্তরে লিখত।

একটা ছোট উদাহরণ। আগে:

const basePrice = order.quantity * order.itemPrice;
return basePrice > 1000;

পরে:

return order.quantity * order.itemPrice > 1000;

basePrice variable-টা একটা রাফ নোট ছিল। তার নাম এমন কিছু বোঝায়নি যা order.quantity * order.itemPrice formula ইতিমধ্যে বলেনি। একবার ব্যবহার হয়েছিল। তাই inline করলাম, নোট ফেলে দিলাম।

দেখো পরিবর্তনটা পাঠকের যাত্রায় কী করে। আগে, পাঠকের চোখকে temp-এ যেতে হয়, জিজ্ঞেস করতে হয় এটা কী ধরে আছে, expression-এ ফিরে trace করতে হয়, তারপর উত্তর সামনে নিতে হয়। পরে, expression ঠিক যেখানে দরকার সেখানেই বসে থাকে:

চিত্র ২: temp-কে জিজ্ঞাসাবাদ করা পাঠক — variable-এর প্রতিটা পড়া মানে assign হওয়ার জায়গায় একটা অতিরিক্ত লাফ।
💡

এক লাইনে মনে রাখার কৌশল: যদি variable-এর নাম expression-এর চেয়ে বেশি কিছু না বলে, তাহলে সেটা শুধু একটা রাফ নোট — inline করে দাও। কিন্তু যদি নামটা সত্যিই একটা বিভ্রান্তিকর formula বোঝায়, রেখে দাও। নামটাই একমাত্র পরীক্ষা।

আরেকটা গুরুত্বপূর্ণ কথা। Inline Temp সাধারণত নিজের সৌন্দর্যের জন্য করা হয় না। নিজে নিজে, এটা একটা লাইন বাঁচায়। এর আসল শক্তি হলো এটা একটা পথ পরিষ্কার করার refactoringExtract Method আর Replace Temp with Query-এর মতো বড় refactoring প্রায়ই ছোট্ট temporary-দের কারণে আটকে যায়, ঠিক গলির মাঝে দাঁড়ানো রিকশার মতো। Inline Temp সেই রিকশা সরিয়ে দেয় যাতে বড় গাড়ি পার হতে পারে।

🔍 কখন এটা দরকার?

কীভাবে বুঝবে একটা temporary variable inline করা উচিত? এই লক্ষণগুলো খোঁজো:

  1. Variable-টা ঠিক একবার assign হয় আর ঠিক একবার ব্যবহার হয়। জন্ম নেয়, একবার পড়া হয়, আর কখনো ছোঁয়া যায় না। এটাই classic রাফ নোট।
  2. নামটা expression-কে পুনরাবৃত্তি করে। const total = a + b; তারপর return total;total নাম নতুন কিছু বলে না। তুলনা করো const isLeapYearEdgeCase = ... — এই নামটা হয়তো সত্যিকারের কাজ করছে, তাই রাখবে।
  3. Variable-টা আরেকটা refactoring আটকাচ্ছে। তুমি Replace Temp with Query করতে চাও, কিন্তু একটা ছোট temp expression আর তার ব্যবহারের মাঝে দাঁড়িয়ে আছে। Fowler-এর catalog সরাসরি বলে Inline Temp প্রায় সবসময় অন্য refactoring-এর সেবায় ব্যবহার হয়, একা নয়।
  4. Method-টা ছোট, কিন্তু temp সেটাকে বড় দেখাচ্ছে। দুই-লাইনের method যেটা একটা স্পষ্ট লাইন হতে পারত।

যদি কোনো সত্যিকারের, একটু অগোছালো method দেখো, এর ভেতরের temporary-গুলো সাধারণত কয়েকটা পরিচিত ধরনে পড়ে। সেই ধরনগুলোর মধ্যে শুধু একটাই আজকের ঝাড়ুর লক্ষ্য:

চিত্র ৩: একটা সাধারণ অগোছালো method-এ temp-দের মোটামুটি ছবি — শুধু একবার-কপি করা রাফ নোটগুলোই Inline Temp-এর কাজ।

৪০ শতাংশের টুকরোটা তোমার ঝাড়ু দেওয়ার। ২৫ শতাংশ — দুটো সম্পর্কহীন কাজের জন্য পুনরায় ব্যবহৃত variable — সেটা Split Temporary Variable-এর কাজ। বাকিগুলো একা রেখে দাও কারণ তাদের নামগুলো সত্যিই সাহায্য করছে।

এটা code smell-এর সাথেও যুক্ত। একটা Long Method প্রায়ই অকেজো এক-ব্যবহারের temp-এর ভিড় বহন করে, সেটা method-কে আরও লম্বা আর ভয়ঙ্কর দেখায়। সেগুলো ঝাড়ু দেওয়া পরিষ্কারের প্রথম ধাপ। Inline Temp চুপচাপ Duplicate Code প্রতিরোধেও সাহায্য করে। Expression মুক্ত হলে পরে সেটাকে একটা shared query method-এ রূপান্তর করা যায়, বরং সবাই ফর্মুলা copy করার চেয়ে।

এগোনোর আগে একটা ছোট সতর্কতা: এই refactoring-এর উল্টো কাজের একটা যমজ আছে। Extract Variable একটা বিভ্রান্তিকর expression-কে একটা নাম দেয়। Inline Temp একটা অকেজো নাম সরিয়ে দেয়। এগুলো বিপরীত, ঠিক যেমন একটা ব্যাগ zip করা আর খোলা। দুটোই জানা মানে তুমি যেদিকে কোড পরিষ্কার হয় সেদিকে যেতে পারবে।

⚖️ এক নজরে আগে আর পরে

TypeScript-এ পরিবর্তনের classic চেহারা। ধরো একটা ছোট দোকান জানতে চাইছে একটা order বিনামূল্যে delivery পাবে কিনা।

আগে:

function qualifiesForFreeDelivery(order: Order): boolean {
  const basePrice = order.quantity * order.itemPrice;
  return basePrice > 1000;
}

পরে:

function qualifiesForFreeDelivery(order: Order): boolean {
  return order.quantity * order.itemPrice > 1000;
}

একই আচরণ। প্রতিটা সম্ভাব্য order-এর জন্য একই ফলাফল। একটা কম লাইন, একটা কম নাম মনে রাখতে হবে, পাঠকের জন্য শূন্য লাফ।

চিত্র ৪: আগে, পাঠককে temp-এর মধ্য দিয়ে লাফাতে হয়। পরে, expression সরাসরি তার ব্যবহারে পৌঁছায়।

লক্ষ্য করো আমরা কী হারাইনি। কোনো অর্থ হারাইনি, কারণ basePrice কখনো এমন কিছু বলেনি যা formula-টা বলেনি। যদি formula টা (q * p) - Math.min(q * p * 0.1, 500)-এর মতো রহস্যময় হতো, তাহলে discountedPrice-এর মতো একটা নাম তার জায়গার মূল্য দিত — আর আমরা সেটা রাখতাম। বিচারটা সবসময় নামের ব্যাপারে।

এই উদাহরণের class-আকারের version-এর জন্য — যেটা Fowler নিজে ব্যবহার করেন — ধরো একটা ছোট Order class। basePrice temp একটা method-এর ভেতরে জন্মায় আর মরে, কিন্তু যে data এটা পড়ে সেটা পুরো object-এর:

চিত্র ৫: Order class — temp ছিল একটা method-এর ভেতরে একটা ব্যক্তিগত নোট, কিন্তু যে data এটা পড়ে সেটা object-এর।

🪜 ধাপে ধাপে, নিরাপদভাবে

Refactoring মানে "কোড বদলাও আর দোয়া করো" নয়। এটা ছোট-ছোট ধাপের একটা sequence, প্রতিটা এত ছোট যে কিছু গোপনে ভাঙতে পারে না। এখানে Inline Temp-এর নিরাপদ recipe। এই কোড দিয়ে হেঁটে দেখাই:

function deliveryFee(order: Order): number {
  let distanceCharge = order.distanceKm * 6;
  return Math.max(distanceCharge, 30);
}

ধাপ ১: ডানদিকে side effect আছে কিনা চেক করো। যে expression-টা assign হচ্ছে সেটা দেখো: order.distanceKm * 6। এটা কি কিছু পরিবর্তন করে? Print, save, send, বা count করে? না — শুধু পড়ে আর গুণ করে। ভালো। যদি expression-এ side effect থাকত (যেমন cart.popItem()), inline করা অনিরাপদ হতো কারণ পরিবর্তনের পরে expression ভিন্ন সংখ্যকবার চলতে পারত। সেক্ষেত্রে থামো।

ধাপ ২: প্রমাণ করো variable-টা মাত্র একবার assign হয়েছে। সবচেয়ে সহজ কৌশল: let থেকে const-এ বদলাও আর compiler-কে চেক করতে দাও।

function deliveryFee(order: Order): number {
  const distanceCharge = order.distanceKm * 6; // let → const
  return Math.max(distanceCharge, 30);
}

Compile করো। Compiler খুশি হলে variable-টার সত্যিই একটাই assignment। Compiler যদি চিৎকার করে "cannot assign to constant", তাহলে variable-টা কোথাও reassign হচ্ছে — এটা একের বেশি কাজ করছে। আগে Split Temporary Variable করো। বহু-কাজের variable inline করো না।

ধাপ ৩: একটা reference expression দিয়ে replace করো। যেখানে variable ব্যবহার হয় সেখানে expression paste করো। Operator precedence সমস্যা হতে পারলে parentheses দাও:

function deliveryFee(order: Order): number {
  const distanceCharge = order.distanceKm * 6; // now unused!
  return Math.max(order.distanceKm * 6, 30);
}

এটা সৎ intermediate state। কোড compile হয় আর একইভাবে চলে। বেশিরভাগ editor এখন distanceCharge-এর নিচে ধূসর underline করবে — "declared but never read"। Tool নিজেই বলছে রাফ নোটটা ডাস্টবিনের জন্য প্রস্তুত।

ধাপ ৪: Test চালাও। হ্যাঁ, এই ছোট পরিবর্তনের জন্যও। সবুজ? চালিয়ে যাও।

ধাপ ৫: Declaration মুছে দাও।

function deliveryFee(order: Order): number {
  return Math.max(order.distanceKm * 6, 30);
}

ধাপ ৬: শেষবার compile করো আর test চালাও। আচরণ হুবহু একই হতে হবে।

জন্ম থেকে ডাস্টবিন পর্যন্ত একটা রাফ-নোট temp-এর পুরো জীবন এরকম:

চিত্র ৬: একটা রাফ-নোট temp-এর জীবন — জন্ম, একবার পড়া, অপ্রয়োজনীয় হওয়া, মুছে যাওয়া।

যদি variable দুই বা তিনটা জায়গায় ব্যবহার হতো, declaration মুছার আগে প্রতিটা ব্যবহারের জন্য একে একে ধাপ ৩ আর ধাপ ৪ পুনরাবৃত্তি করতে হতো। আর যদি অনেক জায়গায় ব্যবহার হয় — থামো। একই expression অনেকবার paste করলে duplicate code তৈরি হয়। তখন ভালো কাজ হলো Replace Temp with Query, যেটা পরের lesson-এ আসছে।

⚠️

সবসময় প্রতিটা ছোট ধাপের পরে test চালাও, শুধু শেষে নয়। Inline Temp এত ছোট মনে হয় যে ব্যর্থ হবে না — এই কারণেই লোকেরা অসতর্ক হয়। দুটো classic ফাঁদ: (১) side effect আছে এমন expression inline করা, ফলে সেটা এখন দুবার চলে। (২) parentheses ভুলে যাওয়া, ফলে a + b * 2 সেখানে ঢুকে পড়ে যেখানে (a + b) * 2 বোঝানো হয়েছিল। Test উভয়ই সেকেন্ডে ধরে ফেলে।

🏫 একটা বড় বাস্তব উদাহরণ

সুমাইয়ার কাছে ফিরে যাই, কিন্তু এখন সে বড় হয়েছে। স্কুলের জন্য একটা ছোট results প্রোগ্রাম লিখছে। নাসরিন ম্যাডাম, যিনি প্রতিদিন চল্লিশটা খাতা দেখেন, একমাত্র user। এখানে প্রথম version। কাজ করে, কিন্তু রাফ নোটগুলো গণনা করো:

interface Subject {
  name: string;
  marks: number;
  maxMarks: number;
}
 
function totalMarks(subjects: Subject[]): number {
  const sum = subjects.reduce((acc, s) => acc + s.marks, 0);
  return sum;
}
 
function totalMaxMarks(subjects: Subject[]): number {
  const sum = subjects.reduce((acc, s) => acc + s.maxMarks, 0);
  return sum;
}
 
function resultLine(student: string, subjects: Subject[]): string {
  const total = totalMarks(subjects);
  const line = `${student} scored ${total} out of ${totalMaxMarks(subjects)}`;
  return line;
}
 
function hasDistinction(subjects: Subject[]): boolean {
  // 10 bonus marks for full attendance are not counted for distinction
  const adjustedPercent =
    ((totalMarks(subjects) - 10) / totalMaxMarks(subjects)) * 100;
  return adjustedPercent >= 75;
}

একজন কড়া কিন্তু ন্যায্য পরীক্ষকের মতো প্রতিটা temporary দেখি।

  • totalMarks-এ sum variable একবার assign হয়, একবার ব্যবহার হয়, আর তার নাম reduce যা দেখায় তা-ই বলে। রাফ নোট। Inline করো।
  • totalMaxMarks-এ sum-এর একই গল্প। Inline করো।
  • resultLine-এ line হলো বিশুদ্ধ আনুষ্ঠানিকতা — string বানাও, line নাম দাও, return করো। Inline করো। total-এর কী হবে? এটা একবার ব্যবহার হয়, আর totalMarks(subjects) ঠিক ততটাই স্পষ্ট। এটাও inline করো।
  • hasDistinction-এ adjustedPercent আলাদা। এর পেছনের formula সত্যিই জটিল — কেন মাইনাস ১০? নাম আর comment মিলিয়ে সত্যিকারের ব্যাখ্যা বহন করছে। রেখে দাও। এটা Extract Variable-এর এলাকা। এখানে inline করলে কোড খারাপ হবে।

পরিষ্কারের পরে:

function totalMarks(subjects: Subject[]): number {
  return subjects.reduce((acc, s) => acc + s.marks, 0);
}
 
function totalMaxMarks(subjects: Subject[]): number {
  return subjects.reduce((acc, s) => acc + s.maxMarks, 0);
}
 
function resultLine(student: string, subjects: Subject[]): string {
  return `${student} scored ${totalMarks(subjects)} out of ${totalMaxMarks(subjects)}`;
}
 
function hasDistinction(subjects: Subject[]): boolean {
  // 10 bonus marks for full attendance are not counted for distinction
  const adjustedPercent =
    ((totalMarks(subjects) - 10) / totalMaxMarks(subjects)) * 100;
  return adjustedPercent >= 75;
}

চারটা রাফ নোট ফেলে দেওয়া হয়েছে, একটা অর্থপূর্ণ নাম রাখা হয়েছে। File ছোট হয়েছে, কিন্তু আরও গুরুত্বপূর্ণ হলো — প্রতিটা remaining নাম এখন তার লাইনের মূল্য দেয়। যখন কোনো পাঠক এই file-এ একটা variable দেখে, সে বিশ্বাস করতে পারে এটা গুরুত্বপূর্ণ কিছু বলছে। এই বিশ্বাসটাই এই refactoring-এর আসল ফল: পরিষ্কার file-এ একটা নামযুক্ত variable হলো একটা signal, noise নয়।

পরিষ্কারটা পড়ার প্রচেষ্টায় কী করল? লাফগুলো গণনা করো — প্রতিবার চোখ variable-এর ব্যবহার থেকে তার assignment-এ ফিরে যায়:

চিত্র ৭: results module-এর পুরো পড়ায় পাঠকের লাফ, চারটা রাফ নোট ঝাড়ু দেওয়ার আগে আর পরে।

রাখো-বা-inline-করো সিদ্ধান্ত দ্রুত কীভাবে নেবে? এখানে চিন্তার পথটা একটা ছবি হিসেবে:

চিত্র ৮: সিদ্ধান্তের পথ — inline করো, রাখো, নাকি ভিন্ন refactoring বেছে নাও।

একই বিচার একটা map হিসেবে আঁকা যায়। যেকোনো temp এই chart-এ রাখো আর সঠিক পদক্ষেপ বের হয়ে আসে:

চিত্র ৯: তোমার temp কোথায় বসে? নিচে-বামে হলো রাফ-নোট জোন — নির্দয়ভাবে inline করো।

CSE-র জন্য গভীর কথা: variable lifetime। Compiler একটা variable-কে তার live range-এর দিক থেকে ভাবে — definition থেকে শেষ ব্যবহার পর্যন্ত কোডের stretch। সুমাইয়ার sum-এর live range ঠিক একটা লাইন: লাইন ১-এ define, লাইন ২-এ শেষবার ব্যবহার, সাথে সাথে dead। Compiler textbook-গুলো def-to-use link-কে def-use chain বলে। একটা chain যার দৈর্ঘ্য একটাই ব্যবহারে — এটাই optimizing compiler-গুলো copy propagation আর তারপর dead-code elimination-এর মাধ্যমে স্বয়ংক্রিয়ভাবে বাদ দেয়। মানে তোমার TypeScript বা C# machine code হওয়ার সময়, sum আর কখনো ছিলই না। এটা তোমাকে দুটো কথা বলে। প্রথমত, Inline Temp কখনো প্রোগ্রামকে দ্রুত বা ধীর করতে পারে না — optimiser ইতিমধ্যে এটা করে ফেলেছে। দ্বিতীয়ত, আরও আগ্রহের কথা: refactoring-টা বিশুদ্ধভাবে মানব পাঠকের জন্য। Machine রাফ নোটের মধ্য দিয়ে অনায়াসে দেখতে পায়, মানুষ পারে না। Clean code হলো মানুষকে সেই স্পষ্টতা দেওয়ার কাজ যা compiler নিজের জন্য compute করে।

CSE-র জন্য গভীর কথা: memory মিথ। একটা সম্পর্কিত মিথ বলে কম variable রাখলে "memory বাঁচে"। এই ধরনের local-দের জন্য, কোনোভাবেই হয় না যা তুমি measure করতে পারবে। Local-রা CPU register বা stack frame-এ থাকে, উভয়ই live range শেষ হওয়ার সাথে সাথে recycle হয়। একটা এক-লাইনের temp সাধারণত register থেকে বেরই হয় না। Register allocator (graph-colouring বা linear-scan — compiler কোর্সে পাবে) live range-এর ভিত্তিতে slot assign করে, তুমি কতগুলো নাম টাইপ করেছ তার ভিত্তিতে নয়। তাই কখনো "memory বাঁচাতে" inline করো না, আর "performance-এর জন্য" অকেজো temp রেখো না। উভয় কারণই গল্পকথা। এখানে একমাত্র সৎ মুদ্রা হলো readability।

🟦 C#-এ একই refactoring

ধারণাটা ভাষা-মুক্ত। একই স্কুলের উদাহরণ C#-এ, যেভাবে একটা .NET project লিখত।

আগে:

public class ResultCalculator
{
    public bool QualifiesForScholarship(Student student)
    {
        var percentage = (double)student.TotalMarks / student.MaxMarks * 100;
        return percentage >= 90.0;
    }
 
    public string AdmitCardLabel(Student student)
    {
        var label = $"{student.RollNumber} - {student.Name}";
        return label;
    }
}

ধাপে ধাপে। আগে নিশ্চিত করো percentage আর label single-assignment। C#-এ local কে readonly declare করা যায় না, কিন্তু চোখ আর IDE দিয়ে নিশ্চিত করো দ্বিতীয় কোনো assignment নেই। তারপর প্রতিটা একক ব্যবহার expression দিয়ে replace করো, declaration মুছে দাও।

পরে:

public class ResultCalculator
{
    public bool QualifiesForScholarship(Student student)
    {
        return (double)student.TotalMarks / student.MaxMarks * 100 >= 90.0;
    }
 
    public string AdmitCardLabel(Student student)
    {
        return $"{student.RollNumber} - {student.Name}";
    }
}

একটা ছোট C#-নির্দিষ্ট সতর্কতা: inline করার সময় cast আর operator precedence সম্পর্কে সাবধান। (double) cast শুধু student.TotalMarks-এ প্রযোজ্য, inline করার পরেও সেটা সত্য থাকতে হবে। একটুও অনিশ্চিত হলে আগে পুরো inline করা expression parentheses দিয়ে মুড়িয়ে দাও, test চালাও, পরে অতিরিক্ত parentheses সরাও। Baby step কোনো খরচ ছাড়াই আসে; ভাঙা arithmetic একটা সন্ধ্যার খরচ করে।

তুমি হয়তো জিজ্ঞেস করবে: "QualifiesForScholarship এখন কি একটা expression-bodied method হওয়া উচিত?" হ্যাঁ, আধুনিক C#-এ => (double)student.TotalMarks / student.MaxMarks * 100 >= 90.0; লিখতে পারো। এটা একই refactoring-এর উপরে একটা style polish।

Python বন্ধুদের জন্য, একই রাফ নোট এভাবে দেখায়:

def qualifies_for_free_delivery(order):
    base_price = order.quantity * order.item_price
    return base_price > 1000
 
# after inlining:
def qualifies_for_free_delivery(order):
    return order.quantity * order.item_price > 1000

তিনটা ভাষা, একটাই কথা: নামকে ভাড়া দিতে হবে নাহলে লাইন ছাড়তে হবে।

🛠️ IDE support

সুখবর: কারণ Inline Temp এত যান্ত্রিক, machine নিখুঁতভাবে করে। হাতে find-replace প্রায় কখনোই করতে হয় না।

ToolVariable inline করার উপায়
Visual StudioVariable-এ cursor রাখো, Ctrl+. (Quick Actions) চাপো, Inline temporary variable বেছে নাও
JetBrains Rider / IntelliJ IDEAVariable-এ cursor রাখো, Ctrl+Alt+N (Windows/Linux) বা Cmd+Option+N (macOS) চাপো — Inline Variable
VS CodeVariable select করো, Ctrl+Shift+R দিয়ে refactoring খোলো; installed language extension-এর উপর নির্ভর করে
Eclipse (Java)Variable-এ cursor রাখো, Alt+Shift+I চাপো — Inline

দুটো practical tips। প্রথমত, IDE সতর্ক করবে যদি variable একের বেশিবার assign হয় বা inline করলে আচরণ বদলাতে পারে — সেই সতর্কতা পড়ো, পাশ কাটিয়ে click করো না। দ্বিতীয়ত, IDE স্বয়ংক্রিয়ভাবে parentheses আর বহু ব্যবহার handle করে — আগে আলোচনা করা দুটো classic ভুল দূর হয়। যখন কোনো refactoring-এ first-class tool support থাকে, হাতে-সম্পাদনার চেয়ে tool বেছে নাও।

📊 সুবিধা আর ঝুঁকি

প্রতিটা refactoring-এর মতো, Inline Temp একটা trade। সৎ balance sheet:

সুবিধাঝুঁকি / খরচ
একটা এক-ব্যবহারের নাম সরায় যা পাঠককে track করতে হতোযদি নামটা আসলে একটা জটিল formula বোঝাত, inline করলে documentation মুছে যায়
ছোট method-গুলোকে direct করে — expression সরাসরি ব্যবহারে পৌঁছায়side effect আছে এমন expression inline করলে effect কতবার চলে তা বদলাতে পারে
Expression মুক্ত করে যাতে Replace Temp with Query বা Extract Method এগোতে পারেকয়েক জায়গায় ব্যবহৃত ভারী computation inline করলে প্রতিবার পুনরায় গণনা হয়
কম কোড, কম লাইন, sync রাখার কিছু নেইঅনেক জায়গায় ব্যবহৃত variable inline করলে সর্বত্র expression paste হয় — duplicate code
mechanics অনুসরণ করলে শূন্য আচরণ পরিবর্তনmanual inline-এ parentheses ভুলে গেলে operator precedence ভুল হয়

সবচেয়ে গুরুত্বপূর্ণ row হলো প্রথম ঝুঁকি। পারিবারিক সম্পর্ক মনে রাখো: Inline Temp হলো Extract Variable-এর একদম উল্টো। Extract Variable বলে "এই expression বিভ্রান্তিকর — একটা নাম দাও।" Inline Temp বলে "এই নাম অকেজো — সরিয়ে দাও।" কোনোটাই সবসময় সঠিক নয়। একজন দক্ষ developer উভয় দিকে স্বাধীনভাবে চলেন, প্রতিবার একটাই প্রশ্ন করে: এই নাম কি ভাড়া দিচ্ছে? হ্যাঁ হলে নাম থাকে। না হলে যায়। Refactoring কম লাইন বা বেশি লাইনের ব্যাপার নয়, প্রতিটা লাইন তার জায়গার মূল্য দেওয়ার ব্যাপার।

জানার মতো একটা sibling-ও আছে: Inline Method একটা variable-এর পরিবর্তে পুরো method-এ "অপ্রয়োজনীয় indirection সরাও" ধারণাটা প্রয়োগ করে।

🧹 এটা কোন smell ঠিক করে?

Inline Temp একটা ছোট ঝাড়ু, তাই ছোট smell ঠিক করে — আর বড় cure-এর জন্য মেঝে পরিষ্কার করে।

SmellInline Temp কীভাবে সাহায্য করে
Long Methodএক-ব্যবহারের temp ঝাড়ু দেয় যেগুলো method-কে hop আর noise দিয়ে ভরিয়ে রাখে, সত্যিকারের logic দেখা যায়
Duplicate Codeপরোক্ষভাবে: expression মুক্ত হলে Replace Temp with Query সম্ভব হয়, calculation-কে একটা shared ঘর দেয়
Commentsপরোক্ষভাবে: সরাসরি লাইনে পড়া কোডে name-hop পূর্ণ কোডের চেয়ে কম ব্যাখ্যামূলক comment দরকার হয়

দিক সম্পর্কে নিজের সাথে সৎ থাকো। যদি একটা method-এ একটা বিশাল expression পড়া কঠিন হয়, চিকিৎসা হলো বিপরীত refactoring — Extract Variable। আর যদি একটা temp দুটো ভিন্ন কাজের জন্য দুবার assign হয়, চিকিৎসা হলো Split Temporary Variable। এই ছোট পরিবার থেকে সঠিক tool বেছে নেওয়াটাই আসল দক্ষতা। পুরো পরিবার একটা ছবিতে:

চিত্র ১০: temp-variable refactoring-এর পরিবার — চারটা tool, একটাই shared প্রশ্ন কোথায় একটা নাম থাকা উচিত।

📦 দ্রুত revision বক্স

+------------------------------------------------------------------+
|                    INLINE TEMP - REVISION CARD                   |
+------------------------------------------------------------------+
| WHAT     : Replace a temp variable with its expression; delete   |
|            the declaration. (2nd edition name: Inline Variable)  |
| WHEN     : Assigned once, used once-ish, name adds NO meaning    |
| TEST     : Does the name pay rent? No rent -> inline it          |
| INVERSE  : Extract Variable (gives a name when needed)           |
| STEPS    : 1. RHS side-effect free?   2. let -> const to prove   |
|            single assignment          3. Replace each use        |
|            4. Test after each step    5. Delete declaration      |
| DO NOT   : - Inline expensive cached values                      |
|            - Inline side-effecting expressions                   |
|            - Inline a temp used in many places (use Replace      |
|              Temp with Query instead)                            |
|            - Inline a reassigned temp (Split it first)           |
| WHY      : Clears the road for Extract Method and                |
|            Replace Temp with Query                               |
+------------------------------------------------------------------+

🏋️ অনুশীলন করো

নিজে ঝাড়ু ধরার সময়। নিচে একটা cinema app-এর ছোট ticket-pricing module। Compile হয় আর কাজ করে। তোমার কাজ হলো প্রতিটা temporary variable বিচার করা: inline করো, রেখে দাও, নাকি ভিন্ন refactoring-এ পাঠাও।

interface Show {
  basePrice: number;
  isWeekend: boolean;
  is3D: boolean;
  occupiedSeats: number;
  totalSeats: number;
}
 
function ticketPrice(show: Show): number {
  const price = show.basePrice;
  let charge = show.isWeekend ? 50 : 0;
  charge = show.is3D ? charge + 80 : charge;
  const final = price + charge;
  return final;
}
 
function isHouseFull(show: Show): boolean {
  const ratio = show.occupiedSeats / show.totalSeats;
  return ratio >= 0.95;
}
 
function popularityScore(show: Show): number {
  // weekend shows get a 1.2x boost, capped so score never crosses 100
  const boostedOccupancy = Math.min(
    (show.occupiedSeats / show.totalSeats) * (show.isWeekend ? 1.2 : 1) * 100,
    100
  );
  return boostedOccupancy;
}

তোমার কাজগুলো:

  1. ticketPrice-এ price, charge, আর final-এর ভাগ্য ঠিক করো। সাবধান — এদের একটা দুবার assign হয়। Inline Temp-এর আগে কোন refactoring সেটা visit করতে হবে?
  2. isHouseFull-এ ratio inline করা উচিত নাকি রাখা উচিত? "নামটা কি ভাড়া দিচ্ছে?" পরীক্ষা ব্যবহার করে তোমার এক-লাইনের কারণ লিখে রাখো।
  3. popularityScore-এ boostedOccupancy temp একবার ব্যবহার হয়। তুমি কি এটা inline করবে? নাকি নাম আর comment মিলিয়ে সত্যিকারের অর্থ বহন করছে? উভয় দিকে সমর্থনযোগ্য উত্তর আছে — তোমারটা লিখে রাখো।
  4. IDE-র inline command ব্যবহার করে তোমার সিদ্ধান্ত প্রয়োগ করো। প্রতিটা পরিবর্তনের পরে test (বা অন্তত নমুনা output পুনরায় চেক করে) চালাও।
  5. পাঁচটা temp-এর প্রতিটা চিত্র ৯-এর quadrant chart-এ রাখো। তোমার স্থান কি ১ থেকে ৩ নম্বর কাজের সিদ্ধান্তের সাথে মেলে? যদি কোনো temp সীমানার কাছে পড়ে, তুমি কোন দিক বেছে নেবে সেটা এক বাক্যে রক্ষা করো।
  6. Bonus: show.occupiedSeats / show.totalSeats expression এখন দুটো function-এ দেখা যাচ্ছে। এই series-এর কোন refactoring এটাকে একটা shared ঘর দেবে? (Hint: এটাই পরের lesson।)

যখন তুমি যেকোনো temporary variable দেখে শান্তভাবে বলতে পারবে "তুমি থাকো" বা "তুমি যাও" — একটা কারণসহ — তুমি Inline Temp আয়ত্ত করেছ। সুমাইয়া দ্বিতীয় চিন্তা ছাড়াই তার রাফ নোট ফেলে দেয়। তোমার কোড একই পরিষ্কার অভ্যাস পাওয়ার যোগ্য। পরের lesson-এ আমরা এর শক্তিশালী বড় ভাই-এর সাথে দেখা করব: Replace Temp with Query

সচরাচর জিজ্ঞাসা

Inline Temp কি অন্য কোনো refactoring-এর উল্টো?
হ্যাঁ। এটা Extract Variable-এর একদম বিপরীত। Extract Variable একটা জটিল expression-কে একটা ভালো নাম দেয়। Inline Temp একটা অকাজের নাম সরিয়ে দেয়। দুটো মিলিয়ে একটাই নিয়ম শেখায়: variable তখনই রাখো যখন তার নামটা সত্যিকারের কিছু বোঝায়।
কখন temporary variable inline করব না?
তিনটা ক্ষেত্রে রেখে দাও। এক, যখন নামটা একটা জটিল formula-কে formula-র চেয়ে ভালো বোঝায়। দুই, যখন এটা একটা ভারী calculation cache করছে যেটা বারবার ব্যবহার হয়। তিন, যখন ডানদিকের expression-এর side effect আছে — যেমন input পড়া বা state বদলানো — inline করলে সেই side effect আবার চলতে পারে।
যদি variable পাঁচটা আলাদা জায়গায় ব্যবহার হয় তাহলে?
তাহলে সরাসরি inline করলে একই expression পাঁচবার paste হবে — এটা duplicate code। এক্ষেত্রে inline করো না। Replace Temp with Query ব্যবহার করো, যাতে পাঁচটা জায়গাই একটা ভালো নামের method call করে।
Inline Temp কি প্রোগ্রাম দ্রুত করে?
না, আর এটা এর কাজও না। আধুনিক compiler সাধারণ temporary variable যেকোনোভাবেই সামলে নেয়। Inline Temp হলো readability-র জন্য, আর Extract Method আর Replace Temp with Query-এর মতো বড় refactoring-এর পথ পরিষ্কার করার জন্য।
Fowler-এর দ্বিতীয় সংস্করণে এটাকে Inline Variable বলা হয় কেন?
একই technique, শুধু নামটা আরও সাধারণ। প্রথম সংস্করণে Inline Temp বলা হতো কারণ variable-টা সাধারণত একটা temporary local। দ্বিতীয় সংস্করণে Inline Variable বলা হয় কারণ এই ধারণা যেকোনো local variable-এ খাটে যার নাম কিছুই যোগ করে না।

আরো দেখো

সম্পর্কিত পাঠ

Extract Variable: ছোট ছোট নামওয়ালা ধাপে বড় হিসাব সমাধান করো

Extract Variable শেখো ধাপে ধাপে। একটা বিশাল, জটিল expression কে ছোট ছোট নামওয়ালা অংশে ভাগ করো — ঠিক যেভাবে গণিতের খাতায় কাজ দেখাও।

আরও পড়ুন

Replace Temp with Query: তাজা জিজ্ঞেস করো, বাসি চিরকুটে ভরসা করো না

ক্যান্টিনের সিঙ্গারার গল্প দিয়ে Replace Temp with Query বোঝো — TypeScript আর C# উদাহরণ, নিরাপদ ধাপ, আর একটাই সত্যের উৎস।

আরও পড়ুন

Split Temporary Variable: একটা বালতি দুই কাজ করতে পারে না

দুই বালতির গল্প দিয়ে Split Temporary Variable শেখো — TypeScript ও C# উদাহরণ আর নিরাপদ ধাপ সহ। প্রতিটা variable-কে একটাই কাজ আর একটাই সৎ নাম দাও।

আরও পড়ুন

Inline Method: যে Shortcut আসলে Shortcut ছিলই না

Inline Method শেখো ধাপে ধাপে। যখন একটা ছোট method-এর body তার নামের চেয়ে বেশি পরিষ্কার, তখন সেই body-টা সরাসরি caller-এ বসিয়ে দাও আর একটা বাড়তি hop সরিয়ে ফেলো।

আরও পড়ুন