Re: Analysis of property visibility, immutability, and cloning proposals
| From: | G. P. B. | Date: | Sun, 10 Jan 2021 01:24:38 +0000 |
| Subject: | Re: Analysis of property visibility, immutability, and cloning proposals | ||
| References: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-112825@lists.php.net to get a copy of this message | ||
On Sun, 10 Jan 2021 at 00:33, Larry Garfield <larry@garfieldtech.com> wrote:
> On Sun, Jan 3, 2021, at 11:29 AM, Olle Härstedt wrote:
>
> > > I'll disagree slightly. A language feature should introduce more
> power than
> > > it does complexity. Not everything *can* be made absolutely simple,
> but the
> > > power it offers is worth it. I'd say it should minimize introduced
> > > complexity, relative to the power offered. Complexity ideally is
> super low,
> > > but it's never zero simply by virtue of being "one more thing" that
> > > developers need to know how to read.
> > >
> > > So in this case, we need to compare the power/complexity of asymmetric
> > > visibility vs the power/complexity of "immutable... except in these
> > > situations." I would argue that asymmetric visibility is more
> > > self-documenting, because it states explicitly what those situations
> are.
> > >
> > > The other point is that, as noted, "initonly" creates a gap if you have
> > > properties that are inter-dependent. Those then cannot be made
> public-read,
> > > because that would also mean public-clone-with, and thus allow callers
> to
> > > violate property relationships. Asymmetric visibility does not have
> that
> > > problem.
> >
> > Can you perhaps be a bit more clear on why initonly/readonly would be
> > a deal breaker? Seems to me like readonly would cover 80% of
> > use-cases? Which is to make data-value objects humane (and fast, since
> > you don't need getters anymore) to work with. Seems like you're
> > focusing too much on an edge case here. Maybe we should list the
> > possibly use-cases? Or at least the main target use-case.
> >
> > If an object has invariants that need to hold, just throw an exception
> > in __clone to force use with withX() instead? Or, as you suggested,
> > improve __clone by giving it arguments?
> >
> > Olle
>
> It took a few days, but I am back with some more concrete examples. I
> decided to try and convert PSR-7 to the various options considered in my
> previous post. Here are the results:
>
>
> https://peakd.com/hive-168588/@crell/object-properties-part-2-examples
>
> Along with an analysis of the pros/cons of each. As shown there,
>
initonly creates backdoors that make any but the most basic
> cases
> untennable.
>
> --Larry Garfield
>
Thanks for dwelling into this.
However, one can already have asymmetric visibility in PHP, just declare a
__get() handler.
Sure it is slow due to the VM -> User code -> VM jumps but it is possible.
Moreover, asymmetric visibility does not prevent mutating an object by
calling the constructor once again as follows:
$obj->__construct(...$args);
This is IMHO the main reason why we want immutability/init only, not to
reduce getter methods or wither methods, even if this makes some of them
redundant.
Also clone-with {} and clone "arguments" could very well be combined by
having the props list being passed to the clone-with instruction as a
$cloneContext array only available in __clone(), similar to how
$http_response_header is populated. [1]
The advantages I see in such a construct is that clone-with can handle any
type concerns (single/union, enums, literals, typed arrays, generics
if/when we get them) for the properties before passing them even to
__clone().
If no __clone() handler is defined then it can just assign them but if
there needs to be one to handle extra validation, such as the type not
being sufficient or a property being dependent on another you are already
guaranteed that the property only needs minimal extra validation.
As such I still believe immutability and asymmetric visibility are
orthogonal features which might be related but fundamentally solve
different problems.
One is about data integrity, the other is about removing getters/setters.
Best regards,
George P. Banyard
[1] https://www.php.net/manual/en/reserved.variables.httpresponseheader.php