পাঠ ০৫ · ৫৮-এর মধ্যে · মডিউল ২
Home / Courses / Software Engineering Principles & Git / ওয়াটারফল মডেল

ওয়াটারফল মডেল

Waterfall model
৭ মিনিট পড়া শুরু · Beginner Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • ওয়াটারফল মডেল ঠিক কীভাবে কাজ করে এবং নামটি কোথা থেকে এসেছে
  • এর সততার সাথে বলা প্রকৃত শক্তি — কখন এটি এখনও যুক্তিসঙ্গত পছন্দ
  • এর সততার সাথে বলা দুর্বলতা — কেন বেশিরভাগ আধুনিক প্রজেক্ট ভিন্ন মডেল বেছে নেয়
  • Python দিয়ে ওয়াটারফলের কঠোরতা সিমুলেট করা — স্কিপ বা পেছনে যাওয়ার চেষ্টা প্রোগ্রাম্যাটিকভাবে প্রত্যাখ্যাত হওয়া

১ · ওয়াটারফল মডেল কী

ওয়াটারফল মডেলWaterfall Modelসবচেয়ে পুরনো, প্রথম আনুষ্ঠানিকভাবে সংজ্ঞায়িত SDLC মডেল -- L04-এর ধাপগুলোকে একটি কঠোর লিনিয়ার সিকোয়েন্সে সাজায়, প্রতিটি ধাপ সম্পূর্ণ শেষ হওয়ার পরই পরেরটি শুরু হয়, কখনো পেছনে ফেরে না। হলো L04-এ যে ছয়টি ধাপ আমরা দেখেছি, তার সবচেয়ে সরল সম্ভাব্য সংগঠন — একটি সম্পূর্ণ লিনিয়ার সিকোয়েন্স। রিকোয়ারমেন্ট সম্পূর্ণভাবে স্পেসিফাই করা হয় শুরুতেই; তারপর সম্পূর্ণ ডিজাইন শেষ হয় কোনো কোড লেখার আগেই; তারপর ইমপ্লিমেন্টেশন, টেস্টিং, ডিপ্লয়মেন্ট — প্রতিটি ধাপ তার আগের ধাপ পুরোপুরি শেষ হওয়ার অপেক্ষায় থাকে। নামটি এসেছে এই ধারণা থেকে যে পানি যেমন শুধু নিচের দিকে গড়ায়, কখনো উপরের দিকে ফেরে না — এই মডেলেও প্রতিটি ধাপ শুধু সামনের দিকেই এগোয়।

২ · সততার সাথে বলা শক্তি

ওয়াটারফলকে সমালোচনা করার আগে এর প্রকৃত সুবিধাগুলো স্বীকার করা জরুরি। এটি বোঝা ও ম্যানেজ করা খুবই সহজ — প্রতিটি ধাপের স্পষ্ট শুরু ও শেষ থাকে, ফলে একটি পরিকল্পনার বিপরীতে অগ্রগতি ট্র্যাক করা সহজ। আর যেখানে রিকোয়ারমেন্ট সত্যিই ভালোভাবে বোঝা ও স্থিতিশীল (যেমন কিছু রেগুলেটেড বা সেফটি-ক্রিটিক্যাল ডোমেইন, যেখানে কমপ্লায়েন্সের কারণে তৈরির আগেই রিকোয়ারমেন্ট সম্পূর্ণভাবে নির্দিষ্ট করা বাধ্যতামূলক) — সেখানে ওয়াটারফল এখনও একটি যুক্তিসঙ্গত পছন্দ হতে পারে।

৩ · সততার সাথে বলা দুর্বলতা

কিন্তু বেশিরভাগ আধুনিক সফটওয়্যার কেন ভিন্ন মডেল ব্যবহার করে, তার তিনটি গুরুতর কারণ আছে। প্রথমত, এটি ধরে নেয় রিকোয়ারমেন্ট বদলাবে না — কিন্তু L02 ইতিমধ্যে দেখিয়েছে বাস্তবে রিকোয়ারমেন্ট বদলায়ই (স্কোপ ক্রিপ, বোঝাপড়ার বিবর্তন)। দ্বিতীয়ত, কার্যকরী সফটওয়্যার দেখা যায় প্রজেক্টের অনেক দেরিতে (সব ডিজাইন কোনো কোড লেখার আগেই শেষ হয়) — ফলে কোনো মৌলিক ভুল বোঝাবুঝি ধরা পড়তে অনেক দেরি হয়ে যায়, যখন তা ঠিক করা ব্যয়বহুল। তৃতীয়ত, এটি L04-এর মেইনটেন্যান্স-থেকে-নতুন-রিকোয়ারমেন্টের সাইকেলকে একদমই স্বাভাবিকভাবে সামলাতে পারে না — মডেলটির নিজস্ব কাঠামোই পেছনে ফেরাকে অস্বীকার করে।

Requirements Design Implementation Testing Deployment Maintenance ✕ পেছনে ফেরা যাবে না
Testing থেকে Requirements-এ ফেরার লাল, ড্যাশড তীরটি প্রত্যাখ্যাত — ওয়াটারফল মডেলের কাঠামোতেই এই "পেছনে ফেরা" অনুমোদিত নয়, নিচের কোড সেলে এটি প্রোগ্রাম্যাটিকভাবে দেখানো হয়েছে।
Python
# WaterfallProject -- শুধুমাত্র ঠিক পরের ধাপে যাওয়ার অনুমতি দেয়। স্কিপ করা বা
# পেছনে ফেরার যেকোনো চেষ্টা ValueError দিয়ে প্রত্যাখ্যাত হয়।

class WaterfallProject:
    PHASES = ["Requirements", "Design", "Implementation", "Testing", "Deployment", "Maintenance"]

    def __init__(self):
        self.current_phase = self.PHASES[0]

    def advance_phase(self, target_phase):
        current_idx = self.PHASES.index(self.current_phase)
        target_idx = self.PHASES.index(target_phase)
        if target_idx != current_idx + 1:
            raise ValueError(
                f"অবৈধ ট্রানজিশন: '{self.current_phase}' থেকে '{target_phase}'-এ সরাসরি যাওয়া যাবে না "
                f"(waterfall শুধু ঠিক পরের ধাপে যেতে দেয়)"
            )
        self.current_phase = target_phase

project = WaterfallProject()
print(f"শুরু: {project.current_phase}")

for next_phase in ["Design", "Implementation", "Testing"]:
    project.advance_phase(next_phase)
    print(f"এগিয়ে গেল → {project.current_phase}")

# বাস্তব দৃশ্যকল্প: Testing-এ একটি রিকোয়ারমেন্ট ভুল বোঝাবুঝি ধরা পড়ল, দল Requirements-এ ফিরতে চায়
try:
    project.advance_phase("Requirements")
except ValueError as e:
    print(f"\nপ্রত্যাখ্যাত: {e}")

# আরেকটি চেষ্টা: Deployment স্কিপ করে সরাসরি Maintenance-এ যাওয়া
try:
    project.advance_phase("Maintenance")
except ValueError as e:
    print(f"প্রত্যাখ্যাত: {e}")

print(f"\nবর্তমান ধাপ এখনও অপরিবর্তিত: {project.current_phase}")

    
লক্ষ্য করুন advance_phase() শুধুমাত্র target_idx == current_idx + 1 হলেই সফল হয় — অর্থাৎ ঠিক পরের ধাপ ছাড়া অন্য কোথাও যাওয়ার চেষ্টা ব্যর্থ হয়, তা পেছনে হোক (Testing → Requirements) বা সামনে স্কিপ করে হোক (Testing → Maintenance, Deployment বাদ দিয়ে)। দুটো চেষ্টাই ValueError রেইজ করে, এবং শেষ লাইনে দেখা যায় প্রজেক্ট এখনও "Testing" ধাপেই আটকে আছে — কোনো ব্যর্থ চেষ্টাই অবস্থা পরিবর্তন করেনি।
মূল কথা · Key takeaway

ওয়াটারফল মডেল সরল ও পরিচালনাযোগ্য, এবং স্থিতিশীল রিকোয়ারমেন্টের ক্ষেত্রে এখনও কার্যকর — কিন্তু এর কঠোর একমুখী কাঠামো বাস্তব সফটওয়্যার প্রজেক্টের পরিবর্তনশীলতা ও L04-এর সাইকেলিক বাস্তবতাকে সামলাতে পারে না। এটিই সরাসরি প্রেরণা দেয় M2-এর পরবর্তী পাঠগুলোর জন্য — ইটারেটিভ, ইনক্রিমেন্টাল, স্পাইরাল ও অ্যাজাইল মডেল, যেগুলো এই কঠোরতার একেকটি ভিন্ন সমাধান প্রস্তাব করে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ একটি ব্যাংকিং রেগুলেশন-কমপ্লায়েন্স সিস্টেম, যেখানে সব রিকোয়ারমেন্ট আইনগতভাবে আগে থেকেই সম্পূর্ণ নির্দিষ্ট, সেখানে ওয়াটারফল কি একটি যুক্তিসঙ্গত পছন্দ হতে পারে?

হ্যাঁ, এটি ঠিক সেই ধরনের পরিস্থিতি যেখানে ওয়াটারফলের অনুমান (রিকোয়ারমেন্ট স্থিতিশীল ও আগে থেকে জানা) বাস্তবেই সত্য — এখানে ওয়াটারফলের সরলতা ও স্পষ্ট মাইলস্টোন-ভিত্তিক ট্র্যাকিং প্রকৃত সুবিধা দেয়, আর "রিকোয়ারমেন্ট বদলাতে পারে" দুর্বলতাটি প্রাসঙ্গিক নয়।

প্র ০২ "কার্যকরী সফটওয়্যার দেরিতে দেখা যাওয়া" ওয়াটারফলের একটি সমস্যা কেন — এটি ঠিক কী ঝুঁকি তৈরি করে?

কারণ যদি ডিজাইন বা রিকোয়ারমেন্টে কোনো মৌলিক ভুল বোঝাবুঝি থাকে, তা টেস্টিং ধাপের আগ পর্যন্ত ধরা নাও পড়তে পারে — ততক্ষণে পুরো ডিজাইন ও ইমপ্লিমেন্টেশন ইতিমধ্যে সেই ভুল ধারণার উপর ভিত্তি করে সম্পূর্ণ হয়ে গেছে। ভুলটি ঠিক করতে তখন অনেক বেশি কাজ আবার করতে হয় — যা প্রজেক্টের শুরুতেই ধরা পড়লে অনেক সস্তায় ঠিক করা যেত।

প্র ০৩ উপরের কোড সেলে দুটো try/except ব্লকই কেন ঠিক একই ধরনের এরর (ValueError) রেইজ করেছে, যদিও একটি পেছনে যাওয়ার চেষ্টা আর অন্যটি সামনে স্কিপ করার চেষ্টা ছিল?

কারণ advance_phase()-এর চেকটি দিক (পেছনে বা সামনে) নিয়ে চিন্তা করে না — এটি শুধু একটি শর্ত পরীক্ষা করে: target_idx == current_idx + 1 কিনা। এই একটি শর্তই দুটো ভিন্ন ধরনের অবৈধ ট্রানজিশন (পেছনে ফেরা এবং সামনে স্কিপ করা) — উভয়কেই একইভাবে ধরে ফেলে, কারণ দুটোই "ঠিক পরের ধাপ নয়" এই একই সংজ্ঞার অধীনে পড়ে।

অনুশীলন

  1. চিন্তা করুন: আপনার পরিচিত এমন একটি প্রজেক্ট বা পরিস্থিতির কথা ভাবুন যেখানে ওয়াটারফল ভালো কাজ করত, এবং আরেকটি যেখানে এটি খারাপভাবে ব্যর্থ হতো — দুটোর পার্থক্য ঠিক কী কারণে তৈরি হয়?

    মূল পার্থক্যকারী ফ্যাক্টর সাধারণত রিকোয়ারমেন্টের স্থিতিশীলতা — যেখানে রিকোয়ারমেন্ট সত্যিই আগে থেকে সম্পূর্ণ ও স্থির জানা যায় (যেমন একটি সরকারি কমপ্লায়েন্স ফর্ম), সেখানে ওয়াটারফল ভালো কাজ করে। যেখানে ব্যবহারকারীর প্রতিক্রিয়ার উপর ভিত্তি করে প্রোডাক্ট বিকশিত হতে থাকে (যেমন একটি নতুন কনজিউমার অ্যাপ), সেখানে ওয়াটারফল সাধারণত ব্যর্থ হয়, কারণ দেরিতে আসা প্রতিক্রিয়া সামলানোর কোনো ব্যবস্থা এতে নেই।

  2. পরীক্ষা করুন: উপরের কোড সেলে for next_phase in [...] লুপের তালিকায় "Testing"-এর পরে সরাসরি "Deployment" যোগ করে (অর্থাৎ তালিকাটি ["Design", "Implementation", "Testing", "Deployment"] করে) Run চেপে দেখুন সব ট্রানজিশন সফল হয় কিনা।

    হ্যাঁ, সবগুলো সফল হবে, কারণ প্রতিটি ধাপ ঠিক তার পরের ধাপেই যাচ্ছে (Testing → Deployment বৈধ, কারণ Deployment ঠিক Testing-এর পরের ধাপ)। শেষে current_phase হবে "Deployment", এবং তারপরের দুটি try/except ব্লকের এরর মেসেজেও "Testing" এর বদলে "Deployment" থেকে শুরু হওয়া ট্রানজিশন দেখাবে, কারণ কোডটি প্রতিবার প্রকৃত current_phase থেকে গণনা করে, হার্ডকোড করা নয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
SDLC ধারণা ওভারভিউ