Skip to content

Rename Core\Reducer to Composite and expose it as a public validator#1650

Draft
henriquemoody wants to merge 1 commit intoRespect:mainfrom
henriquemoody:rule/composite
Draft

Rename Core\Reducer to Composite and expose it as a public validator#1650
henriquemoody wants to merge 1 commit intoRespect:mainfrom
henriquemoody:rule/composite

Conversation

@henriquemoody
Copy link
Member

The term "Reducer" is widely used in functional programming to describe a specific pattern: a function that takes an accumulator and a value, returning a new accumulator (e.g., array_reduce, Redux reducers). This class does not perform that operation. Instead, it consolidates multiple validators into a single one, which is the definition of composition.

The new name "Composite" accurately reflects what this validator does: it composes zero or more validators into a unified validation unit. This aligns with the Composite design pattern terminology and avoids semantic confusion with functional programming concepts.

The class has also been moved from the internal Core namespace to the public Validators namespace. This change acknowledges that composing validators dynamically is a legitimate use case for library consumers, not just an internal implementation detail. The library itself uses this pattern in Attributes and KeySet validators, demonstrating its practical value.

The signature has been extended to accept zero or more validators:

  • Zero validators: Returns AlwaysValid (useful for conditional chains)
  • One validator: Pass-through without wrapping (avoids unnecessary nesting)
  • Multiple validators: Combines using AllOf (all must pass)

This flexibility is particularly useful when building validation chains dynamically, where the number of validators may vary at runtime based on configuration or user input.

Assisted-by: Claude Code (Claude Opus 4.5)

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR renames the internal Core\Reducer class to Composite and promotes it to a public validator in the Validators namespace. The change addresses semantic confusion with functional programming's "reducer" concept and better reflects the class's purpose of composing multiple validators into a unified validation unit. The signature has been enhanced to accept zero or more validators, with intelligent behavior: zero validators returns AlwaysValid, one validator acts as pass-through, and multiple validators are combined using AllOf.

Changes:

  • Renamed Core\Reducer to Validators\Composite with enhanced variadic parameter support (zero or more validators)
  • Updated all internal usages in Attributes and KeySet validators to use the new class
  • Added comprehensive mixin interfaces for the new public validator across all builder patterns

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Validators/Composite.php New public validator that composes zero or more validators using AlwaysValid, pass-through, or AllOf patterns
src/Validators/Core/Reducer.php Removed - replaced by the new Composite validator
src/Validators/Attributes.php Updated to use new Composite class, simplified logic by removing empty validator check
src/Validators/KeySet.php Updated to use new Composite class instead of Reducer
tests/unit/Validators/CompositeTest.php Renamed test class and added test for zero-validator case
tests/src/SmokeTestProvider.php Added smoke test for the new Composite validator
src/Mixins/*.php Added method signatures for Composite across all mixin interfaces (Chain, Builder, and various decorators)
docs/validators/Composite.md Comprehensive documentation with usage examples and use cases
docs/validators.md Added Composite to the validator list in appropriate categories

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link

codecov bot commented Jan 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.20%. Comparing base (ec16b3d) to head (8df357c).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #1650      +/-   ##
============================================
+ Coverage     99.19%   99.20%   +0.01%     
- Complexity      908      919      +11     
============================================
  Files           190      191       +1     
  Lines          2117     2150      +33     
============================================
+ Hits           2100     2133      +33     
  Misses           17       17              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@henriquemoody henriquemoody force-pushed the rule/composite branch 3 times, most recently from ccc2ce1 to e29f7fa Compare January 31, 2026 03:13
The term "Reducer" is widely used in functional programming to describe
a specific pattern: a function that takes an accumulator and a value,
returning a new accumulator (e.g., array_reduce, Redux reducers). This
class does not perform that operation. Instead, it consolidates multiple
validators into a single one, which is the definition of composition.

The new name "Composite" accurately reflects what this validator does:
it composes zero or more validators into a unified validation unit. This
aligns with the Composite design pattern terminology and avoids semantic
confusion with functional programming concepts.

The class has also been moved from the internal Core namespace to the
public Validators namespace. This change acknowledges that composing
validators dynamically is a legitimate use case for library consumers,
not just an internal implementation detail. The library itself uses this
pattern in Attributes and KeySet validators, demonstrating its practical
value.

The signature has been extended to accept zero or more validators:

- Zero validators: Returns AlwaysValid (useful for conditional chains)
- One validator: Pass-through without wrapping (avoids unnecessary nesting)
- Multiple validators: Combines using AllOf (all must pass)

This flexibility is particularly useful when building validation chains
dynamically, where the number of validators may vary at runtime based on
configuration or user input.

Apart from that, we consolidaded the `LogicalComposite` as a composite
that would accept at least two validators. The shifted the logic from
`AllOf` to the `Composite`, and made the `LogicalComposite` extends the
`Composite`, so other classes can leverage the same logic.

Co-authored-by: Alexandre Gomes Gaigalas <alganet@gmail.com>
Assisted-by: Claude Code (Claude Opus 4.5)
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.

2 participants