On Wed, Feb 21, 2024 at 12:57 PM Larry Garfield <la...@garfieldtech.com>
wrote:

> After much on-again/off-again work, Ilija and I are back with a more
> polished property access hooks/interface properties RFC.  It’s 99%
> unchanged from last summer; the PR is now essentially complete and more
> robust, and we were able to squish the last remaining edge cases.
>
> Baring any major changes, we plan to bring this to a vote in mid-March.
>
> https://wiki.php.net/rfc/property-hooks
>
> It’s long, but that’s because we’re handling every edge case we could
> think of.  Properties involve dealing with both references and inheritance,
> both of which have complex implications.  We believe we’ve identified the
> most logical handling for all cases, though.
>

Once again in reading the proposal, the first thing I'm struck by are the
magic "$field" and "$value" variables inside accessors. The first time they
are used, they're used without explanation, and they're jarring.

Additionally, once you start defining the behavior of accessors... you
don't start with the basics, but instead jump into some of the more
esoteric usage, which does nothing to help with the questions I have.

So, first:

- Start with the most basic, most expected usage for each of reading and
writing properties.
- I need a better argument for why the $field and $value variables exist.
Saying they're macros doesn't help those not deep into internals. As a
user, why do they exist?

Honestly, it's not obvious at all that I can just set something to the
variable "$field", and if I didn't know about the feature and stumbled
across a class that used accessors, I'd be wondering what "$field" is, and
how the property ever gets set. (And yes, I've read the FAQ. Saying it's
used in another language doesn't automatically make it good design.)

I know you say in the narrative that you _can_ use `$this->propertyName = `
to set the value, but you also say it's _not recommended_ (though you do
not indicate _why_). To somebody coming primarily from userland who's been
doing OOP in PHP for over 20 years, it's far more clear what's happening.
Alternately, I'd argue that both the accessors should require an argument
that represents the reference to the property:

    public string $username {
        set($field, string|Stringable $value) {
            $field = (string) $value;
        }
        get ($field) => strtolower($field);
    }

The same is true for $value. I'd recommend only ever allowing the construct
`set ($value) {}`, as it's immediately clear that `$value` is the argument
and value being provided to the accessor. When it's implicit, it's easy to
lose context.

Second: you don't have examples of defining BOTH get and set OTHER than
when using expressions for both accessors or a mix. I'm actually unclear
what the syntax is when both are defined. Is there supposed to be a `;`
terminating each? Or  a `,`? Or just an empty line? Again, this is one of
the more common scenarios. It needs to be covered early, and clearly.

Third: the caveats around usage with arrays... give me pause. While I'm
personally trying to not use arrays as much as possible, a lot of code I
see or contribute to still does, and the fact that an array property that
uses a write accessor doesn't allow the same level of access as a normal
array property is something I see leading to a lot of confusion and errors.
I don't have a solution, but I worry that this one thing alone could be
enough to prevent the passage of the RFC.

Fourth: the syntax around inheritance is not intuitive, as it does not work
in the same way as the rest of the language. I'm talking about this:

    public int $x {
        get: 2 * parent::$x::get()
    }

Why do we need to use the accessors here? Why wouldn't it just be
`parent::$x`?

I want to be clear: I really like the idea behind this feature, and
overall, I appreciate the design. From a user perspective, though, the
above are things that I found jarring as they vary quite a bit from our
current language design.

>
> Note the FAQ question at the end, which explains some design choices.
>
> There’s one outstanding question, which is slightly painful to ask:
> Originally, this RFC was called “property accessors,” which is the
> terminology used by most languages.  During early development, when we had
> 4 accessors like Swift, we changed the name to “hooks” to better indicate
> that one was “hooking into” the property lifecycle.  However, later
> refinement brought it back down to 2 operations, get and set.  That makes
> the “hooks” name less applicable, and inconsistent with what other
> languages call it.
>
> However, changing it back at this point would be a non-small amount of
> grunt work. There would be no functional changes from doing so, but it’s
> lots of renaming things both in the PR and the RFC. We are willing to do so
> if the consensus is that it would be beneficial, but want to ask before
> putting in the effort.
>

I personally would go with just "accessors".


-- 
Matthew Weier O'Phinney
mweierophin...@gmail.com
https://mwop.net/
he/him

Reply via email to