docs: Document String Calculator Bug Hunt Kata

- Add comprehensive String Calculator section to README
- Document Bug Hunt approach: test-driven bug finding
- List all 5 bugs found and fixed with RED-GREEN commits
- Include code examples and usage
- Update comparison table to include all 4 katas
- Add 'What Each Kata Teaches' for String Calculator
- Update progressive learning path to include fourth kata
This commit is contained in:
fiatcode 2026-02-18 13:00:26 +07:00
parent ab5a97acc8
commit ad774b89c8

134
README.md
View file

@ -219,6 +219,99 @@ gildedRose.updateQuality(); // Updates all items per domain rules
--- ---
### 4. String Calculator ✅
**Implementation:** [`lib/string_calculator.dart`](lib/string_calculator.dart)
**Tests:** [`test/string_calculator_test.dart`](test/string_calculator_test.dart)
A Bug Hunt Kata demonstrating how to use TDD to discover and fix bugs in existing code. Each bug is exposed with a RED test, then fixed with GREEN implementation.
#### Domain Context
A simple calculator that sums numbers from a string input with various delimiter support:
**Features:**
1. **Empty String:** Returns 0
2. **Single Number:** Returns that number (`"5"` → 5)
3. **Comma Delimiter:** Sums comma-separated numbers (`"1,2,3"` → 6)
4. **Custom Delimiters:** Supports format `"//[delimiter]\n[numbers]"` (`"//;\n1;2"` → 3)
5. **Ignore Large Numbers:** Numbers > 1000 are ignored (`"2,1001"` → 2)
#### The Bug Hunt Approach
**Different from Previous Katas:** This wasn't built test-first. Instead, we started with **buggy working code** and used tests to expose and fix bugs one by one.
**Bug Hunt Process:**
1. **RED:** Write test exposing a specific bug
2. **GREEN:** Fix only that bug
3. **Commit:** Document the bug found and fixed
4. **Repeat:** Move to next bug
#### Bugs Found & Fixed
**Bug #1: Empty String Returns Wrong Value**
- **Bug:** Returned 1 instead of 0
- **Test:** `expect(calculator.add(''), equals(0))`
- **Fix:** Changed return value from 1 to 0
- **Commits:** RED → GREEN
**Bug #2: Single Number Off-By-One**
- **Bug:** Added +1 to parsed number
- **Test:** `expect(calculator.add('5'), equals(5))`
- **Expected:** 5, **Actual:** 6
- **Fix:** Removed `+ 1` from parsing
- **Commits:** RED → GREEN
**Bug #3: Summation Loop Misses Last Element**
- **Bug:** Loop condition `i < length - 1` skipped last item
- **Test:** `expect(calculator.add('1,2'), equals(3))`
- **Expected:** 3, **Actual:** 1
- **Fix:** Changed to `i < length`
- **Commits:** RED → GREEN
**Bug #4: Custom Delimiter Not Extracted**
- **Bug:** Delimiter extraction line was commented out
- **Test:** `expect(calculator.add('//;\n1;2'), equals(3))`
- **Error:** FormatException trying to parse '1;2'
- **Fix:** Uncommented `delimiter = parts[0].substring(2)`
- **Commits:** RED → GREEN
**Bug #5: Missing Feature - Ignore Numbers > 1000**
- **Bug:** All numbers included in sum
- **Test:** `expect(calculator.add('2,1001'), equals(2))`
- **Expected:** 2, **Actual:** 1003
- **Fix:** Added `.where((n) => n <= 1000)` filter
- **Commits:** RED → GREEN
#### Usage
```dart
import 'package:tdd_katas/string_calculator.dart';
final calculator = StringCalculator();
calculator.add(''); // Returns: 0
calculator.add('5'); // Returns: 5
calculator.add('1,2,3'); // Returns: 6
calculator.add('//;\n1;2'); // Returns: 3
calculator.add('2,1001'); // Returns: 2 (1001 ignored)
```
#### The "Aha!" Moments
1. **Tests as Bug Detectors:** Each test acted like a spotlight, illuminating exactly ONE bug at a time. No guessing—the test tells you what's broken.
2. **RED-GREEN Still Works:** Even when fixing bugs (not adding features), the RED-GREEN rhythm provides safety. You're never fixing blind.
3. **Regression Prevention:** After fixing each bug, ALL previous tests stay green. This proves you didn't break something while fixing something else.
4. **Incremental Debugging:** Fixing one bug at a time with commits creates a clear audit trail. You can see exactly what each bug was and how it was fixed.
5. **Real-World Skill:** This mirrors production work—most code you touch is existing code with bugs, not greenfield TDD.
---
## Running Tests ## Running Tests
```bash ```bash
@ -229,6 +322,7 @@ dart test
dart test test/roman_numerals_test.dart dart test test/roman_numerals_test.dart
dart test test/bowling_game_test.dart dart test test/bowling_game_test.dart
dart test test/gilded_rose_test.dart dart test test/gilded_rose_test.dart
dart test test/string_calculator_test.dart
# Run with coverage # Run with coverage
dart test --coverage dart test --coverage
@ -536,22 +630,23 @@ Decision: Skip refactor commit—code is already excellent.
## Comparing the Katas ## Comparing the Katas
### All Three Katas at a Glance ### All Four Katas at a Glance
| Aspect | Roman Numerals | Bowling Game | Gilded Rose | | Aspect | Roman Numerals | Bowling Game | Gilded Rose | String Calculator |
|--------|----------------|--------------|-------------| |--------|----------------|--------------|-------------|-------------------|
| **Complexity** | Beginner | Intermediate | Advanced | | **Complexity** | Beginner | Intermediate | Advanced | Beginner |
| **Approach** | Greenfield TDD | Greenfield TDD | Legacy refactoring | | **Approach** | Greenfield TDD | Greenfield TDD | Legacy refactoring | Bug hunting |
| **State** | Stateless | Stateful | Stateful | | **State** | Stateless | Stateful | Stateful | Stateless |
| **Algorithm** | Table-driven lookup | Frame iteration | Strategy pattern | | **Algorithm** | Table-driven | Frame iteration | Strategy pattern | String parsing |
| **Key Challenge** | Pattern recognition | State & bonuses | Refactoring safely | | **Key Challenge** | Pattern recognition | State & bonuses | Refactoring safely | Finding bugs |
| **Design Pattern** | Value Object | Implicit strategy | Explicit strategy | | **Design Pattern** | Value Object | Implicit strategy | Explicit strategy | Filters & pipes |
| **Lines of Code** | ~45 production | ~30 production | ~120 production | | **Lines of Code** | ~45 production | ~30 production | ~120 production | ~25 production |
| **Test Count** | ~15 tests | ~10 tests | ~17 tests | | **Test Count** | ~15 tests | ~10 tests | ~17 tests | 6 tests |
| **Aha! Moment** | Table = data structure | Simple → complex works | Refactoring = safety | | **Aha! Moment** | Table = data | Simple → complex | Refactor = safe | Tests find bugs |
### What Each Kata Teaches ### What Each Kata Teaches
**Roman Numerals:**
**Roman Numerals:** **Roman Numerals:**
- Converting domain rules into data structures - Converting domain rules into data structures
- Value Objects for enforcing constraints - Value Objects for enforcing constraints
@ -561,22 +656,29 @@ Decision: Skip refactor commit—code is already excellent.
- State management without over-engineering - State management without over-engineering
- Look-ahead logic in sequential data - Look-ahead logic in sequential data
- How correct abstractions scale beyond test cases - How correct abstractions scale beyond test cases
**Gilded Rose:** **Gilded Rose:**
- Safely refactoring legacy code with characterization tests - Safely refactoring legacy code with characterization tests
- Strategy pattern for eliminating conditional complexity - Strategy pattern for eliminating conditional complexity
- Open-Closed Principle for extensibility - Open-Closed Principle for extensibility
- Working effectively with code you didn't write - Working effectively with code you didn't write
**String Calculator:**
- Using tests to expose bugs in existing code
- Bug hunting with RED-GREEN discipline
- Incremental debugging with clear commits
- Regression prevention through test accumulation
### Progressive Learning Path ### Progressive Learning Path
1. **Roman Numerals first:** Learn TDD fundamentals without state complexity 1. **Roman Numerals first:** Learn TDD fundamentals without state complexity
2. **Bowling Game second:** Apply TDD to stateful problems 2. **Bowling Game second:** Apply TDD to stateful problems
3. **Gilded Rose third:** Master refactoring legacy code with tests as safety net 3. **Gilded Rose third:** Master refactoring legacy code with tests as safety net
4. **Next kata:** Choose based on what you want to practice: 4. **String Calculator fourth:** Practice bug hunting and fixing with TDD
- **String Calculator:** Parsing, validation, error handling 5. **Next kata:** Choose based on what you want to practice:
- **Mars Rover:** Command pattern, multiple behaviors
- **Prime Factors:** Mathematical decomposition, algorithmic thinkingsts
- **Mars Rover:** Command pattern, multiple behaviors - **Mars Rover:** Command pattern, multiple behaviors
- **Prime Factors:** Mathematical decomposition, algorithmic thinking
- **Tennis Scoring:** State machines, domain language
--- ---