Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
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
Uh oh!
There was an error while loading.Please reload this page.
Conversation
sstok commentedApr 30, 2018
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. |
nicolas-grekas commentedApr 30, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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. |
lyrixx left a comment
There was a problem hiding this 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)
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
69525e5 to1446d14Comparederrabus commentedApr 30, 2018
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. |
nicolas-grekas commentedApr 30, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@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 commentedMay 1, 2018
I really like the idea of separating abstractions from implementations.
Regarding EventDispatcher, a (dead-simple) class would be among the candidates for me:
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. |
ostrolucky commentedMay 1, 2018
This PR is weird, seeing#6129 was voted down on. What has changed? |
nicolas-grekas commentedMay 2, 2018
Thanks for the link@ostrolucky. About your question, re-reading my own downvote, I then stated:
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. |
jakzal commentedMay 2, 2018
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 the 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 the |
javiereguiluz commentedMay 2, 2018
@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 commentedMay 2, 2018
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). |
Uh oh!
There was an error while loading.Please reload this page.
3d2b01d toe6b23dbComparenicolas-grekas commentedJun 15, 2018
ping @symfony/deciders |
weaverryan commentedJun 15, 2018
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 smaller Are there any big downsides? |
| * process loop (note that we advise making your services stateless instead of | ||
| * implementing this interface when possible.) | ||
| */ | ||
| interface ResettableInterface |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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...
src/Symfony/Contract/README.md Outdated
| 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. |
There was a problem hiding this comment.
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.
src/Symfony/Contract/README.md Outdated
| Design Principles | ||
| ----------------- | ||
| * contracts are split by domain, each into their own sub-namespace; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
namespaces
src/Symfony/Contract/README.md Outdated
| ###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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
you are able
src/Symfony/Contract/README.md Outdated
| 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.) |
There was a problem hiding this comment.
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.
src/Symfony/Contract/README.md Outdated
| 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 |
There was a problem hiding this comment.
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)
src/Symfony/Contract/README.md Outdated
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
PHP-FIG
fabpot commentedJul 9, 2018
The |
02f8c05 tob90951aComparenicolas-grekas commentedJul 9, 2018
Here we are, the interface is now
Makes perfect sense to me, everything ready to put it into practice :) |
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
derrabus commentedJul 9, 2018
I absolutely agree.
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. |
nicolas-grekas commentedJul 11, 2018
@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 |
Uh oh!
There was an error while loading.Please reload this page.
fabpot commentedJul 13, 2018
Thank you@nicolas-grekas. |
… 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-grekas commentedJul 13, 2018
\o/ thank you all for the discussion, to the core team for their support and to fabpot for merging. |
derrabus commentedJul 13, 2018
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 commentedJul 13, 2018
I just createdhttps://github.com/symfony/symfony/projects/7 so we can track ideas and progress. |
Uh oh!
There was an error while loading.Please reload this page.
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/abstractionspackage, 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
docblocks and reference test suites when applicable, etc.;
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 twodifferent 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
send Pull Requests
in themain Symfony repository