Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:109286 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 10490 invoked from network); 25 Mar 2020 12:32:34 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 25 Mar 2020 12:32:34 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id BACB51804F2 for ; Wed, 25 Mar 2020 03:57:13 -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,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE, SPF_PASS 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-ot1-f44.google.com (mail-ot1-f44.google.com [209.85.210.44]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 25 Mar 2020 03:57:13 -0700 (PDT) Received: by mail-ot1-f44.google.com with SMTP id e19so1469734otj.7 for ; Wed, 25 Mar 2020 03:57:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=gaWKB7d3FYdnvuHr+yQgEQ969Z5Upx9z92S2pPgdzrs=; b=eGf+I8EX34OKCLracAyCB0Ik2VDX+5Jnfh34pg5BQN90d3d19Mi9r57bPqavtl+yGF Kat6GciuW6Jpsr5kwnPcbtODWrcD6AKL1TzGuevLYmYuert5rECOG2buMXtGDoErjmqb RpWXf5e1IzzCixgeoExD8dvbzE4Jt2/OEo0FH7CtuyFwh48usKUlPla7krKkL91O3dTN 62vxpmr3bNNx/OILVp/MUA5+Y4RFImwddU4jsdy6fRQ8AtzifEQNoGIeKRHuR9qMKLj8 T85yU2XRrW2H9rsC69XSJ7a2I6AgsdmIRZR+j0O5MS42qWZ5/5To8dYpWvfXVtgVGw4Y EkTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=gaWKB7d3FYdnvuHr+yQgEQ969Z5Upx9z92S2pPgdzrs=; b=A4uhm9tKBTqz0NXq3bdweHZOuuT6bldvsYCgDSHtl7T4fO0nlDhfLQTX9Q6WHdii0f TF3/qieFxTP1xSKgIFu+Mn7UjFFzGyVkoQO2qc+RWiWSS1J23CyXWI4ItZ0pCQOlG9jh 2wtnNRX97Uclft80OEOQhYxjumA4HysQjW5lP8+oNm/N5ggXNzshLKRGg67nN/uEAiaa MHxZDrGO62ub5O1Lq9m1FvaYXNuG4tGHHUucNqjkiS4UCNDYLo4TdUq+Kc0lqmuI3VpN qVhzL/umcBJD+LHyeoLSBFp49BNIQx23TRbAsrB3Sj1vVU4yVei/Q1m0m6svq5Gj4Au4 CTUg== X-Gm-Message-State: ANhLgQ0ZE+veyGn+G6UeUtUemWc2LbbM1tuWCCPCMp1MzF8fRI5huIOD R9SQi4sBft70wM9Rbwb4tyaFHQ5tG2hwcnwSjxM= X-Google-Smtp-Source: ADFU+vv4MvUR4xNlcBNa5UvID+M4UV4zjrrb1EnymChLmfRSb/pPQrp+TfVxRNA3W5TUauAbmfDb0uO/Xv/BMqpE6js= X-Received: by 2002:a05:6830:10c2:: with SMTP id z2mr423449oto.234.1585133832350; Wed, 25 Mar 2020 03:57:12 -0700 (PDT) MIME-Version: 1.0 References: <1b781e1e-3f27-485b-ab47-5eeaf9496548@www.fastmail.com> In-Reply-To: Date: Wed, 25 Mar 2020 11:57:00 +0100 Message-ID: To: Nikita Popov Cc: Larry Garfield , php internals , =?UTF-8?B?TcOhdMOpIEtvY3Npcw==?= Content-Type: multipart/alternative; boundary="000000000000ffaf3905a1abbabc" Subject: Re: [PHP-DEV] Improving PHP's Object Egonomics: A broad analysis From: nicolas.grekas+php@gmail.com (Nicolas Grekas) --000000000000ffaf3905a1abbabc Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable > > https://hive.blog/php/@crell/improving-php-s-object-ergonomics Thanks Larry, that's a good way to move forward on these topics. I generally like the ideal of combining property declaration and > constructors. I've had this on my mind for a while already, and also > received the same suggestion from a couple of other people (I think Nicol= as > was one of them?) I confirm: that'd be super useful to clean the boilerplate. > large enough that I will often go with a quick and simple ad-hoc array > structure rather than declaring an explicit value object type. Yes > The main concern, as others have already mentioned, is that these inline > declarations can end up being quite verbose, especially once attributes g= et > involved. > I don't share this concern with attributes: they mix without any ambiguity, which is what matters. No syntax is perfect, ppl that prefer the current way will still be able to use it. > Named parameters are a pretty tough topic. I think one of the main points > of contention is that they make the parameters names part of the API > contract, and as such also subject to LSP. Your proposal offers two > possible ways to side-step this: First, by making named parameters opt-in > with a special syntax {}. Second, by limiting them to constructors. The > latter variant still exposes parameter names in the API, but at least doe= s > not require their preservation across inheritance, as constructors are > excluded from LSP. I'm somewhat torn on this, because it makes named > parameters unusable with the very large body of existing methods, and > introduces an inconsistency in which methods can use named params and whi= ch > don't. > I'd like to propose something on the topic. I'm adding object literals to the mix because that's another feature of the language that we're missing a lot IMHO. Actually, there is one existing syntax for objects: (object) [...] My proposal is to allow any class in the casting operator: (Foo) [...] By default, all keys of the casted array would map to properties (with an error when no matching property exists in the current visibility scope). We would then allow for a new constructor method, either: public function __create(array $values) or: public static function __create(array $values): static This method would take over the cast operator and decide how to construct an instance of such a class. There is one drawback: accepted keys are not documented. Sure, property declarations can give a big hint. But I think we can solve this issue later: it's not a blocker to still make things work nicely. Also, this issue already exists with all methods that accept an array of options - and we'll find a solution for those - either using docblocks (there are already ways to use them for that) or using attributes (would be the best of course, once we have them.) Note that this __create() method looks a lot like __unserialize(): it's just called at a different place, but the implementations could be essentially the same. Regarding the remainder, I think that all of readonly properties, > asymmetric visibility and property accessors have their place and value, > with some overlap between them. As you already mentioned, the previous > property accessors proposal also included asymettric visibility as a > special case, and that's how I would introduce it as well. > M=C3=A1t=C3=A9 suggested this syntax and it has my preference over the one = you menton Larry: doubling the visibility keyword could be enough to express read+write access: public private $property; <=3D public read access, private write access However, I generally think that the main value really is the readonly > properties as proposed in the recent RFC. Nowadays, a large fraction of t= he > classes I use are immutable value objects, for which public readonly > properties provide a much closer match to the semantics I want. > > I think that the problem with with-er methods is just that: It's a proble= m > with with-er methods. It's what happens when you try to shove immutabilit= y > into something that is not actually being used in an immutable manner. > Don't pretend things are immutable when they aren't... > I think "withers" solve the problem of immutability in a very pragmatic and convenient way. Take e.g. "private": it can be bypassed using closure rebinding or reflection, and this is really useful, e.g. to build "friendship" relations between classes in the same package (like in C++). On the other side, "final" is a real pain when needing to write proxies/decorators. It just blocks extensibility for no technical reasons really. Let me explain: If as a consumer, I DO want to extend a class, nothing will prevent me to do so. There is always the last resort solution, which is patching the too restrictive source class, either using a fork or some code rewriting tool. Either way, what matters is who is in charge of dealing with the issues this might create. In both ways, what matters is that the original author won't be bothered for things that are not its responsibility. "I broke your app because you messed up with that private property on a class I authored?" no my problem. About final, I usually prefer using the "@final" annotation: it expressed exactly what I need to express as the author of the code: "if you extend, you're on your own - but I'm not dictating what you can/can't do either". I think this reasoning applies to my view on immutability :) Cheers, Nicolas --000000000000ffaf3905a1abbabc--