Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:124546 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 29DC11A00B7 for ; Mon, 22 Jul 2024 11:52:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1721649229; bh=Ln3wlz7zUl48CbFCYZoRzZWEDZBks21Z9OWEQ9d4lJ8=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=dZelHZJq1J8zNs9o/ZY6dQ15VokkIAQ2FXzFUP7m36UcWJxdFwbYRJCDseOogn2iY QSXnx7PORpVtVSF3Y9LL/wnCM6HqmqNjgMZGe+GPBbVrF4pVxCxmKRH1u4SFL4SEKY rBOSF1/Gajx078Jd5M0YgoFAj+2edEF/GVR4zZJ21DbDgFke7500WfL41OeIprUjD9 ADdYfpvF1q25PcL7PZBvfJy/fFJovx0Qi8xBEaGklrjpGx3vZnr7rtgiJLz8cJdAfX 6WPmVLNPM9lPMK8HTrzABeHuOEpMb/zQ1QomKoaVfMJIF8O1gU+7Zl5I/w34ucgHXV V4YrI1tYXicsg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B04B0180039 for ; Mon, 22 Jul 2024 11:53:48 +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=0.8 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DMARC_MISSING,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-vs1-f50.google.com (mail-vs1-f50.google.com [209.85.217.50]) (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, 22 Jul 2024 11:53:48 +0000 (UTC) Received: by mail-vs1-f50.google.com with SMTP id ada2fe7eead31-492aae5fd78so189516137.2 for ; Mon, 22 Jul 2024 04:52:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=beberlei-de.20230601.gappssmtp.com; s=20230601; t=1721649134; x=1722253934; 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=DEDPbfY0k6+YWmzF4tcqEZQmNkP1rpQRufOOKAtxqpc=; b=dm5AnJ70PqcD9pIJsLqEYBpbeDnbnHI4IwQpuG/uNlEZGwt2/673FumgZd3jGpEtia OATIz25tajhFoEjzZ+vzJY91u6SI+LROyBWtC3glQ8BZvn6GebNil2df/RNpNaxpBTUi sSvQeN+MIp4IFiGAXhizbkKGM3F5ZAbhfDXC1hrplCb3yl/ImLZL1Fv4qx1MSCcfyeem xoyDL9bUW+AOErvEhF4aCZK9WaKhsiE+BMh8WO68TStl0hH6pKMdSPwdomMk+zSq7v7U X21mfprlc6JtKUdIfpOE17eFO92cb9OrOF41HUYps9wcyGuNXHHjztdhkDtffemQJTEJ pvbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721649134; x=1722253934; 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=DEDPbfY0k6+YWmzF4tcqEZQmNkP1rpQRufOOKAtxqpc=; b=oUzr+ZPsCep0OP18qWNIsIAWTj8gptAQiSe5PMgj0eEwNvTbrgY+/M87HQhT4QPEUf b5WnMi8iXcuac7ZOWAPKVD+NGNS8roKQC5r3sam1Av/5w2hfIyEazb2ubY53cAKu9e3w VZgc9B9aqlV9LiHqxukTq/Z8qnc9U5aF2fX6M2PIzzffiL3zi6voSgyREivj0BUHRdU1 kjnUUdSKV3KepM8fWCnQZS3RFiEfAAWs9PKaoibAFis8ENRXzZf1iwBwD3WSt8f68u9i RLUIJreDcirKv+Gr5mp5Oo9i4JWhLyeS5K4qV3KUmrIfH//p02GuHIJhhT74aU65izzK VyfA== X-Forwarded-Encrypted: i=1; AJvYcCWrkBs9Ri0qQ+wBc2dXUNu1+rLXuL7rKA0gXYKyB/GSQswc6ldjuYox2ZwLjhQQgcvk0NUoQYyJa1IP2mFXfP6VEf33waUGcA== X-Gm-Message-State: AOJu0YwvoGnz/qrE83PmONegd3UNyJGCrY2VByAZtwey7HJd8fA3xPZa oOyVUMcD2klZs84JfyQDT/Lv85Ar4dRXcJGGEhEJh5qhVew1KHabSHBu0YY4jA6JGdesTbn9DA6 I9MZe4H3a2gt6PSyPoiH4hg0rmvATgGmOG1/hKw== X-Google-Smtp-Source: AGHT+IGUTLK4v8GM9QgjmIV4gnJkGwXwAbO37BrExvsuVKLkgwUi6yrl3EPieG/upzmTc5kOZZEEBjLpPc9P33SKAQE= X-Received: by 2002:a05:6102:6c5:b0:48f:e802:4b26 with SMTP id ada2fe7eead31-4928b9e2c75mr7342718137.18.1721649134259; Mon, 22 Jul 2024 04:52:14 -0700 (PDT) Received: from 1064022179695 named unknown by gmailapi.google.com with HTTPREST; Mon, 22 Jul 2024 13:52:13 +0200 Received: from 1064022179695 named unknown by gmailapi.google.com with HTTPREST; Mon, 22 Jul 2024 13:52:11 +0200 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 (Mimestream 1.3.6) References: <1118bbcd-a7b4-47bf-bf35-1a36ab4628e1@bastelstu.be> <45847b93-02bf-459f-bcd2-81ba35a12c24@bastelstu.be> <46bd4098-2936-4e46-98e9-fe55118325c2@bastelstu.be> <61ab36bc-b045-452a-84e0-87367d4c680e@bastelstu.be> <07e065f2-8f64-4bad-9a98-51f4eaf63ddb@app.fastmail.com> <2a0a4650-c2c5-4c6d-ad3a-25365b3391b2@bastelstu.be> In-Reply-To: Date: Mon, 22 Jul 2024 13:52:13 +0200 Message-ID: Subject: Re: [PHP-DEV] [RFC] Lazy Objects To: Nicolas Grekas Cc: Rob Landers , PHP Internals List , =?UTF-8?Q?Tim_D=C3=BCsterhus?= Content-Type: multipart/alternative; boundary="000000000000136a4c061dd4ad1d" From: kontakt@beberlei.de (=?UTF-8?Q?Benjamin_Au=C3=9Fenhofer?=) --000000000000136a4c061dd4ad1d Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Am 17.07.2024, 20:31:02 schrieb Nicolas Grekas : > Dear all, > > Le mar. 16 juil. 2024 =C3=A0 17:51, Nicolas Grekas < > nicolas.grekas+php@gmail.com> a =C3=A9crit : > >> Hi there, >> >> Le mar. 16 juil. 2024 =C3=A0 10:13, Nicolas Grekas < >> nicolas.grekas+php@gmail.com> a =C3=A9crit : >> >>> >>> >>> Le lun. 15 juil. 2024 =C3=A0 21:42, Tim D=C3=BCsterhus a >>> =C3=A9crit : >>> >>>> Hi >>>> >>>> On 7/15/24 09:25, Nicolas Grekas wrote: >>>> > Testing is actually a good domain where resetting lazy objects might >>>> open >>>> > interesting use cases. >>>> > This reminded me about zenstruck/foundry, which leverages the >>>> > LazyProxyTrait to provide refreshable fixture objects >>>> > < >>>> https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#= auto-refresh >>>> > >>>> > and provides nice DX thanks to this capability. >>>> > >>>> >>>> I have not used this library before, but I have taken a (very) brief >>>> look at the code and documentation. >>>> >>>> My understanding is that all the fixture objects are generated by a >>>> corresponding Factory class. This factory clearly has the capability o= f >>>> constructing objects by itself, so it could just create a lazy proxy >>>> instead? >>>> >>>> I'm seeing the `instantiateWith()` example in the documentation where >>>> the user can return a constructed object themselves, but I'm not seein= g >>>> how that can safely be combined with the `reset*()` methods: Anything >>>> special the user did to construct the object would be reverted, so the >>>> user might as well rely on the default construction logic of the >>>> factory >>>> then. >>>> >>>> What am I missing? >>>> >>> >>> Finding the spot where the reset method would be useful is not easy. >>> Here it is: >>> >>> https://github.com/zenstruck/foundry/blob/v2.0.7/src/Persistence/IsProx= y.php#L66-L76 >>> >>> Basically, the reset method is not needed when creating the lazy proxy. >>> But it's needed to refresh it when calling $object->_refresh(). The >>> implementation I just linked swaps the real object bound to the proxy f= or >>> another one (the line >>> "Configuration::instance()->persistence()->refresh($object);" swaps by >>> reference). >>> >> >> >> After chatting a bit with Benjamin on Slack, I realized that the sentenc= e >> "The indented use-case is for an object to manage its own laziness by >> calling the method in its constructor" was a bit restrictive and that th= ere >> are more use cases for reset methods. >> >> Here is the revised part about resetAsLazyGhost in the RFC: >> >> This method allows an object to manage its own laziness by calling the >> method in its constructor, as demonstrated here >> . In >> such cases, the proposed lazy-object API can be used to achieve lazy >> initialization at the implementation detail level. >> >> Another use case for this method is to achieve resettable services. In >> these scenarios, a service object already inserted into a complex >> dependency graph can be reset to its initial state using the lazy object >> infrastructure, without its implementation being aware of this concern. = A >> concrete example of this use case is the Doctrine EntityManager, which c= an >> end up in a hard to recover >> "closed" state, preventing its use in long-running processes. However, t= hanks >> to the lazy-loading code infrastructure >> , >> recovering from such a state is possible. This method would be instrumen= tal >> in achieving this capability without resorting to the current complex co= de >> used in userland. >> >> I hope this helps. >> > > A bit unrelated to the above topic: we've further clarified the RFC by > addition restrictions to what can be done with lazy proxies. Namely, when > the factory returns an object from a parent class, we describe that addin= g > more on the proxy class would throw, and we also explain why. We also add= ed > a restriction to prevent a proxy from having an overridden __clone or > __destruct when the factory returns a parent, and explained why again. > > This should simplify the overall behavior by preventing edge case that > wouldn't have easy answers. If those limitations prove too restrictive in > practice (my experience tells me they should be fine), they could be > leveraged in the future. > > On our side, this should close the last topics we wanted to address befor= e > opening the vote. > > Please let us know if anyone has other concerns. > I have discussed all my open topics and hope this has improved and clarified the RFC in a way that it gets accepted! The note about resetting an object back to its initial state with reset* was the relevant extra information that was missing for me to understand the need for resetAs*. While that is not a use-case I need myself I can see its usefulness especially when running PHP in worker-mode context either as message queue processing daemon or for FrankenPHP and related application frameworks. > Cheers, > Nicolas > --000000000000136a4c061dd4ad1d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


Am 17.07.2024, 20:31:02 schrieb N= icolas Grekas <nicolas= .grekas+php@gmail.com>:
Dear all,

Le=C2=A0mar. 16 juil= . 2024 =C3=A0=C2=A017:51, Nicolas Grekas <nicolas.grekas+php@gmail.com> a =C3=A9crit=C2=A0= :
Hi there,

Le=C2=A0mar. 16 juil. 2024 =C3=A0=C2=A010:= 13, Nicolas Grekas <nicolas.grekas+php@gmail.com> a =C3=A9crit=C2=A0:
<= div dir=3D"ltr">

Le=C2=A0lun. 15 juil. 2024 =C3=A0=C2=A021:42, Tim D=C3= =BCsterhus <tim@ba= stelstu.be> a =C3=A9crit=C2=A0:
Hi

On 7/15/24 09:25, Nicolas Grekas wrote:
> Testing is actually a good domain where resetting lazy objects might o= pen
> interesting use cases.
> This reminded me about zenstruck/foundry, which leverages the
> LazyProxyTrait to provide refreshable fixture objects
> <https://s= ymfony.com/bundles/ZenstruckFoundryBundle/current/index.html#auto-refresh>
> and provides nice DX thanks to this capability.
>

I have not used this library before, but I have taken a (very) brief
look at the code and documentation.

My understanding is that all the fixture objects are generated by a
corresponding Factory class. This factory clearly has the capability of constructing objects by itself, so it could just create a lazy proxy
instead?

I'm seeing the `instantiateWith()` example in the documentation where <= br> the user can return a constructed object themselves, but I'm not seeing=
how that can safely be combined with the `reset*()` methods: Anything
special the user did to construct the object would be reverted, so the
user might as well rely on the default construction logic of the factory then.

What am I missing?


= Basically, the reset method is not needed when creating the lazy proxy. But= it's needed to refresh it when calling $object->_refresh(). The imp= lementation I just linked swaps the real object bound to the proxy for anot= her one (the line "Configuration::instance()->persistence()->ref= resh($object);" swaps by reference).


After chatting a bit with Benjamin on S= lack, I realized that the sentence "The indented use-case is for an ob= ject to manage its own laziness by calling the method in its constructor&qu= ot; was a bit restrictive and that there are more use cases for reset metho= ds.

Here is the revised part about resetAsLazyGhos= t in the RFC:

This method allows an object to = manage its own laziness by calling the method in its constructor, as demonstrated here. In such cases, the proposed lazy-obj= ect API can be used to achieve lazy initialization at the implementation de= tail level.

Another use case for this method is to achieve resettab= le services. In these scenarios, a service object already inserted into a c= omplex dependency graph can be reset to its initial state using the lazy ob= ject infrastructure, without its implementation being aware of this concern= . A concrete example of this use case is the Doctrine EntityManager, which = can end up in a hard to recover "closed" state, preventing its= use in long-running processes. However, thanks to the lazy-lo= ading code infrastructure, recovering from such a state is possible. Th= is method would be instrumental in achieving this capability without resort= ing to the current complex code used in userland.

= I hope this helps.

A bit = unrelated to the above topic: we've further clarified the RFC by additi= on restrictions to what can be done with lazy proxies. Namely, when the fac= tory returns an object from a parent class, we describe that adding more on= the proxy class would throw, and we also explain why. We also added a rest= riction to prevent a proxy from having an overridden __clone or __destruct = when the factory returns a parent, and explained why again.

<= /div>
This should simplify the overall behavior by preventing edge case= that wouldn't have easy answers. If those limitations prove too restri= ctive in practice (my experience tells me they should be fine), they could = be leveraged in the future.

On our side, this shou= ld close the last topics we wanted to address before opening the vote.

Please let us know if anyone has other concerns.
=

I have discus= sed all my open topics and hope this has improved and clarified the RFC in = a way that it gets accepted!
The note about resetting an = object back to its initial state with reset* was the relevant extra informa= tion that was missing for me to understand the need for resetAs*.=C2=A0

While that is not a use-case I need myself I can see its use= fulness especially when running PHP in worker-mode context either as messag= e queue processing daemon or for FrankenPHP and related application framewo= rks.


Cheers,
Nicolas
--000000000000136a4c061dd4ad1d--