arkitect
arkitect copied to clipboard
Add HaveMethod expression
Feature Request
| Q | A |
|---|---|
| New Feature | yes |
| RFC | no |
| BC Break | no |
Summary
I would like to enforce this constraint:
Rule::allClasses()
->that(new HaveNameMatching('App\*\Command\*Handler'))
->should(new HaveMethod('__invoke'))
->because('command handlers should be invokable');
ATM we don't have any mechanism to check stuff on class implementation, isn't it?
I think this is a useful addition. Would you elaborate a bit more about how is it supposed to work? In particular:
- should the class directly implement the method or it can also inherit it?
- should pattern matching work?
Regarding your questions:
- Class can implement or inherit the method.
- Patter matching could be useful, someone could enforce rules like "Repository should have findBy* methods"; even I dislike it, there are frameworks that work this way.
I am not sure we capture inherited methods in ClassDescription objects but we can probably discuss the implementation later
For consistency we should also have a NotHaveMethod
Good to go for me
At the moment we don't have a mechanism to check stuff on class implementation because we were focused on rules for dependencies. We can try to understand if now it's time to develop something to create rules for methods.
That's a good point with __invoke for command handlers, but isn't self validated at runtime? It sounds more of unit test territory than architect decision.
As for generic methods, shouldn't developer cover this with interfaces? Maybe only magic method expression?
Would love to see this feature coming!
One of my use case would be to check for "valid" method names on a controller. Valid according to this list of actions: https://laravel.com/docs/9.x/controllers#actions-handled-by-resource-controller
Example:
Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Http\Controllers'))
->should(new HaveMethod(['index', 'create', 'store', 'show'...]))
->because('something');