What's wrong with declaring all the methods as final eg. https://github.com/lnear-dev/ada-url/blob/main/ada_url.stub.php
On Mon, Feb 24, 2025, 7:00 a.m. Gina P. Banyard <intern...@gpb.moe> wrote: > On Monday, 24 February 2025 at 11:08, Nicolas Grekas < > nicolas.grekas+...@gmail.com> 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 >