Add split-loop-with-lambda learning hour: draft, pre-factored exercise, solution
- Samman learning hour: 5/5/10/25/5 outline; pairs stop at extracted method taking the lambda as a parameter - exercise/java: pre-factored variant of the kata (Q1/Q4 dead branch stripped, dates as constant), approval test red/flaky by design - exercise/solution: collectExpectedWeather(LongFunction<Boolean>) + no-arg overload; deterministic approval test (all-sunny lambda) - rehearse-with-agent.md: rehearsal setup with qwen + java-refactoring-mcp
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
# Exercise folder — Split Loop with Lambda (learning hour)
|
||||
|
||||
Contents:
|
||||
|
||||
- `java/` — pre-factored exercise repo (prefactored-longrange; runs with `mvn test`)
|
||||
- `solution/` — reference end state after step 3 (extracted method taking the lambda)
|
||||
- `rehearse-with-agent.md` — how Willem rehearses this with qwen-code + java-refactoring-mcp
|
||||
|
||||
## Reference solution
|
||||
|
||||
See `solution/`. End state of the production code (simplified):
|
||||
|
||||
```java
|
||||
public Map<IceCream, Integer> longRangeForecast() {
|
||||
return longRangeForecast(daysForward -> {
|
||||
scorer.updateSelection();
|
||||
return scorer.lookupWeather(daysForward);
|
||||
});
|
||||
}
|
||||
|
||||
public Map<IceCream, Integer> longRangeForecast(
|
||||
LongFunction<Boolean> dayOffsetToWeather) {
|
||||
var expectedWeather = collectExpectedWeather(dayOffsetToWeather);
|
||||
// ... reset loop + scoring loop, unchanged ...
|
||||
}
|
||||
|
||||
private static List<Boolean> collectExpectedWeather(
|
||||
LongFunction<Boolean> dayOffsetToWeather) {
|
||||
var expectedWeather = new ArrayList<Boolean>();
|
||||
for (Instant interestingDate : DATES) {
|
||||
long daysForward = ChronoUnit.DAYS.between(ANCHOR_DATE, interestingDate);
|
||||
expectedWeather.add(dayOffsetToWeather.apply(daysForward));
|
||||
}
|
||||
return expectedWeather;
|
||||
}
|
||||
```
|
||||
|
||||
Notes on the end state:
|
||||
|
||||
- Key move: `scorer` is used **only inside the lambda**; the extracted method
|
||||
`collectExpectedWeather` has no dependency on `Scorer` at all — all its
|
||||
inputs are parameters.
|
||||
- The public no-arg overload keeps callers unchanged; it injects the
|
||||
"real" weather lambda. The test calls the overload with a pure
|
||||
`daysForward -> true` instead.
|
||||
- The test is pure and glanceable: `alwaysSunny` weather gives
|
||||
`{Strawberry:12, Chocolate:12, Vanilla:17, }` (approved file included).
|
||||
- `scorer.updateSelection()` turned out to be deletable (it only mutates
|
||||
static `Scorer.flavour` state that this method never reads). Leaving it
|
||||
in the lambda is fine for step 3; deleting it is a debrief aha.
|
||||
Reference in New Issue
Block a user