Am 17.07.2024, 20:31:02 schrieb Nicolas Grekas <nicolas.grekas+...@gmail.com >:
> Dear all, > > Le mar. 16 juil. 2024 à 17:51, Nicolas Grekas < > nicolas.grekas+...@gmail.com> a écrit : > >> 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. >> > > 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 adding > more on the proxy class would throw, and we also explain why. We also added > 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 before > 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 >