Hi there,

Le mar. 16 juil. 2024 à 10:13, Nicolas Grekas <nicolas.grekas+...@gmail.com>
a écrit :

>
>
> Le lun. 15 juil. 2024 à 21:42, Tim Düsterhus <t...@bastelstu.be> a écrit :
>
>> 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 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
<https://gist.github.com/arnaud-lb/9d52e2ba4e278411bff3addf75ce56be>. 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 <https://github.com/doctrine/orm/issues/5933>
"closed" state, preventing its use in long-running processes. However, thanks
to the lazy-loading code infrastructure
<https://github.com/symfony/symfony/blob/1a16ebc32598faada074e0af12a6a698d2964a5e/src/Symfony/Bridge/Doctrine/ManagerRegistry.php#L42>,
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

Reply via email to