On Mon, Apr 10, 2023, at 10:09 PM, Deleu wrote:
> On Mon, Apr 10, 2023 at 7:03 PM Larry
>
>>
>> Again, let's assume there is no question it will happen.  The question for
>> you: What process for making it happen would you consider sufficiently
>> BC-friendly?  What timeline?  What level of pre-review?  What reasonable
>> process would you propose that maximizes the ability of the language to
>> remove its own design bugs while minimizing the hassle for responsible
>> developers?  (Responsible: They actually pay attention to upcoming changes
>> and prepare for them in less than 7 years.)
>>
>
> What I would consider sufficiently BC-friendly is having a cut-off. Any
> code written by the previous generation (folks that are long gone or
> retired by now) continue to work as it used to while I catch up in removing
> it from production systems. If the code was written in 2010 or earlier and
> uses $a++; with the expectation that it will result in "b", leave it as-is.
> If the code was written in 2018 or earlier, feel free to break it.
>
> Several discussions around this have happened, but unfortunately none
> landed anywhere. Whether it be a new opening tag of <php8 or <php9 or a new
> directive/edition. In fact, if we're talking about my opinion only (what
> works for me personally), make this change behind the existing
> strict_types=1. There's no "PHP 5 Era" code under my responsibility that
> has strict_types enabled so if it were up to me, make every BC break you
> want behind strict_types=1 but keep PHP with strict_types=0 running without
> BC breaks for about 10 years.
>
> When PHP libraries break BC, it often comes with options of 1) extend the
> original class and override something 2) opt-in to old behavior 3) register
> a callback that can be used to define the old behavior back in or 4) work
> with an interface or 5) last resort to fork the library if taking the
> maintenance burden is worth it. I don't have any of these options when PHP
> breaks BC.
>
> Yes, old PHP has some bad and weird behaviors. I don't like it, you don't
> like it, nobody likes it. I don't want to use those weird stuff, but I'm
> doing the best I can to replace every single line of old code that has been
> written in an era that "best practices for PHP development" were not what
> you and I know today.
>
> Take PHP 7.2 deprecation of counting non-countable arguments. Could that
> broken code have been taken out of PHP Core, made it available as a legacy
> PHP extension and just kept alive for the foreseeable future? Can we have
> an additional PHP extension that allows us to still pass null to
> non-nullable internal function parameters? Something like php56_substr().
>
> I don't mind if its BC breaks are opt-in or opt-out as long as we can have
> a single cut-off and make it easier for us to keep running legacy code
> until we succeed in decommissioning it.
>
> In fact, if you wanted to deprecate `readonly` in PHP 8.3 because (as
> you've said it), it's a broken behavior that prevents you to move forward
> with asymmetric visibility or property accessors, I wouldn't care because
> readonly was something introduced in a time that the code being written
> using it has 100% test coverage and static analysers protecting it. It's
> easier for me to deal with any BC breaks of PHP 7.1 or higher than it is to
> deal with deprecations of PHP 5.6 or lower.

Thank you, now that's a proposal that we can actually discuss.

That said, I don't think that strategy would be viable, for a couple of reasons.

1) It assumes a strong correlation between "code was written in <2010" and "the 
QA process is crap", and likewise between "code was written >2010" and "the QA 
process is pretty solid."  I strongly suspect that correlation is a lot weaker 
than you make it out to be.  The really-old public projects I know (I've worked 
on Drupal and TYPO3 cores personally, both of which are 20+ year old code 
bases) have pretty solid test coverage now, and ample QA processes around them. 
 They're possibly tedious to update for deprecations et al, but not per se 
hard.  In contrast, I now work with some 7.x-era Laravel projects that, well, 
"get the QA tooling out of the stone age" was the first task I took on when I 
joined the company because they desperately needed it.  I don't think "it's 
newer so the QA safety net is in place" is a safe assumption.

2) The vast majority of issues that need to be fixed are the old stuff; most 
are from PHP 4 or PHP 3, so we're talking pre-2005.  The features introduced 
from 5.3 onward are, for the most part, pretty reasonable.  (Not perfect, but 
way way better than the PHP 3-era stuff.)  So "you can only clean up recent 
messes" translates to "you can never clean up a mess."

3) There can absolutely be code written in 2020 that relies on the current 
behavior of array_sum, or $string++, or passing null to strlen().  Some of it 
has been mentioned in this thread.  So "only old code relies on old, bad 
language design decisions" is not really a safe statement, either.  We could 
say "well those devs should have known better," but... in most cases the code 
from 2005-2010 was also written by devs who "should have known better," as many 
of these issues were known-problematic even then.  (Dynamic properties, for 
instance, have been not-recommended since at least 5.2, if not earlier.)

4) It doesn't answer the question of when it *is* OK to start fixing the old 
issues.  "When I'm done cleaning up the mess I inherited" is not a metric that 
Internals can really work with, but locking in "bad design decisions from 
before 2010 are locked in forever, just in case, but we can correct stuff after 
that without warning" is not really sustainable.

5) Different running "modes" have been discussed several times.  Usually they 
come back to "if we were to do it, declare statements are the best mechanism."  
But they also almost always run into "every declare statement means we have to 
add a bunch of conditionals in the engine or stdlib to check it, which is a lot 
of complexity to maintain."  And those are multiplicative, so if, eg, we added 
declare(allow_dyn_props=1), declare(allow_null_string=1), and 
declare(modern_numeric_strings=1), in addition to the existing strict_types, 
that's 2*2*2*2 = 16 possible combinations of run modes.  Regardless of what the 
default values are, just thinking about the number of test cases that would 
need to be written for that makes me sweat.  And that's before we even get into 
bifurcating PHP into multiple incompatible rulesets that make it hard for 
anyone to even learn how to use PHP.

If you want to polyfill old core stdlib function behavior, there might be a way 
to be extra tricksy with namespaces and autoloading (if that passes) to make 
something work, but that sounds unreliable.  The real answer here would be the 
old runkit extension, but most people who know of that are afraid of it, 
because they know exactly how much confusion that could cause. ;-)  

If the stdlib were written in PHP, not C, as has been suggested a few times, 
that might open up other options.  I've not thought that through entirely.  
That's still not at the point that it wouldn't have a performance impact to do, 
though, which is why there's been no serious attempt at it.

--Larry Garfield

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to