On 20 May 2025 15:04:49 BST, Michael Morris <tendo...@gmail.com> wrote:
>The Problem: Interoperability.
>
>That's really it.  Scenario
>Alice provides whatchamacallit A that depends on other whatchamacallit D to
>work.
>Bob provides whatchamacallit B that also depends on D.
>Charles is using A and B.
>D gets updated with a new incompatible API to its prior version.
>Alice publishes an update which includes a security fix.
>Bob retired.
>Charles, who can't program, can't update to Alice's latest code. His site
>eventually gets pwned.

Let me correct something here. The whole reason I was bringing in the 
distinction between "module" and "container" is that B and C are one kind of 
thing, but D is a *different* kind of thing. 

D is something like Guzzle. There is zero motivation for Guzzle to be rewritten 
in a way that forces its dependencies to be isolated. It depends on packages 
like "psr/http-client" whose *entire purpose* is to define interfaces that 
multiple packages agree on.

A, meanwhile, isn't a thing at all; it's just any old PHP code - in your 
example, the whole spaghetti of WordPress core.

B and C are the only "whatchamacallits" - they are, in your example, WordPress 
plugins. They are the thing you want a boundary around, the black box you want 
conflicting names to be hidden by.



>Suppose we have a whatchamacallit that declares its namespace as a new root
>independent of / .  If a file inclusion happens in this namespace, this
>namespace prepends everything in the included file. So if I do a file
>include in the \MyPlugin namespace and that file declares its namespace as
>Twig, it will become \MyPlugin\Twig.

What does it mean, exactly, for a file inclusion to "happen in a namespace"? 
Bear in mind, most of the files we want to load, whether explicitly or via an 
autoloader, are not requests from A (the WordPress plugin) directly to D 
(Guzzle); they are references between files inside D, or in further 
dependencies that A has no idea about at all.

What PHP needs to track, somehow, is that a whole bunch of code is "inside" 
something, or "coloured by" something, in a way that is completely recursive.



>That works, but direct file include is no longer the PHP norm though.
>Autoloading is. So we need to tell the Autoloader that we want a file path
>returned - do NOT require the file yourself in your namespace.

This for me is a non-starter:  the existing packages which you want to make use 
of have little or no motivation to adapt to this new system.

Again, think about Linux containers: applications don't get a message saying 
"you're running in a container, please use different file I/O conventions"; 
they *think* they are accessing the root filesystem, and the host *silently* 
rewrites the access to be somewhere in the middle of a larger tree.

I think the way it would need to work would be some global state inside the 
compiler, so that regardless of how the code ended up being loaded, an extra 
transform was included in the compilation pipeline to attempt to rewrite all 
definitions, and all references to those definitions.

(I say "attempt", because even with all this built into the compiler, PHP's 
highly dynamic nature means there would be code patterns that the rewriter 
would not see; the whole thing would come with a bunch of caveats.)


>The above I think would more or less work, but it would lead to massive
>code duplication as Whatchamacallit A and B now have their own D's at \A\D
>and \B\D (assuming namespaces match whatchamacallit names).

I don't think this is a problem that can or should be solved.

Imagine A and B both use the same version of E, but different versions of D; 
and E references D. If we try to de-duplicate, we load one copy of E, but when 
called from A it needs to reference \A\D and when called from B it needs to 
reference \B\D. Clearly, that's not going to work, so we're forced to define a 
separate \A\E and \B\E.

Note that this is completely different from any de-duplication of files on disk 
that a package manager might perform. It's a bit like the same C source file 
being compiled into two different object files with different #defines in 
effect.


I'm still not convinced that all this complexity actually leaves you better off 
than building a Composer plugin that automatically applies the rewriting to a 
whole directory at source code level.

Rowan Tommins
[IMSoP]

Reply via email to