The PHP 7 Revolution: Return Types and Removed Artifacts

There is a big difference between voluntarily migrating to a new language (which I have done 3 times in my long career) and having your existing language changed under your feet without your approval.

I still would have questioned the need for such a change which did not fi any problem but which instead created them.

Are you aware for example that shortly after PHP 5 came out some over-eager core developer decided to remove support for the “var” keyword with the justification that developers should be using “public/private/protected” instead? He was quickly shot down as this was considered to be too much of a BC break for too little benefit to anybody.

Not at all. I changed my framework to allow the use of either the original or the improved extension for MySQL as soon as I had upgraded to MySQL 4.1 and the “improved” extension became available. My code will use the new extension if it has been loaded, but fall back to the old one if it has not. I did not wait until the old extension was marked as deprecated before I made that decision because there were genuine reasons to use the new extension. There are NO such genuine reasons for removing PHP 4 constructors.

What’s the problem with the return types feature?
Either

  1. return an example type, e.g.,
    return 0; //int return “”; string return ;//array , return “True || False”; (recognizing that True or False evalutate to an int 1 or 0) and so on.
  2. dual purpose the ‘as’ keyword and a string representation of the type, e.g.,
    return as “int”; return as “string”; return as “bool”; return as “array”; return as “array” “iterator”; OR return as “array iterator”; or as a shorthand to returning a string, return as “”;
  3. create a “type” keyword just for this.
    return type “int”; return type “bool”; return type “string”; return type “array”; OR the specific return type “array” “iterator”, and so on…
    With strings, a lot can be accomplished, solved. Good Luck.

On return types, it seems a bit remiss to just typehint and return typehint “array”. Shouldn’t we be have : int or : Object arrays being type hinted?

If the RFC was to suggest that, you can be sure it wouldn’t have passed, and thus we would not have ANY type hints.

There was a separate RFC about collection type hints (parameter type hints; but it would’ve applied to return ones, had it passed). It seems it’s been removed, as I can’t find it in the current list of RFCs.

If I remember correctly, the biggest discussion that stood in its way was about NULL as a value. On one side, you have people who believe NULL should not be allowed by this type hint by default, or be in any way doable, while on other you had others who thought (I can imagine for ease of implementation reasons…) believe NULL should be allowed, and some who even proposed it should be so by default when using this type hint. In my personal opinion, those type hints should behave same as today - not allow NULL by default, unless null is specified as a default value.

I don’t understand this; do sites just suddenly stop working when a new version is released? Is every version of PHP going to suddenly upgrade to 7 when it comes out? Am I missing something, or aren’t there plenty of hosts still running PHP 5.3? Any developer who is using PHP4 constructors has a long time to get that fixed before 5.6 is EOL’d, and if the current method of using them can cause conflicts, I’m not sure what the downside is here besides a principled stand against things changing.

I was not, no, but I am aware of quite a few shenanigans from the internals discussions - it’s often been a tragicomic adventure. : )

I believe the argument here is that Tony likes to keep the PHP version up to date, but not the code. In other words, the effort it takes to modernize the code to best practices as recommended by the internals group is not worth it, while the effort of upgrading to a new version of PHP (arguably taking longer), is.

I can sort of relate to this, to each his own after all, but it still seems like resistance for the sake of resistance.

I do completely agree with Tony, however, that a deprecation notice should be implemented first, before removing functionality that can cause BC breaks. It’s simple custom and good manners. Let’s hope the PHP 5.7 vote re-opens soon, and that the meta-version comes to life for the sake of easier adoption. PHP 7 is shaping up to be absolutely amazing, and it would be a shame if all those stuck on horrid old code were abruptly left behind unable to upgrade versions just because of inertia.

There are two degrees of “hurt” when you break BC.

The first is if you do any BC breaks at all you need to involve a developer to do an upgrade. That’s problematic for existing deployed software, because there might not actually be a developer around. At that point, it may make more sense to switch to a different platform / solution entirely. Any BC break in PHP therefore leads to users abandoning the platform. Meanwhile, you don’t gain any new users, because supporting less syntax never wins someone over. Only if you break BC to introduce new and amazingly improved syntax do you gain users. Breaking BC loses you users but doesn’t win you new ones to replace them. Maybe those lost users are the kind you don’t want, but still, it happens and it is a choice platform owners must make deliberately. For me this would be a reason to never drop support for old syntax unless it is needed to introduce new syntax. I would have kept the old constructor syntax in.

The second is death by a thousand paper cuts. Every BC break adds cognitive load to the developer supporting their software. Each time you need to change, and retest. Real world software does not have perfect unit test coverage, so costly manual testing is necessary each time, which you shouldn’t force your users into unless it’s really necessary. That’s why when you need to break BC, you should do it all at once, so for me PHP 7 is a good time to do it. However, that does not mean that breaking BC in every PHP release is a good idea. PHP’s strength is BC support. Let’s not lose that.

Finally, let me mention that if PHP had LTS releases this issue would be much less critical. If say PHP 5.6 was supported for 10 years after its initial release (similar to what Microsoft would do with their server products), then people could migrate those codebases as part of the natural upgrade cycle that befalls all software. Again this is a choice you make as a platform. Drop support quickly, and you bleed users but have the agility to win new ones through building a better platform. Drop support slowly and you have a larger user community, but platform improvement must happen orthogonal to existing syntax.

All I would ask for is for choices around BC to be made deliberately and with due consideration to the difficulty of finding resources to adapt a codebase to changes in the underlying platform when the business owners want us developers to be building all features all the time.

3 Likes

Excellent feedback, thank you. You make valid points.

I often wonder why they don’t have a simple ini_set command to essentially say “I want BC” as they did with ini_set(‘zend.ze1_compatibility_mode’). This is a best of both worlds approach as it allows people to upgrade their PHP version and at the same time, individual scripts can easily be fixed by a single line at the top of the page.

Alternatively do it like Perl with “use strict” and have it enable a set of BC breaking features. Anyone who develops with this flag turned on knows what they’re doing. Even better, make it a per-file flag and all problems are solved.

Yes, If they try to upgrade to the new release.

No, because their applications will more that likely stop working because of a BC break.

They are still running older versions of PHP simply because their customers’ applications won’t run on the latest release due to all those BC breaks.

PHP 4 constructors are still fully supported in PHP simply because they have NEVER been marked as deprecated, so to say that they are obsolete and should not be used is just plain WRONG!

[quote=“mAAdhaTTah, post:40, topic:110202”]
and if the current method of using them can cause conflicts, [/quote]
The only “conflict” that has been reported is where a newbie programmer creates a class method with the same name as the class, and without a separate __construct() method, without realising that it automatically becomes the constructor instead of a separate callable method. Such newbie developers should RTFM (Read The Friggin’ Manual).

The downside is all the unnecessary refactoring that developers have to go through in order to upgrade to a new release because of a frivolous BC break. I use the term “frivolous” because it is not to solve a genuine bug or security issue.

There simply needs to be an ini switch which enables php4 constructors and all these issues are solved. It’s off by default and people with legacy code can enable it. Newbies don’t get confused, the manual can be simplified and anyone who really needs this behaviour can enable it.

I agree that breaking BC for everyone is not really a viable solution. It causes problems because someone can’t simply upgrade PHP on a site without investing time redeveloping parts. Clearly that’s not good from a business perspective. The result of this is that old PHP versions stay on servers running old sites, which then become security issues because updates are no longer issued for those versions.

Breaking BC for everyone is a bad move but so is keeping BC for everyone.

FWIW: It would take about 10 minutes to write a script that updated all PHP4 constructors in .php files to use the PHP5 __construct()

Then take a look at http://php.net/manual/en/language.oop5.changelog.php which show that this faux pas was fixed in version 5.1.3

Correct. I want to ensure that I am up-to-date with all bug fixes, but I do not see why I should be forced to refactor my code for an unnecessary and frivolous break in BC. If it is a choice between a single core developer doing an hour’s work and 240 million website owners doing an hour’s work each then which would you describe as being the most cost effective?

Wrong. I am complaining about being forced to do some unnecessary refactoring because of a frivolous break in BC.

Your use of the word “horrid old code” is entirely subjective and unnecessary. Code does not have to be “pretty”, it has to be “effective”. Ugly code which works is far better than pretty code which does not. I do not like having to refactor my code just because some junior programmer has taken it upon himself to redefine what “pretty” means.

This was discussed on the internals list and rejected. Quite rightly, as far as I am concerned.

Why is keeping BC for everyone bad?

That’s still more effort than would be required to leave them in.

Because it gets in the way of the language evolving and improving. It would be very nice if PHP fixed the inconsistently named str* functions but they can’t because of BC.

10 minutes every 10 years doesn’t sound bad to me. PHP4 constructors have been referred to as “old style” in the manual for quite some time (Possibly even since PHP5 was released)

I am grateful that you have taken it upon yourself to engage in this topic. I know how much effort it takes to argue against such a tide, and standing your ground so firmly is admirable at the very least. I also appreciate and understand that you may have code you don’t feel like refactoring, and I completely agree that a feature should be marked deprecated before being removed. But I assure you, and I say this with the utmost sincerity, that I am junior to you only in age. That is not to say I may outdo you in this or that kind of task, but that I have seen and dealt with enough code, both legacy and up to date, to be able to objectively conclude which code is and is not pretty. One might argue that beauty is relative, and prettiness of code in peers of the similar level of experience may very well be, but generally, a senior will likely be able to recognize pretty (and, by extension, ugly) code sooner than a junior.

Just as we once considered crinoline supported dresses to be what gives women the default of beauty and elegance, and doctors recommended cigarettes as a good solution to that nasty cough, so too can code standards change and we can alter opinions on what good, healthy and pretty code should look like. Not based on feeling or a mere whim, but based on research and countless experiences in the field.

I would argue, therefore, that code that has the potential to confuse, even the least bit, is uglier than code which is effective.

2 Likes

The language can be improved by adding new features, but the removal of an existing and still used feature will NEVER be regarded as an “improvement” by all those to have to spend valuable time in refactoring their code.

The str* function names are not inconsistent - they are consistent with the names of the corresponding functions within the ‘C’ language upon which PHP is rooted. Besides, the “funny” names do not prevent millions of developers from writing effective programs. I myself cannot remember the name of every available function and it sequence of arguments, which is why I use a proper IDE instead of a primitive text editor.

You must not have any experience with .NET then :smile:

Major versions (based on any version pattern your read) typically do not guarantee backwards compatibility. PHP has been permitting this for so long, it is likely leading to code staleness, redundancy, additional tests, and many hidden problems as they implement the same feature in different ways. It isn’t good for the language as a whole for those reasons, let alone the support time it takes to properly ensure each way a feature can be implemented is working properly.

Don’t get me wrong. I’ve enjoyed PHP since I started using it when it was in the stage of going from PHP 3 to PHP 4, but I’m completely shocked they really haven’t introduced breaking changes across their major versions (to the extent .NET has).

.NET 1.1 had many breaking changes when going to 2.0, then it had a few more going to 3.5 and 4.0 introduced even more. All of the changes actually have been better for the language. It standardized a lot of the internal classes of the framework and it speed up the CLR by allowing it to do less processing.

Their support time increased and their development time for patches also saw improvements since they didn’t have to support the initial implementations that existed way back in 1.1. As a whole the language was in better position to tackle “how can we help our developers use this language going forward” versus “how do we ensure we don’t break X which still exists from 2-3 versions ago”.

As a developer, I write a lot of APIs (that is probably 80% of the work I do on a regular basis). If I had to support v1 of the API and keep it running through v4, I’d go crazy. The amount of bloat that would add, the strain it would be on our QA department, and the little benefit it would really have for our users isn’t worth it. There are reasons why changes were made, to provide a better overall experience/performance boost.

You may see it as unnecessary changes, but really it is a gateway for you to radically improve your codebase and reconsider some of the legacy aspects of your product. What you did back then, might not be the best approach, best performing way today (I know code I wrote in PHP 4 definitely wasn’t the best approach to what exists today).

2 Likes

So you’re expecting developers will upgrade to PHP7 and leave their code exactly as-is? But we shouldn’t fix this conflict b/c it caters to newbie developers?

I mean, PHP7 is a major release; while I don’t know for sure, I’m extremely doubtful the only change you’ll have to make to your code to make it work with PHP7 is changing your constructors. If this is one of several BC-breaking improvements to PHP, I really don’t see why this is an issue.