Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:121784 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 81416 invoked from network); 23 Nov 2023 18:03:22 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 23 Nov 2023 18:03:22 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id F3F1418003F for ; Thu, 23 Nov 2023 10:03:25 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail.online-presence.ca (online-presence.ca [216.128.176.244]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 23 Nov 2023 10:03:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=online-presence.ca; s=default; t=1700762600; bh=A0tVJDAUuUL9xPBeQOXtrCjKEj45q6tcTj/JDbwnRSA=; h=Date:Subject:To:References:From:In-Reply-To:From; b=MCm6cMMiITmdunIoHjq4Ydo1n9OHNNQAlOAeJRUOromegkPmJIjGPuco53+ObRBXm pqQFMCgrfurYkWaoJBkl/ZN3K1KkfVY4XkgySSBbLQedj21DM+jy6lTFAZJo0RmTTC tKZUrPuRWvMf6M/GSkfiQGdWAwsnrI3OfWTU6UgxxiUe262nSvMXrvNCy9wKqmv/pX nKsOrKfNeyS176kJmF569PwdqqMZtzqmbeka9UlLpyEmR6FJgoyp2r4XdsYqrMAadr FrIE/AsB3WLQOT76rWdRcmOKiNuoqwcvX51v/2g2U5etf5XOaLAwi4JM9kb0Z5fs41 mmZSaur84G8mg== Received: from [10.0.0.211] (S01064075c3d865eb.ed.shawcable.net [70.74.109.64]) (Authenticated sender: lanre@online-presence.ca) by mail.online-presence.ca (Postfix) with ESMTPSA id 0EA34105CB7 for ; Thu, 23 Nov 2023 18:03:19 +0000 (UTC) Message-ID: <7128925a-a314-440d-bda2-1bbb0e4ccca7@online-presence.ca> Date: Thu, 23 Nov 2023 11:03:18 -0700 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: internals@lists.php.net References: <79d675e3-95b4-40bb-baf4-3e1c998f5390@online-presence.ca> <2dc2e032-b10b-4d50-9a64-8f88c37583d1@app.fastmail.com> Organization: Online Presence In-Reply-To: <2dc2e032-b10b-4d50-9a64-8f88c37583d1@app.fastmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Subject: Re: [PHP-DEV] RFC Proposal - static modifier for classes From: lanre@online-presence.ca (Lanre Waju) Again, with so many absolutes. Static APIs aren't inherently bad; rather, bad programmers write poor code. It seems like you're assuming that PHP developers can't make decisions about what tools to use independently and need explicit encouragement or endorsement from you. Just because you are using what I would call "garbage" (my preferred term for legacy) Stripe API doesn't mean we all do. When did I ever say the cost to add this would be zero? If everything has a non-zero development cost, doesn't that make it implied? What exactly is your point? For example, the get/set hooks you proposed: why go the C# route instead of using JS-like modifiers, which PHP already supports? What was the cost analysis on that? Then, you talk about Laravel. How are Facades anything like what I have suggested exactly? The idea that Laravel is somehow more difficult to test than any other framework is simply a myth; they have a robust test suite. I write embedded code for a living; I have crafted far more critical tests for code being shipped to millions of devices that may never update, compared to your "legacy" Stripe code that you still use for some reason. So, you don't have to explain how mocks and unit tests work, but thanks for your summary. I made a suggestion for something i thought would be a nice addition to the language, and instead of questions, I'm met with absolutes on why my Idea is bad, and some nonsense about how everything has maintenance cost. On 2023-11-20 4:28 p.m., Larry Garfield wrote: > On Mon, Nov 20, 2023, at 9:00 PM, Lanre Waju wrote: >> I will have to disagree with everything you said: >> >> I outlined what a static class would be: A class that cannot be >> instantiated in which all members are implicitly static. We already have >> static members, so please elaborate on the maintenance burden that >> adding static to a class as that could help explain better, i mean what >> feature doesn't have technical debt associated with it? The new JIT engine? > That's part of the point. Literally every feature added to a system (PHP or otherwise) has some maintenance overhead associated with it. It may be small, it may be huge, it may be worth it, it may not be worth it, but it's always non-zero. > > As for what a static class is, from your description I am understanding it to mean this: > > static class Foo { > public function beep(): string { ... } > public function boop(): string { ... } > } > > Is effectively a shorthand for: > > class Foo { > public function __construct() { throw new \Exception("You can't do that"); } > > public static function beep(): string { ... } > public static function boop(): string { ... } > } > > Much the same way a readonly class is. Is that understanding of the intent more or less accurate? > >>>> 3. It is entirely opt-in. If you hold reservations about using static >>>> classes, you can simply choose not to use them. >>> This is a spurious and disingenuous argument, even if it gets trotted out frequently on many RFCs. I'm not picking on you in particular here, but it's a bad argument to use, period, 99% of the time, no matter who is saying it. >> If you insist, Mr. Larry. > Cultural side note: At least in the US, where I am, "Mr. Firstname" is pretty much never used except with some families that teach their children to use that with adults. It's not necessary and kind of weird. "Mr. Garfield" if you want to be formal is fine, or just Larry, or Crell, as that's the handle I use virtually everywhere and there are people who know me as that more than as Larry. (I am not offended, just noting a cultural mismatch point.) > >>> Similarly, if we add a static marker to classes, that means all future improvements to classes need to consider "but what if the class is static?" Eg, there was discussion a while back about `data` classes. What happens if you have a `static data class`? Is that a syntax error? Does it work? If it works, what does "work" mean? What about sealed classes? Can you have a sealed static class? What would that mean? Those are questions that would need to be answered, because this feature exists. >> Either i'm in an alternate reality where the data classes and sealed >> classes rfcs passed, or I've just been straw-manned. Either way, is it >> really that difficult to decide on as a community what a static data >> class implies? We have already established that a static class means all >> the members are static, but i can try to dumb it down for you if need be. > There is no need to dumb it down, just to read what I actually wrote. *Every* feature added has implications for future features added. Data and Sealed classes are ideas that have been floated but never to a full RFC, but may end up as an RFC in the future. They were convenient examples of future work that would be impacted by adding a static keyword to classes, as those RFCs would have to determine how to interact with static classes. Maybe the solution would be simple, maybe it wouldn't, I have no idea. It is just an example to show that the cost of adding a feature is never zero, and so the "if you don't like it don't use it, so you're always wrong for voting against an RFC" argument is nonsensical and disingenuous. > >>> It impacts all users, too, because almost no one builds a 100% self-written codebase anymore. 99% of projects are 80% someone else's code via Composer packages large and small, which means every language feature they use, you need to be aware of how to use. If some library has a static class as part of its API, I am now forced to work with static classes, whether I like it or not. >> If you had told me we were allowed to pull numbers out of our asses, i >> would have mentioned that 100% of php users will benefit from this, >> Including people like you who don't necessarily see the value in it. As >> a user of a class, it shouldn't matter whether it's static or not, the >> static members will be the same as using a normal class with static >> members, in fact, people already simulate this in userland by making >> __construct private and only using static members, does that impede your >> ability to use such libs? How is this forcing you to use static classes? >> The dev of said library(which no one is forcing you to use) would be the >> one who made that call. After which it's your call to decide whether or >> not the library suites you. I don't see any forcing here but do >> enlighten me. > Funny you should mention it, in fact. One of the systems I maintain at work currently is using an older version of Stripe's authentication library, which is written as all static calls. That makes them unmockable. That sucks horribly, because that means when our test suite runs we're sending *thousands of auth calls* to Stripe, because there is no way to mock out that call with a no-op, when we don't actually care what Stripe does in 99% of those tests. > > We're currently in the process of upgrading to a newer version of the library that has a proper instantiated service object instead of global static calls, which will allow us to properly mock it, and save Stripe tens of thousands of API hits per day and us probably multiple minutes on every test run. But it's a slow process, and taking a lot of time/money to clean up. > > *This is why static APIs are bad*. That's not just me making stuff up, this is a well-understood principle around anyone who's done any serious work with unit testing. It's easily the #1 argument people use against Laravel, which also does a lot of static APIs and is, guess what, extremely hard to test properly as a result. > > A language-level feature that explicitly endorses and encourages those all-static APIs (which is what is being proposed) would actively encourage code like that Stripe library, which is wasting time, money, and network traffic for us literally every single day. We should be discouraging that design, not encouraging it. > >>>> The proposal is designed with the intention of improving code clarity, >>>> reinforcing design principles, and establishing a clear and standardized >>>> approach to expressing the intended usage of a class. While I advocate >>>> for member properties and methods to be implicitly static, I am open to >>>> understanding alternative viewpoints on why this might not be the >>>> optimal choice. >>> Emphasizing: >>> >>>> reinforcing design principles, >>> Which is exactly the problem. All-static classes *are a bad design principle that should not be encouraged*. They're a namespace cheat, not a good design. They should be discouraged, not encouraged. >> They could be used as a namespace cheat yes, they could be used wrongly, >> but that doesn't mean it doesn't have any valid uses or make it >> inherently bad. You remind me of the people that literally never use >> inheritance because they read "inheritance over composition" somewhere. >> Please elaborate more on why it's a bad design principle. > See above. > > (sarcastic sniping removed) > >> I am still holding out for a productive conversation based on facts, >> regardless, you are entitled to your opinions on the matter. > That static methods make unit testing harder and sometimes impossible is a fact. That is not an opinion, it is an objective fact. > > Language features that encourage making testing harder are bad features. > > That's the long and short of it. > > --Larry Garfield >