Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126496 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 8A9371A00BC for ; Mon, 24 Feb 2025 14:29:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1740407225; bh=9VbR/FEXBGon1G9mrKfOHJAlD4HixgOMzIDuWispo3s=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=UgJqGadSlw0LQsNwIZPac3V5fMOzrji6/KZs34Lr+CmEbPsQBrflJwckCcFuUul98 IJobByHLu82RC9dZnqY91nd9LTS7piiFt5UUulKQzc/cdKgmx2E0zqssBqfEythr0A xa2/mVLkVl5zBzAAQCPrshiteeQNSdlBwjaWIfQqvbmHGKs1Cxx18wOlYXAGPTIP8w PPR/qHnyDgWwJjRMajKZlXwgG9Hce0GS936kyCo/k01fE/L/blOjFxtKQIq+vkejh3 7E+CvsBGvjfZvTSLPJgaAtfGZ1JgTDfDCLvFLUB+H8pf/c6y0uF/uyomRcJiaNJ4OV qsYZo96BrlEog== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 47D09180086 for ; Mon, 24 Feb 2025 14:27:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=BAYES_40,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, FREEMAIL_REPLY,HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2, SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-lf1-f54.google.com (mail-lf1-f54.google.com [209.85.167.54]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 24 Feb 2025 14:27:03 +0000 (UTC) Received: by mail-lf1-f54.google.com with SMTP id 2adb3069b0e04-5452ed5b5b2so4487210e87.0 for ; Mon, 24 Feb 2025 06:29:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1740407381; x=1741012181; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=XCayOPw5rH5KbkmnQ/0LMstdRiVP2Uwsf1g/O84xXiM=; b=E4a0CWDPYaLzcLYuJ1ZpfsPiTt7AAVxB1TW+d5a6FxZbe1ME56R0nobgMA649mREae pdPbgz506wpiOqhT/FFgJUQI2hyBLuG6uBeszPqmz65x0UnV9ycVUQw0Fz2LaEacfYrG ExwEkHNI0B58Yt6LNc42YAvZrl3yyqVk3eWw+jphBOaxDL5GsR4y+aqv0Y5A3lamQXIM LpBlcFh6nvWsC2m7jwCpn/nqwRP4LCNQxOOXyR9F/wmO0LtkNw1NNKIZiOXed34ZDfdn rTyeeJGYTpyeoiaRCZkaNYhXXtgD4b9c5mnY5o6vpYNeyNd4ywZR8wnvVGTjS2KHmLE3 oUmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740407381; x=1741012181; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=XCayOPw5rH5KbkmnQ/0LMstdRiVP2Uwsf1g/O84xXiM=; b=C8/v+pmtwnpcL+zdUqz32g7wCVeoP6Xy43SKum6n6hXwI6r/4AAwra4r382Y8N2MYA qV/jealJ9ZJfXv+Lw/BXsKlyZnZcdtfU6GRjpk5LxbRNxu3voaXzGq5tqkegQnNvwLoP nT82ZDahcDyhblU7b+DNYa0f7iGzhdaZ8JnSnP7MH1454W37/wyw7sUWRNIoaxE2xUSW Gq184chYsNcbfoBbeM1L5V9d6ygpNqQKxCDRQI7I/AYLFuYHdXOdWLcUsQOW7nQD0Ikv XjGTkx/85qZvDBg5ntqZYzSKnq6UXaDpRHSbUrIuElvZdmJUJ6SNamgTQP+9AZ6xmdAk Nxsw== X-Gm-Message-State: AOJu0YzBtSXBu+QmCBsjL+eWtlYNXeeg3GhcGJBtn/y33cDc+yXcsnLY E1zYcm1nP1fqn2dOsdJcT07sI1fPREMmQGVoNf0OI4k+2WSY8MmBCdydixWKIt2r1kUtnYz466A KOPJbdYju+Z65Id/5ru/qOLcYS12lP1kczlQ= X-Gm-Gg: ASbGncvlMUd8SxrGd0e6CEG/BWWfTN9gdMxwvnt5vnuHw+AbWdLEimuC6RWNmBytZ/G oEdmeU336ZMUQCmW7G/EpAsSE5LwXUqcPaMrdZ8lYI1XROwRCZDyvwaPYpZ4uHccx2613rmxMBu ZeSahilw== X-Google-Smtp-Source: AGHT+IHSQUU4DT8i/u5ZhlO/m3JP2gycGCnwvzMDOzUIqMSUepnoJ+VOaZJaV5ImY7h46Xtxvqgxacw/F49dk22oTXA= X-Received: by 2002:a05:6512:b8c:b0:545:22fe:616f with SMTP id 2adb3069b0e04-54838ef7278mr5857392e87.24.1740407380944; Mon, 24 Feb 2025 06:29:40 -0800 (PST) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: <1BCB4144-231D-45EA-A914-98EE8F0F503A@automattic.com> <8E614C9C-BA85-45D8-9A4E-A30D69981C5D@automattic.com> <9bf11a89-39d9-457b-b0ea-789fd07d7370@gmail.com> In-Reply-To: Date: Mon, 24 Feb 2025 15:29:28 +0100 X-Gm-Features: AWEUYZl9kaEH3L0ArtF-VMIadCiOUvkS-0DyhL-VJOELeKVBQxGkBxcLbZc6l8I Message-ID: Subject: Re: [PHP-DEV] [RFC] [Discussion] Add WHATWG compliant URL parsing API To: "Gina P. Banyard" Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary="000000000000b4b334062ee42b3a" From: nicolas.grekas+php@gmail.com (Nicolas Grekas) --000000000000b4b334062ee42b3a Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Le lun. 24 f=C3=A9vr. 2025 =C3=A0 14:57, Gina P. Banyard a =C3=A9crit : > On Monday, 24 February 2025 at 11:08, Nicolas Grekas < > nicolas.grekas+php@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 th= e > 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 maki= ng > the type non-final, we keep things open enough for userland to build on i= t. > 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 upo= n > 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 m= y > 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=E2=80=93closed principle (OCP) s= tates > "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. > Yes. You can strike decoration with a non-final class (and no base interface), that's my point. > 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 rejec= t > 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. > A couple of non-final Url classes would still be absolutely useful: e.g. as a consumer/callee, I would have stated very clearly that I need an object that behaves like native Url objects. Then, if the implementation doesn't, that's on the caller. The abstraction would do its job. I don't think the extra guarantees you're describing would be useful in practice (but you could still do an exact ::class comparison if you'd really want to). > It also seems you did not read the relevant "Why a common URI interface > is not supported?" [2] section of the RFC. > This sentence comes to me as unnecessarily confrontational. I=E2=80=99d rea= lly like to keep this discussion as constructive as possible so that php-internal remains a welcoming space for everyone. > The major reason why this RFC has had so many iterations and been in > discussion for so long is because M=C3=A1t=C3=A9 tried, again and again, = to have a > common interface. > But this just does not make any sense, you cannot make something extremel= y > concrete vague and abstract, unless you want to lose all the benefits of > the abstraction. > I was considering the alternative of providing TWO interfaces indeed. Sorry if that wasn't clear enough. Nicolas --000000000000b4b334062ee42b3a Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


Le=C2=A0lun. 24= f=C3=A9vr. 2025 =C3=A0=C2=A014:57, Gina P. Banyard <internals@gpb.moe&g= t; a =C3=A9crit=C2=A0:
On Monday, 24 February 2025 at 11:08, Nicolas Grekas <nicolas.greka= s+php@gmail.com> wrote:
I'm seeing a push to make the classes final. Pl= ease don't!
This would badly break the o= pen/closed principle to me.

When shipping a new class, one ships two things: a beha= vior and a type. The behavior is what some want to close by making the clas= s 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 im= plementation - the internal one.

<= div class=3D"gmail_attr">The situation I'm telling about is when one wi= ll accept an argument described as
function = (\Uri\WhatWg\Url $url)

If the Url class is final, this signature means only one po= ssible implementation can ever be passed: the native one. Composition canno= t be achieve because there's no type to compose.

Fine-tuning the behavior provi= ded by the RFC is what we might be most interested in, but we should not fo= rget 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 im= plementation, 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, th= ere 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 pu= lling in the Wikipedia definition: [1]

In o= bject-oriented programming, the open=E2=80=93closed 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 d= ecorator or the delegation pattern.
Yes.
You can strike decoration with a non-final class= (and no base interface), that's my point.

=C2= =A0
But most importantly, I would like to focus on the "clos= ed for modification" part of the principle.
Unless we make *all* the methods final, inheritance allows you t= o modify the behaviour of the methods, which is in *opposition* to the prin= ciple.

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

Quoting Dijkstra:
=
The purpose of abstracting is not to be vague, but to cr= eate a new semantic level in which one can be absolutely precise.

A concrete WhatWg\Uri type is abst= racting over a raw string.
And it creates a new semantic level where when you are in possession of s= uch 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.
T= his 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 method= s.
I.e. you are now vague, and any consumer of the type needs to do validati= on because it ***cannot*** trust the type, and you have created a useless a= bstraction.

A couple of non-final Url classes would still be absolutely useful: e.g. = as a consumer/callee, I would have stated very clearly that I=C2=A0need an = object that behaves like native Url objects. Then, if the implementation do= esn't, that's on the caller. The abstraction would do its job. I do= n't think the extra guarantees you're describing would be useful in= practice=C2=A0(but you could still do an exact ::class comparison if you&#= 39;d really want to).

=C2=A0
It also seems you did not r= ead the relevant "Why a common URI interface is not support= ed?" [2] section of the RFC.

This sentence comes to me as unnecessarily confrontati= onal. I=E2=80=99d really like to keep this discussion as constructive as po= ssible so that php-internal remains a welcoming space for everyone.
=C2=A0
= The major reason why this RFC has had so many iteration= s and been in discussion for so long is because = M=C3=A1t=C3=A9 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.

I was considering the altern= ative of providing TWO interfaces indeed. Sorry if that wasn't clear en= ough.

Nicolas


<= /div> --000000000000b4b334062ee42b3a--