Skip to content

refactor(view): align ViewInterface bindings with Marko's simple-binding preference#90

Merged
markshust merged 1 commit into
developfrom
feature/view-bindings-cleanup
May 27, 2026
Merged

refactor(view): align ViewInterface bindings with Marko's simple-binding preference#90
markshust merged 1 commit into
developfrom
feature/view-bindings-cleanup

Conversation

@markshust
Copy link
Copy Markdown
Collaborator

@markshust markshust commented May 27, 2026

Summary

The view-latte and view-twig module.php files wrapped ViewInterface in a closure that manually built LatteView / TwigView. The closure existed for a real reason — the engine (Latte\Engine / Twig\Environment) needs LatteEngineFactory::create() (a method call, not direct autowiring). But the closure was at the wrong level: LatteView and TwigView both have fully-autowirable constructors (only type-hinted interfaces/classes).

Per Marko's binding guidance in architecture.md:

Prefer simple bindings. Only use closures when autowiring can't express what you need. If a class takes only type-hinted interfaces/classes as constructor params, it's autowirable — no closure needed.

The closure should sit on the dependency that genuinely needs the factory method, not bubble up to the parent.

Before

return [
    'bindings' => [
        ViewInterface::class => function (ContainerInterface \$container): ViewInterface {
            \$engine = \$container->get(LatteEngineFactory::class)->create();
            \$resolver = \$container->get(TemplateResolverInterface::class);
            return new LatteView(\$engine, \$resolver);
        },
    ],
];

After

return [
    'bindings' => [
        ViewInterface::class => LatteView::class,
        Engine::class => function (ContainerInterface \$container): Engine {
            return \$container->get(LatteEngineFactory::class)->create();
        },
    ],
];
  • ViewInterface binding becomes a simple class mapping (autowired)
  • The closure is scoped to Latte\Engine (or Twig\Environment for view-twig) — the actual service that needs custom build logic
  • LatteView's autowired constructor receives the engine (from closure) and resolver (autowired); the setLoader() side effect still runs in the constructor

Same restructure applied to both view-latte/module.php and view-twig/module.php to keep them symmetric.

Why this matters

Future copy-paste from view's module.php propagates the correct pattern. View is one of the most-likely-to-be-cargo-culted module configurations in the framework, so getting its shape right matters beyond just these two packages.

Test plan

  • packages/view-latte/tests/ — 29 tests pass (ModuleTest updated to verify new shape)
  • packages/view-twig/tests/ — 48 tests pass (ModuleTest updated)
  • packages/view/tests/ — 43 tests pass (no changes here, regression check)

🤖 Generated with Claude Code

…nding

ViewInterface binding was a closure that built the view manually. The
closure existed because the engine needs LatteEngineFactory::create()
(method call, not autowire). But the closure was at the wrong level —
LatteView and TwigView have fully-autowirable constructors.

Per Marko's binding guidance ("Prefer simple bindings. Only use closures
when autowiring can't express what you need"), the closure should sit on
the dependency that genuinely needs the method call (Latte\Engine /
Twig\Environment), not bubble up to the parent.

After this change:
- ViewInterface => LatteView::class (simple binding, autowired)
- Latte\Engine::class => closure calling LatteEngineFactory::create()
- ViewInterface => TwigView::class (simple binding, autowired)
- Twig\Environment::class => closure calling TwigEngineFactory::create()

Module tests updated to verify the new binding shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the refactor Code refactoring with no behavior change label May 27, 2026
@markshust markshust merged commit e0c479b into develop May 27, 2026
2 checks passed
@markshust markshust deleted the feature/view-bindings-cleanup branch May 27, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Code refactoring with no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant