Re: [RFC] [DISCUSSION] Immutable/final/readonly properties
| From: | Mike Schinkel | Date: | Sun, 23 Feb 2020 08:39:33 +0000 |
| Subject: | Re: [RFC] [DISCUSSION] Immutable/final/readonly properties | ||
| References: | 1 2 3 4 5 6 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108725@lists.php.net to get a copy of this message | ||
> On Feb 21, 2020, at 6:17 PM, Larry Garfield <larry@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.
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