6.6 KiB
Workshop Facilitator Guide — Quick Reference
Duration: 80 minutes
Format: Live demo + hands-on practice with Password Validator or Shopping Cart katas using 3-Way Ping-Pong (mob programming)
Team Size: 3 people (2 developers + you as facilitator/participant)
Note: For the complete detailed plan with minute-by-minute timing, scripts, and checklists, see WORKSHOP_PLAN.md. This guide focuses on facilitation tips and kata-specific insights.
Facilitator Role: You'll participate as the 3rd person in the rotation, experiencing TDD alongside the developers. This creates a collaborative learning environment rather than traditional top-down teaching.
Essential Documents
Before the workshop, familiarize yourself with:
- WORKSHOP_PLAN.md — Complete schedule, scripts, and preparation checklist
- fizzbuzz/DEMO_SCRIPT.md — Step-by-step live demo walkthrough
- TDD_REFERENCE_CARD.md — Participant handout
- SETUP_GUIDE.md — For helping participants with technical issues
Quick Preparation Checklist
1 Week Before
- Send SETUP_GUIDE.md to participants
- Confirm everyone completes setup and verifies
dart testworks - Practice FizzBuzz live demo using DEMO_SCRIPT.md
Day Of
- Arrive 15 minutes early
- Test projector/screen sharing
- Open fizzbuzz kata with git log ready
- Have solution files ready (but don't share early!)
- Write schedule on whiteboard
Updated Session Structure
| Time | Activity | See |
|---|---|---|
| 0:00-0:05 | Welcome & Setup Check | WORKSHOP_PLAN.md |
| 0:05-0:20 | Live Demo: FizzBuzz TDD | fizzbuzz/DEMO_SCRIPT.md |
| 0:20-0:25 | Exercise Intro (3-Way Ping-Pong) | Section below |
| 0:25-1:05 | Hands-on Practice (Mob Programming) | Circulate & nudge |
| 1:05-1:20 | Combined Retrospective | WORKSHOP_PLAN.md |
Live Demo: FizzBuzz (NEW SECTION)
Purpose: Show RED-GREEN-REFACTOR cycle in real-time
Setup
- Open
fizzbuzz/directory - Have
fizzbuzz/DEMO_SCRIPT.mdopen on second screen - Terminal ready with
dart test - Reset git to initial commit:
git reset --hard <first-commit-hash>
Key Points to Emphasize
- Run tests frequently (every 30 seconds)
- Minimal implementations (hardcode "1" for first test)
- Test-driven design (algorithm emerges from tests)
- Order matters (check 15 before 3 and 5)
Timing
- 0-2 min: Introduce FizzBuzz rules
- 2-4 min: Cycle 1 (input 1 → "1")
- 4-6 min: Cycle 2 (input 2 → "2")
- 6-9 min: Cycle 3 (input 3 → "Fizz")
- 9-11 min: Cycle 4 (input 5 → "Buzz")
- 11-14 min: Cycle 5 (input 15 → "FizzBuzz")
- 14-15 min: Wrap up, show git log
See fizzbuzz/DEMO_SCRIPT.md for complete talking points and what to code at each step.
What to watch for while participating
Your dual role: You're both a participant in the rotation AND a gentle guide.
Good signs:
- Running
dart testafter every small change - Seeing RED before touching
lib/ - Short, focused commits (or at least talking through each step)
- Smooth keyboard passing between the 3 roles (Red, Green, Refactor)
Gentle interventions (when it's not your turn at keyboard):
- "Have you run the test yet? What did it say?" — nudge anyone writing too much code before testing
- "Can you make it pass with even less code?" — push toward minimal Green
- "Now that it's Green, what could you clean up?" — prompt the Refactor step
- "It's time to pass the keyboard! Let's rotate." — enforce the rotation
When it's your turn:
- Model the behavior you want to see (run tests frequently, minimal code, think aloud)
- Ask questions rather than giving answers: "What's the simplest thing that could work here?"
- Show vulnerability: "Hmm, I'm not sure. What do you think?"
Feature A: Password Validator — facilitator notes
Likely first implementation (all rules as if-blocks):
ValidationResult validate(String password) {
final errors = <String>[];
if (password.length < 8) errors.add('Must be at least 8 characters long');
if (!password.contains(RegExp(r'[A-Z]'))) errors.add('Must contain at least one uppercase letter');
// ... etc
return ValidationResult(isValid: errors.isEmpty, errors: errors);
}
The refactor insight to guide toward (Step 6):
Each rule is just a function String? Function(String). They can live in a list.
Adding a new rule = adding one function. No touching existing code.
This is the Open-Closed Principle — same insight as Gilded Rose's Strategy pattern.
Talking point: "If you had 20 rules, how readable would 20 if-blocks be? What would you do?"
Feature B: Shopping Cart — facilitator notes
Likely first implementation (List-based):
final List<CartItem> _items = [];
double subtotal() => _items.fold(0, (s, i) => s + i.price * i.quantity);
The Map insight (Step 3 — remove by name):
When participants try to implement removeItem(name) with a List, they'll write a .removeWhere().
This works, but nudge them: "What data structure makes 'find by name' really natural?"
Let the remove-by-name test drive them toward Map<String, CartItem>.
CartItem validation (Step 5):
Many will put validation in addItem(). Ask: "What if someone creates a CartItem and passes it somewhere else? Who validates it then?"
This conversation leads naturally to Value Objects.
Bonus design question: The duplicate name test has no right answer. Both "replace" and "accumulate" are valid. The point is: TDD forces you to decide, and the test documents the decision permanently.
Closing discussion questions
- "What was the first test you wrote? Why that one?"
- "Did your design change as you added more tests? How?"
- "Did you ever feel tempted to skip the Red step and just write the code?"
- "How did the 3-way ping-pong dynamic change how you wrote code?"
- "What would have been different if you'd designed the class first, then written tests?"
Common questions and answers
"Can I write all the tests first, then implement?" Not quite — TDD is one test at a time. Write one, watch it fail, make it pass, then the next. Writing all tests upfront is a different practice (it's fine, but it's not TDD).
"What if I don't know what test to write next?" Ask: "What's the simplest behavior this thing should have that it doesn't have yet?" Start with the empty/zero case. Then one item. Then two. Then edge cases.
"Is this realistic? Do people actually do this for real code?" Yes — especially for domain logic (pricing, validation, calculations). It's less common for framework glue code, and that's okay. Apply it where behavior matters most.