Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:121741 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 48922 invoked from network); 20 Nov 2023 23:29:12 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 20 Nov 2023 23:29:12 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 4B2C118003E for ; Mon, 20 Nov 2023 15:29:14 -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.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) (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 ; Mon, 20 Nov 2023 15:29:13 -0800 (PST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 7E47B5C15C7 for ; Mon, 20 Nov 2023 18:29:09 -0500 (EST) Received: from imap50 ([10.202.2.100]) by compute1.internal (MEProxy); Mon, 20 Nov 2023 18:29:09 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= garfieldtech.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1700522949; x=1700609349; bh=WUqYtC8pDz oMgVC4byQ/mMPR12zpRiPe+n8iOSiBt0w=; b=QF3RlI/KDWeDBMd0OZ/qEgpyzk ft+Tdfi93s2n8FmlP8GjwOViqefaLQlZGsaA1KUUtZ80A/GIRKXDUSN5mvyMgkyP kZY/A/s1br7xgBEbG7nOpDRNHR87mfgu+0NpllgQjJp5t9UuSPq22rWCbt7jHoVk 1BkpjWACp8NPZDJYo3U0GMkYWJ0xqVJ8Ai0T1N1sBCro4CGGRiTZsQvhg1JNGg6y VpCNTYuusA28h47JoQ2CK0fueK/DMEIeQQAYSB9TM/lbzyG3zrOmlg6xL1a4FRtu qLc1sOHUzBp8MMtH779HIUtuhldtJ7MlwH1xXpvX+lyAde8W9LgLcwvhQvhg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1700522949; x= 1700609349; bh=WUqYtC8pDzoMgVC4byQ/mMPR12zpRiPe+n8iOSiBt0w=; b=M awGxYvOLJKSZsUww4Owf8D3XjdzZwkScc1P8V7K/NzHsN1/eAaIUvGTNaICKT8mj bSLbHXXnkqyuNmv6+Q+rh+QOOqt8DHZwJhg3u4vZuv5+M7WIiS3xxXTnsJKB8QkK Pe5g5R8jfTwYbCoaEOodWF6ISgGAz/iskMw1O6DpViM6KrNTIDuHAIWU9m+8/5y+ A/Q8/CF8qVaNrnPW6TEozz0Q1ESkbtEvbJIvNw6I3txGU2pSRICd/lIhiZ4FhDtO F+2gdN3c3r6ME6AKDMy992uxEBLeROhCvcHRvAt1Lc85MAIrI7MRl6OmPonKI37U lRSUjNRJDQPxUfe6UqLJA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrudegkedguddvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepofgfggfkjghffffhvffutgfgsehtqhertderreejnecuhfhrohhmpedfnfgr rhhrhicuifgrrhhfihgvlhgufdcuoehlrghrrhihsehgrghrfhhivghlughtvggthhdrtg homheqnecuggftrfgrthhtvghrnhepffffffejffdugfegvedviedttedvgfejffefffej leefjeetveehgefhhfdvgfelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpe hmrghilhhfrhhomheplhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrdgtohhm X-ME-Proxy: Feedback-ID: i8414410d:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id E65461700089; Mon, 20 Nov 2023 18:29:08 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.9.0-alpha0-1108-g3a29173c6d-fm-20231031.005-g3a29173c MIME-Version: 1.0 Message-ID: <2dc2e032-b10b-4d50-9a64-8f88c37583d1@app.fastmail.com> In-Reply-To: References: <79d675e3-95b4-40bb-baf4-3e1c998f5390@online-presence.ca> Date: Mon, 20 Nov 2023 23:28:35 +0000 To: "php internals" Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] RFC Proposal - static modifier for classes From: larry@garfieldtech.com ("Larry Garfield") 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=C2=A0cannot be=20 > instantiated in which all members are implicitly static. We already ha= ve=20 > static members, so please elaborate on the maintenance burden that=20 > adding static to a class as that could help explain better, i mean wha= t=20 > feature doesn't have technical debt associated with it? The new JIT en= gine? That's part of the point. Literally every feature added to a system (PH= P or otherwise) has some maintenance overhead associated with it. It ma= y 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 tha= t"); } public static function beep(): string { ... } public static function boop(): string { ... } } Much the same way a readonly class is. Is that understanding of the int= ent 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 p= retty much never used except with some families that teach their childre= n 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 kn= ow me as that more than as Larry. (I am not offended, just noting a cul= tural mismatch point.) >> Similarly, if we add a static marker to classes, that means all futur= e improvements to classes need to consider "but what if the class is sta= tic?" Eg, there was discussion a while back about `data` classes. What= happens if you have a `static data class`? Is that a syntax error? Do= es it work? If it works, what does "work" mean? What about sealed clas= ses? Can you have a sealed static class? What would that mean? Those = are questions that would need to be answered, because this feature exist= s. > Either i'm in an alternate reality where the data classes and sealed=20 > classes rfcs passed, or I've just been straw-manned. Either way, is it=20 > really that difficult to decide on as a community what a static data=20 > class implies? We have already established that a static class means a= ll=20 > 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 a= nd Sealed classes are ideas that have been floated but never to a full R= FC, but may end up as an RFC in the future. They were convenient exampl= es of future work that would be impacted by adding a static keyword to c= lasses, as those RFCs would have to determine how to interact with stati= c classes. Maybe the solution would be simple, maybe it wouldn't, I hav= e no idea. It is just an example to show that the cost of adding a feat= ure 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-w= ritten codebase anymore. 99% of projects are 80% someone else's code vi= a 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 sta= tic class as part of its API, I am now forced to work with static classe= s, whether I like it or not. > If you had told me we were allowed to pull numbers out of our asses, i=20 > would have mentioned that 100% of php users will benefit from this,=20 > Including people like you who don't necessarily see the value in it. A= s=20 > a user of a class, it shouldn't matter whether it's static or not, the=20 > static members will be the same as using a normal class with static=20 > members, in fact, people already simulate this in userland by making=20 > __construct private and only using static members, does that impede yo= ur=20 > ability to use such libs? How is this forcing you to use static classe= s?=20 > The dev of said library(which no one is forcing you to use) would be t= he=20 > one who made that call. After which it's your call to decide whether o= r=20 > not the library suites you. I don't see any forcing here but do=20 > 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 libr= ary, 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 li= brary that has a proper instantiated service object instead of global st= atic calls, which will allow us to properly mock it, and save Stripe ten= s of thousands of API hits per day and us probably multiple minutes on e= very 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, extre= mely hard to test properly as a result. A language-level feature that explicitly endorses and encourages those a= ll-static APIs (which is what is being proposed) would actively encourag= e code like that Stripe library, which is wasting time, money, and netwo= rk 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 clarit= y, >>> reinforcing design principles, and establishing a clear and standard= ized >>> approach to expressing the intended usage of a class. While I advoca= te >>> 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 p= rinciple 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 wrongl= y,=20 > but that doesn't mean it doesn't have any valid uses or make it=20 > inherently bad. You remind me of the people that literally never use=20 > inheritance because they read "inheritance over composition" somewhere= .=20 > 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,=20 > 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