[BYLAW] Proposal: let PSRs evolve with the language

瀏覽次數:590 次
跳到第一則未讀訊息

Alessandro Lai

未讀,
2019年6月6日 清晨5:16:262019/6/6
收件者:PHP Framework Interoperability Group
Hello everyone,
I would like to push forward a proposal that is bugging me for so long. Today I read this comment on our GitHub: https://github.com/php-fig/fig-standards/pull/1171#issuecomment-499382349

Larry correctly shot down the last in a long list of small PRs that our approved PSRs had received in the past. This is because the PSRs, as standards, should be immutable, and they cannot be changed meaningfully, apart from small erratas. 

I would like to change that.

This is a topic that many times surfaced in our chats, but we never tried to solve it. The release schedule of the language is a lot more tight and fast compared to the past, and we need to keep up the pace, to avoid that our PSRs become obsolete in a matter of years.

My proposal is simple but limited; I didn't work on a full text change of our bylaws, but before I delve in the technicalities I would like to try and explain my idea succinctly, to see if I have some consensus about it.

This is the summary of my proposal:
 - PSRs packages can receive new major releases
 - new majors should be used just to improve the code, so that it can use new language features (types, return type, void, \Throwable...)
 - the new major should never break the spec
 - implementors should be able to easily support all majors of the package (AKA "psr/*": "^1.0|^2.0"); even more, it should be recommended
 - if possible, the additions to the spec should just be added to implement in code something from the spec that before wasn't expressible before (like exceptions interfaces extending `\Throwable`)
 - a changelog should be appended to the PSR to reflect the changes in the new version
 - the process to make this happen should be:
 -- PR to the PSR
 -- demonstrate straightforward cross-compat between version
 -- editor approval, calls a CC vote
 -- CC vote with 2/3 majority

What do you think? Do you think this is doable?

Woody Gilk

未讀,
2019年6月6日 上午9:07:442019/6/6
收件者:PHP Framework Interoperability Group
Alessandro,

Thank you for taking this on!

I completely agree with everything you said, and I would also add this to the summary:

- if possible, additions to the spec should be resolvable in implementations by running a tool such as phpcbf or php-cs-fixer

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/89341907-fca6-448a-a887-531d0f7b6a89%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Larry Garfield

未讀,
2019年6月6日 上午10:13:112019/6/6
收件者:PHP-FIG
There's been discussion of "point release PSRs" in the past, which is similar but perhaps a bit larger in scope.

My main concern is this point:

> - the new major should never break the spec
> - implementors should be able to easily support all majors of the
> package (AKA "psr/*": "^1.0|^2.0"); even more, it should be recommended

The scope of possible changes that wouldn't "break the spec" is exceedingly small. There are numerous changes that would not break the semantics of the spec, but would break the strict "composer update and ignore" compatibility of the spec. Remember, much of what we release is interfaces, and changing an interface even slightly can have huge knock-on effects.

As a few examples:

* Adding the `object` type hint to PSR-14's Dispatcher::dispatch() return. This was left out to ease BC, and anyone not returning the event there is Wrong(tm). However, adding that type hint later in a few years would break any existing implementation because they don't have a return type specified and thus it would be type widening a return. So that's a spec change.

* PSR-6 didn't include a DateTimeInterface parameter on one method, for PHP 5.4 compatibility. That caused a bug where it was unclear how to handle error conditions, leading to an errata that took two tries to get through. If we were to now add the parameter hint, that would break PHP 7.0-based implementations that don't support type widening on parameters. (That came in later versions.) It also changes the behavior in an error condition, as it would now throw TypeError rather than whatever the errata recommended (which was a different exception, I think). So that's a spec change.

* PSR-7 would greatly benefit from adding return types to its methods, as has been discussed before. However, for the same reason as the first example that would not change the semantics, but would break all existing implementations.

So while I am open to improved ways for specs to "keep up withe times" without being redesigned, in practice I don't think 100% transparent changes are really possible outside of a few very very specific cases like the "CustomException extends \Traversable" example.

--Larry Garfield

Matthew Weier O'Phinney

未讀,
2019年6月6日 上午10:14:042019/6/6
收件者:php...@googlegroups.com
On Thu, Jun 6, 2019 at 4:16 AM Alessandro Lai <alessand...@gmail.com> wrote:
I really like this idea!

The one part I don't think is possible is the line "implementors should be able to easily support all majors of the package ... it should be recommended."

Why?

Because some language changes are not compatible with previous versions.

As an example, if we have the following in the original spec:

    interface Car
    {
        /**
         * @param string $brand
         * @return self
         */
        public function withBrand($brand);
    }

and v2 then updates to take advantage of scalar type hints and return type hints:

    interface Car
    {
        public function withBrand(string $brand) : self;
    }

then an implementation MUST choose one version or the other. Why?

If it targets the v1 spec, it will be incorrect for v2, as the typehints are missing entirely.
- If it adds typehints to follow v2, it's invalid for usage with v1, because v1 defined no typehints. (This is not a problem if only an RTH is added; however, as soon as any arguments have typehints, it is.)

(See https://3v4l.org/JbEJI for an example; you can comment out one or the other implementation to see the errors each produces.)

Consumers generally won't need to care much, as the _usage_ will be identical. They can safely pin to multiple versions of the PSR package. However, the packages _providing the implementations_ will have to do some nasty dynamic polyfill stuff to make it work, and it will only get harder the more versions they need to support. I'd argue implementors should bump major versions to support new versions of the PSR package.

--
he/him

Stefano Torresi

未讀,
2019年6月6日 下午5:11:052019/6/6
收件者:PHP Framework Interoperability Group
Hey list,

First of all, thanks Alessandro for bringing this up.
I have given a lot of thought on this topic, which, as most of you will know, has been recurring pretty much since PHP7 was released.
I never actually sat down and write these thoughts of mine, though, so I better do it now, finally.

While I agree that something *must* be done to ease the process of keeping PSRs up to date, I think the suggested approach is too simplistic and would introduce more problems than it solves.

There are multiple facets to this issue, here are some we need to solve to fully address it:
- The common Git workflow of opening a PR doesn't really fit a project that is meant be immutable once released, bar minor erratas that can't effectively harm users.
- The specification documents are separate from the actual code, if any; I think this is exactly why simply opening a PR, voting it, and merging may seem easy, but it's actually not. If we update the interfaces and release a new version of the Composer package, we also need to update the specs, and vice-versa. While updating the package is a simple as bumping a tag, updating the specification documents has no actual release process instead, because a new PSR is supposed to be created instead. We can't simply make the old specification documents disappear by merging a PR. Also, superseded major versions should still be accessible for future reference.
- All specs are all in the same repository, so their lifecycle cannot be managed independently.
- The namespace of the code we produce (Psr\Foo\Bar and Fig\Bar\Baz) is fragmented, ambiguous and wouldn't accommodate multiple major version of the same PSR living in the same codebase. This makes effectively impossible to provide soft migration paths from one version to another, which would probably end up in a Python 3 scenario, where not enough people will migrate to the new ones to simply declare the old one DEAD, thus incurring in the risk of very long and painful transition timeframes where multiple incompatible standards are used in the wild.

Now, at the cost of sounding preposterous, I will propose the following:
I think we need to completely overhaul our naming conventions, the PSR release process (just the release, not the production workflow!), and how we use VCS to manage the documents and sources we produce. This involves a lot of changes and the willingness to turn page quite drastically.

Here comes some craziness, but bear with me.

We could overhaul the naming scheme by introducing the concept of Revisions:

Standard name: PSR-$n - $topic [ - Revision $major.$minor.$patch]
Package name: fig/psr-$n-$topic[-rev-$major]:$major.$minor.$path
Namespace: Fig\Psr$n[\Rev$major]\

Example 1:
PSR-7 - HTTP Messages - Revision 1.0.0
Package name: fig/psr-7-http-messages:1.0.0  
Namespace: Fig\Psr7\  
Example 2:
PSR-7 -  HTTP Messages - Revision 2.0.0
Package name: fig/psr-7-http-messages-rev-2:2.0.0  
Namespace: Fig\Psr7\Rev2\  

Example 3:
PSR-7 -  HTTP Messages - Revision 2.0.1
Package name: fig/psr-7-http-messages-rev-2:2.0.1
Namespace: Fig\Psr7\Rev2\  

Note that:
- The Revision number matches the Semver package version, but it's doesn't map exactly to the same concept. The most relevant part is obviously the major number because minor and patch should not break compatibility, thus releasing a new Revision will not be required.
- If the Revision is omitted, it means it's 1.x, thus referring just to "PSR-7" implies version 1.x.
- The $n is still determined at PSR entrance, but it is *never* changed unless the PSR purpose changes substantially, enough to grant a scenario where two standards may coexist and both be current (e.g. "PSR-6 - Caching Interface" and "PSR-16 - Simple Cache"). 
- Deprecated minor and patch versions are not accessible other than via Composer.
- The Composer package should contain both the specification documents AND the sources, if any.
- For simplicity, $topic refers to both a text representation and a slugified one.

In hindsight, I think the IETF naming convention has *heavy* negative trade-offs. Some will argue that it's a good naming scheme, but I think we can agree that trying to remember what RFC is about what is a waste of neurons. We have had it easy because we only had to deprecate one standard, PSR-2, but, believe it or not, I have seen people still getting confused about this, because someone would refer to a spec as "the autoloader PSR", to only later mention the actual version, leading to undesirable "gotchas".
Considering that if we had to keep the pace with the engine development cycle, in the worst case we would need to release a new version every two years, simply using natural numbers to identify standards would quickly become a mess. Also, we can't make it match with Semver major versions, and this should be enough to prove it ineffective as a versioning scheme.
The main reason for introducing a separate concept from the Composer version is because Composer doesn't allow for multiple versions of the same package to coexist.
That said, using the major Semver number in the namespace would allow very straight forward migration paths, avoiding the Python scenario: we could produce backwards compatible adapters for newer Revisions, that could coexist with previous ones, actively encouraging adoption of the new and deprecation of the old.
Separating it from the PSR number allows unambiguous and clear naming, ensuring that a specification will successfully endure the test of time without causing headaches, contrary to things like RFC2616.
Omitting the Revision for V1 allows for a cleaner transition from the current status quo, and avoids unnecessary verbosity for standards that would hardly be ever updated because of inherent characteristics.
Bundling documents *with* the sources I think just makes sense, I can't imagine why they should continue to be separated. If someone wants to implement a spec, they will just have to require the package and open the included markdown in the vendor dir, which they will be *sure* it matches the interfaces they are trying to implement.

On a side note, I would also take the chance to rename the topic of some of the current PSRs, because sometimes we have a pleonastic "Interfaces" in the name that just drives me crazy, but hey, that's just me.

So how do we release this stuff?

Simple enough: different repos for each PSR, for each Revision. A new Revision is a fork of the previous one. If a PR is opened to a current PSR but it requires a new Revision, it should be straightforward to retarget it to a new fork, once the due voting process is done. The WG members will be maintainers of all the repos of a PSR. This should also make it *much easier* the governance of the access and the contribution process, which I reckon it hasn't always been exactly seamless with the current flow (e.g. sometimes PRs have been hanging for a lot of time because the Editor or anyone in the WG was not notified, or they needed approval from the secretaries, etc).

We could also talk about a Revision Approval voting protocol, which could maybe be a shorter version of the corresponding PSR Readiness and Acceptance, or maybe just use those instead, but I'll leave this particular issue open because I think is not that crucial right now.

This is all I got for now, I realise that there may be unclear details, but at least we started a discussion on this problem.

I know for a fact that some people won't approve any of this, so I'll now let you throw figurative milk shakes at me.

Cheers,
Stefano

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Korvin Szanto

未讀,
2019年6月6日 下午6:00:402019/6/6
收件者:php...@googlegroups.com

Hi Everyone,
I'm glad to see this coming up, this is something I've seen discussed a lot on and off the list.

It strikes me that asking an implementor to support multiple PSR versions is too much if we're just using composer versions. The only way I can imagine implementing something like that is by detecting the spec version and loading different versions of your implementation with your class loader.

I really like Stefano's thinking. The namespace bit isn't my favorite but I understand why it could be important.

- The Revision number matches the Semver package version, but it's doesn't map exactly to the same concept. The most relevant part is obviously the major number because minor and patch should not break compatibility, thus releasing a new Revision will not be required.

What would distinguish a "minor" change from a "patch" change? Are you thinking a minor change would be errata and a patch would be typo fixes?

Thanks,
Korvin
 

Alessandro Lai

未讀,
2019年6月7日 凌晨4:46:182019/6/7
收件者:PHP Framework Interoperability Group
I'm very interested in Stefano's proposal, but I have one doubt: using this namespace strategy, it seems to me that a consumer of the spec can only require one revision at a time, is that correct (and desired)?
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscribe@googlegroups.com.

Alessandro Lai

未讀,
2019年9月18日 上午10:29:312019/9/18
收件者:PHP Framework Interoperability Group
A Twitter thread started from Nicolas Grekas is gaining traction about this specific discussion: https://twitter.com/nicolasgrekas/status/1174290079105392645

Can we push this forward somehow?

Stefano Torresi

未讀,
2019年9月18日 上午11:52:172019/9/18
收件者:PHP Framework Interoperability Group
Hey Ale,

Can we push this forward somehow?

My proposal didn't receive much feedback tbh, but nobody proposed alternatives.


I have one doubt: using this namespace strategy, it seems to me that a consumer of the spec can only require one revision at a time, is that correct (and desired)?

Nope, that's quite the opposite: having the revision in the namespace *and* in the package name means multiple revisions can be imported in the same codebase, which solves the main problem of being able to provide migration paths to BC breaks.
This is actually the main point that should justify the clunkiness of the proposal.

I would invite all the people in the group to provide feedback, expecially negative, so that we can asses if there is ground to start editing a new bylaw and finally get things moving.

Cheers!
Stefano

Cees-Jan Kiewiet

未讀,
2019年9月18日 下午3:07:392019/9/18
收件者:PHP Framework Interoperability Group
EHLO,

From a consumers perspective the namespaced revisions sounds like hell to me to be honest. As a consumer I care about the highlevel Psr\Log\LoggerInterface interface, not whether it's rev1, 2, or 35. To me the packages for each PSR should be handled like any other PHP package and receive major new versions introduction updates/maintenance for that package. And as a consequence only one version of a PSR should be active, like PSR-12 supersedes PSR-2 or PSR-4 supersedes PSR-0. This means that consumers should always be moving forward, but at their own pace. Even though PSR-0 is deprecated you can still use it in composer today.

For example we do a follow up on PSR-3 adding (return) type hints. We would deprecated PSR-3 in favour of the new PSR, tag v2.0.0 on the psr/log package and watch as all package maintainers slowly upgrade their packages to the new PSR. At some point all packages you use in your projects will have upgraded and you can upgrade to PSR-3NEXT. (Dependabot is a great tool to automate that.)

This is the way is goes with any package, whether it's a small library or a mayor framework. I don't see why our PSR's should be any different from the already unwritten conventions and ways of working in the community. Yes that means it might take a while before you can upgrade, and yes that means effort from package maintainers to update and release a new version. But we as a community can help with that. 

With all respect to you and your idea Stefano but it feels like a bureaucrats way of solving a developer problem. This problem IMHO needs a very simple solution, not a one that will complicate the ecosystem over time. And I'm afraid that with using versioned namespaces and package names will lead to more fragmentation. The beauty of having these PSR's is that you can rely on everything in your application behaving the same way. And tbh I really don't want two different PSR-7's in my applications, I want one where I can rely on that everything in the applications follows that specific version of the spec.

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/CAFojS1ui6M7EZH5hnTh64enmRhX-HxPd7bw5-DELTxa_7R2xaQ%40mail.gmail.com.

Alessandro Lai

未讀,
2019年9月18日 下午6:25:052019/9/18
收件者:PHP Framework Interoperability Group
Since there seems to be a lot of confusion about what changes could be made code-wise and what not, I prepared a summary table for all the combinations of possible versions, using PSR-3 and Monolog v1-v2 as test subjects:


It's basically a double-entry table with all the combinations of with/without argument/return types, on both sides (interface & concrete implementation); I've linked 3v4l pages for all the entries, except the trivial ones on the diagonal where interface and implementation match perfectly.

As you can see it's quite the minefield, and trying to add only the return type to the interface (column D) is a complete disaster, as it's broken in all cases except a perfect match; but I've highlighted in green what seems to me a good upgrade path, both on the PSR side, that for the implementation. The path is as follows:

psr/log v1, as we know it: log($level, $message, array $context = [])
psr/log v2, adds argument types: log(string $level, string $message, array $context = []); (REQUIRES PHP 7.2)
psr/log v3, adds both types: log(string $level, string $message, array $context = []): void; (REQUIRES PHP 7.2)

Monolog v1 (as released): compatible with both psr/log v1 & v2
Monolog v2 (as released, adds return type): compatible with all psr/log versions
Monolog v3 (adds both return and arguments types): compatible with both psr/log v2 & v3

So, basically every version from Monolog is compatible with at least two adjacent versions of the interface. This seems to me a perfect upgrade path, that would require a new PSR only for the last step, because PSR-3 would be compatible with v1 and v2, and PSR-3-next would be declared compatible with v2 and v3. This would mean no need to change package and/or namespaces, the interface would remain the same, it would just evolve through SemVer with a "bridge" version between the two (nearly identical) PSRs. Obviously PSR-3 would require an amendment, but it would just to declare the compatibility with the bridge version, and announce the future deprecation in favor of the new one.

If this seems reasonable to you, tomorrow I'll try to draft a PR to the bylaws to have an actual text to discuss over.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscribe@googlegroups.com.

Alexandru Pătrănescu

未讀,
2019年9月18日 下午6:43:002019/9/18
收件者:php...@googlegroups.com
Hi Cees-Jan, guys,

Well, there is a difference here that maybe should be articulated a bit more clearly.

PSRs that are problematic in terms of evolution and in discussion here are most of the time declaring interfaces.
That means that for them the dependent packages are coupled with PSR package by inheritance.

If it would be coupled by composition, as there are cases encountered in the wild, a dependent package could support more than one major version of a dependency even if they would use the same namespace/class.

When the dependency is used in a lot of cases, supporting two or more major version of it is what dependents of your library needs in order to upgrade.

For inheritance coupling a namespaced version would work and it would probably be the simplest solution.

Alessandro, to your example, if you add another few libraries that are having a different timeline to upgrade to the new PSR3 version, you will end up with even more chaos and not being able to upgrade any of a project libraries individually.
IMO, adding namespaced version will mostly simplify evolution.

Regards,
Alex

To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/a9ae0dd1-e07f-4cb5-a8d2-8e2928378d1e%40googlegroups.com.

Edward Almasy

未讀,
2019年9月18日 晚上8:17:292019/9/18
收件者:'Alexander Makarov' via PHP Framework Interoperability Group
On Sep 18, 2019, at 2:07pm, Cees-Jan Kiewiet <cees...@gmail.com> wrote:
From a consumers perspective the namespaced revisions sounds like hell to me to be honest. As a consumer I care about the highlevel Psr\Log\LoggerInterface interface, not whether it's rev1, 2, or 35. To me the packages for each PSR should be handled like any other PHP package and receive major new versions introduction updates/maintenance for that package. And as a consequence only one version of a PSR should be active, like PSR-12 supersedes PSR-2 or PSR-4 supersedes PSR-0. This means that consumers should always be moving forward, but at their own pace.

I'd like to second this sentiment.  Simplicity promotes clarity and adoption.

Ed


-- 
Edward Almasy <eal...@scout.wisc.edu>
Director  •  Internet Scout Research Group
Computer Sciences Dept  •  U of Wisconsin - Madison
1210 W Dayton St  •  Madison WI 53706  •  3HCV+J6
608-262-6606 (voice)  •  608-265-9296 (fax)



Adrien Crivelli

未讀,
2019年9月19日 凌晨12:40:112019/9/19
收件者:PHP Framework Interoperability Group

On Wednesday, 18 September 2019 17:17:29 UTC-7, Edward Almasy wrote:
On Sep 18, 2019, at 2:07pm, Cees-Jan Kiewiet <cees...@gmail.com> wrote:
From a consumers perspective the namespaced revisions sounds like hell to me to be honest. As a consumer I care about the highlevel Psr\Log\LoggerInterface interface, not whether it's rev1, 2, or 35. To me the packages for each PSR should be handled like any other PHP package and receive major new versions introduction updates/maintenance for that package. And as a consequence only one version of a PSR should be active, like PSR-12 supersedes PSR-2 or PSR-4 supersedes PSR-0. This means that consumers should always be moving forward, but at their own pace.

I'd like to second this sentiment.  Simplicity promotes clarity and adoption

Me too, find that using the de-facto standard of managing dependencies and their breaking version is the simplest and best way to approach this.

If your lib inherit from a PSR interface, then you cannot support both PSR major versions at once, but you can, and should, release a new major of your lib with the support of latest PSR version. This is how it is done for pretty much everything else since composer came to be. I don't see why it could not be applied to PSR too.

Please, Keep It Stupid Simple.
 

Alexandru Pătrănescu

未讀,
2019年9月19日 凌晨1:35:092019/9/19
收件者:php...@googlegroups.com
I apologize if my answer didn't provide clearer cases where this solution that seems to be the simplest one is just not working:

- If I have a small project where I use slim framework and guzzle http client, both having implementation of PSR-7, I should be allowed to upgrade each one to another major version with no impact on the other.
If the project is bigger, you might find more than two implementations, including PSR-17 factories that also implements PSR-7.

- Another example would be the case of PSR-11, the container interoperability interface and actually all interop related PSR that by design are meant to allow projects with more than one implementation at runtime.

There are problems that could require a more complex solution, but still the simplest that would work.
I believe namespaced interfaces would be needed here.

Alex


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

Alexander Makarow

未讀,
2019年9月19日 凌晨2:19:182019/9/19
收件者:php...@googlegroups.com
Namespaced interfaces won't work because there's no method overloading in PHP thus a library can not implement two versions of the interface at the same time. 

чт, 19 сент. 2019 г., 8:35 Alexandru Pătrănescu <drea...@gmail.com>:

Alexandru Pătrănescu

未讀,
2019年9月19日 凌晨3:27:092019/9/19
收件者:php...@googlegroups.com
Yes, you are right and, of course, there needs to be different classes implementing different incompatible interface versions.

And this would introduce flow control conditions in dependent libraries.
It's not a simple solution, as I mentioned. But I think it might be the simplest one if we would want to allow upgrading major version of slim without upgrading to a major version of guzzle.

I'll take more time and try to analyse and understand how a real world example would look like.

Maybe how guzzle separated the PSR-7 implementation in a different package would help with the same-namespace version.
Problem appears with packages implementing the interface and not with packages calling methods of the interface (because of the different coupling level, mentioned earlier).
So separating implementations in a different package that could be maintained longer time in different major versions might work.

Alessandro Lai

未讀,
2019年9月19日 凌晨4:14:502019/9/19
收件者:PHP Framework Interoperability Group
I took more time on this issue and I've added a second sheet to the previous document:


The second page stems from my proposal, and it shows the scenario for a package that extends Monolog, so it has to be compatible with both psr/log and Monolog to work.

As shown in the table, if the package adds only argument types, it will be broken in any upstream version combination that is working on itself, and that's bad. But if it adds the return type first, following Monolog's example, all is fine; the only downside is that adding argument types too would break compat with Monolog v2, regardless of psr/log version.

So, to summarize, the upgrade path of this downstream package would be:

Version N:
psr/log: ^1.0
monolog/monolog: ^1.0

Version N+1: adds return type like Monolog v2, will use v2 only if PHP >= 7.2
psr/log: ^1.0|^2.0
monolog/monolog: ^1.0|^2.0

Version N+2: add argument types too:
psr/log: ^2.0|^3.0
monolog/monolog: ^3.0

This IMHO would make releasing version N+2 very unlikely in the short term, due to not having cross compatibility with 2 major versions of Monolog at the same time.

Adrien Crivelli

未讀,
2019年9月19日 下午3:23:582019/9/19
收件者:PHP Framework Interoperability Group

On Thursday, 19 September 2019 00:27:09 UTC-7, Alexandru Pătrănescu wrote:
we would want to allow upgrading major version of slim without upgrading to a major version of guzzle.

You assume that this is a requirement, to be able to upgrade major version independently. I am saying that this is not a requirement, and it should not be.

The exact same problem of being forced to wait for both libs to be upgraded before you can upgrade your own project already exists today in composer ecosystem. And it is already solved simply by having a little bit of patience and/or contributing to libs to upgrade them. I really don't see why PSR should have a special status and be managed differently than the entire composer ecosystem.

Alessandro Lai

未讀,
2019年10月4日 上午9:57:302019/10/4
收件者:PHP Framework Interoperability Group
Adrien the issue lies in the fact that in that way you would be forced to update ALL the dependencies that rely on that interface. In the case of very common PSRs, like psr/log, that would mean being blocked a lot, and having to be forced to do a big-bang update with a single deploy, and no way to split that up in any way. That's bad.

In the meantime, with Larry's help, we condensed the proposal in a blog post that we just published, followed by a poll to get some feedback; please read and give us your opinion: https://www.php-fig.org/blog/2019/10/upgrading-psr-interfaces/

Alexandru Pătrănescu

未讀,
2019年10月4日 晚上8:41:172019/10/4
收件者:php...@googlegroups.com
Hi Alessandro,

After I gave it more though, I agree that this idea will most probably work.
Thank you, Larry. The condensed proposal looks simple to read and understand.

The main advantage of this proposal that I didn't understood before is that new versions of libraries with parameter and return type declared can be installed and coexist with a library that didn't upgrade anything but did just the small change to allow also v2.

Alex


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

G. P. B.

未讀,
2019年10月5日 上午9:21:472019/10/5
收件者:PHP Framework Interoperability Group
Greetings PHP-FIG,


From my understanding this project is to add parameter and return types to some of the interfaces defined in PSRs before those exists in PHP.


First, adding parameter types is the easiest and also, in my mind, the most important type information to add, as it is impossible to add a more specific type from a mixed type as it goes against LSP.
This is easy to add as it doesn't break compatibility with current implementations, as parameter types can be widened. 
Adding parameter types can be tagged as a version 1.1.0 because semver allows to upgrade dependencies in minor version. i.e. updating the PHP version is a dependency update.

Determining whether the change is a patch level or minor level modification depends on whether you updated your dependencies in order to fix a bug or introduce new functionality. I would usually expect additional code for the latter instance, in which case it’s obviously a minor level increment.


Secondly adding return types, this cannot be done in a BC compatible way as having a wider (i.e contravarient) return type breaks LSP.
However, I would argue that with the imminent release of PHP 7.4 this is a non-issue.
Indeed PHP 7.4 comes with the feature of contravarient parameter types (i.e type widening) and covarient return types (i.e limiting the return type).
This means that a library will be able to add return types even though the PSR interface doesn't specify a return type if it decides to only support PHP 7.4 as a minimum version, which IMHO is bound to happen as there are a ton of features bundled with this release of PHP.

I hope that everyone can agree that adding parameter types in a minor version of the PSR spec and leaving return types alone is a better plan than, IMHO, the various other proposals which seem unnecessary complicated.

Best regards

George Peter Banyard

 

David Négrier

未讀,
2019年10月7日 凌晨4:06:492019/10/7
收件者:PHP Framework Interoperability Group
Hey FIG,

It's been a while since I last posted here. Just wanted to give a huge +1 to Stefano Torresi proposal.
Having a different package with a different namespace for major version would solve compatibility issues instantly. I think this is something we ought to consider.

Also, this is something that has already be done in other languages.
For instance, when Microsoft releases a new version of DirectX, it prefixes all classes with the version: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/

Without going as far as Stefano proposes, it could possible to propose a v2 without completely changing the naming scheme. For instance v2 of PSR-11 could be:

- Namespace: Psr\Container\v2
- package: psr/container2 

Stefano's idea is far from crazy, it totally makes sense.

Additionally, you can mark "psr/container" as deprecated in composer, asking to migrate to "psr/container2" in order to speed up adoption.

++
David.

Alessandro Lai

未讀,
2019年10月7日 凌晨4:10:062019/10/7
收件者:PHP Framework Interoperability Group
Hello George,
I agree with you with the first part: the first step in our proposal could be easily wrapped in a minor release, it shouldn't hinder the adoption, and it would even encourage it, since it would be automatically adopted by any package that declares ^1.0 as a constraint.
But making the second step (with return types) is IMHO the good step forward then, because it would push the standard forward, accompanying any library that would add return types, maybe thanks to PHP 7.4 too.

Alexandru Pătrănescu

未讀,
2019年10月7日 清晨7:22:262019/10/7
收件者:php...@googlegroups.com
Hi George, Alessandro,

I had this idea that this could be a minor version as well: https://twitter.com/drealecs/status/1180258126215430150 but few minutes later realized that it's not going to work everywhere without BC break on the client side.

If an interface was designed to accept a specific parameter type TypeA but, being defined without a parameter type declaration, the implementation could maybe allowed it to accept other types there: TypeB.
A client would be able in the current version to call the interface with parameter TypeB.
After tagging a new minor version with parameter TypeA, client code will break.

To be perfectly safe, we need to mark it as a major version and all libraries are required to make a small change.

Regards,
Alex

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

Alessandro Lai

未讀,
2019年10月8日 凌晨3:21:212019/10/8
收件者:PHP Framework Interoperability Group
Hi Alexandru,
to be completely truthful, your case shouldn't be an issue for us, because we're starting from the assumpion that that implementation follows the PSR, which also describe (at the very least with PHPDoc) what types are allowed. If the implementation allows other types (on top of the requested ones), it's not our concern, per Liskov Substitution principle.

The major is requested to the end users only when adding the argument types which, since it's narrowing it's accepted types, is a BC due to the same principle.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscribe@googlegroups.com.

Alexandru Pătrănescu

未讀,
2019年10月8日 下午3:31:152019/10/8
收件者:php...@googlegroups.com
Hi Alessandro,

But you can find example very easily.
Take monolog: is not verifying that the $message is string but it's casting it to string later.
If you send an object, it works now. After FIG releases a minor version, it will break.

And I choose an object as example. But if they have strict_types=1. there will be a lot other cases that will stop functioning.

I'm afraid it will require a major version FIG release and from how it looks like, it will require changes in libraries implementing it, not just changing one line in composer.json.
Or am I missing something?

Alex

To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/e91b3c88-c434-4a3d-bbf4-194b3340f369%40googlegroups.com.

G. P. B.

未讀,
2019年10月8日 下午4:31:182019/10/8
收件者:php...@googlegroups.com


On Tue, 8 Oct 2019, 20:31 Alexandru Pătrănescu, <drea...@gmail.com> wrote:
Hi Alessandro,

But you can find example very easily.
Take monolog: is not verifying that the $message is string but it's casting it to string later.
If you send an object, it works now. After FIG releases a minor version, it will break.

And I choose an object as example. But if they have strict_types=1. there will be a lot other cases that will stop functioning.

I'm afraid it will require a major version FIG release and from how it looks like, it will require changes in libraries implementing it, not just changing one line in composer.json.
Or am I missing something?

Alex

You are indeed missing something.
The interface is only a "base" contract that should be enforced by implementations, but nothing prevents an implementation of accepting a larger set of types (to stringable objects for example or something completely different altogether), this is called contravariance.

This is possible because it does not violate type safety (see Liskov Substitution Principle i.e. LSP for more details).
This in turn means that implementation can safely upgrade from an interface which does NOT define argument/parameter type to the one which does specify them.

This is however NOT the case with return types as only subsets of the return type insure type safety (e.g. if return type is iterable an implementation can define an array return type but the inverse is not true).
This is why adding return types is a BC-break and would need a new version (which I argue is less of an issue with the upcoming covariant return types in PHP 7.4, which allows implementation to add return type information without breaking the contract it holds with the interface).

Moreover, strict_types has nothing to do with this as its behaviour is confined on whether or not the implementation uses it or not.

I hope this clears it up.

Alessandro Lai

未讀,
2019年10月14日 清晨5:10:112019/10/14
收件者:PHP Framework Interoperability Group
Thanks for clarifying the point.

I've now opened a WIP PR with a first draft of how this bylaw should look in my opinion: https://github.com/php-fig/fig-standards/pull/1195

I'm not calling the vote yet, because I would like to gather opinions on it.
回覆所有人
回覆作者
轉寄
0 則新訊息