<p dir="auto">Hi,</p>
<p dir="auto">I did a search for contracts inside the issues. Didn't noticed anything. In case this is already discussed, my apologies. Please link me to the particular thread.</p>
<p dir="auto">The idea is to split some of the interfaces that are needed / useful inside certain components.</p>
<p dir="auto">I have a feeling that when interfaces are split to its own ( probably single interfaces ) it will help not to include the library itself on the require-dev. But it will help to make use of the interface being used inside the component.</p>
<p dir="auto">So if someone need to make use of a third party component they could just implement the interface and make use of their own components so will reduce a tight coupling. And as Symfony components already implement them users can just bind it easily.</p>
<p dir="auto">Interested to hear if anyone have thought / discussed this. ( Inspired by Illuminate contracts , psr/log, psr/http-message)</p>
<p dir="auto">Thank you.</p>
<p dir="auto">Hi everyone,</p>
<p dir="auto">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.</p>
<h5 dir="auto">Problem (updated December 5, 2012)</h5>
<p dir="auto">I just had a longer discussion with <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/fago/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/fago">@fago</a>, 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 <code class="notranslate">Symfony\Component\Translation\TranslatorInterface</code> in their code, this still pulls in all of the Symfony Translation implementation (and its potential dependencies).</p>
<p dir="auto">The same is true for any Symfony component/bundle/bridge. When someone wants to use A which relies on <strong>B's interfaces</strong>, and B relies on C and D, he needs to pull in A, B, C and D <em>and</em> provide a custom implementation for B (that might depend on E and F). Lots of installed dependencies: A, B, C, D, Bcustom, E, F</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="         A
      .·´ `·.
     B     Bcustom
   .´`.     .´`.
  C    D   E    F"><pre class="notranslate"><code class="notranslate">         A
      .·´ `·.
     B     Bcustom
   .´`.     .´`.
  C    D   E    F
</code></pre></div>
<h5 dir="auto">Proposal (updated January 7, 2013)</h5>
<p dir="auto">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).</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="      A
      |
   Bcustom
    .´`.
   E    F"><pre class="notranslate"><code class="notranslate">      A
      |
   Bcustom
    .´`.
   E    F
</code></pre></div>
<h6 dir="auto">Implementation</h6>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="api/
    Symfony/
        Component/
            Translation/
                TranslatorInterface.php
    composer.json [symfony/api]
src/
    Symfony/
        Component/
            Translation/
                Translator.php
                composer.json [symfony/translation, requires symfony/api, provides symfony/translation-implementation]
            Validator/
                composer.json [symfony/validator, requires symfony/api, suggests symfony/translation-implementation]"><pre class="notranslate"><code class="notranslate">api/
    Symfony/
        Component/
            Translation/
                TranslatorInterface.php
    composer.json [symfony/api]
src/
    Symfony/
        Component/
            Translation/
                Translator.php
                composer.json [symfony/translation, requires symfony/api, provides symfony/translation-implementation]
            Validator/
                composer.json [symfony/validator, requires symfony/api, suggests symfony/translation-implementation]
</code></pre></div>
<h6 dir="auto">Example: Replacing the translator</h6>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Drupal/
    Translation/
        composer.json [drupal/translation, requires symfony/api, provides symfony/translation-implementation]"><pre class="notranslate"><code class="notranslate">Drupal/
    Translation/
        composer.json [drupal/translation, requires symfony/api, provides symfony/translation-implementation]
</code></pre></div>
<p dir="auto">The package MUST NOT add <code class="notranslate">symfony/translation</code> to its "replace" section. Multiple implementations of the same interface are NOT mutually exclusive and CAN be used at the same time.</p>
<h6 dir="auto">Example: Using the Validator with its simplistic default translator</h6>
<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
    &quot;require&quot;: {
        &quot;symfony/validator&quot;: &quot;2.2.*&quot;
    }
}"><pre class="notranslate">{
    <span class="pl-ent">"require"</span>: {
        <span class="pl-ent">"symfony/validator"</span>: <span class="pl-s"><span class="pl-pds">"</span>2.2.*<span class="pl-pds">"</span></span>
    }
}</pre></div>
<h6 dir="auto">Example: Using the Validator with the Symfony Translation component</h6>
<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
    &quot;require&quot;: {
        &quot;symfony/validator&quot;: &quot;2.2.*&quot;,
        &quot;symfony/translation&quot;: &quot;2.2.*&quot;
    }
}"><pre class="notranslate">{
    <span class="pl-ent">"require"</span>: {
        <span class="pl-ent">"symfony/validator"</span>: <span class="pl-s"><span class="pl-pds">"</span>2.2.*<span class="pl-pds">"</span></span>,
        <span class="pl-ent">"symfony/translation"</span>: <span class="pl-s"><span class="pl-pds">"</span>2.2.*<span class="pl-pds">"</span></span>
    }
}</pre></div>
<h6 dir="auto">Example: Using the Validator with a custom implementation</h6>
<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
    &quot;require&quot;: {
        &quot;symfony/validator&quot;: &quot;2.2.*&quot;,
        &quot;drupal/translation&quot;: &quot;...&quot;
    }
}"><pre class="notranslate">{
    <span class="pl-ent">"require"</span>: {
        <span class="pl-ent">"symfony/validator"</span>: <span class="pl-s"><span class="pl-pds">"</span>2.2.*<span class="pl-pds">"</span></span>,
        <span class="pl-ent">"drupal/translation"</span>: <span class="pl-s"><span class="pl-pds">"</span>...<span class="pl-pds">"</span></span>
    }
}</pre></div>
<p dir="auto">The API would comprise a <em>closed set</em> of interfaces and classes of the components, that is:</p>
<ul dir="auto">
<li>the top-level interface(s)</li>
<li>the classes and interfaces that the top-level interface(s) refer to in type hints and <code class="notranslate">@return</code> tags</li>
<li>the classes and interfaces that <em>these</em> classes and interfaces refer to</li>
<li>etc.</li>
</ul>
<p dir="auto">Because of composer, this change would be fully BC.</p>
<h5 dir="auto">Benefits (updated December 5, 2012)</h5>
<ol dir="auto">
<li>A Symfony component A can rely on interfaces of another component B without forcing the user to use B.</li>
<li>Other projects can depend on Symfony's interfaces with a lower barrier to entry.</li>
<li>The API clearly documents the stable part of the components (it is ideally guaranteed not to change)</li>
<li>The separation helps us to decouple our components more. For example, if a component A instantiates a class of another component B and thus requires "symfony/b", we can improve it to make use of DI so that it only depends on "symfony/api" instead.</li>
</ol>
<h5 dir="auto">Drawbacks (updated January 8, 2013)</h5>
<ol dir="auto">
<li>One more composer package (symfony/api) has to be downloaded when using a Symfony component.</li>
<li>Core developers have to maintain interfaces in a separate directory.</li>
</ol>
<p dir="auto">Please let me know what you think.</p>