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