Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:121117 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 89790 invoked from network); 21 Sep 2023 18:02:00 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 21 Sep 2023 18:02:00 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C198018004A for ; Thu, 21 Sep 2023 11:01:59 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 21 Sep 2023 11:01:59 -0700 (PDT) Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-31ff985e292so1163457f8f.1 for ; Thu, 21 Sep 2023 11:01:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1695319318; x=1695924118; darn=lists.php.net; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=ObRuP7a44a+2GTMzMYMN5NWRlfjD5y1tEKjn/RkPykU=; b=IsmTATGYu7V6A0kTopV3T1MSlqlsML6+c4/UmucDUlt+c/RGJ3S9DO/oEg1sAChuZA fVd8AY2hg4b9/luLO/LEECCDgmREXMS+FrK2KY6tiJKoe/HVhkN7tPLaCiWLC4jpm+tM /KRDH7mpEv3eLhcO7cRrZQkwZwAx4B3uhqQDGts7vVh5cm9q77JdXb9kKw+EN/jETqlf tWCEQWleW2IzogxbUIFLbzOyDIEEq4FK1HNyPF+/c3/16zCNFmE2v9vTzeuMOqrbzcQe /0gdow8owS7B6Ziw7hVfeppoTp9o5LehUBeFhfZ2SgtCmC7ZMH/pVgKiwyOTDj1nUCg6 U4fQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695319318; x=1695924118; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ObRuP7a44a+2GTMzMYMN5NWRlfjD5y1tEKjn/RkPykU=; b=b5/YUQGFAdvvIzQp9RwgZo96TM3KueKWnOyHeZRcPYJ7pEIKKOno2YPkZnjBBl9+M8 lXpoB5d5PXdbk0VW161UqN8Uu2FmUmYsgGhNzoQZ9dd3S39t+4w+rLd1AgAS0DgyS95m yoBKIAdjOmTKLG5GVp3fbnMC/8ZpWP2pkdwnR2S+Bxq5kfqQ4Tk9uyaqUAmhm1VzQ/TP CH0XlT9EgtsB2OX57zlRLWwSXnk7gtRBACQHRJXttnkr/j6U7dzJIqEz+LCzRdGRevp6 B95OZK+CzIbaafgmo8eSduFR6MI2oyBlFwZsDDe3f3Ei3/6jB6k1Y/Xf4VwTUBOjQxwI XFGg== X-Gm-Message-State: AOJu0Yznog6xTzCtJbraXsJLprlZzBz8qPu1H4I3xuDUI1dFd3bbCE8h ZgIVvIjcexMgR05A7zK9eoStGMu7aSk= X-Google-Smtp-Source: AGHT+IGoiEXyhNmpig+crAfadmd0OrvwIjHakr4PyE8/0DtvLsbJdLoxHpZ9J8b48SYBYYh/jAqyDA== X-Received: by 2002:a5d:628b:0:b0:31f:fb02:4dcd with SMTP id k11-20020a5d628b000000b0031ffb024dcdmr5588083wru.4.1695319317446; Thu, 21 Sep 2023 11:01:57 -0700 (PDT) Received: from ?IPV6:2a02:1811:cc83:ee50:280e:1e36:3a00:824? (ptr-dtfv08akcem5xburtic.18120a2.ip6.access.telenet.be. [2a02:1811:cc83:ee50:280e:1e36:3a00:824]) by smtp.gmail.com with ESMTPSA id q26-20020a1709064c9a00b009ad87fd4e65sm1384476eju.108.2023.09.21.11.01.56 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 21 Sep 2023 11:01:57 -0700 (PDT) Message-ID: <4e59cb39-915e-4468-890d-00ae68ba93bb@gmail.com> Date: Thu, 21 Sep 2023 20:01:56 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: Stephen Reay Cc: PHP Internals References: <29eb53a7-9aef-4e48-999e-97574f27a9df@gmail.com> <4C6FD028-4E34-4578-AF04-EDAC120E3E94@koalephant.com> <872B9392-D91A-45BC-8956-3E53B16723A6@koalephant.com> <39d49239-c87c-2c95-c293-f2952b5e3307@bastelstu.be> <4F202884-AB40-49A2-BB5B-CF7915942E63@koalephant.com> In-Reply-To: <4F202884-AB40-49A2-BB5B-CF7915942E63@koalephant.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: Re: [PHP-DEV] [RFC] [Discussion] DOM HTML5 parsing and serialization support From: dossche.niels@gmail.com (Niels Dossche) Hi Stephen On 20/09/2023 12:02, Stephen Reay wrote: > > >> On 20 Sep 2023, at 03:03, Niels Dossche wrote: >> >> Hi Stephen >> >> On 19/09/2023 09:58, Stephen Reay wrote: >>> >>> >>>> On 19 Sep 2023, at 14:30, Tim Düsterhus wrote: >>>> >>>> Hi >>>> >>>> On 9/19/23 08:35, Stephen Reay wrote: >>>>> Regarding the private constructor: I understand the issue with the *old* class being confusing - but your new class doesn't have that issue, because there are no "loadXXX" methods: as you said, if you're loading an existing document, you're forced to do it via the static factory methods. With that change alone, there's zero risk of confusion in allowing direct constructor calls, because once the object is instantiated there is no subsequent way to load a document and inadvertently change the encoding. >>>>> Having a regular constructor and then one or more factory methods for specific cases is already a concept in PHP (i.e. DateTime[Immutable]'s  `createFromXXX` as well as a constructor), and IMO needing to call a factory method to get an "empty" document seems out of place in PHP - it seems a bit like a Java-ism - using a factory, where one just isn't required. >>>> >>>> I was one of the persons who discussed this updated API with Niels in private and looking up the discussion it was me who proposed making the constructor private and just providing named constructors. >>>> >>>> From the perspective of the user of the API, I like the symmetry between all the named constructors: >>>> >>>> Whenever I want to create a new document, I use one of the fromXyz() methods. And when I use those, I get exactly what it says on the tin. >>>> >>>> Making the regular constructor available for use would effectively make whatever that constructor does a special case / the default case. This makes sense for DateTimeImmutable, because the __construct() variant is likely much more often used than the various createFromXyz() variants. For the HtmlDocument I find it less obvious that creating an empty document would be the default case compared to loading an existing document from a file. >>>> >>>> We should probably rename the named constructors to include the "create" prefix for consistency with DTI though. >>>> >>>> Best regards >>>> Tim Düsterhus >>>> >>> >>> Hi Tim, >>> >>> >>> Thanks for providing context on where this idea came from. >>> >>> >>> The constructor + specialised factory methods pattern is not exactly new in PHP (e.g. it took about 3 minutes to find multiple Symphony classes doing this), and disabling the public constructor for purely cosmetic reasons sounds like a very weird, and ironic choice to me, when the stated goal is to make the API *less surprising* than the previous one. >>> >> >> Besides the points that have been mentioned by Tim and Larry, there's also the expectation of the programmer that migrates to the new classes to take into account. >> They're used to calling the constructor on the old class and calling a load method afterwards. >> As there is still a constructor, but no load method, this might be confusing for them. >> So in my opinion, disabling it makes it less surprising than the previous one. >> Also, just because Symfony does this doesn't mean it's automatically something we should follow. >> >>> >>> Cheers >>> >>> Stephen  >> >> Kind regards >> Niels >> >> --  >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: https://www.php.net/unsub.php > > Hi Niels, Larry > > To clarify my earlier message about having the factory methods on the faux-interface - when I said meta programming that was probably the wrong term to use, so I apologise for the confusion.  > It's true that the *developer* needs to know the expected type of the string being parsed. It's not true that the code directly invoking the 'fromString' method necessarily needs to know - passing classnames as a string and calling static methods on the string is also an established concept in PHP, which works really well when the method being called is defined on a single top-level class or interface. > A real world example I had in mind, is a Request (e.g. a curl request, or some other http-fetching) class that can decode responses into native PHP objects, with options for the callee to define the object type that's wanted; with just the two provided classes there's already double the checks required to know if the specified class name is one the library knows how to use. If a hypothetical class to handle SVG, RSS, ODF (or any other specialised use of XML) class uses the faux-interface from this RFC as it's base, there's no way for the Request class to know that it can instantiate an instance from a string, without falling back to method_exists() checks. > You'd still have to know the signature, and what options it accepts and affect the parser to be able to use it in a meaningful way. Anyway, you can still do this use-case without a method_exists check or something alike by using union types for example. You'll likely still want to put some kind of limitations on, so limiting via type seems sensible. > > The only reason I mentioned the DateTime or Symphony classes at all, is to highlight that people have been using classes with a regular constructor, and one or more static factory methods, for years, and if there has been any confusion about it thus far, it's not something I've ever heard complaints about, nor seen efforts to address. > > > Calling arbitrarily named static methods "named constructors" doesn't really make a convincing argument when someone suddenly realises that the names should be something else halfway through the same conversation. That doesn't mean there's something wrong specifically with having static factory methods when they're needed, but that's my whole point: the *default* way to instantiate an object in PHP is through its constructor, and classes that *don't* provide a public constructor are *much* less common, usually with an obvious reason why (e.g. they're a singleton, or they're objects migrated from resource handles). > > > I've had enough of these conversations to realise that you've made a decision and you're sticking to it, regardless of what I might write (well except for changing the completely arbitrary names, I guess), so I won't continue trying to make my point to you. > > Please at least do one thing though: make it *clear* in the RFC that the public constructor is removed because ... well I don't know, pick one of the reasons you've thrown up I guess. But right now the only reason even vaguely mentioned in the RFC is that it prevents the "changed encoding" issue, but it doesn't do that, the lack of a load method achieves that, and IMO the lack of a regular constructor is a significant enough change from most PHP classes, that people should be aware of that when reading and voting on your proposal. > I will list the reasons more clearly in the RFC. > > > Cheers > > > Stephen  Kind regards Niels