Skip to content

feat: (W-005) Interface-driven design contracts for Wheels 4.0#2014

Open
bpamiri wants to merge 5 commits intodevelopfrom
grove/W-005-wheels-4-0-interface-driven-design-contr
Open

feat: (W-005) Interface-driven design contracts for Wheels 4.0#2014
bpamiri wants to merge 5 commits intodevelopfrom
grove/W-005-wheels-4-0-interface-driven-design-contr

Conversation

@bpamiri
Copy link
Copy Markdown
Collaborator

@bpamiri bpamiri commented Apr 3, 2026

Summary

Defines interfaces for all core subsystems, enabling drop-in replacements as part of the Wheels 4.0 architecture (#1967, epic #1917).

  • 22 interface CFCs across 7 subsystem groups: model (6), controller (3), view (3), routing (2), database (2), DI (1), events (1), plus 4 cross-cutting interfaces
  • ISP-compliant decomposition — each interface covers a single responsibility facet
  • Compile-time enforcement on Injector.cfc and EventMethods.cfc via implements=
  • Runtime reflection tests for 16 mixin-based interfaces (Model, Controller, View, Mapper patterns)
  • DI container bindings in Bindings.cfc for all 16 mixin interfaces
  • 43+ contract compliance tests in 9 spec files

Interface Groups

Group Interfaces Enforcement
Model Association, Callback, Finder, Persistence, Property, Validation Runtime reflection
Controller Filter, Flash, Rendering Runtime reflection
View Content, Form, Link Runtime reflection
Routing RouteMapper, RouteResolver Runtime reflection
Database ModelAdapter, MigratorAdapter Runtime reflection
DI Injector Compile-time (implements=)
Events EventHandler Compile-time (implements=)
Cross-cutting Middleware, ServiceProvider, Authenticator, AuthStrategy Compile-time

Quality Process

  • Adversarial review of initial plan — rejected with 6 critical issues, revised
  • Second adversarial review after implementation — found 11 mechanical signature errors, all fixed
  • Verified on Lucee 6, Lucee 7, and Adobe 2025 with 0 failures

Known Follow-up Items

Coverage gaps that should be tracked as separate issues:

  1. ModelPropertyInterface covers ~8 of ~45 public methods
  2. No interface for calculation methods (average, maximum, minimum, sum)
  3. ViewFormInterface missing ~50% of tag helpers (*Tag variants)
  4. No interface for asset/text view helpers
  5. Controller missing verifies, provides, SSE, request predicates

Test plan

  • All 22 interfaces compile on all CFML engines
  • Compile-time enforcement verified on Injector and EventMethods
  • Method existence and parameter name verification for all subsystems
  • DI container bindings resolve correctly for all 16 interfaces
  • Full test suite passes on Lucee 6 (2278 pass), Lucee 7 (2278 pass), Adobe 2025 (2287 pass)

Closes #1967

🤖 Generated with Claude Code

bpamiri and others added 4 commits April 3, 2026 09:13
Define 18 CFML interfaces covering Model, Controller, View, Routing, Events,
Database, and DI subsystems. Add 4 re-export wrappers for existing interfaces
(MiddlewareInterface, ServiceProviderInterface, AuthenticatorInterface,
AuthStrategy) to provide a unified catalog at vendor/wheels/interfaces/.

- Add implements= to Injector.cfc (InjectorInterface) and EventMethods.cfc
  (EventHandlerInterface) for compile-time enforcement
- Register 16 interface→implementation bindings in Bindings.cfc
- All method signatures verified against actual source code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 9 test spec files verifying:
- All 22 interface CFCs compile cleanly on all engines
- Re-export wrappers extend their original interfaces
- Compile-time implements= enforcement on Injector and EventMethods
- Method existence and parameter signature verification for Model,
  Controller, View, Routing, Event, Database, and DI contracts
- DI binding resolution for all 16 registered interface mappings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…compliance

- EventHandlerInterface: remove explicit types from parameters to match
  implementation (CFML implements= requires exact type matching)
- ModelPersistenceInterface: remove allowExplicitTimestamps from save()
  (not present in actual implementation)
- RouteResolverInterface: remove $findMatchingRoute (lives on Dispatch,
  not Mapper which is the binding target)
- DatabaseInterfaceSpec: fix H2 adapter component paths (H2.H2Model)
- InterfaceCompilationSpec: handle cross-engine metadata differences for
  interface extends
- InjectorInterfaceSpec: create fresh Injector instance instead of relying
  on application.wheelsdi (reset during test lifecycle)
- Bindings.cfc: fix comment with correct adapter path

Verified: Lucee 6 + Lucee 7, H2, 2319 pass / 0 fail / 0 error

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tations

Fixes all signature mismatches identified in adversarial review:
- ModelFinderInterface: count param boolean→numeric, useIndex string→struct,
  count() return numeric→any with added group param
- ModelPropertyInterface: tableName() remove phantom param, table() required any,
  primaryKeys() add position param, add primaryKey() method
- ModelPersistenceInterface: useIndex string→struct in 4 methods
- ControllerFlashInterface: flashDelete void→any, key required
- ControllerRenderingInterface: renderNothing/renderText status types
- ViewContentInterface: contentFor position/overwrite string/boolean→any
- ViewLinkInterface: paginationLinks add 5 missing params, encode boolean→any

Tests updated with param checks for count() and paginationLinks().
Verified: 2321 pass, 0 fail, 0 error on Lucee 6 + Lucee 7.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ams, new interfaces

Fixes 2 blocking issues and adds 3 non-blocking improvements from adversarial review:

Blocking:
- Fix ModelPersistenceInterface binding: wheels.model.crud → wheels.model.create
- Fix ViewContentInterface binding: wheels.view.content → wheels.view.miscellaneous
- Add back, method, url params to ControllerRenderingInterface.redirectTo (14→17 params)

Non-blocking:
- New ModelErrorInterface (8 methods: addError, hasErrors, allErrors, etc.)
- Add average/maximum/minimum/sum to ModelFinderInterface
- Add scope/enum to ModelPropertyInterface

Tests: getInstance() resolution test catches broken bindings at test time.
Verified: Lucee 6 + Lucee 7, H2 — 2334 pass, 0 fail, 0 error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wheels 4.0: Interface-driven design contracts Issue #1967

1 participant