Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:124448 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 D698D1A00B7 for ; Tue, 16 Jul 2024 15:51:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1721145167; bh=uXy0KB9SN7JAoETeoiPWaB3pWGYcODgV72GGk7Tk+Es=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=KTi3tg9cH8gNEOCZIXDtEQxyq6tjj54BMuPPKTbsVmEBWS5NQ1w8XXxXqvmCK6BsT QrHlo4PhWveeuDXCXpfoQ5uZ+vTi4BuGyp4gC5Upo4Sda39jRdeAHwt45iUdWC/mr9 y2Un/3bc6OaMlWYht7rQbvi+674rVZpS2H5M7XyI//UFRzc+mhToVqGAa9hCfFllpu rG1LpIh7bepNabat8VuOBrn1hhDh+NnfOf82PTFoXe0yDEBV+Xty8k1UkLr8bueaS5 Y2J4ZlvFcoCQxpLMHDs9S2btUFXpSHMIY+fVaLs+w3omNqmjqc50VNabNY8YW5SEJb GFrq1JPtxrltw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6C5AF180056 for ; Tue, 16 Jul 2024 15:52:46 +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.6 required=5.0 tests=BAYES_50,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-lj1-f182.google.com (mail-lj1-f182.google.com [209.85.208.182]) (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 ; Tue, 16 Jul 2024 15:52:45 +0000 (UTC) Received: by mail-lj1-f182.google.com with SMTP id 38308e7fff4ca-2ee920b0781so57575121fa.1 for ; Tue, 16 Jul 2024 08:51:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721145075; x=1721749875; 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=uXy0KB9SN7JAoETeoiPWaB3pWGYcODgV72GGk7Tk+Es=; b=b7qdwDpCyE/Xi2P9Ld/aoA3eKZtl1L6JwTCn4Tq9tEJkThTowdDqeIrEuhxnYlx/qa iZqJu7SDAbGPh1XjlBnbWHR4//+QKqgt1yYwzoWsksOUk1O8qT9ScPeufvWahBgYCCNS Tu5uA7I4LndRyOk5X6QVxVwXNmotKm5GWyhfLWY4tkoCipw2JzQlhz/j9DXkDakrzqSq bVVWvBGrMjJNbENcDKC0J0+NCqA5smV2oMaxEdagfBeCeOCzFeHdjVQ6PzgFE7nLUj5y 9b7LNzg9f+2RSF8/xoH2mXc2sLIQMjNeHxsrZxMe7fa2u69x6baYX8GsI7wtXFj0IVsF xX9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721145075; x=1721749875; 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=uXy0KB9SN7JAoETeoiPWaB3pWGYcODgV72GGk7Tk+Es=; b=XYGABOuB5u1n147QymBnMuzMLGOm37TEgMFcU9+PjE8oIcMmTFssTD/DOMyjhio/Fj KvEVz//UaLfarlvwGRvEcJFso+qqQ+zqaZem3WcK/kULVo2G/RmWbIo4/WcmoHNUeCr8 QMelgVXIjm4FfgHR0o9RLqq7O/oJqN0TtN+1cTs0bxGSSTXqLIwAXxpCyAqPe4jsc4JT zSM/2RkjFbql3GkHucF7MTfx19q876rIc+trZzKk+xsRcHH/iYMsOJB23N6i8/kEQ83J fMKg2l1Y6RkMqNrlgQ0XkIzcnIskjt2+k+t2hA3XzkCG42xMGuKbZIfFFO3zeON22N0H WwPQ== X-Forwarded-Encrypted: i=1; AJvYcCWm2qbTNfLDExg1sylnt1I0iPB8oikJzHa8VA4fINPKk3vRg+3qanj5eK69y5RvHf8WbZTeNNi5Qob1lBnTkd9cbZ3B8uaHTw== X-Gm-Message-State: AOJu0YwQrqZ2AgC0vGhREA/ST9BX9AWpwnHEzztyMt7uddaL2cR/u2hO J0EvX1PuDDe8M1MedUB3rYepQzywWgABPlJBP1HRt2XLGMb83StnpWaA5uDvDZy8/pBvUkwmnTF c+OA7svrvjOCn02SJ7r27EBjYRCE= X-Google-Smtp-Source: AGHT+IHv4mwpewSBVxZgUZ0Paox1y/hqiCXPf+gwG50z33iinIL2nzc+Ji8et3JwwFJp2UZJ7HYCmCblOgIi217Vr9E= X-Received: by 2002:a2e:7d12:0:b0:2ee:8698:10ed with SMTP id 38308e7fff4ca-2eef41f4b9cmr16260591fa.49.1721145074442; Tue, 16 Jul 2024 08:51:14 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 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: Tue, 16 Jul 2024 17:51:01 +0200 Message-ID: Subject: Re: [PHP-DEV] [RFC] Lazy Objects To: =?UTF-8?Q?Tim_D=C3=BCsterhus?= Cc: Rob Landers , =?UTF-8?Q?Benjamin_Au=C3=9Fenhofer?= , PHP Internals List Content-Type: multipart/alternative; boundary="000000000000c4e9a2061d5f50a9" From: nicolas.grekas+php@gmail.com (Nicolas Grekas) --000000000000c4e9a2061d5f50a9 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi there, Le mar. 16 juil. 2024 =C3=A0 10:13, Nicolas Grekas 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#au= to-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 >> 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? >> > > 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/IsProxy.= 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 for > another one (the line > "Configuration::instance()->persistence()->refresh($object);" swaps by > reference). > After chatting a bit with Benjamin on Slack, I realized that the sentence "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 there 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 can end up in a hard to recover "closed" state, preventing its use in long-running processes. However, than= ks to the lazy-loading code infrastructure , recovering from such a state is possible. This method would be instrumental in achieving this capability without resorting to the current complex code used in userland. I hope this helps. Cheers, Nicolas --000000000000c4e9a2061d5f50a9 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
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">


<= div dir=3D"ltr" class=3D"gmail_attr">Le=C2=A0lun. 15 juil. 2024 =C3=A0=C2= =A021:42, Tim D=C3=BCsterhus <tim@bastelstu.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 de= monstrated here. In such cases, the proposed lazy-object API can be use= d to achieve lazy initialization at the implementation detail level.
Another use case for this method is to achieve resettable services. In th= ese scenarios, a service object already inserted into a complex dependency = graph can be reset to its initial state using the lazy object infrastructur= e, without its implementation being aware of this concern. A concrete examp= le of this use case is the Doctrine EntityManager, which can end up in a hard to recover &= quot;closed" state, preventing its use in long-running processes. Howe= ver, = thanks to the lazy-loading code infrastructure, recovering from such a = state is possible. This method would be instrumental in achieving this capa= bility without resorting to the current complex code used in userland.

I hope this helps.

Cheers,
Nicolas
--000000000000c4e9a2061d5f50a9--