-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Extract API from Implementation #6129
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
👍 |
1 similar comment
+1 |
For anybody not being allowed to use composer this will (worst case) double the amount of dependencies. |
Having the interface separated would be really useful. In fact, we even think about extracting it ourselves for Drupal - see http://drupal.org/node/1852106. @havvg: Having a bunch of unused source code lying around which is actually duplicating existing functionality isn't very nice. The duplicated code is potentially confusing for newcomers who try to wrap their heads around the source code as it isn't immediatelly clear that the implementation is not used. |
👍 for separation of API |
+1 |
@fago What about symfony developers who'd have to look into 2 differents directories ? 👎 because IMHO saving some KB doesn't justify complexifying the directory structure. |
@adrienbrault The more complex directory structure is mainly relevant for us core developers, and then only in part, because the interface certainly will change much less frequently than the implementation. |
-1 for the same reasons @havvg mentioned. |
This is indeed very interesting, but then we're not really talking about API, but SPI (Service Provider Interface). We already have this approach in eZ Publish 5 (though not separated in Composer), so I'm obviously +1 😃 . |
I added an example above on how this would make it possible to replace Symfony packages by custom implementations. |
Updated the description to be less vague (I hope). |
its certainly interesting .. i am hoping that we will have a general trend where PSR will provide those interface packages rather than Symfony2. |
It shouldn't be done by changing the structure of the source code. |
I am kind of -1, it will duplicate the amount of symfony packages you have installed for not so much gain. If it's done in a generalized manner for all components I'm definitely -1. If targetted to a few specific components maybe, but I am not sure where we would draw the line. |
I'm +1, but wouldn't a possible compromise be to store the interfaces both in a separate API package, and in the Symfony component package, and mark the component as a replacement for the API package? It would make it a bit more of a hassle when the interfaces are changed (but still possible to automate), but it's not THAT different from the component subtree splits on GitHub. |
@Seldaek Could the people who vote -1 please also propose an alternative? The use case to replace a core component apparently exists, so we need to find a solution. |
@Seldaek Maybe a package called "symfony-api", that includes all api interfaces? |
Let's be clear that replacing a core component is already possible. I read @fago's point and I can appreciate that, but I don't agree that this is the best solution. Maybe having one Symfony\Interface package with all the main interfaces that really glue stuff together would be ok. I'd guess we only need 5-10 interfaces in there, and the components needing them could require it. That way we don't have an explosion of packages/complexity, but we still provide some amount of separation for those that really need it. Most likely the drupal guys would anyway need most of the other interfaces that are put in there, so combining them is not a huge problem. Edit: Eh well, @DavidBadura beat me to it :) |
I'm kind of -1 and don't like the Symfony\Interface package, too. An alternative: Maybe this cannot work, but just an idea: Let's pimp Composer to be able to download only certain packages / directories like this for example (I hope, @Seldaek doesn't get headache, after he has read this suggestion ;-)): {
"require": {
"symfony/translation": {
"version": "2.1.4",
"directories": ["Interface/"]
}
}
} All interfaces of Translation component are moved into Interface directory. |
Do a few classes more or less really matter that much? On Sun, Dec 2, 2012 at 10:37 PM, Fabian Spillner
|
I'm also -1 for this. Besides skipping a few files what's the point? If it's not extensible for Drupal or any other project it means it's not extensible for many other projects so maybe we need to have a look on how to change that rather that change the whole structure of the framework. Splitting the structure now would confuse the new developers even more and to be honest it would be really annoying to have the files split like that :) |
-1 Agree on @dlsniper. |
Why do you think that this would confuse? How often do you change an API method and touch both files - interface and implementation? And as a beginner, you don't dive into the core components on your first day... Separating interfaces and implementation is a good idea IMO. I would even say that interfaces should always be designed from the client's point of view and therefore be placed outside of the implementation's structure. |
There might be some value in extracting the top-most interfaces of a On Mon, Dec 3, 2012 at 1:13 PM, seiffert notifications@github.com wrote:
|
@schmittjoh Your last statement is a bit unclear. It would be necessary to extract a closed set of interfaces and classes, i.e., the topmost interface, all interfaces and classes that this interface refers to (via type hint or @return annotation), all interfaces and classes that these interfaces and classes refer to etc. Of course, if an interface is not referenced in any way from the topmost interface, it's not necessary to include it in the API. A single "symfony/api" package would be fine for me (but using the same namespaces that we have now). |
So if I understand correctly, basically we should have: interface YamlInterface {} but in the file symfony/api/Symfony/Component/Yaml/YamlInterface.php and then a vendor could write into his lib something like: namespace Symfony\Component\Yaml Sorry, I really don't understand the use case and I want to learn more about this :) (if the example is not easy to understand I'll write a gist later on) Thanks! |
👎 I think maybe this problem happens because of coupling between components. Also if someone is using just one package then why do i need all Symfony interfaces? is loading extra files I don't need. So that cons the point from @fago coming from Drupal. Some problem similar happens with the DI and Config component and how Drupal is not putting the last one under vendors folder #10920 (comment). Drupal is already hell heavy so I don't see the point of loading some extra classes. 👎 |
Hi @webmozart , This is a great proposal and I love to see this. I have seen many of the core people disagree here, but you should consider the advantage of this than saying hard to look that code. API's once finalized will not change like implementations. Thank you. |
I would like to see a generic container interface, event dispatcher interface, response/request perhaps.. But that's not up to Symfony. I think this should be done via PSR and can then be implemented backwards compatible |
As I've mentioned in #12544 and #12115, if you want to use some generic service that Symfony doesn't have yet (e.g. service which gets source code of closure), you are in difficult position as you can't add interface in any of existing components. It looks like separate package with API solves my problem. |
@harikt well, I was talking about last comment in #12115. Current structure forces to couple interface with one of the components. Yet another example: Symfony has So it looks like a good idea for me. 👍 |
More examples:
|
I think decoupling/modularity is one of the goals of Symfony 4.0? I think this is perfect opportunity to reopen discussion about this. I welcome idea for something like |
I am not sure if this is something that Symfony should do. For reusable interfaces across projects there already is the PHP FIG. This group is doing a good job in creating standards for components that need a common interface and we were always fast in implementing those interfaces. |
You are probably right, this is ideal job for php-fig, even though I'm not confident in their activity level. Anyway I investigated current situation and picked interfaces which might seem useful for general purpose. I also found some which might seem they should belong to the list but are IMO too coupled to implementation:
As you see in the end there isn't many of them. It's mostly interfaces of Serializer, because they are lean enough. Also I checked coupling of Validator to Translator and it seems it can be decoupled? Anyway I would like to put the end to this old RFC and see official decision. |
👎 for me to make this change. @symfony/deciders What is your opinion on this topic? |
If I'm right, this is what Laravel does in its "Contracts" package, which contains all the interfaces used in their framework: https://github.com/laravel/framework/tree/5.4/src/Illuminate/Contracts |
@ostrolucky if one doesn't use Symfony at all, I don't see reason to use Symfony contracts. Symfony interfaces don't magically make things better. Moreover, they are designed for Symfony needs and they probably won't satisfy your needs later, so you restrict yourself for no reason. Why people are so obsessed with frameworks so they want to couple their projects with them as much as they can? What's the problem to make your own contracts? https://speakerdeck.com/jakzal/decoupling-from-the-framework — probably, you may find it interesting (by the way, @jakzal is one of the Symfony maintainers). |
This makes me believe you don't understand point of this proposal at all? It's not coupling to a framework but opposite. Currently when you depend on Symfony interface you need to pull all components that depend on implementation. Point of not writing own interface is to allow people of your project to swap implementation with some other (that is already made) without writing adapter. For example Doctrine could adopt many interfaces from symfony serializer and you would be able to use implementations across these projects as you seem fit. |
I think there is value in having shared interfaces, as the FIG does. Instead, I strongly suggest people to contribute to the FIG to move useful stuff there. |
I'm closing this as "won't fix" because at least two core members voted against it. Thank you all for the discussion! |
We don't understand each other, because we use this term differently. I mean coupling between classes/interfaces, you talk about, in fact, composer packages. So when you start to use Symfony interfaces directly in your project you make coupling with Symfony. Symfony is a tool with its own restrictions, models, etc. Let's say you depend on |
Continued in #27093 |
Hi everyone,
We had this discussion before, but at a point when we didn't have composer yet. I would like to bring this topic up again now.
Problem (updated December 5, 2012)
I just had a longer discussion with @fago, who is currently integrating the Validator component into Drupal. For Drupal it is necessary to replace the translation mechanism used in the Validator component by a custom implementation. Even when implementing
Symfony\Component\Translation\TranslatorInterface
in their code, this still pulls in all of the Symfony Translation implementation (and its potential dependencies).The same is true for any Symfony component/bundle/bridge. When someone wants to use A which relies on B's interfaces, and B relies on C and D, he needs to pull in A, B, C and D and provide a custom implementation for B (that might depend on E and F). Lots of installed dependencies: A, B, C, D, Bcustom, E, F
Proposal (updated January 7, 2013)
I would like to suggest and discuss a backwards compatible extraction of the Symfony API. In a nutshell, make it possible to use A which relies on B's interfaces but replace B with a custom implementation (i.e. only install A, Bcustom, E, F).
Implementation
Example: Replacing the translator
The package MUST NOT add
symfony/translation
to its "replace" section. Multiple implementations of the same interface are NOT mutually exclusive and CAN be used at the same time.Example: Using the Validator with its simplistic default translator
Example: Using the Validator with the Symfony Translation component
Example: Using the Validator with a custom implementation
The API would comprise a closed set of interfaces and classes of the components, that is:
@return
tagsBecause of composer, this change would be fully BC.
Benefits (updated December 5, 2012)
Drawbacks (updated January 8, 2013)
Please let me know what you think.
The text was updated successfully, but these errors were encountered: