On Sun, 10 Jan 2021 at 00:33, Larry Garfield <la...@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

Reply via email to