On Tue, Mar 24, 2020, at 6:52 AM, Nikita Popov wrote:
> On Mon, Mar 23, 2020 at 1:48 AM Larry Garfield <la...@garfieldtech.com>

> Thanks for the write-up Larry. I like where you're going with this.
> 
> If we were starting from a blank slate design, I would advocate for:
> 
> a) having an object initializer syntax
> b) not having first-class constructors at all
> c) using named constructors instead.
> 
> This also happens to be exactly what Rust does, go figure... Unfortunately
> this kind of approach is hard to retrofit into PHP, because we already have
> constructors, almost all classes define them, and it's hard to reconcile
> object initialization syntax and non-trivial constructors in a meaningful
> way. Combining this with the "no public properties" cargo cult we have
> inherited from Java, the paradigm shift is probably too large here.

If wishes were horses, I'd agree.  Though both you and Mate mentioned named 
constructors; I am not sure how that would play into the compacted constructor 
here.

> If we can't have object initializers, then improving what we can do with
> constructors is the next best thing :)
> 
> I generally like the ideal of combining property declaration and
> constructors. I've had this on my mind for a while already, and also
> received the same suggestion from a couple of other people (I think Nicolas
> was one of them?) The current amount of boilerplate that is needed is just
> large enough that I will often go with a quick and simple ad-hoc array
> structure rather than declaring an explicit value object type. The main
> concern, as others have already mentioned, is that these inline
> declarations can end up being quite verbose, especially once attributes get
> involved.
> 
> I think I will write up a quick implementation & RFC for this part, as it
> seems like something we should at least consider in more detail.

I look forward to it!  I am quite open to alternate syntaxes that are more 
amenable to attributes and delegation, as long as the net result is what we're 
after: Less repetition so making record-like classes is easier.

> Named parameters are a pretty tough topic. I think one of the main points
> of contention is that they make the parameters names part of the API
> contract, and as such also subject to LSP. Your proposal offers two
> possible ways to side-step this: First, by making named parameters opt-in
> with a special syntax {}. Second, by limiting them to constructors. The
> latter variant still exposes parameter names in the API, but at least does
> not require their preservation across inheritance, as constructors are
> excluded from LSP. I'm somewhat torn on this, because it makes named
> parameters unusable with the very large body of existing methods, and
> introduces an inconsistency in which methods can use named params and which
> don't.

My own feeling here is that making people care about parameter names is not 
actually that big of a deal.  You should really be caring about variable names 
anyway.  Python seems to do fine with named parameters being part of the 
contract AFAIK.  Especially if we could get it in for PHP 8, that's a major 
anyway, so I would be fine with it.

The other options (opt-in or constructor only) are IMO fallbacks in case we're 
nervous about it, or if the parser ends up being happier with a more explicit 
syntax.  (Gotta keep the parser happy.)

> Regarding the remainder, I think that all of readonly properties,
> asymmetric visibility and property accessors have their place and value,
> with some overlap between them. As you already mentioned, the previous
> property accessors proposal also included asymettric visibility as a
> special case, and that's how I would introduce it as well.
> 
> However, I generally think that the main value really is the readonly
> properties as proposed in the recent RFC. Nowadays, a large fraction of the
> classes I use are immutable value objects, for which public readonly
> properties provide a much closer match to the semantics I want.
> 
> I think that the problem with with-er methods is just that: It's a problem
> with with-er methods. It's what happens when you try to shove immutability
> into something that is not actually being used in an immutable manner.
> Don't pretend things are immutable when they aren't...
> 
> Regards,
> Nikita

I agree that Withers are solving an odd problem; however, it's the same 
approach that PHP itself takes already.  Consider DateTimeImmutable:

$d = new DateTimeImmutable();
$d2 = $d->setDate(2020, 1, 3)
               ->setTime(12, 45)
               ->setTimezone(new DateTimeZone('America/Chicago')
               ->modify('+1 week');


That's a Wither pattern.  The names a a bit wonky for compatibility with 
DateTime, but that's the exact approach that Wither methods model.  From a user 
perspective it's pretty good.

If the answer to that is "well don't do that", then what's the alternative?  
PHP offers no other syntax for evolvable immutable objects than private 
properties with Wither methods.  Making Wither methods harder makes evolvable 
immutable objects harder.  Unless there's some entirely different approach I am 
not aware of to achieve the same goal, in which case please share. :-)

Asymmetric visibility gives us the same public result as a readonly flag but 
doesn't break the existing Wither pattern; it means properties are still 
modifiable internally, but it's way easier to have self-discipline and not muck 
with a private property by convention than for a public property.  It also 
flows naturally into property accessors, whereas I really don't know how a 
readonly flag would interact with them.

--Larry Garfield

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

Reply via email to