Does updating dependencies break backwards compatibility (semver major version change)? - php

Let's say I publish a new library Foo v1.0.0 which requires php 5.6 as a dependency.
Now I would like to use some of the newer language constructs in php 7.0 internally within some of the method implementations. However, my entire public API (method names, parameters, returns, etc.) remain unchanged.
Following semver, what version number should I now release?
It seems to me that requiring a new major platform dependency will break backwards compatibility for existing users running php 5.6 who will not be able to simply upgrade with composer update so it should now be v2.0.0. On the other hand, because nothing has changed about my exposed API, I feel like this should instead just be a patch v1.0.1

No, you got wrong what backward compatibility means. If your library's API remains unchanged then it may be just new major version but it is still backward compatible, which means upgrading does not require changes in code using your library. Requiring PHP 7 is just requirement but it got nothing with compatibility.
Other projects I saw usually do major number bump but that's mostly because they only changed requirements but also did some changes to benefit from i.e. new PHP functionalities. So ask yourself if you will really benefit from just requiring PHP 7 or it will be sort of cosmetic change or code cleanup. It also depends how many users your change would really affect.
EDIT
Requiring PHP 7 is sometimes huge change as many people are still on 5.x and don't want or can't upgrade yet and while it is not the backward compatibility issue here, I'd make it 2.0.0 to clearly indicate this change as major.

Related

What are the consequences of using a non-semantic version number in composer for packagist?

I want to publish a fork of a PHP library on Packagist.
However as not really big changes may be made we want to use the official version number and just modify it a bit to add our own one.
So in the end we came up with the idea of a version number like this one: v1.1.3-CE.1.
However there is a problem: This is not a semantical one. And especially for composer/packagist everywhere it is recommend to use semantical versioning.
But as you can see it is still quite similar to a semantic version number, but we misuse the "pre-release version" "tag" (which is normally alpha, beta or similar).
That's why I'd like to ask what effect non-semantically version numbers as our one have if we use them in composer? Are the updating processes affected e.g.?
If you really discourage us from using such a version number construction, we may also use a new version (starting from 0.1) for our fork, but we do not really want to do this.
If you fork, you have a new package. So you require a new package name.
Not renaming your fork will lead to problems. First of all, you will publish new versions of the same package name parallel to the original. This will lead to angry users if you succeed, but it is more likely that the original vendor name is protected on Packagist, so you already cannot publish the fork under the same name, no matter which version you assign.
So it is a new package name, but you are free to start with any version number you want. Note that semantic versioning does have different rules for the "0.x" series, specifically a minor update can break compatibility there. That's why Composer's ^ caret operator behaves differently: ^1.2.3 would allow updates up to 1.99999.99999, but ^0.7.1 will stay inside the 0.7.x range.
Don't overload the stability flag with something meaningless (i.e. I don't know what "CE.1" means or should indicate). Stability flags work great to tag pre-releases (with alpha indicating it is likely that incompatible changes will occur, beta indication compatible changes, and RC indicating only bugfixes) that are not meant for general public consumption.

How to version-control different features within one web application?

We have some web applications, and now these websites are being upgraded, not for the first time, but it is becoming very dificult to control the version for the users and for the developers.
We have many clients, some of they are running the same application, but they need to pay for upgrades. But, not all clients pay for upgrades, and because this we have some clients running one version and another clients running another version.
We have two ways, and we are researching for a third way:
Put the version in the path, like this: www\project\version\system-files
But this way became confusing for some users, because for they the URL became: www.website.com/app-version, and when the system is upgraded, the URL change.
Put the version in the function, like this: function V1_functionX()
When the function need to be upgraded, we create a new function called V2_functionX. But, this create a "fat" website, and the team did some mistakes during development, because we don't have "one development version", but "many versions to develop", and some functions are used in more than one website.
The very first way was abandoned a long time ago. We developed the web application, and "closed the version", and all requests was included in the upgraded version, that version when finished was "closed" too. But this was too slow too made corrections and deploy "small upgrades"
We talked about the way in another companies: they "shutdown" the website to upgrade the system. This will be probably our way.
But, if anyone have another idea to not shutdown a website for upgrade the application, we will be glad to listen.
Note: this is not about SVN.
You say you have different versions of your applications that must be maintained for different clients. I expect you don't need me to tell you this adds significantly to the complexity of your overall system, and thus your first priority is to reduce the number of versions you are maintaining in parallel.
API services have the same problem: a new version with more features is offered, but the old one needs to be maintained to give the new version time to stabilise and to give users sufficient time to upgrade their code. Your difficulty is similar. The first question I would therefore ask is whether it is possible to maintain only two versions.
If that is not possible, try at least minimising the number of concurrent versions: where a new version must be created, you need to encourage users to migrate from one version to another. (You've said you cannot unify your users onto one version, but without further information about your exact use-case, it is not possible to offer an independent view on that). So, perhaps one approach is to never maintain more than, say, five versions.
There are a number of strategies you can take to mitigate the complexity of the system you now have. Firstly, consider separating your code into a "core" of features that all versions absolutely must have. This will be common to all versions, so that if you fix a bug here, all clients benefit from the fix. This might be a visible feature (e.g. a product editing screen) or a framework feature (e.g. force SSL during checkout).
Your core libraries and client-specific functions could then reside in a set of libraries like so:
/project/core
/project/versions/1/Class.php
/project/versions/1.1/Class.php
/project/versions/2/Class.php
/project/versions/2.1.1/Class.php
/project/versions/...
(Class.php is of course an example - in practise there would be many class files here, each named appropriately.)
In this way, you do not need to call functions with a V1_ prefix, since that will require the replication of your version choosing code in a lot of places. It is much better to just load the library pertaining to the correct version, and as long as the function names are the same across all versions, you can just use the function name and your library loader will take care of the rest.
Another approach is to use plugins, like WordPress does. Where a plugin is added, it modifies some core functionality by adding new or different behaviour. The "middleware" design pattern may be useful here - the Slim framework (and undoubtedly others) uses this approach to add pre- or post-call hooks to an existing route handler, and thus offers a clean mechanism to edit existing functionality in a variety of combinations.
To summarise, your current situation is not just a management problem, but will cost you in slow development time and additional debugging. Whilst the above approaches will still be necessary to reduce some of the complexity, consider also:
forcing laggard clients to upgrade to one of your currently supported versions
giving an upgrade to laggard clients to the oldest possible supported version for free
Some additional thoughts based on new information. I had pondered whether splitting the code into separate repositories would help, one for each client. However I wonder if there is no guarantee that they would; even if you pull core features in using Composer, or a Git submodule, there is still the possibility of divergence between your latest core and your earliest client code. At some point your worst laggard client is going to hold back development on the core.
You can always leave this client on an abandoned version, but if they spot a bug, it is not worth back-porting a fix from your latest core, since that will cause you all the compatibility headaches you've been trying to avoid. Either they upgrade to a minimum client version that works with the latest core (and pay to do so if necessary) or they tolerate the bug indefinitely.
You've mentioned that each client gets his or her own database. That is helpful, up to a point, since it means that client versions are not entirely constrained with database schema decisions that have been forced by the core. However, this will still have a knock-on effect on how much code you can move to the core.
For example, let us assume that you have seven clients, and six of them have a User entity that has an email address, to handle password change requests (one client has a User entity without this field). This means that, if the awkward schema may not change, the core cannot assume that an email address is available. (In this trivial case it might be cheaper to upgrade the odd-one-out for free, so that more code can go in the core, rather than maintaining such a standard thing as a version enhancement).
Given the level of complexity, and since it sounds like you are maintaining this for the long term, I think you should set up some unit and functional tests. You'll need to split these into "core" and "per version" as well. If you find a bug, regardless of whether it is caused by feature versioning or not, write a failing test, and then fix it. You'll then have - at least in theory - a way to check if a change will impact on a particular client's version in a way you did not envisage.
We have this at my work :
Local dev website(SVN)
dev server where all developer test
Preprod where everything is Ok
Prod (rsync from preprod)
The rsync between 2 server is super fast, when we do a major update its in less than 5s

PHP4 `aggregate` function in php5 Godaddy server

I've been tasked to migrate an old PHP4.3 site (using CVS version control) to a more modern 5.2 install (lower version number for compatibility issues) on a shared GoDaddy server. I've gotten through most of the issues, but this particular one is a tough nut.
Inside the administration view, there is an export to excel function which uses the Spreadsheet_Excel_Writer (0.9.3) PEAR package. However, this line keeps throwing a fatal error:
aggregate( $sheet, 'Spreadsheet_Excel_Writer_Sheet_Patch' );
where $sheet is defined by
$sheet =& $xls->addWorksheet( 'Customer Data' );
My issue is that aggregate no longer exists in PHP5, and I cannot install runkit as I do not have root permission to execute the pecl install command on the server.
I'd rather not have to rewrite the existing functionality, so is there a drop-in replacement for aggregate that I can install without requiring root permissions?
With regard to the Excel library you're using, you will need to upgrade that to a version that supports PHP5, or else migrate to an alternative library. There are several Excel libraries available which do support recent PHP versions, so you should probably investigate those.
I won't recommend any specific library now, as I haven't worked with any of them for a little while and so my recommendation may not be the best. And in any case, your needs may be different to mine. Instead, simply googling for 'php excel' will give you plenty of results to help you find a library to suit you. You will obviously need to rewrite your code where it uses the old library so make it work with whatever new library you choose, but that will be infinitely easier than trying to make the old library itself work. (also, newer libraries will support newer excel versions, which is probably quite important; things do move on)
I certainly wouldn't recommend trying to keep using the existing library; it's clearly written for PHP4, and would likely be a very difficult task to bring it up to date.
You mention runkit: that wouldn't likely be a good solution here even if you were able to use it. For something closer to what the aggregate() function does, you might want to investigate the Reflection class, which allows some similar class- and object-level trickery, but in general well-written code shouldn't need that kind of thing anyway (it may have done in PHP4 days, but much less so today).
Another alternative to aggregate() might be the Traits feature in PHP 5.4 and up. This can give some of the multi-inheritance functionality that aggregate() was sometimes used to simulate. Obviously, you'd need to upgrade to 5.4 for this though, and the actual code you'd write would be quite different.

Upgrading Zend Framework from version X to version Y

Whenever I upgrade Zend Framework I study the changelogs ( http://framework.zend.com/changelog ) but still feel like I am going through a bit of leap of faith to ensure my application does not break.
So far, I have not really had any problems. A large amount of the application is under unit test and web test. But, tests do not have 100% coverage so the whole process of upgrading ZF is still a bit unnerving.
So the Question is...
Where would I be able to find definitive information on interface changes and 'backwards compatibility breaks' when upgrading from 'ZF version X' to 'ZF version Y'?
Also if anyone has any general upgrade tips on upgrading vendor code smoothly then that would be of interest.
i.e.
Do you write a set of unit tests to work on all framework components used by your app?
Also any specific tips on upgrading from ZF 1.8 to 1.11 would be welcomed in comments.
ZF's has a strict release policy
A major release may contain any changes, including bug fixes, backwards compatible features and functionality enhancements, and backwards incompatible releases.
A minor release may only contain backwards compatible changes, including bug fixes and backwards compatible features and functionality enhancements.
A mini release may only contain bug fixes. Note that no new features, functionality enhancements, or API changes are allowed whatsoever. The framework should look and behave the same across mini releases.
The release notes usually contain information about changes that are not backwards compatible. And as you can see, those may only happen between major releases, which is from ZF1 to ZF2, but not from ZF1.8 to ZF1.11.
Now, just because the may not happen, doesnt mean they dont happen, but from my experience all changes were backwards compatible. I remember they changed the autoloader and static Filter invocation in some previous version. ZF would continue to work as usual, but raise deprecation notices. So you are encouraged to take action then, but it won't break your application if you don't.
Basically, as long as your application is Unit-Tested, you should not have any (or very little) problems updating. Update, run your test, if something breaks, fix. Push the updated release to your development and see if it has any notices or warnings.
If you really, really want to know all the changes, then do an SVN Diff between your old version and the version you want to update to.

Framework updates how long do you wait?

In a development team how long do you think you should wait to implement the latest stable version of Framework?
I am asking about different Frameworks we are using Zend Framework, HTMLPurifier, jQuery and jQuery UI.
After a release how long do you wait to update your framework(s)?
If it's revision release (x.y.z -> x.y.z+1), you should deploy it ASAP, because it usually related to bug fix. For example list of fixes from ZF 1.7.7 → 1.7.8.
Standard versioning scheme is «major».«minor».«revision». Change in revision number usually means a bug fix. Change in minor version number, means minor change, usually backwards compatible. Change in major version is significant change, that might not be backwards compatible. See also: Software versioning (wiki).
That depends somewhat on if any of the changes in the framework will require code to be reworked or not. If no, there's less reason to put off an upgrade, and it should be done more or less immediately. If yes, the upgrade may not ever happen without a more compelling argument.
I always use the latest and greatest of everything. Whenever I run into trouble, which I very rarely do, it's relatively easy to find what has changed.
I usually start updating framework even before it becomes final. But then when framework becomes final I immediately replace pre-RTM version with the final one, make final changes in my application and publish it right away (put it into production).
If you start working on new framework integration only AFTER it's RTM release you risk to complete it and some time later hear that a new RIM was released, which is not good.

Categories