Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add symfony/contracts: a set of abstractions extracted out of the Symfony components#27093

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
fabpot merged 1 commit intosymfony:masterfromnicolas-grekas:abstraction
Jul 13, 2018

Conversation

@nicolas-grekas
Copy link
Member

@nicolas-grekasnicolas-grekas commentedApr 30, 2018
edited
Loading

QA
Branch?master
Bug fix?no
New feature?yes
BC breaks?-
Deprecations?no
Tests pass?yes
Fixed tickets-
LicenseMIT
Doc PR-

A set of abstractions extracted out of the Symfony components.

This is a topic I've been thinking about for a long time. I feel like the time has come for Symfony to publish some abstractions so that people could build on them in a decoupled way.
I've identified interfaces in some components that would greatly benefit from being moved out from the components where they are for now. E.g.#26929 is something that has a broader scope than the Cache component itself.

By putting them in a newsymfony/abstractions package, we would allow more innovation in the Symfony community, at the abstraction level.

In order to start small, I propose only one interface that gathers a concept that is shared amongst many components already:ResetInterface. It would provide a standardreset() method, whose purpose is to set an object back to its initial state, allowing it to be reused many times with no side effects/leaks related to its history. By this definition, it could also be autoconfigured (as done here, see update in FrameworkExtension). See wording in the docblock in the attached source code.

Ideally, I'd like this package to provide not only interfaces, by also generic traits, and reference test suites when possible. We could work on adding more abstractions during the 4.2 cycle. WDYT?

Here is the attached README:

A set of abstractions extracted out of the Symfony components.

Can be used to build on semantics that the Symfony components proved useful - and
that already have battle tested implementations.

Design Principles

  • contracts are split by domain, each into their own sub-namespaces;
  • contracts are small and consistent sets of PHP interfaces, traits, normative
    docblocks and reference test suites when applicable, etc.;
  • all contracts must have a proven implementation to enter this repository;
  • they must be backward compatible with existing Symfony components.

FAQ

How to use this package?

The abstractions in this package are useful to achieve loose coupling and
interoperability. By using the provided interfaces as type hints, you are able
to reuse any implementations that match their contracts. It could be a Symfony
component, or another one provided by the PHP community at large.

Depending on their semantics, some interfaces can be combined with autowiring to
seamlessly inject a service in your classes.

Others might be useful as labeling interfaces, to hint about a specific behavior
that could be enabled when using autoconfiguration or manual service tagging (or
any other means provided by your framework.)

How is this different from PHP-FIG's PSRs?

When applicable, the provided contracts are built on top of PHP-FIG's PSRs. But
the group has different goals and different processes. Here, we're focusing on
providing abstractions that are useful on their own while still compatible with
implementations provided by Symfony. Although not the main target, we hope that
the declared contracts will directly or indirectly contribute to the PHP-FIG.

Why isn't this package split into several packages?

Putting all interfaces in one package eases discoverability and dependency
management. Instead of dealing with a myriad of small packages and the
corresponding matrix of versions, you just need to deal with one package and one
version. Also when using IDE autocompletion or just reading the source code, it
makes it easier to figure out which contracts are provided.

There are two downsides to this approach: you may have unused files in your
vendor/ directory, and in the future, it will be impossible to use two
different sub-namespaces in different major versions of the package. For the
"unused files" downside, it has no practical consequences: their file sizes are
very small, and there is no performance overhead at all since they are never
loaded. For major versions, this package follows the Symfony BC + deprecation
policies, with an additional restriction to never remove deprecated interfaces.

Resources

lyrixx, pyrech, derrabus, linaori, ostrolucky, sdelicata, Pierstoval, apfelbox, nunomaduro, mmarchois, and 11 more reacted with thumbs up emojistloyd, sstok, jvasseur, jakzal, unkind, Koc, julienfalque, fbourigault, alcalyn, deflock, and 9 more reacted with confused emoji
@nicolas-grekasnicolas-grekas added this to thenext milestoneApr 30, 2018
@sstok
Copy link
Contributor

This would only work if the used terms have an equal purpose and meaning, Resettable has a different purpose in Cache than OutputFormatterStyleStack or Compiler in the Expression-Language.

Basically this would make the interfaces extreme generic in purpose and less about their specific situation. A Trait can be easily re-used as it's simple code-level copy-paste but doesn't enforce an interface contract.

jvasseur and DavidBadura reacted with thumbs up emoji

@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedApr 30, 2018
edited
Loading

This would only work if the used terms have an equal purpose and meaning

Correct, and that's actually the exact purpose of the proposed interface. I don't know why you state that they have a different purpose in your list, because AFAIK, they have the exact same one: resetting an object to its initial state. This is even more apparent when considering that all (most) these existing "reset" methods are bound to "kernel.reset" tags.

Copy link
Member

@lyrixxlyrixx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I like it 👍
(minor comments / questions)

@derrabus
Copy link
Member

Maybe we should use the discussion of PR to assemble a list of classes, interfaces and traits that could possibly be moved into the abstractions package, to get an idea of where we would be heading to with this idea.

sroze and xphere reacted with thumbs up emoji

@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedApr 30, 2018
edited
Loading

@derrabus why not. Here is my short list (I would really try hard tonot add any classes here, even abstract ones):

There might be more abstractions that we could extract from other components (Console, EventDispatcher, Lock, Messenger, Routing, Translation, HttpKernel, etc.?)

@derrabus
Copy link
Member

I really like the idea of separating abstractions from implementations.

I would really try hard tonot add any classes here

Regarding EventDispatcher, a (dead-simple) class would be among the candidates for me:

  • EventDispatcherInterface
  • EventSubscriberInterface
  • Event

Event could be split into an interface + a trait, but I don't see much benefit here.

Moving those to interfaces into an abstraction package would allow components to define optional event subscribers without depending on the actual event dispatcher. We could also simplifycode like this.

nicolas-grekas reacted with thumbs up emoji

@ostrolucky
Copy link
Contributor

This PR is weird, seeing#6129 was voted down on. What has changed?

derrabus and jvasseur reacted with thumbs up emoji

@nicolas-grekas
Copy link
MemberAuthor

Thanks for the link@ostrolucky. About your question, re-reading my own downvote, I then stated:

Symfony didn't embrace the mission of providing generic interfaces on their own

that's exactly what I'm proposing here: have the Symfony project broaden its missions a bit, and allow itself to publish interfaces on their own for genericity. The benefits are well discussed and presented in the issue. Why did I change my mind? Because I feel like not having this package is preventing us from some kind of innovation we'd like to do. E.g. taggable cache items, this linked cache interface, the attached reset method, etc. It comes also as a realization that the FIG is not the right place for all of these: I don't expect everyone in the FIG to agree on all things we'd still like to do. And this is fine, we don't have the exact same goals obviously. We need our own freedom on the "abstractions" topic, so that we're able to contribute to this space also. Some topicscould be of interest to the FIG (e.g. taggable cache items), still that shouldn't prevent us from being able to move forward at our own pace.

lyrixx and sroze reacted with thumbs up emoji

@jakzal
Copy link
Contributor

I like the idea of creating standards by extracting or defining interfaces out of established and working solutions. This is what PSRs are missing in many cases.

However, how do you see thesymfony/abstractions package to be consumed by others?

My main issue with this idea is that the package wouldn't be cohesive, as a lot of unrelated interfaces would be packaged together. If I only need theResettableInterface I shouldn't be forced to bring in theServiceSubscriberInterface.

xphere and Saphyel reacted with thumbs up emoji

@javiereguiluz
Copy link
Member

@nicolas-grekas to better understand the purpose (and limits) of this new package, which of the following packages fits the idea of symfony/abstractions better?

Thanks!

@nicolas-grekas
Copy link
MemberAuthor

a lot of unrelated interfaces would be packaged together

That's a desired property of the package IMHO: it will ease discoverability and dependency maintenance (there are some comments in#6129 on the topic). We might reconsider later if the number of interfaces grows out of control, but I don't expect this to happen anytime soon. Meanwhile, we could/should group domains in subnamespaces, when cohesiveness is desired (not the case for ResettableInterface, but could be for the mentioned Cache interfaces.) The fact that you get potentially unused interfaces poses no issues IMHO.

@javiereguiluz certainly not like doctrine/common, which is not an abstraction at all. What I presented above: this would contain interfaces (=abstractions), related documentation defining their semantics (in docblocks), generic traits (=type-less behaviors) and reference test suites when applicable (of primary importance, see eghttps://github.com/php-cache/integration-tests/ for what I mean).

@nicolas-grekas
Copy link
MemberAuthor

ping @symfony/deciders

@weaverryan
Copy link
Member

This seems like a simple optimization: by moving some interfaces to this component, the only practical difference is that you're allowing a library that wants to use that interface (butnot use our implementation) to depend on the smallerabstractions component instead of needed to require the entire component (but then only use the interface). A real-world example would ishttp-kernel, which is used in several libraries that don't use its implementation (e.g. Laravel who only referencesHttpKernelInterface &HttpExceptionInterface).

Are there any big downsides?

* process loop (note that we advise making your services stateless instead of
* implementing this interface when possible.)
*/
interface ResettableInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

In the Symfony world, we would sayResetInterface (I don't think we have any -able interface right now in Symfony). In the ZF world, it would beResettable. I propose to rename toResetInterface here for consistency with our practices. Any better ideas?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@fabpotSymfony\Component\HttpKernel\RebootableInterface,Symfony\Component\HttpKernel\TerminableInterface,Symfony\Component\Cache\PruneableInterface,Symfony\Component\Cache\ResettableInterface...

A set of abstractions extracted out of the Symfony components.

Can be used to build on semantics that the Symfony components proved useful - and
that already have neat implementations if you don't mind.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I would removeneat.
if you don't mind -> can be removed.

Design Principles
-----------------

* contracts are split by domain, each into their own sub-namespace;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

namespaces

###How to use this package?

The abstractions in this package are useful to achieve loose coupling and
interoperability. By using the provided interfaces as type hints, you will
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

you are able

interoperability. By using the provided interfaces as type hints, you will
be able to reuse any implementations that match their contracts. It could be a
Symfony component, or another one provided by the PHP community at large
(or by you.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I would remove this last part.

encourage relying on them and won't duplicate the effort. Still, the FIG has
different goals and different processes. Here, we don't need to seek universal
standards. Instead, we're providing abstractions that are compatible with the
implementations provided by Symfony components. This should actually also
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

by Symfony (components can be removed as we are talking about the project here)

different goals and different processes. Here, we don't need to seek universal
standards. Instead, we're providing abstractions that are compatible with the
implementations provided by Symfony components. This should actually also
contribute positively to the FIG (from which Symfony is a member), by hinting the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

PHP-FIG

@fabpot
Copy link
Member

Thecontracts should have a different versioning than Symfony. As we won't break BC for instance, we just have to increase the minor version. Having a 5.0 version next years does not really make sense. So, here is the plan: we keep the code undersymfony/symfony to make it easier to move interfaces from the actual code to the contracts ones, but the release cycle is going to be different and done directly via the subtree-split.

@nicolas-grekasnicolas-grekasforce-pushed theabstraction branch 4 times, most recently from02f8c05 tob90951aCompareJuly 9, 2018 16:21
@nicolas-grekas
Copy link
MemberAuthor

Here we are, the interface is nowResetInterface. PR green.

we keep the code under symfony/symfony to make it easier to move interfaces from the actual code to the contracts ones, but the release cycle is going to be different and done directly via the subtree-split.

Makes perfect sense to me, everything ready to put it into practice :)
I've updated the branch-alias and the composer.json to reference v1.0.

@derrabus
Copy link
Member

Thecontracts should have a different versioning than Symfony.

I absolutely agree.

the release cycle is going to be different and done directly via the subtree-split

I see how keeping the contracts inside the monorepo would ease the extraction of more interfaces, but I must admit that the detached versioning confuses me already, thinking about branching tagging of releases. A separate repository would be easier to maintain and understand in the long run, I guess.

How about this: We could start with the contracts in the monorepo to ease the extraction for now and right before the feature freeze of Symfony 4.2 (which would be 1.0 of the contracts), the subtree split becomes an independant repository like the polyfills or the monolog bundle.

ostrolucky reacted with thumbs down emoji

@nicolas-grekas
Copy link
MemberAuthor

@derrabus we'll have some time to figure out what works best. For now, we anticipate that the easiest to maintain could be a subtree-splitted repository.

Status: needs review

derrabus reacted with thumbs up emoji

@fabpot
Copy link
Member

Thank you@nicolas-grekas.

derrabus reacted with hooray emoji

@fabpotfabpot merged commit8982036 intosymfony:masterJul 13, 2018
fabpot added a commit that referenced this pull requestJul 13, 2018
… out of the Symfony components (nicolas-grekas)This PR was merged into the 4.2-dev branch.Discussion----------Add symfony/contracts: a set of abstractions extracted out of the Symfony components| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | yes| BC breaks?    | -| Deprecations? | no| Tests pass?   | yes| Fixed tickets | -| License       | MIT| Doc PR        | -A set of abstractions extracted out of the Symfony components.This is a topic I've been thinking about for a long time. I feel like the time has come for Symfony to publish some abstractions so that people could build on them in a decoupled way.I've identified interfaces in some components that would greatly benefit from being moved out from the components where they are for now. E.g.#26929 is something that has a broader scope than the Cache component itself.By putting them in a new `symfony/abstractions` package, we would allow more innovation in the Symfony community, at the abstraction level.In order to start small, I propose only one interface that gathers a concept that is shared amongst many components already: `ResetInterface`. It would provide a standard `reset()` method, whose purpose is to set an object back to its initial state, allowing it to be reused many times with no side effects/leaks related to its history. By this definition, it could also be autoconfigured (as done here, see update in FrameworkExtension). See wording in the docblock in the attached source code.Ideally, I'd like this package to provide not only interfaces, by also generic traits, and reference test suites when possible. We could work on adding more abstractions during the 4.2 cycle. WDYT?## Here is the attached README:A set of abstractions extracted out of the Symfony components.Can be used to build on semantics that the Symfony components proved useful - andthat already have battle tested implementations.Design Principles----------------- * contracts are split by domain, each into their own sub-namespaces; * contracts are small and consistent sets of PHP interfaces, traits, normative   docblocks and reference test suites when applicable, etc.; * all contracts must have a proven implementation to enter this repository; * they must be backward compatible with existing Symfony components.FAQ---### How to use this package?The abstractions in this package are useful to achieve loose coupling andinteroperability. By using the provided interfaces as type hints, you are ableto reuse any implementations that match their contracts. It could be a Symfonycomponent, or another one provided by the PHP community at large.Depending on their semantics, some interfaces can be combined with autowiring toseamlessly inject a service in your classes.Others might be useful as labeling interfaces, to hint about a specific behaviorthat could be enabled when using autoconfiguration or manual service tagging (orany other means provided by your framework.)### How is this different from PHP-FIG's PSRs?When applicable, the provided contracts are built on top of PHP-FIG's PSR. Weencourage relying on them and won't duplicate the effort. Still, the FIG hasdifferent goals and different processes. Here, we don't need to seek universalstandards. Instead, we're providing abstractions that are compatible with theimplementations provided by Symfony. This should actually also contributepositively to the PHP-FIG (from which Symfony is a member), by hinting the groupat some abstractions the PHP world might like to take inspiration from.### Why isn't this package split into several packages?Putting all interfaces in one package eases discoverability and dependencymanagement. Instead of dealing with a myriad of small packages and thecorresponding matrix of versions, you just need to deal with one package and oneversion. Also when using IDE autocompletion or just reading the source code, itmakes it easier to figure out which contracts are provided.There are two downsides to this approach: you may have unused files in your`vendor/` directory, and in the future, it will be impossible to use twodifferent sub-namespaces in different major versions of the package. For the"unused files" downside, it has no practical consequences: their file sizes arevery small, and there is no performance overhead at all since they are neverloaded. For major versions, this package follows the Symfony BC + deprecationpolicies, with an additional restriction to never remove deprecated interfaces.Resources---------  * [Documentation](https://symfony.com/doc/current/components/contracts.html)  * [Contributing](https://symfony.com/doc/current/contributing/index.html)  * [Report issues](https://github.com/symfony/symfony/issues) and    [send Pull Requests](https://github.com/symfony/symfony/pulls)    in the [main Symfony repository](https://github.com/symfony/symfony)Commits-------8982036 Added symfony/contracts: a set of abstractions extracted out of the components
@nicolas-grekasnicolas-grekas deleted the abstraction branchJuly 13, 2018 13:27
@nicolas-grekas
Copy link
MemberAuthor

\o/ thank you all for the discussion, to the core team for their support and to fabpot for merging.
There are more interfaces to move in contracts before releasing 1.0 in November.
PRs welcome!

@derrabus
Copy link
Member

There are more interfaces to move in contracts before releasing 1.0 in November.
PRs welcome!

I'd love to help. I would start with the event interfaces as I suggested in my comment:#27093 (comment)

Do you track somewhere what needs to be done and who's already working on which part?

@nicolas-grekas
Copy link
MemberAuthor

I just createdhttps://github.com/symfony/symfony/projects/7 so we can track ideas and progress.
Please open issues/PRs and add them to the project (if permissions don't allow it, @symfony/deciders can do it.)

@nicolas-grekasnicolas-grekas modified the milestones:next,4.2Nov 1, 2018
This was referencedNov 3, 2018
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@weaverryanweaverryanweaverryan left review comments

@stofstofstof left review comments

@derrabusderrabusderrabus requested changes

@fabpotfabpotfabpot approved these changes

@lyrixxlyrixxlyrixx approved these changes

@javiereguiluzjaviereguiluzjaviereguiluz approved these changes

+8 more reviewers

@WironeWironeWirone left review comments

@ogizanagiogizanagiogizanagi approved these changes

@pyrechpyrechpyrech left review comments

@hhamonhhamonhhamon left review comments

@unkindunkindunkind left review comments

@localheinzlocalheinzlocalheinz requested changes

@michaelcullummichaelcullummichaelcullum approved these changes

@HeahDudeHeahDudeHeahDude approved these changes

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Projects

None yet

Milestone

4.2

Development

Successfully merging this pull request may close these issues.

22 participants

@nicolas-grekas@sstok@derrabus@ostrolucky@jakzal@javiereguiluz@weaverryan@unkind@sebastianblum@palex-fpt@Wirone@sroze@fabpot@michaelcullum@hhamon@lyrixx@stof@localheinz@pyrech@ogizanagi@HeahDude@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp