কন্ট্রোল স্ট্রাকচার এবং এক্সিকিউশন ফ্লো

কোড লেখার সময় আমরা লজিক ফ্লো কন্ট্রোল করতে if, else, loop ব্যবহার করি। একজন জুনিয়র ডেভেলপার শুধু কোড রান করানোর চিন্তা করে, কিন্তু একজন Senior Developer চিন্তা করে CPU Cycle এবং Memory Optimization নিয়ে।

এই অধ্যায়ে আমরা পিএইচপির কন্ট্রোল স্ট্রাকচারের গভীরে প্রবেশ করব

২.১ if-else: লজিক্যাল অপ্টিমাইজেশন (Deep Logic)

আমরা সবাই if-else লিখতে পারি, কিন্তু পারফরম্যান্স অপ্টিমাইজড if-else লেখা একটি আর্ট

১. টাইপ সেফটি এবং পারফরম্যান্স (Strict vs Loose)

পিএইচপি যখন == পায়, সে ভ্যালু কনভার্ট করার চেষ্টা করে (Type Juggling)। এটি সিপিইউ-এর জন্য বাড়তি কাজ।

// ❌ Bad (Slow & Risky)
if ($value == "10") { ... } 

// ✅ Senior Way (Fast)
if ($value === 10) { ... }

কেন ফাস্ট? === কোনো কনভার্সন করে না, সরাসরি মেমোরি ভ্যালু চেক করে।

২. লজিক্যাল অর্ডারিং (Short-Circuit Evaluation)

সবসময় "সবচেয়ে সস্তা" (Cheapest) কন্ডিশন আগে চেক করুন।

// ✅ Optimized Order
if ($isCacheHit && $expensiveDbQuery) { ... }

এখানে যদি $isCacheHit false হয়, পিএইচপি পরের অংশ ($expensiveDbQuery) আর এক্সিকিউটই করবে না। একে বলা হয় Short-Circuiting। এটি ডাটাবেস বা API কল বাঁচাতে পারে।

৩. ট্রুথিনেস ট্র্যাপ (Truthiness Trap)

নিচের সবগুলোর মানে পিএইচপিতে false:

if ("0")   ❌ (স্ট্রিং জিরো)
if (0)     ❌ (ইন্টেজার জিরো)
if ([])    ❌ (ফাঁকা অ্যারে)

Senior Practice: কখনোই অস্পষ্ট চেক করবেন না।

// ✅ Specific Check
if ($value !== "" && $value !== null) { ... }

২.২ Switch বনাম Match: আধুনিক পিএইচপি (PHP 8+)

switch পুরনো এবং কিছুটা ত্রুটিপূর্ণ। PHP 8-এ আসা match এক্সপ্রেশন অনেক বেশি শক্তিশালী।

⚠️ Switch এর সমস্যা:

  • Type Juggling: এটি == ব্যবহার করে। case 1: এবং case "1": তার কাছে সমান
  • Fall-through: break দিতে ভুলে গেলে সে পরের case-এ চলে যায়

✅ Match এর সুবিধা (Senior Choice):

  • Strict (===): টাইপ এবং ভ্যালু দুটোই চেক করে
  • Return Value: এটি সরাসরি ভ্যালু রিটার্ন করতে পারে
  • No Fall-through: একটার পর আরেকটায় যাওয়ার ভয় নেই

তুলনামূলক উদাহরণ:

// ❌ Old Switch
switch ($x) {
    case 1:
    case 2:
        echo "One or Two";
        break; // ভুলে গেলে সমস্যা!
    default:
        echo "Other";
}

// ✅ Modern Match
echo match($x) {
    1, 2 => "One or Two",
    default => "Other",
};

২.৩ লুপ অপ্টিমাইজেশন (Internal Working)

🔄 For Loop (The C-Style Optimization)

পিএইচপির for লুপ সরাসরি C ল্যাঙ্গুয়েজ স্টাইলে অপ্টিমাইজড। কিন্তু এখানে একটি সাধারণ ভুল সবাই করে:

// ❌ Bad Practice (O(n²) Complexity)
for ($i = 0; $i < count($arr); $i++) { ... }

এখানে প্রতিবার লুপ ঘোরার সময় count($arr) কল হয়। অ্যারে বড় হলে এটি সিস্টেম স্লো করে দেবে।

✅ Senior Fix:

$len = count($arr); // একবার ক্যালকুলেট করুন
for ($i = 0; $i < $len; $i++) { ... }

🔄 While Loop

while লুপ সিম্পল, কিন্তু for লুপের তুলনায় সামান্য কম অপ্টিমাইজড হতে পারে যদি কন্ডিশন জটিল হয়। তবে ফাইল রিডিং বা ইনফিনিট লুপের জন্য এটি বেস্ট।

২.৪ Foreach এবং Copy-On-Write (COW)

foreach পিএইচপির সবচেয়ে পাওয়ারফুল কিন্তু ট্রিকি লুপ।

📦 মেমোরি বিহেভিয়ার

$arr = [1, 2, 3];
foreach ($arr as $item) { ... }

ইন্টারনালি, পিএইচপি এখানে অ্যারে কপি করে না। সে শুধু ইন্টারনাল পয়েন্টার শিফট করে। তাই এটি মেমোরি ফ্রেন্ডলি

⚠️ মডিফিকেশন ট্র্যাপ (Reference & Unset)

যদি আপনি লুপের ভেতর অ্যারেকে মডিফাই করতে চান, তবে & (reference) ব্যবহার করতে হয়।

foreach ($arr as &$v) {
    $v = $v * 2;
}
unset($v); // ⚠️ অত্যন্ত গুরুত্বপূর্ণ!

কেন unset($v) করবেন? foreach শেষ হওয়ার পরেও $v ভেরিয়েবলটি মেমোরিতে অ্যারের শেষ আইটেমকে পয়েন্ট করে থাকে। আপনি যদি পরে কোডের অন্য কোথাও $v ব্যবহার করেন, তবে অজান্তেই আপনার অ্যারের শেষ ভ্যালুটি পরিবর্তন হয়ে যাবে। এই বাগটি খুঁজে বের করা খুবই কঠিন।

২.৫ Break এবং Continue: মাল্টি-লেভেল কন্ট্রোল

অনেক ডেভেলপার জানেন না যে break এবং continue আর্গুমেন্ট রিসিভ করতে পারে। নেস্টেড লুপের (Nested Loop) ক্ষেত্রে এটি জাদুকরী

⏹️ Break

  • break 1 (বা শুধু break): বর্তমান লুপটি থামিয়ে দেয়
  • break 2: বর্তমান লুপ এবং তার প্যারেন্ট লুপ (Total 2 levels) থামিয়ে দেয়

⏭️ Continue

  • continue 1: বর্তমান ইটারেশন স্কিপ করে পরেরটায় যায়
  • continue 2: বর্তমান লুপ স্কিপ করে প্যারেন্ট লুপের পরের ইটারেশনে চলে যায়

📋 বাস্তব উদাহরণ (Nested Loop Control):

$rows = [[1, 2], [3, 'error'], [5, 6]];

foreach ($rows as $row) {
    echo "Processing Row... ";
    
    foreach ($row as $col) {
        if ($col === 'error') {
            echo "Error found! Skipping row.\n";
            continue 2; // ভেতরের লুপ থেকে বের হয়ে সোজা বাইরের লুপের পরের ধাপে যাবে
        }
        echo $col . " ";
    }
    echo "Row Done.\n";
}

দেখুন, 'error' পাওয়ার পর "Row Done" প্রিন্ট হয়নি, কারণ continue 2 তাকে সরাসরি পরের Row-তে পাঠিয়ে দিয়েছে।

২.৬ জেনারেটর (Generators): মেমোরি অপ্টিমাইজেশন

বড় ডেটা প্রসেসিংয়ের জন্য Generator হলো সিনিয়রের হাতিয়ার

❌ সাধারণ ফাংশন

সাধারণ ফাংশন return করলে পুরো অ্যারে মেমোরিতে লোড হয়

(High RAM usage)

✅ জেনারেটর

yield ব্যবহার করে, যা একবারে একটি করে ভ্যালু দেয়

(Low Memory Usage)

Senior Example (Memory Safe):

function getBigData() {
    for ($i = 1; $i <= 1000000; $i++) {
        yield $i; // এখানে ফাংশনটি Pause হয় এবং ভ্যালু রিটার্ন করে
    }
}

🔍 কীভাবে কাজ করে? (Coroutine Style)

  • যখন yield কল হয়: ফাংশনটি সাময়িকভাবে Pause হয়
  • বর্তমান স্টেট (ভেরিয়েবল ভ্যালু) মেমোরিতে সেভ থাকে
  • পরের বার লুপ ঘুরলে ঠিক সেখান থেকেই আবার শুরু হয়

এটি মেমোরি খরচ প্রায় শূন্যের কোঠায় নামিয়ে আনে।

২.৭ রিকারশন বনাম ইটারেশন (Performance Check)

🔄 Recursion

  • ফাংশন নিজেকে কল করে
  • কোড ছোট হয়, কিন্তু মেমোরি স্ট্যাক (Stack) বেড়ে যায়
  • গভীর রিকারশন Stack Overflow এরর দিতে পারে

⚡ Iteration (Loop)

  • লুপ ব্যবহার করা
  • কোড একটু বড় হতে পারে, কিন্তু এটি ফাস্ট এবং মেমোরি এফিশিয়েন্ট

💡 Senior Advice: ট্রি বা গ্রাফ ট্রাভার্সাল ছাড়া সাধারণ গণনার জন্য (যেমন ফ্যাক্টরিয়াল) সবসময় ইটারেশন (Loop) ব্যবহার করুন।

🎯 Senior Developer Interview Questions (Part 2)

Q: continue 2 এবং break 2 এর মধ্যে পার্থক্য কী?

break 2 নেস্টেড লুপের দুটি লেভেলই ভেঙে বের হয়ে আসে। আর continue 2 ভেতরের লুপের বর্তমান ইটারেশন বন্ধ করে বাইরের (প্যারেন্ট) লুপের পরবর্তী ইটারেশনে চলে যায়।

Q: পিএইচপিতে foreach লুপে reference (&) ব্যবহারের ঝুঁকি কী?

লুপ শেষ হওয়ার পরেও রেফারেন্সটি অ্যারের শেষ এলিমেন্টকে পয়েন্ট করে থাকে। unset() না করলে পরবর্তী কোডে ভেরিয়েবল রিইউজ করলে মূল ডেটা করাপ্ট হতে পারে।

Q: ১ জিবি সাইজের একটি লগ ফাইল রিড করার জন্য আপনি file() ফাংশন ব্যবহার করবেন নাকি Generator? কেন?

অবশ্যই Generator বা fopen/fgets। কারণ file() পুরো ফাইলটি অ্যারে হিসেবে র‍্যামে লোড করে, যা মেমোরি ক্র্যাশ ঘটাবে। জেনারেটর লাইন বাই লাইন প্রসেস করে মেমোরি বাঁচায়।

🎯 অধ্যায় ২ এর সারাংশ (Summary)

এই অধ্যায়ে আমরা শিখলাম:

  • if-else Optimization: === ব্যবহার করুন, Cheapest condition আগে দিন
  • Switch vs Match: PHP 8+ এ match ব্যবহার করুন (Strict comparison, No fall-through)
  • Loop Optimization: count() বাইরে ক্যালকুলেট করুন, reference ব্যবহারে unset() করুন
  • break/continue: numeric arguments দিয়ে মাল্টি-লেভেল কন্ট্রোল
  • Generators (yield): বিশাল ডেটা মেমোরি-এফিশিয়েন্টভাবে প্রসেস করুন

✨ পরবর্তী অধ্যায়: Part 3 - Functions (Deep Theory) — যেখানে মেমোরি স্ট্যাক, ক্লোজার এবং ভ্যারিয়াডিক ফাংশন নিয়ে আলোচনা হবে।

প্রস্তুত তো? 🚀

🔒 কপিরাইট সুরক্ষিত কন্টেন্ট 🔒

কপি, স্ক্রিনশট, প্রিন্ট করা সম্পূর্ণ নিষিদ্ধ।