🏫 The School›🏅 Engineering Leadership›⚖️ धडा 06 — Prioritisation: RICE, cost of delay आणि CD3
🖼️ See the drawing + lab 🏠 Course home 🌿 Branch on GitHub ✏️ View source
🖼️ आकृती आणि labThe drawing + lab पूर्ण पानावर उघडा ↗Open full page ↗

⚖️ धडा 06 — Prioritisation: RICE, cost of delay आणि CD3

📍 तुम्ही इथे आहात: 12 पैकी धडा 06 · मागे: lesson-05-forecasting · पुढे: lesson-07-technical-debt


📦 या ब्रँचमध्ये काय आहे

धडा 05, आणि कामाचा क्रम निवडणे. RICE (reach × impact × confidence ÷ effort), cost of delay — एखादी गोष्ट न झाल्याने दर आठवड्याला जाणारे मूल्य — आणि CD3 (cost of delay भागिले duration), WSJF मागचा scheduling नियम. मुद्दा सूत्राचा नाही: मुद्दा आहे गृहीतके लिहून ठेवण्याचा, जेणेकरून लोक त्यावर वाद घालू शकतील. lead/demo.py मधले priorities(); lead/models.py मधले rice(), delay_cost() आणि cd3_order().

🧒 5 वर्षांच्या मुलाला समजावल्यासारखे

कतरिनाच्या विभागात चार कामे वाट पाहत आहेत, आणि त्या एका वेळी एकच करू शकतात: 📋

प्रत्येकीचे स्वतःचे मत आहे. पालक portal सर्वात मौल्यवान आहे, म्हणून "सर्वात मोठी गोष्ट आधी करा!" असे एक शिक्षिका म्हणते.

कतरिना वेगळा प्रश्न विचारते: "आपण प्रत्येक आठवडा थांबलो तर आपले किती नुकसान होते?" ⏳ Export fix मुळे आठवड्याला 5 गुण जातात, पण त्याला फक्त 1 आठवडा लागतो. म्हणून ते आधी करा — त्यामुळे नुकसान लवकर थांबते. मग निकालाचे पान. त्यानंतर मोठे portal.

ती थांबण्यात झालेले सगळे नुकसान मोजते. "सर्वात मोठे आधी" मध्ये 142 गुण जातात. "कामाच्या प्रत्येक आठवड्यामागे सर्वात जास्त नुकसान असलेले आधी" मध्ये फक्त 118. तीच चार कामे, त्याच शिक्षिका — फक्त चांगला क्रम. 🎯

🗺️ आकृती

flowchart LR
    r["📊 RICE<br/>results page 600 · portal 500<br/>export fix 320 · timetable 75"] --> a["⚠️ portal confidence 50% → 80%<br/>RICE 500 → 800, jumps to first"]
    c["⏳ cost of delay / weeks<br/>export 5/1 · results 6/2<br/>portal 8/4 · timetable 3/6"] --> b["biggest value first<br/>delay cost 142"]
    c --> d["CD3: value per week ÷ duration<br/>export → results → portal → timetable<br/>delay cost 118"]

🗺️ काढलेली आवृत्ती + एक lab: https://school-edh.pages.dev/engineering-leadership/lesson-diagrams.html#l06

❓ काय

🤔 का

कारण प्रत्येक टीमकडे क्षमतेपेक्षा जास्त चांगल्या कल्पना असतात, आणि निवडीइतकाच क्रमही महत्त्वाचा असतो. सामायिक model शिवाय prioritisation आत्मविश्वास आणि पदाची स्पर्धा बनते. Reach, confidence, cost of delay आणि duration लिहून ठेवल्याने "मला वाटते portal सर्वात महत्त्वाचे आहे" याचे रूपांतर "मला वाटते तिमाहीला 2,000 पालक ते वापरतील आणि मला 50% खात्री आहे" मध्ये होते — असा दावा जो इतर व्यक्तीला आव्हान न देता तपासू, सुधारू किंवा आव्हान देऊ शकतात.

🔧 कसे (या repo मध्ये)

lead/models.py मधले rice(reach, impact, confidence, effort) हे सूत्र आहे. delay_cost(order, items) {name: (cost of delay per week, weeks)} घेते, कामे एकामागून एक चालवते आणि प्रत्येकासाठी cost of delay × finish week ची बेरीज करते — थांबण्यात गेलेले मूल्य. cd3_order(items) cost of delay ÷ duration नुसार क्रम लावते. lead/demo.py मधले priorities() विभागाच्या चार कामांना दोन्ही प्रकारे गुण देते. सर्व inputs बनावट "value points" मधले अंदाज आहेत: विचार करण्याचे साधन, माणसांसाठीचे सूत्र नाही — उपयुक्त output म्हणजे inputs बद्दलची चर्चा.

🧪 करून पाहा

python3 lead/demo.py priorities
python3 - <<'EOF'
import sys; sys.path.insert(0, "lead"); from models import rice, delay_cost, cd3_order
from itertools import permutations
cod = {"gradebook export fix": (5, 1), "exam results page": (6, 2), "parent portal login": (8, 4), "timetable rewrite": (3, 6)}
costs = sorted((delay_cost(list(p), cod), " → ".join(n.split()[0] for n in p)) for p in permutations(cod))
print(f"all {len(costs)} orders: cheapest {costs[0][0]} ({costs[0][1]}) · dearest {costs[-1][0]} ({costs[-1][1]})")
cod["exam results page"] = (20, 2)          # results day is in 3 weeks: time criticality jumps
print("results page becomes urgent → CD3 order:", " → ".join(n.split()[0] for n in cd3_order(cod)), "· cost", delay_cost(cd3_order(cod), cod))
for conf in (0.3, 0.5, 0.8, 1.0):
    print(f"portal confidence {conf:.0%} → RICE {rice(2000, 2, conf, 4):>4.0f}")
EOF

✅ तपासा — तुम्हाला काय दिसायला हवे

priorities असे print करते:

   exam results page       1500 × 1 × 80% ÷ 2 =   600
   parent portal login     2000 × 2 × 50% ÷ 4 =   500
   gradebook export fix     400 × 1 × 80% ÷ 1 =   320
   timetable rewrite        300 × 3 × 50% ÷ 6 =    75
   raise the portal's confidence from 50% to 80% → 800, and it jumps to first — the ranking is only as good as that guess
   biggest value first: parent portal login → exam results page → gradebook export fix → timetable rewrite → total delay cost 142
   CD3 (cost of delay ÷ duration): gradebook export fix → exam results page → parent portal login → timetable rewrite → total delay cost 118

तुमचा snippet असे print करतो:

all 24 orders: cheapest 118 (gradebook → exam → parent → timetable) · dearest 235 (timetable → parent → exam → gradebook)
results page becomes urgent → CD3 order: exam → gradebook → parent → timetable · cost 150
portal confidence 30% → RICE  300
portal confidence 50% → RICE  500
portal confidence 80% → RICE  800
portal confidence 100% → RICE 1000

🏁 तुम्ही आत्ताच काय सिद्ध केले

सर्व 24 क्रम तपासल्याने खात्री होते की इथे CD3 क्रम सर्वात स्वस्त आहे (118), आणि सर्वात वाईट क्रमाची किंमत 235 आहे — त्याच कामासाठी दुप्पट. "सर्वात मोठे मूल्य आधी" ची किंमत 142 होती. निकालाचा दिवस जवळ आला आणि निकालाच्या पानाचा cost of delay आठवड्याला 20 वर गेला, तेव्हा CD3 ने ते आपोआप पुढे आणले. आणि RICE ची क्रमवारी एकाच confidence आकड्यावर उलटली: कोणी किती खात्री असल्याचा दावा केला त्यानुसार portal ला 300 ते 1000 पर्यंत कुठलाही गुण मिळाला.

⚠️ नेहमीच्या चुका

🏭 प्रत्यक्ष वापरात

Inputs backlog शेजारी एका सामायिक तक्त्यात ठेवा, म्हणजे मतभेद एका cell बद्दल असतो:

| Item                  | Reach/qtr | Impact | Confidence | Effort (pm) | RICE | CoD/wk | Weeks | CD3  | Why (assumptions)                      |
|-----------------------|-----------|--------|------------|-------------|------|--------|-------|------|----------------------------------------|
| Exam results page     | 1500      | 1      | 80%        | 2           | 600  | 6      | 2     | 3.0  | results day 20 June; last year's visits |
| Parent portal login   | 2000      | 2      | 50%        | 4           | 500  | 8      | 4     | 2.0  | survey of 40 parents — small sample    |
| Gradebook export fix  | 400       | 1      | 80%        | 1           | 320  | 5      | 1     | 5.0  | 12 support tickets a week              |
| Timetable rewrite     | 300       | 3      | 50%        | 6           | 75   | 3      | 6     | 0.5  | pain is real; benefit unmeasured       |

आकडे ज्यांच्याकडे आहेत त्या लोकांसोबत (support, product, शिक्षिका) याचा आढावा घ्या, फक्त टीमसोबत नाही. एखादी तारीख सरकली किंवा नवा पुरावा आला की पुन्हा गुण द्या. अनेक trackers या मूल्यांसाठी custom fields ठेवू शकतात; सुरुवातीला spreadsheet पुरेसे आहे.

🏭 प्रत्यक्ष वापरात हे का महत्त्वाचे आहे: सर्वात चांगली prioritisation meeting लहान असते कारण वाद आधीच तक्त्यात झालेला असतो. Score शेजारी गृहीतके लिहा, आणि मग जिंकण्यासाठी सर्वात मोठ्या आवाजालाही एखादा आकडा — सर्वांसमोर — बदलावा लागतो.

⏭️ पुढे

एका प्रकारचे काम RICE ची स्पर्धा कधीच जिंकत नाही, तरीही बाकी सगळे हळू करते: technical debt. पुढे: त्याला portfolio म्हणून हाताळणे.

git checkout lesson-07-technical-debt

⚖️ Lesson 06 — Prioritisation: RICE, cost of delay and CD3

📍 You are here: Lesson 06 of 12 · Previous: lesson-05-forecasting · Next: lesson-07-technical-debt


📦 What's in this branch

Lesson 05, plus choosing the order of work. RICE (reach × impact × confidence ÷ effort), cost of delay — the value lost for every week something is not done — and CD3 (cost of delay divided by duration), the scheduling rule behind WSJF. The point is not the formula: it is writing the assumptions down so people can argue with them. priorities() in lead/demo.py; rice(), delay_cost() and cd3_order() in lead/models.py.

🧒 Explain like I'm 5

Katrina's department has four jobs waiting, and they can only do one at a time: 📋

Everyone has an opinion. The parent portal is the most valuable, so "do the biggest thing first!" says one teacher.

Katrina asks a different question: "For each week we wait, how much do we lose?" ⏳ The export fix loses 5 points a week, but takes only 1 week. So do it first — it stops the losing quickly. Then the results page. The big portal after that.

She adds up all the losing-while-waiting. "Biggest first" loses 142 points. "Most lost per week of work, first" loses only 118. Same four jobs, same people — just a better order. 🎯

🗺️ Diagram

flowchart LR
    r["📊 RICE<br/>results page 600 · portal 500<br/>export fix 320 · timetable 75"] --> a["⚠️ portal confidence 50% → 80%<br/>RICE 500 → 800, jumps to first"]
    c["⏳ cost of delay / weeks<br/>export 5/1 · results 6/2<br/>portal 8/4 · timetable 3/6"] --> b["biggest value first<br/>delay cost 142"]
    c --> d["CD3: value per week ÷ duration<br/>export → results → portal → timetable<br/>delay cost 118"]

🗺️ Drawn version + a lab: https://school-edh.pages.dev/engineering-leadership/lesson-diagrams.html#l06

❓ What

🤔 Why

Because every team has more good ideas than capacity, and the order matters as much as the choice. Without a shared model, prioritisation becomes a contest of confidence and rank. Writing down reach, confidence, cost of delay and duration turns "I think the portal matters most" into "I think 2,000 parents a quarter will use it and I am 50% sure" — a claim others can check, improve or challenge without challenging the person.

🔧 How (in this repo)

rice(reach, impact, confidence, effort) in lead/models.py is the formula. delay_cost(order, items) takes {name: (cost of delay per week, weeks)}, runs the items one after another and adds up cost of delay × finish week for each — the value lost while waiting. cd3_order(items) sorts by cost of delay ÷ duration. priorities() in lead/demo.py scores four department jobs both ways. All inputs are guesses in made-up "value points": a thinking tool, not a formula for people — the useful output is the conversation about the inputs.

🧪 Try it

python3 lead/demo.py priorities
python3 - <<'EOF'
import sys; sys.path.insert(0, "lead"); from models import rice, delay_cost, cd3_order
from itertools import permutations
cod = {"gradebook export fix": (5, 1), "exam results page": (6, 2), "parent portal login": (8, 4), "timetable rewrite": (3, 6)}
costs = sorted((delay_cost(list(p), cod), " → ".join(n.split()[0] for n in p)) for p in permutations(cod))
print(f"all {len(costs)} orders: cheapest {costs[0][0]} ({costs[0][1]}) · dearest {costs[-1][0]} ({costs[-1][1]})")
cod["exam results page"] = (20, 2)          # results day is in 3 weeks: time criticality jumps
print("results page becomes urgent → CD3 order:", " → ".join(n.split()[0] for n in cd3_order(cod)), "· cost", delay_cost(cd3_order(cod), cod))
for conf in (0.3, 0.5, 0.8, 1.0):
    print(f"portal confidence {conf:.0%} → RICE {rice(2000, 2, conf, 4):>4.0f}")
EOF

✅ Verify — what you should see

priorities prints:

   exam results page       1500 × 1 × 80% ÷ 2 =   600
   parent portal login     2000 × 2 × 50% ÷ 4 =   500
   gradebook export fix     400 × 1 × 80% ÷ 1 =   320
   timetable rewrite        300 × 3 × 50% ÷ 6 =    75
   raise the portal's confidence from 50% to 80% → 800, and it jumps to first — the ranking is only as good as that guess
   biggest value first: parent portal login → exam results page → gradebook export fix → timetable rewrite → total delay cost 142
   CD3 (cost of delay ÷ duration): gradebook export fix → exam results page → parent portal login → timetable rewrite → total delay cost 118

Your snippet prints:

all 24 orders: cheapest 118 (gradebook → exam → parent → timetable) · dearest 235 (timetable → parent → exam → gradebook)
results page becomes urgent → CD3 order: exam → gradebook → parent → timetable · cost 150
portal confidence 30% → RICE  300
portal confidence 50% → RICE  500
portal confidence 80% → RICE  800
portal confidence 100% → RICE 1000

🏁 What you just proved

Trying all 24 orders confirms that the CD3 order is the cheapest here (118), and the worst order costs 235 — twice as much for the same work. "Biggest value first" cost 142. When results day came close and the results page's cost of delay jumped to 20 a week, CD3 moved it to the front on its own. And RICE's ranking flipped on a single confidence number: the portal scored anywhere from 300 to 1000 depending on how sure someone claimed to be.

⚠️ Common mistakes

🏭 In production

Keep the inputs in a shared table next to the backlog, so a disagreement is about a cell:

| Item                  | Reach/qtr | Impact | Confidence | Effort (pm) | RICE | CoD/wk | Weeks | CD3  | Why (assumptions)                      |
|-----------------------|-----------|--------|------------|-------------|------|--------|-------|------|----------------------------------------|
| Exam results page     | 1500      | 1      | 80%        | 2           | 600  | 6      | 2     | 3.0  | results day 20 June; last year's visits |
| Parent portal login   | 2000      | 2      | 50%        | 4           | 500  | 8      | 4     | 2.0  | survey of 40 parents — small sample    |
| Gradebook export fix  | 400       | 1      | 80%        | 1           | 320  | 5      | 1     | 5.0  | 12 support tickets a week              |
| Timetable rewrite     | 300       | 3      | 50%        | 6           | 75   | 3      | 6     | 0.5  | pain is real; benefit unmeasured       |

Review it with the people who hold the numbers (support, product, the teachers), not only with the team. Re-score when a date moves or new evidence arrives. Several trackers can hold custom fields for these values; a spreadsheet is enough to start.

🏭 Why this matters in production: the best prioritisation meeting is short because the argument already happened in the table. Write the assumptions next to the score, and the loudest voice has to change a number — in public — to win.

⏭️ Next

One kind of work never wins a RICE contest, yet slows everything else down: technical debt. Next: treating it as a portfolio.

git checkout lesson-07-technical-debt
← PreviousforecastingNext →technical debt

This page is the lesson's README from the lesson-06-prioritisation branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.