Re: [RFC] [Discussion] Add WHATWG compliant URL parsing API

From: Date: Mon, 24 Feb 2025 13:57:55 +0000
Subject: Re: [RFC] [Discussion] Add WHATWG compliant URL parsing API
References: 1 2 3 4 5 6 7 8 9  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message
On Monday, 24 February 2025 at 11:08, Nicolas Grekas <[email protected]> wrote:

> I'm seeing a push to make the classes final. Please don't!
> This would badly break the open/closed principle to me.
>
> When shipping a new class, one ships two things: a behavior and a type. The behavior is what
> some want to close by making the class final. But the result is that the type will also be final.
> And this would lead to a situation where people tighly couple their code to one single
> implementation - the internal one.
>
> The situation I'm telling about is when one will accept an argument described as
> function (\Uri\WhatWg\Url $url)
>
> If the Url class is final, this signature means only one possible implementation can ever be
> passed: the native one. Composition cannot be achieve because there's no type to compose.
>
> Fine-tuning the behavior provided by the RFC is what we might be most interested in, but we
> should not forget that we also ship a type. By making the type non-final, we keep things open enough
> for userland to build on it. If not, we're going to end up with a fragmented community: some
> will tightly couple to the native Url implementation, some others will define a UriInterface of
> their own and will compose it with the native implementation, all these with non-interoperable base
> types of course, because interop is hard.
>
> By making the classes non-final, there will be one base type to build upon for userland.
> (the alternative would be to define native UrlInterface, but that'd increase complexity
> for little to no gain IMHO - althought that'd solve my main concern).

The open/closed principle does not mean "open to inheritance".
Just pulling in the Wikipedia definition: [1]

> In object-oriented programming, the open–closed principle (OCP) states "software
> entities (classes, modules, functions, etc.) should be open for extension, but closed for
> modification";

You can extend a class by using a decorator or the delegation pattern.
But most importantly, I would like to focus on the "closed for modification" part of the
principle.
Unless we make *all* the methods final, inheritance allows you to modify the behaviour of the
methods, which is in *opposition* to the principle.

Moreover, if you extend a WhatWg\Uri to behave differently to the WhatWg spec, then you do *not*
have a WhatWg URI.
Which means the type becomes meaningless.

Quoting Dijkstra:

> The purpose of abstracting is not to be vague, but to create a new semantic level in which one
> can be absolutely precise.

A concrete WhatWg\Uri type is abstracting over a raw string.
And it creates a new semantic level where when you are in possession of such a type,

you _know_ with *absolute* certainty how it behaves and what you can do with it, and know that if a
consumer needs a WhatWg URI it will not reject it.
This also means consumers of said WhatWg\Uri type do not need to care about validation of it.

If one is able to extend a WhatWg URI, then none of the above applies, and you just have a raw
string with fancy methods.

I.e. you are now vague, and any consumer of the type needs to do validation because it ***cannot***
trust the type, and you have created a useless abstraction.

It also seems you did not read the relevant "Why a common URI interface is not supported?"
[2] section of the RFC.
The major reason why this RFC has had so many iterations and been in discussion for so long is
because Máté tried, again and again, to have a common interface.
But this just does not make any sense, you cannot make something extremely concrete vague and
abstract, unless you want to lose all the benefits of the abstraction.

Best regards,
Gina P. Banyard

[1] https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle
[2] https://wiki.php.net/rfc/url_parsing_api#why_a_common_uri_interface_is_not_supported


Thread (152 messages)

« previous php.internals (#126493) next »