Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:121732 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 29714 invoked from network); 20 Nov 2023 20:01:08 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 20 Nov 2023 20:01:08 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6B92818002B for ; Mon, 20 Nov 2023 12:01:09 -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=-3.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_H5,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 out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) (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 12:01:08 -0800 (PST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 2DFDC5C05DE for ; Mon, 20 Nov 2023 15:01:05 -0500 (EST) Received: from imap50 ([10.202.2.100]) by compute1.internal (MEProxy); Mon, 20 Nov 2023 15:01:05 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= garfieldtech.com; h=cc: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=1700510465; x= 1700596865; bh=dIBvaJ8GLBGkO+a/Bz0Akwmq6rxLYXyAbxetGeZ7he0=; b=x 4P7Yqp5e6fHtd6z7UZ8AxU/hSBGNJTysfo2urZWkvKsoJCWxSXa6/MN0Dh3Dfmdd Xz0lFgSor4CL27BrC3BxCnW4g7b/5kFWn13Epzp2C/A3noTrc+hGxE2g7q0U9KxH HlTnGe/p9xHrxxeAtndl0747Y/xgZ9Uvm4bfdpZIAqVG5oXRAtUg0a0qfFlSpJsg tGe6DpsFzEbYhVLGTYoItPzp29yZZleCMM0RmKdWGNGL8PoVTRAGmRdUrV5t7A5S Gjnh+aaYkJG9zVxDbzNcpfJzFm4pX4NqM5EDxJgFNFi8l+MzZup0SLJeCOnOiF5z YKBcAEX1mCZDbodIErRig== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc: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=1700510465; x=1700596865; bh=dIBvaJ8GLBGkO +a/Bz0Akwmq6rxLYXyAbxetGeZ7he0=; b=R8QeQgbx4OvtPICPyf/waRy8z0Rls YQt7NxBNESytFtzqZXFjMX1851ffnqkZ4/U4WFH1YITorYAjiudAnECT+AMs5Ci2 yu65c2V9w2kHu1CP+giPaqdtHFWEXIt/sbM9kdeDWD0o63ZBh7/iAJrkvDw469Dt 8BYzKW2EIRyfPmHbpka/cAJ/vhH2S/xE/piHj7UpRIg5m69yZJjgmVr09rpNAGbM lDeIfcqMIX9c5LUi/rRZbeiVwzx0GFda9im9RMj75X/0okS4qYnqs3Yq7+XaeBxi YyA7CKzs+sW52i3pP3hMq7iBZdqfIXvGLKv8QHLBvlwoqKWK493ktfcdA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrudegjedguddtgecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpefofgggkfgjfhffhffvufgtsehttdertderredtnecuhfhrohhmpedfnfgr rhhrhicuifgrrhhfihgvlhgufdcuoehlrghrrhihsehgrghrfhhivghlughtvggthhdrtg homheqnecuggftrfgrthhtvghrnhepgeefffekleetgfekleegleffffdujeejvedvjedt leekuddufeelleevffeuheejnecuffhomhgrihhnpehphhhprdhnvghtpdgvgihtvghrnh grlhhsrdhiohenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhr ohhmpehlrghrrhihsehgrghrfhhivghlughtvggthhdrtghomh X-ME-Proxy: Feedback-ID: i8414410d:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id 8BAEC1700089; Mon, 20 Nov 2023 15:01:04 -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: In-Reply-To: References: <79d675e3-95b4-40bb-baf4-3e1c998f5390@online-presence.ca> Date: Mon, 20 Nov 2023 19:59:10 +0000 To: "php internals" Content-Type: text/plain Subject: Re: [PHP-DEV] RFC Proposal - static modifier for classes From: larry@garfieldtech.com ("Larry Garfield") On Mon, Nov 20, 2023, at 7:52 AM, Rowan Tommins wrote: > On 19 November 2023 21:28:08 GMT, Lanre Waju wrote: >>Hi, similar to the abstract and readonly modifiers to classes (similar in syntax only), I propose a class level "static" modifier that ensures: > > > Hi Lanre, > > There was a proposal for this several years ago which was declined at > the voting stage: https://wiki.php.net/rfc/abstract_final_class > > That doesn't mean we can't look again, but any new proposal would need > to at least address the reasons the previous one was declined. I > believe these are the relevant discussion threads: > https://externals.io/message/79211 https://externals.io/message/79338 > https://externals.io/message/79601 > > My memory is that one of the main points against was that a class with > only static methods is just a namespace, and you can already put > functions directly in a namespace. The only issue being that we don't > have good autoloading support for such functions, and that's a whole > different problem... I wasn't a voter at the time, but I would absolutely vote against a `static class` RFC today, for largely the same reasons. On Mon, Nov 20, 2023, at 8:35 AM, Lanre Waju wrote: > 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. Rowan already mentioned the maintenance burden that it entails. I'll go a step further. We've already seen that "readonly" properties have their uses, though not everyone uses them. So far so good. But readonly also was implemented with a stealth extra asymmetric visibility implication, which made the design and implementation of real asymmetric visibility harder, and very likely contributed to that RFC not passing due to the perceived extra complexity of working around readonly's shortcomings. 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. 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. Certainly, many features are worth the extra burden to maintain and to train for. We pass new RFCs all the time that we collectively decide are worth it, I've proposed several, etc. But "if you don't like it, just ignore it" has always been a misleading and ignorant claim to make about any proposed feature. "The implications are small so you probably won't need to worry outside of these situations" is a valid argument to make (and to disagree about), but that's a different thing. > 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. If the methods are pure functions, then they really ought to just be namespaced functions. Those work. They're fine. Autoloading is frankly mostly solved by using the `files` block in your composer.json's autoload config, and then you don't need to care. Pure functions are OK. The obsession with avoiding functions in many parts of PHP culture is really not to its credit. (And I admit going through my own phase where I thought that; it was incorrect then, it's incorrect now, and it's been incorrect pretty much since 5.5 gave us an always-on opcache.) If the methods are non-pure... then it has no business being a static method. It needs to be an object method, otherwise it breaks testing. Yes, there are a lot of older libraries and APIs that use static methods in a stateful way, or make IO calls to a remote service, etc. Those libraries are wrong. Period. Language features that encourage that anti-pattern are anti-features. Those should be instantiated objects which can be injected and mocked and use mocks and be tested easily and so on. To be clear, static methods have their place. I'm not against static methods. I'm against static methods as a cheap discount-bin namespace, as that shows a lack of understanding of the language and of OOP design. Yet that is precisely what `static class` would be. If we really wanted the language to reinforce good design principles, we would make a class that has only static methods and nothing else a syntax error. :-) I do not proposed we actually do that, but that's what "reinforcing design principles" would mean in practice. --Larry Garfield