Repository navigation
feat(types)!: preserve immutable types under explicit contracts - #47
Conversation
Rename existing concrete spatial classes with the Immutable suffix and make them final. Separate read, immutable copy and mutable metadata interfaces, and reject mutable aggregate descendants without conversion. BREAKING CHANGE: Former concrete spatial class names are removed without aliases. Copy operations now belong to ImmutableSpatialInterface and immutable type contracts; factories return immutable contracts. Refs #39
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #47 +/- ##
============================================
+ Coverage 99.40% 99.48% +0.07%
- Complexity 703 719 +16
============================================
Files 132 134 +2
Lines 1525 1557 +32
============================================
+ Hits 1516 1549 +33
+ Misses 9 8 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Alexandre-T
left a comment
There was a problem hiding this comment.
READY FOR MERGE
Independent agent review of Story #39 / Epic #38 at commit a7ab9bc1d791dea47562153c83c3f7611e987f0a.
No blocking findings or unresolved gates remain. The public naming and breaking changes are explicitly required by #38/#39: all 84 existing concrete spatial classes are final and use the Immutable suffix without former-name aliases. Common interfaces expose reads, immutable interfaces expose copy operations and immutable component contracts, and mutable interfaces establish the metadata mutation contracts for the subsequent Stories. The neutral base does not expose variant-specific copy/mutation methods.
Reviewed aggregate admission, nested ownership checks, replacement/copy paths, factory contracts, dimensional layouts, both families, EMPTY values and the partially null ordinate regressions from #36. No automatic geometric validation, coordinate transformation or dimension conversion is introduced. Auxiliary Coordinates and SpatialReference remain immutable with their existing names. Documentation corrections identified during review have been verified, including retaining the JSON type label Triangle.
Independent validation:
composer test-local: 690 tests, 6,627 assertions, successful; 99.55% line coverage.composer quality: successful (PHP CS Fixer, PHPStan level 9, PHPMD, PHP_CodeSniffer). PDepend emits dependency deprecation notices under local PHP 8.5; the command exits 0.composer validate --strictandgit diff d0d711d..HEAD --check: successful.- Latest-commit CI: PHP 8.4, PHP 8.5 and GitGuardian successful.
The applicable pre-merge Definition of Done is satisfied. This independent agent verdict is recorded as a review comment because the connected GitHub identity is also the PR author. Human merge authority remains with Alexandre; the PR has not been merged and Story #39 is not declared Done.
Pull Request
Closes #39. Implements the first Story of Epic #38, after merged dependency #36.
Summary
Existing concrete spatial classes now use an
Immutablesuffix and are final, preserving constructor, accessor, copy and partially null ordinate behavior. For example,Dimension2\Geometry\PointbecomesDimension2\Geometry\PointImmutable; former names are removed without aliases.Common spatial/type interfaces expose read operations only. The new
ImmutableSpatialInterfaceand immutable type contracts own copy methods and immutable component return types.MutableSpatialInterfacedeclares chainable family, reference and SRID setters; mutable type contracts reserve the subsequent Stories' editing APIs. The sharedAbstractSpatialTypeexposes no copy or mutation operations; immutable implementation bases contain copy/hydration behavior.Immutable aggregates reject mutable components and nested mutable descendants without conversion. Indexed coordinate arrays continue to create immutable descendants. Factories and repository documentation use the renamed classes and immutable return contracts. Coordinates and SpatialReference retain their existing immutable names.
Acceptance criteria
with…methods or dimension setter.Validation
composer test-local— 690 tests, 6,627 assertions, successful; line coverage 99.55%.composer quality— PHP CS Fixer, PHPStan level 9, PHPMD and PHP_CodeSniffer successful.composer validate --strictandgit diff --checksuccessful.ImmutableComponentContractTestandSpatialVariantContractTest; existing regressions now use renamed immutable classes.Local validation used PHP 8.5.11 with PCOV. PDepend emitted dependency deprecation notices under PHP 8.5; the quality command exited successfully. Required PHP 8.4/8.5 CI and independent review are now complete on the final revision.
Standards
The change concerns the PHP representation/ownership contracts approved by #38/#39, not a new interpretation of ISO/IEC 13249-3 or OGC requirements. No automatic validation, repair, dimension conversion or coordinate transformation is added.
Architecture and compatibility
Breaking changes: every former concrete spatial name is removed without aliases/deprecation; concrete immutable classes are final;
with…methods move from common interfaces to immutable interfaces; factories expose immutable return/component contracts. Consumers must update imports and type copy-capable variables against immutable contracts. Internal abstract implementation bases are renamed to make their immutable responsibilities explicit.Concrete mutable classes and detailed type-specific setters are intentionally delivered by #40–#45; selectable factory variants belong to #46. Immutable family/dimension namespaces remain fixed, and declared-reference copy operations never recalculate ordinates.
Documentation
Developer handoff
Final revision:
a7ab9bc1d791dea47562153c83c3f7611e987f0a.Independent Reviewer verdict: READY FOR MERGE, after verifying acceptance criteria, implementation, documentation corrections, tests and quality. Independent validation reproduced 690 tests, 6,627 assertions and 99.55% line coverage, with all quality checks successful.
Final CI run: PHP 8.4 successful (1m0s), PHP 8.5 successful (16s), GitGuardian successful (1s).
No blocking finding or unresolved Gate remains. The PR remains open and unmerged; Story #39 remains In review and is not declared Done. Merge requires Alexandre's decision.