Rename pattern to Slice with Lambda; add no-loop minimal shape and capture-to-parameter lesson

This commit is contained in:
Your Name
2026-09-29 13:32:47 +00:00
parent c153aba61e
commit f9bb7b982a
2 changed files with 37 additions and 4 deletions
@@ -1,6 +1,6 @@
# Split Loop with Lambda — storyboard / handout # Slice with Lambda — storyboard / handout
Step-by-step mechanics of the **Split Loop with Lambda** refactoring, one diagram per Step-by-step mechanics of the **Slice with Lambda** refactoring (formerly called "Split Loop with Lambda"), one diagram per
step, each step followed by the exact code (full before/after, highlights as `←` step, each step followed by the exact code (full before/after, highlights as `←`
comments). Written to be sliced into slides later; until then it works as a handout. comments). Written to be sliced into slides later; until then it works as a handout.
@@ -8,6 +8,7 @@ Sources: `../zeroth-draft-of-refactoring-pattern.md` (the mechanics),
`../split-loop-with-lambda-learning-hour.md` (where we stop: after step 3 + the test), `../split-loop-with-lambda-learning-hour.md` (where we stop: after step 3 + the test),
`../exercise/rehearsal-findings.md` (the drift anti-pattern and the "both calls!" `../exercise/rehearsal-findings.md` (the drift anti-pattern and the "both calls!"
caution). Java only. Pristine start: `../exercise/java`, end state: `../exercise/solution`. caution). Java only. Pristine start: `../exercise/java`, end state: `../exercise/solution`.
C# demo examples live at `../exercise/csharp/` (MetaphorFree.cs, WeatherStation.cs, IceCreamShop.cs), and there is a reveal.js deck at `/home/cardfanatic/qwan/slides-rjs/decks/slice-with-lambda/slides.md`.
## How to read the diagrams ## How to read the diagrams
@@ -4,7 +4,7 @@
# Introduction # Introduction
This is a zeroth draft. Our meta-goals are being more explicit in naming the refactorings and patterns we used to ourselves, and enable others to name the patterns, so they can reproduce the mechanics reliably on their own. This is a zeroth draft of the **Slice with Lambda** refactoring pattern (formerly called "Split Loop with Lambda"). Our meta-goals are being more explicit in naming the refactorings and patterns we used to ourselves, and enable others to name the patterns, so they can reproduce the mechanics reliably on their own.
Initial literature survey (see related patterns below) has not yet revealed an existing Refactoring Pattern description. In order to fit some or all of this refactoring in a learning hour, it is worth writing down what we mean, with examples (so, in case the resulting exercise does not fit in a learning hour, we have a blog post to refer to for more details and/or recapturing the mechanics). Initial literature survey (see related patterns below) has not yet revealed an existing Refactoring Pattern description. In order to fit some or all of this refactoring in a learning hour, it is worth writing down what we mean, with examples (so, in case the resulting exercise does not fit in a learning hour, we have a blog post to refer to for more details and/or recapturing the mechanics).
@@ -24,7 +24,39 @@ Split loop suggests “‘introduce variable’ refactorings and ‘slide statem
3. Extract the method below the slides statement. You now have a new method, that takes the lambda as a parameter 3. Extract the method below the slides statement. You now have a new method, that takes the lambda as a parameter
4. Move the method to another class where the unwanted dependency is not present 4. Move the method to another class where the unwanted dependency is not present
5. Move and/or create tests, using the lambda as a stub instead of a concrete invocation of the unwanted dependency. 5. Move and/or create tests, using the lambda as a stub instead of a concrete invocation of the unwanted dependency.
6. Check that “everything that could possibly break” is tested \- the extracted lambda allows more combinations to be easily tested. 6. Check that "everything that could possibly break" is tested \- the extracted lambda allows more combinations to be easily tested.
## The no-loop minimal shape
The mechanics above are usually applied inside a loop, but the pattern does not require one. The minimal shape is a method consisting of guard clauses, then ONE call on an unwanted dependency in the middle, then a tail that depends on the value the call produced:
```csharp
public int Calculate(int a)
{
if (a < 0) return 0;
int b = _someDependency.mightThrowWhenPreconditionNotSatisfied(a);
int c = a + b;
return c * 2;
}
```
The same mechanics apply: extract the call into a lambda, slide the lambda definition to the top, extract the method below the slide statement with the lambda as a parameter. There is simply no loop to split — hence "Slice".
### Capture-to-parameter: the lambda cannot capture the method's parameters
When the lambda is moved up into the function head (as a parameter via the overload seam), it cannot capture the method's parameters — they are not in scope there — so the lambda must take them explicitly:
```csharp
Func<int, int> readB = a => _someDependency.mightThrowWhenPreconditionNotSatisfied(a);
```
and every invocation becomes
```csharp
int b = readB(a);
```
Note that the Java storyboard lambda already took `daysForward` as its parameter, so the Java walkthrough does not hit this; the C# metaphor-free demo (`exercise/csharp/MetaphorFree.cs`) does.
# Consequences / resulting context. # Consequences / resulting context.