পাঠ ৫৬ · ৫৮-এর মধ্যে · মডিউল ১৩
Home / Courses / Software Engineering Principles & Git / প্রজেক্ট ম্যানেজমেন্ট ও চূড়ান্ত প্রকল্প

এস্টিমেশন টেকনিক — স্টোরি পয়েন্ট ও প্ল্যানিং পোকার

Estimation techniques — story points & planning poker
৮ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

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

  • স্টোরি পয়েন্ট কী এবং কেন এটি রাফ ঘণ্টা-এস্টিমেটের চেয়ে বাস্তবে বেশি নির্ভরযোগ্য প্রমাণিত হয়েছে
  • ফিবোনাচি-স্টাইল পয়েন্ট স্কেলের পেছনের যুক্তি
  • প্ল্যানিং পোকার এবং কেন এটি সমসাময়িক গোপন প্রকাশের মাধ্যমে অ্যাংকরিং বায়াস এড়ায়
  • ভেলোসিটি হিসাব করে ভবিষ্যৎ স্প্রিন্ট ফোরকাস্ট করা — একটি সম্পূর্ণ, হাতে-যাচাই করা গণনা

১ · স্টোরি পয়েন্ট — কেন ঘণ্টার বদলে আপেক্ষিক ইউনিট

এস্টিমেশনEstimationএকটি কাজ (M3/L13-এর ইউজার স্টোরি) সম্পন্ন করতে কত effort লাগবে তা আগে থেকে অনুমান করার প্র্যাক্টিস। সততার সাথে বলতে গেলে নোটোরিয়াসভাবে কঠিন — L02-এ দেখা ওভার-বাজেট, ওভার-শিডিউল প্রজেক্টের ইতিহাসের একটি বড় কারণ দুর্বল এস্টিমেশন। স্টোরি পয়েন্টStory Pointseffort/জটিলতা/অনিশ্চয়তার একটি বিমূর্ত, আপেক্ষিক ইউনিট -- সরাসরি সময়ের পরিমাপ নয়। হলো Agile-এর প্রচলিত, রাফ ঘণ্টা/দিন এস্টিমেটের বিকল্প — টিম একটি স্টোরির পয়েন্ট অন্য, ইতিমধ্যে-এস্টিমেট-করা স্টোরির সাপেক্ষে বিচার করে ("এটি সেই ৩-পয়েন্টের স্টোরির চেয়ে প্রায় দ্বিগুণ জটিল মনে হচ্ছে, তাই ৫ বলা যাক") — সরাসরি পরম ঘণ্টা অনুমান করার চেষ্টার বদলে, যা বাস্তবে বারবার কম নির্ভরযোগ্য প্রমাণিত হয়েছে।

ফিবোনাচি-স্টাইল স্কেল কেন

টিমগুলো সাধারণত 1, 2, 3, 5, 8, 13, 21 — এই ফিবোনাচি-স্টাইল প্রগ্রেশনের পয়েন্ট মান ব্যবহার করে। বড় সংখ্যার মধ্যে ইচ্ছাকৃতভাবে বাড়তে থাকা ফাঁক (৮ থেকে ১৩-এর লাফ, প্রতিটি পূর্ণসংখ্যা নয়) সচেতনভাবে প্রতিফলিত করে যে বড়, জটিল কাজের এস্টিমেট স্বাভাবিকভাবেই কম নির্ভুল — "৮" নাকি "১৩" বেছে নেওয়ার এই জোরপূর্বক বড় লাফ সেই ক্রমবর্ধমান অনিশ্চয়তাকে স্বাভাবিকভাবেই ধরে রাখে।

২ · প্ল্যানিং পোকার — অ্যাংকরিং বায়াস এড়ানো

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

৩ · ভেলোসিটি ও স্প্রিন্ট ফোরকাস্টিং

ভেলোসিটি হলো টিম প্রতি স্প্রিন্টে (M2/L09) গড়ে কত স্টোরি পয়েন্ট সম্পন্ন করে — অতীত স্প্রিন্টগুলোর প্রকৃত ডেটা থেকে গণনা করা হয়, ভবিষ্যৎ স্প্রিন্টে টিম বাস্তবসম্মতভাবে কতটা কমিট করতে পারে তা ফোরকাস্ট করতে ব্যবহৃত হয়। নিচের কোড সেলে তিনটি ফাংশন — একটি planning-poker কনভার্জেন্স চেক, ভেলোসিটি ক্যালকুলেটর, এবং একটি স্প্রিন্ট ফোরকাস্টার — সবই আসল ডেটা থেকে সত্যিকারের গণনা করে।

Python
import math

FIBONACCI_POINTS = [1, 2, 3, 5, 8, 13, 21]

def planning_poker_round(individual_estimates):
    indices = sorted(FIBONACCI_POINTS.index(e) for e in individual_estimates)
    spread = indices[-1] - indices[0]
    converged = spread <= 1
    result = {"estimates": individual_estimates, "converged": converged}
    print(f"  এস্টিমেট: {individual_estimates}")
    if converged:
        print(f"  ✓ কনভার্জড (index spread={spread}, ≤1) -- চূড়ান্ত এস্টিমেট নেওয়া যায়।")
    else:
        median_index = indices[len(indices) // 2]
        outliers = [e for e in individual_estimates if abs(FIBONACCI_POINTS.index(e) - median_index) > 1]
        result["outliers"] = outliers
        print(f"  ✗ কনভার্জড হয়নি (index spread={spread}) -- আলোচনা দরকার। বহিরাগত এস্টিমেট: {outliers}")
    return result

def calculate_velocity(past_sprint_points_list):
    return sum(past_sprint_points_list) / len(past_sprint_points_list)

def forecast_sprints_needed(remaining_points, velocity):
    return math.ceil(remaining_points / velocity)

print("রাউন্ড ১ -- প্রথম এস্টিমেট (ডাইভার্জড):")
round1 = planning_poker_round([2, 3, 13])

print()
print("রাউন্ড ২ -- আলোচনার পর পুনরায় এস্টিমেট (কনভার্জড):")
round2 = planning_poker_round([5, 5, 8, 5, 8])

print()
past_sprints = [23, 19, 25, 21]
velocity = calculate_velocity(past_sprints)
print(f"অতীত ৪টি স্প্রিন্টের পয়েন্ট: {past_sprints}")
print(f"গড় ভেলোসিটি: {velocity} পয়েন্ট/স্প্রিন্ট")

remaining = 100
sprints_needed = forecast_sprints_needed(remaining, velocity)
print(f"\nবাকি {remaining} পয়েন্ট শেষ করতে প্রয়োজনীয় স্প্রিন্ট সংখ্যা: {sprints_needed}")

    
হাতে-যাচাই: রাউন্ড ১-এ [2, 3, 13]-এর ফিবোনাচি ইনডেক্স যথাক্রমে [1, 2, 5] — spread = 5-1 = 4 > 1, তাই কনভার্জড নয়; মিডিয়ান ইনডেক্স (মাঝেরটি, ২) থেকে ১-এর বেশি দূরে থাকা মান (৫-এ থাকা ১৩, দূরত্ব ৩) বহিরাগত হিসেবে চিহ্নিত হয়। রাউন্ড ২-এ [5, 5, 8, 5, 8]-এর ইনডেক্স [3, 3, 3, 4, 4] — spread = 4-3 = 1 ≤ 1, কনভার্জড। ভেলোসিটি: (23+19+25+21)/4 = 88/4 = 22.0। ফোরকাস্ট: 100/22.0 ≈ 4.55, এবং math.ceil(4.55) = 5 — যাচাই: ৪ স্প্রিন্টে 4×22=88 < 100 (যথেষ্ট নয়), ৫ স্প্রিন্টে 5×22=110 ≥ 100 (যথেষ্ট) — তাই ৫টি স্প্রিন্ট সঠিক উত্তর।
মূল কথা · Key takeaway

স্টোরি পয়েন্ট, প্ল্যানিং পোকার, ও ভেলোসিটি — এই তিনটি একসাথে এস্টিমেশনকে আরও নির্ভরযোগ্য করে তোলে, পরম নির্ভুল ঘণ্টা-অনুমানের মিথ্যা প্রতিশ্রুতি না দিয়ে বরং আপেক্ষিক বিচার ও বাস্তব ঐতিহাসিক ডেটার উপর ভিত্তি করে।

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

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

প্র ০১ একটি টিম যদি সরাসরি "এই স্টোরিতে ৭.৫ ঘণ্টা লাগবে" এর মতো নির্দিষ্ট ঘণ্টা এস্টিমেট করে, স্টোরি পয়েন্টের তুলনায় এর সমস্যা কী হতে পারে?

নির্দিষ্ট ঘণ্টা এস্টিমেট একটি মিথ্যা নির্ভুলতার অনুভূতি দেয় — বাস্তবে সফটওয়্যার কাজের সময় নানা অপ্রত্যাশিত কারণে (অজানা এজ কেস, নির্ভরতা, ইন্টারাপশন) ব্যাপকভাবে পরিবর্তিত হতে পারে, এবং মানুষ পরম সময় অনুমানে বারবার ভুল করে দেখা গেছে। স্টোরি পয়েন্ট এই সমস্যা এড়ায় আপেক্ষিক তুলনার মাধ্যমে — "এটি ওই স্টোরির চেয়ে জটিল" বলা "এটি ঠিক ৭.৫ ঘণ্টা লাগবে" বলার চেয়ে অনেক বেশি নির্ভরযোগ্যভাবে করা যায়।

প্র ০২ যদি সবাই এস্টিমেট প্রকাশের আগে দেখতে পেত অন্যরা কী বলেছে, প্ল্যানিং পোকারের ফলাফলে কী পরিবর্তন হতে পারত?

স্বাধীন বিচারের বদলে দলগত গোষ্ঠী-চিন্তা (groupthink) এবং অ্যাংকরিং বায়াস প্রাধান্য পেত — বিশেষ করে জুনিয়র বা কম আত্মবিশ্বাসী সদস্যরা সিনিয়র সদস্যদের বলা সংখ্যার দিকে ঝুঁকে যেতে পারতেন, নিজেদের প্রকৃত মূল্যায়ন থেকে সরে গিয়ে। এতে এস্টিমেট দ্রুত "কনভার্জড" দেখাতে পারে, কিন্তু সেটি প্রকৃত স্বাধীন consensus নয়, বরং একজনের মতামতের প্রতিধ্বনি মাত্র — যা এস্টিমেটের প্রকৃত নির্ভরযোগ্যতা কমিয়ে দেয়।

প্র ০৩ ভেলোসিটি দিয়ে স্প্রিন্ট ফোরকাস্ট করা কতটা নির্ভরযোগ্য — এটি কি একটি নিশ্চিত প্রতিশ্রুতি না অনুমান?

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

অনুশীলন

  1. চিন্তা করুন: এস্টিমেট [8, 13]-এর জন্য planning_poker_round কনভার্জড বলবে নাকি না, হাতে-কলমে ফিবোনাচি ইনডেক্স বের করে হিসাব করুন।

    FIBONACCI_POINTS-এ 8-এর ইনডেক্স 4, 13-এর ইনডেক্স 5। spread = 5 - 4 = 1, যা ≤ 1 শর্ত পূরণ করে — তাই কনভার্জড বলা হবে। এটি ব্যাখ্যা করে ফিবোনাচি স্কেলের মূল যুক্তি: পাশাপাশি দুটো ধাপের (৮ ও ১৩) মধ্যে পার্থক্য থাকা স্বাভাবিক গণ্য হয়, যেহেতু বড় সংখ্যার জন্য নিখুঁত ঐকমত্য পাওয়া কঠিন।

  2. পরীক্ষা করুন: উপরের কোড সেলে past_sprints-এ একটি পঞ্চম স্প্রিন্টের পয়েন্ট (যেমন 27) যোগ করে Run চেপে দেখুন নতুন ভেলোসিটি ও ফোরকাস্ট সংখ্যা কীভাবে বদলায়।

    নতুন গড় = (23+19+25+21+27)/5 = 115/5 = 23.0 — ভেলোসিটি বেড়ে যাবে। নতুন ফোরকাস্ট = math.ceil(100/23.0) = math.ceil(4.347...) = 5 — এই নির্দিষ্ট ক্ষেত্রে ফোরকাস্ট সংখ্যা এখনও ৫-ই থাকবে (যেহেতু ৪×২৩=৯২ এখনও ১০০-এর কম), যদিও ভেলোসিটির প্রকৃত মান বেড়েছে — দেখায় ছোট ভেলোসিটি পরিবর্তন সবসময় ফোরকাস্ট সংখ্যা বদলায় না, কারণ ceil ফাংশন পূর্ণসংখ্যায় রাউন্ড করে।

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

আগের পাঠ
DevOps কালচার ও প্র্যাক্টিস