As per recent discussions on Twitter, we are back to 2012, when I was still trying to build interceptor proxies with the __call() magic method approach. Evidently, people never learn that this approach isn't safe, and while it seems to save you time, it actually makes things harder to understand and debug when incompatible method calls happen.
An article could be needed, where following concepts are cleared up:
- In an object oriented world, each object just has a
public receive(Call $command) : Response; method, and only that method
- Type safety is ensured by either compile- or runtime-checking of the
$command and Response
- Type-safety is really orthogonal to the OOP design, as well as optional. It is an anti-corruption layer for our commands and responses
- It is possible to write generic middle-man objects, but duplicating the type checking efforts makes for easier to understand error messages both at compile and runtime
- Duplicating the checking can be done via type inference or by adding some trickery upfront
- Show how
Gorilla#eat(Banana $banana) : bool; is Gorilla#receive(EatBanana $command) : StillHungry;, which can be wrapped with a generic LogAround#receive(Command $command) : Result
- Show unsafe operations in the above
- Re-convert the above to traditional PHP object signatures with methods
- Show the possible failures also there
- "Type check escapes" lead to unknown message types reaching the recipient, which now has to deal with them (additional work) or crash or do unexpected operations (security issue)
- Show that it is possible to build a minimalist wrapper that builds a type-safe logger around a
Gorilla
- Show failures with the safer approach, show introspection failures too (maybe reflection?)
- Conclusion:
__call could work, but is not an anti-corruption layer due to its generic signature
- 99% of users will always benefit from proactive anti-corruption layers via AOT- or runtime- type checks
As per recent discussions on Twitter, we are back to 2012, when I was still trying to build interceptor proxies with the
__call()magic method approach. Evidently, people never learn that this approach isn't safe, and while it seems to save you time, it actually makes things harder to understand and debug when incompatible method calls happen.An article could be needed, where following concepts are cleared up:
public receive(Call $command) : Response;method, and only that method$commandandResponseGorilla#eat(Banana $banana) : bool;isGorilla#receive(EatBanana $command) : StillHungry;, which can be wrapped with a genericLogAround#receive(Command $command) : ResultGorilla__callcould work, but is not an anti-corruption layer due to its generic signature