Status: Accepted Date: 2026-02-28 Authors: Walmir Silva walmir.silva@kariricode.org
The initial design had AttributeScanner extends FileScanner, with FileScanner exposing three protected methods (parseFile, extractAttribute, collectPhpFiles) forming an implicit extension API.
Code review (2026-02-28) identified three problems:
- Fragile base class: Any change to
FileScanner's protected methods could breakAttributeScannersilently. - No-op override:
AttributeScanner::parseFile()read the file twice (once for astr_contains('#[')check, once viaparent::parseFile()) and both branches executed identical code — the "early-exit optimization" was dead code. - Prevents sealing:
FileScannercould not befinal, leaving its internals exposed.
DirectoryScanner already used composition (delegating to FileScanner), making the inheritance in AttributeScanner inconsistent.
Refactor AttributeScanner to compose FileScanner (same pattern as DirectoryScanner). Make FileScanner final with all methods private.
Before:
FileScanner (class, 3 protected methods)
└── AttributeScanner (extends)
DirectoryScanner (composes FileScanner)
ReflectionScanner (composes FileScanner)
After:
FileScanner (final class, all private)
├── AttributeScanner (composes)
├── DirectoryScanner (composes)
└── ReflectionScanner (composes)
Positive:
FileScannerisfinal— no unintended subclassing- All internal methods are
private— no implicit extension API - Eliminates the double file read (BUG-006)
- Consistent composition pattern across all scanner variants
- Each scanner variant can evolve independently
Negative:
AttributeScannercannot overrideparseFilefor future token-level optimizations- Slight indirection:
AttributeScanner.scan()delegates toFileScanner.scan()
Mitigations:
- Token-level optimizations can be added to
FileScanneritself (configurable via constructor flags) - Delegation overhead is negligible (one method call per scan)
- Gamma, E. et al. (1994). Design Patterns, Ch. 1 — "Favor object composition over class inheritance."
- Bloch, J. (2018). Effective Java, 3rd ed., Item 18 — Favor composition over inheritance.