Re: [RFC] Asymmetric Visibility, v2

From: Date: Tue, 11 Jun 2024 06:47:24 +0000
Subject: Re: [RFC] Asymmetric Visibility, v2
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-123576@lists.php.net to get a copy of this message
On Mon, Jun 10, 2024, at 19:51, Rodrigo Vieira wrote: > I didn't like the Prefix-style syntax. I prefer the > Hook-embedded-style syntax. First let's look at the > counterpoints of the Prefix-style syntax: > > ## 1) "Prefix-style is more visually scannable" > > The set visibility is 10 lines away from the get visibility! > > Solution: > ```php > class HookEmbeddedStyle > { > public string $phone { > private set { > $this->phone = implode('', array_filter(fn($c) => is_numeric($c), > explode($value))) > } > get { > if (!$this->phone) { > return ''; > } > if ($this->phone[0] === 1) { > return 'US ' . $this->phone; > } > return 'Intl +' . $this->phone; > } > } > } > ``` > The set visibility is not 10 lines away from the get visibility if you put it at the top. For > me this is about code convention, not about syntactic structure: > only put the hook with explicit visibility at the top, when some of the hooks do not have > explicit visibility! > > ## 2) "Prefix-style is shorter" > ```php > public private(set) string $name; > > public string $name { private set; } > ``` > > Irrelevant to consider 1-2 characters. > If you break the lines needed for the hook block, the line (the horizontal size) is smaller > when using Hook-embedded-style and in my opinion it is more readable > because there is less information per line: > ```php > public private(set) string $name; > > public string $name { > private set; > } > ``` > > ## 3) "Prefix-style doesn't presume a connection with > hooks" > > As noted above in "Interaction with hooks", visibility controls exist > > independently of hooks. > > I agree, but with Property Hooks, this should now define the overall visibility only. Like a > bigger gate that you open, and there are other doors defining the visibility of the operations get, > set (hooks). > > > In fact, as implemented, they don't interact at all. Using hook syntax for visibility > > controls is therefore surprising and confusing. > > Why "surprising and confusing"? I see hooks as a different kind of function/method. > Property Hooks RFC shouldn't pass without requiring hook parentheses, for any hook when > the property is not abstract. The $value in the > set hook seems to come out of nowhere to some people (the exception > is for hooks declared on an abstract property which you can define without parameters and thus you > are free to define whatever parameters you want on the concrete property). > > When you define a method in PHP, it should be possible to omit the "function", but > the parameters should be required because that's the nature of a function/method: to have > parameters. > > ## 4) "It's non-obvious in Hook-embedded-style what > hook behavior should be implied" > > > ...So “arrays with hooks can do less” is already an established fact of the language. > > However, if the hook-style syntax is used for visibility: > > ```php > class A > { > public array $arr { protected set; } > } > > class B extends A > { > public function add(int $val) > { > // Should this be legal? > $this->arr[] = $val; > } > } > > $b = new B(); > > $b->add(5); > ``` > First of all: non-abstract property hook must have a body. > Second: when asymmetric visibility is explicit, it means that symmetric visibility is implicit: > a declared hook that does not have declared visibility has the same general visibility as the > property, in this case: public. > > Third: > There's another limitation on hooks here that makes things a bit confusing: there's a > missing hook for a specific operation because you can clearly separate the > set from the push operation... > > Solution: > ```php > abstract class A > { > abstract public array $arr { > push; // Hook available only for "array" type properties only; public > visibility > private set; > } > } > > class B extends A > { > public array $arr { > push ($value) { // public push ... here is redundant > // Mandatory to implement logic here. > } > private set ($value) { > // Mandatory to Implement logic here. > } > } > > public function __construct () > { > // Legal ✅ (set hook is protected) > $this->arr = [1]; // call set hook > } > public function add(int $value) > { > // Legal ✅ (push hook is public) > $this->arr[] = $value; // call push hook > } > } > > $b = new B(); > > $b->add(5); > $b->arr; // Legal ✅ (Inherited from the general visibility that is public) > $b->arr = [1, 2, 3]; // Fatal error ❌ - access to set hook is private only > $b->arr[] = 4; // Legal ✅ - call public push hook > ``` > > My point: Prefix-style is not future-proof > ## 1) The Prefix-style is not compatible with new hooks > If more hooks are added in the future, such as the push hook > for arrays or even a hook that is compatible with all types such as > init, Hook-embedded-style will > become compatible, but Prefix-style not. > > ## 2) Hook overloading > If hook overloading is added in the future, Prefix-style would > not be supported to have this granular visibility into operations. For example, it might be possible > to add a public hook and a protected hook for the same operation, where one would be triggered if > the operation occurred from outside the class, and the other if the operation occurred from inside > the class. > Em 10 de jun. de 2024 13:15 -0300, Tiffany <tiffany.k.taylor@gmail.com> escreveu: >> >> On Wed, May 29, 2024, 2:16 PM Larry Garfield <larry@garfieldtech.com> wrote: >>> As promised, Ilija and I offer this revised version of asymmetric visibility. >>> >>> https://wiki.php.net/rfc/asymmetric-visibility-v2 >>> >>> It's still essentially the same as last year's version, but with a few >>> adjustments and changes: >>> >>> * readonly properties are now supported in a logical fashion. >>> * We've brought back the abbreviated form, as public-read, something else set is >>> the most common use case. >>> * The section on magic methods has been greatly simplified. The implementation itself >>> hasn't changed, but the explanation is a lot less confusing now. >>> * We've explained how aviz interacts with hooks (they don't, really) and with >>> interface properties (in the obvious way), which didn't exist at the time of the last draft. >>> * We've added a section with examples of how aviz is a concrete improvement, even >>> in a world with readonly and hooks. >>> * We've added a section discussing why the prefix-style syntax was chosen. >>> >>> *dons flame retardant suit* >>> >>> -- >>> Larry Garfield >>> larry@garfieldtech.com >> >> Sending an email to quickly enable a new mailing list subscriber to engage in the >> conversation. I’m also not a fan of the prefix style, but for different reasons. My main reason is that it increases the minimum line-length, potentially forcing you to chop things down into awkward looking lines: public private(set) string $longvarname { get; set; } I find that extremely hard to scan, but maybe others do not. The more natural looking syntax is easier to scan and reason about (IMHO): public string $longvarname { get; private set; } If I’m having to read the code, I prefer to have everything near where it is used so I don’t have to scroll up to the top and see its visibility. Granted, I haven’t used property hooks and I have no idea how IDEs will help here; maybe it is a non-issue — but I guess people still have to do code reviews which very rarely comes with IDE powers. — Rob

« previous php.internals (#123576) next »