On 28 June 2026 09:49:51 BST, Alexander Egorov <[email protected]> wrote:

>In my vision, the primary use of containers would be through supplying
>proper autoloaders for them. In this case, all code inside the container
>and which relies by default on autoloading (which is the majority of cases)
>will load all classes in a way we expect with corresponding tags. And so we
>would be able to easily match all classes.

OK, then your vision is fundamentally different from mine. I don't want the 
container to know *anything* about how the code inside it works. 

Remember that autoloading is something that any library can implement its own 
version of. There are autoloaders which fetch from PHAR files, autoloaders 
which generate code on demand, and so on. 

Version tags break the abstraction of the container, and I don't think they 
solve a real problem.



>Your case differs from that because, as I understand it, it loads classes
>manually depending on the conditions.


No, just that the container configuration doesn't know anything about 
"packages" or "versions". You run 'require "$someDir/vendor/autoload.php";' 
inside the container as normal. Or maybe you don't, and you just list a big 
bunch of includes for some reason. The container doesn't care.

As a human author, you maybe know what versions of packages are in your 
container - depending how tightly you've configured them - but you have no idea 
what someone *else* might include in their container. 

If you include version 2.11 of Monolog and version 2.0 of psr/log, but some 
other container includes version 2.11 of Monolog and version 3.0 of psr/log, 
those objects aren't interchangeable. If you treat them as though they are, 
something is going to blow up in your face.



>$client2 = $container->run(fn() => new \Google\Client);
>$logger2 = $client2->getLogger();
>
>match (true) {
>    $logger2 instanceof Logger => ...., // here I mean less formal instanceof
>    $logger2 instanceof LoggerV1 => ...,
>    $logger2 instanceof LoggerV2 => ...,
>}


I think you're still missing the point - if I pass around $client2, and it 
passes checks for "instanceof Google\Client", I can pass it to functions which 
have no idea it came from a different container. They will have no idea that it 
might return an object from getLogger() which doesn't pass a check for 
"instanceof Logger".



>In my vision, "tag" does not really identify the container. It is whatever
>we wish semantically. For example, let's say we're using Monolog\Logger 2.0
>as our "default" logger. But we also use another library which is designed
>for 1.0. And for us that Logger from version 1.0 would be identified as
>("1.0", Logger) according to the semantics we've chosen and which is
>reflected in our autoloader.


I think the only way for two containers to agree that a class is the same, is 
if they both start with that class name already defined, so it points to the 
same class entry in memory.

Otherwise, containers can completely break each other by using the same tags 
for different definitions.


>But speaking about the example you provided with google
>client, it is a good example why such "polymorphic" libraries themselves
>would benefit from such class-versioning and containerization and would
>themselves want to switch to it to get rid of all that compatibility
>shenanigans.

On the contrary, the entire point of packages like psr/log is to define objects 
which can be passed around from one package to another. By advertising that it 
can be installed with multiple versions of something, a library is giving 
applications freedom to resolve a set of versions which works for them.

That's exactly why I've been arguing for a distinction between "modules" and 
"containers", and saying that the vast majority of current code would not 
benefit from containers at all.


Rowan Tommins
[IMSoP]

Reply via email to