On Sun, Feb 23, 2020, at 2:39 AM, Mike Schinkel wrote:
> > On Feb 21, 2020, at 6:17 PM, Larry Garfield <la...@garfieldtech.com> wrote:
> > I'm totally on board for better value object support, so that's a good 
> > motive for me.  The question I have is whether this is really a good 
> > stepping stone in that direction or if it would lead down a wrong path and 
> > lock us into too much TIMTOWTDI (for the Perl fans in the room).  So let's 
> > think that through down that path.  How would write-once properties lead 
> > into properly immutable value objects?  Or do they give us that themselves?
> > 
> > The biggest challenge for immutable objects, IMO, is evolving them.  Eg, 
> > $result->withContentType(...) to use the PSR-7 example.  Would we expect 
> > people to do it with a method like that, or would there be some other 
> > mechanism?  If the properties are public, would we offer a more syntactic 
> > way to modify them directly?
> > 
> > The with*() method style requires cloning the object.  What happens to the 
> > locked status of a set property if the object is cloned?  Are they then 
> > settable again, or do they come pre-locked?
> > 
> > Neither of those seem good, now that I think about it.  If they come 
> > pre-locked, then you really can't clone, change one property, and return 
> > the new one (as is the standard practice now in that case).  If they don't 
> > come pre-locked, then the newly created object can have everything on it 
> > changed, once, which creates a loophole.  I'm not sure what the right 
> > answer is here.
> > 
> > My other concern is a public property (the most likely use case) would have 
> > to be set in the constructor.  If it's not, then callers cannot rely on it 
> > having been set yet if it's set lazily.  And if code inside the class tries 
> > to set it lazily, it may already have been set by some external code 
> > (rightly or wrongly) and cause a failure.
> 
> > 
> > How do we address that?  There's absolutely use cases where setting 
> > everything in the constructor ahead of time is what you'd do anyway, but 
> > there are plenty where you wouldn't want to, either, which creates a race 
> > condition for who sets it first, or tries to access it before it gets set, 
> > etc.  (This is where my repeated questions about lazy initialization come 
> > from.)
> 
> 
> I have struggled to follow this RFC thread fully, so if I am getting 
> something out of context, please note that and I apologize in advance.
> 
> However, it would see that rules for `write once` properties to support 
> lazy loading would be rather simple:
> 
> 1. Write-once properties can only be updated once.
> 2. Write-once properties can only be updated within the class where 
> they are declared.

This is the common use case I think many envision, but nothing in the proposal 
requires that.  A public write-once property (as currently written) would be 
world-readable, and world-writeable, once.

Separate visibility for internal and external access is a separate matter.  
(Also potentially useful, but not part of the write-once proposal at the 
moment.)

> 3. If you want to update a property from outside the class, create a 
> set_<property>() method to allow it to happen.
> 4. If you do not want it to be set externally, do not implement a 
> set_<property>() method.
> 5. If you want it to be implemented externally sometimes but not 
> others, implement guard classes inside the set_<property>() method.
> 
> I think that addresses all scenarios, no?
> 
> -Mike

It does not.  

1) Race condition if I assume that a public write-once property is a 
materialized value, but access it before it gets materialized.

2) Race condition if internal non-constructor code wants to set the value, but 
some external routine has set it first.

3) Cloning creates an interesting and complicated case of both of the above.  
Does a cloned object start with its write-once bits reset or no?  There's 
problems both ways.

Making a write-once property implicitly write-only-from-inside-the-class would 
help address point 2, but not points 1 or 3.

Adding separate get/set visibility modifiers is another interesting idea, but 
is separate and should be evaluated on its own merits.  It is not at this time 
part of this proposal.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to