Skip to content

refactor(engine): extract RowSlots helper for weights/children guard#85

Merged
DemchaAV merged 1 commit into
developfrom
refactor/extract-row-slots-validation
May 31, 2026
Merged

refactor(engine): extract RowSlots helper for weights/children guard#85
DemchaAV merged 1 commit into
developfrom
refactor/extract-row-slots-validation

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Summary

Polish pass surfaced by retrospective senior review of PR-7.3 (f868499b) through the new graphcompose-senior-review skill. PR-7.3 added a defence-in-depth IllegalArgumentException guard for the row weights / children size mismatch at two engine call sites — and shipped no test that drives those guards directly, because the path is unreachable through the public API (RowNode's canonical constructor blocks the mismatched state at construction time).

Unreachable code without coverage rots: the next engine refactor can silently delete either guard with no test going red. This PR locks the contract behind a covered surface.

Changes

  • New RowSlots (src/main/java/com/demcha/compose/document/layout/RowSlots.java, package-private) with a single helper, validateWeightsMatchChildren(weights, n). Package-private intentionally — engine surface, not public API. Error message unchanged from PR-7.3.
  • Both call sites collapsed: LayoutCompiler#distributeRowSlotWidths (was lines 746-750) and NodeDefinitionSupport#measureRow (was lines 324-328) now delegate to RowSlots.validateWeightsMatchChildren(...).
  • New RowSlotsTest (src/test/java/com/demcha/compose/document/layout/RowSlotsTest.java) with 4 tests:
    • Happy path: matching sizes pass without throwing.
    • More weights than children → IAE with both sizes named.
    • Fewer weights than children → IAE with both sizes named.
    • Message-quality check: the error tells the caller how to fix it (containsAnyOf("Pass","Provide","Use")) without locking the exact wording.
  • Javadoc polish on GraphCompose.DocumentBuilder#pageBackgrounds(...) — empty-list-clears semantics now spelled out in a <p> block instead of only the @param line. Inner comment in DocumentBuilder.create() shortened — rationale moved up to the public Javadoc where it belongs.
  • CHANGELOG gets a new ### Engine internals (no behaviour change) subsection under ## v1.6.6 — Planned.

Why this PR, not a comment on PR-7.3

PR-7.3 shipped in v1.6.5. The guard was correct and the public-API surface is right — what was missing is the test-the-helper scaffolding that survives a future refactor. Fixing it forward as a small isolated PR (zero behaviour change, japicmp clean) is cheaper than retroactively reopening a closed release.

The retrospective senior review also flagged the duplicated error message as a future-drift risk (PR-7.1 lesson generalised: any literal in two files is a drift waiting to happen). The helper kills the duplication in one move.

Verification

$ ./mvnw test -pl . -Dtest=RowSlotsTest,RowBuilderTest,PageBackgroundTest
Tests run: 33, Failures: 0, Errors: 0, Skipped: 0

$ ./mvnw test -pl .
Tests run: 1023, Failures: 0, Errors: 0, Skipped: 0  (+4 from RowSlotsTest)

The new binary-compat CI job (PR-84) will check japicmp against v1.6.5 — expecting No changes since the helper is package-private and the public-API contract is identical.

Test plan

  • Full canonical suite green locally (1023 / 0 / 0)
  • RowSlotsTest covers happy + both negative directions + message quality
  • CI green (Guards / JDK 17/21/25 / Examples Smoke / binary-compat)
  • japicmp diff: No changes (package-private extraction = no public-surface delta)
  • Reviewer skim of helper class (45 LOC) — package-private gate held, contract documented in Javadoc

Senior review findings addressed

Severity Finding Resolution
Major Engine guards have zero test coverage New RowSlots + 4-test RowSlotsTest covers it directly
Minor Duplicated error message string in two engine call sites Single source in RowSlots; both sites delegate
Minor GraphCompose.java inner comment + builder Javadoc don't surface the empty-list-clear contract in prose <p> block added to builder Javadoc; inner comment shortened

Polish pass on PR-7.3's defence-in-depth IllegalArgumentException added
in v1.6.5 (commit f868499). The guard lived inline as duplicated code
at two engine call sites — LayoutCompiler#distributeRowSlotWidths and
NodeDefinitionSupport#measureRow — with no direct test. The path is
unreachable through public API (RowNode canonical constructor blocks
the mismatched state), but unreachable code that lacks coverage rots:
the next refactor can silently delete either guard with no test going
red.

Changes:

- New com.demcha.compose.document.layout.RowSlots (package-private)
  with a single helper, validateWeightsMatchChildren(weights, n).
  Error message unchanged from PR-7.3.
- Both call sites replaced with the helper call.
- New RowSlotsTest with 4 tests: happy path, more-weights-than-children,
  fewer-weights-than-children, and a message-quality check that the
  error tells the caller how to fix it.
- GraphCompose.DocumentBuilder#pageBackgrounds(...) Javadoc now spells
  out the empty-list-clears semantics in prose, not just in @param.
  Inner comment in DocumentBuilder.create() shortened — the rationale
  moved up to the public Javadoc where it belongs.

No behaviour change. Suite: 1023 tests, 0 failures, 0 errors (~47s).

Surfaced by retrospective senior-review of PR-7.3 via the new
graphcompose-senior-review skill.
@DemchaAV DemchaAV merged commit 1637adf into develop May 31, 2026
10 checks passed
@DemchaAV DemchaAV deleted the refactor/extract-row-slots-validation branch May 31, 2026 10:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant