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]\
URI: php-fig.org/psr/psr-$n-$topic[-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\
URI: php-fig.org/psr/psr-7-http-messages

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\
URI: php-fig.org/psr/psr-7-http-messages-rev-2

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\
URI: php-fig.org/psr/psr-7-http-messages-rev-2

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

Il giorno gio 6 giu 2019 alle ore 16:14 Matthew Weier O'Phinney <
[email protected]> ha scritto:

>
>
> On Thu, Jun 6, 2019 at 4:16 AM Alessandro Lai <[email protected]>
> wrote:
>
>> 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?
>>
>
> 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.
>
> --
> Matthew Weier O'Phinney
> [email protected]
> https://mwop.net/
> he/him
>
> --
> 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 [email protected].
> To post to this group, send email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/CAJp_myV0%2B-cEKFyNdTZxZX-2rOVLpTvP0pvU5F5iJO4m_aYDkg%40mail.gmail.com
> <https://groups.google.com/d/msgid/php-fig/CAJp_myV0%2B-cEKFyNdTZxZX-2rOVLpTvP0pvU5F5iJO4m_aYDkg%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/CAFojS1tVZ8CCU%2BqLqCprcHWD66ETR_sZ70JgLQXWjU1Z_LCNKw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to