- 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
51 lines
1.9 KiB
Markdown
51 lines
1.9 KiB
Markdown
# 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.
|