fmgasparino / google-gin

Automatically exported from code.google.com/p/google-gin
Apache License 2.0
0 stars 0 forks source link

Reduce code bloat for multiple instances of the same PrivateGinModule #200

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

1. Create a hierarchy of classes which you need to bind to the same interface 
with different parameterizing type:

public interface MyInterface<T>
{
     void doSomething();
}

public class MyInterfaceImpl<T> implements MyInterface<T>
{
    //External services (usually singletons), defined in a global GinModule
    @Inject
    Service1 service1;
    @Inject
    Service2 service2;

    //some base logic
}

public class MyInterfaceStringImpl extends MyInterfaceImpl<String>
{
    //some logic for String implementation
}

public class MyInterfaceIntegerImpl extends MyInterfaceImpl<Integer>
{
    //some logic for Integer implementation
}

public class MyInterfaceDoubleImpl extends MyInterfaceImpl<Double>
{
    //some logic for Double implementation
}

2. Make PrivateGinModule which exposes interface with different parameterizing 
type:

public class MyPrivateGinModule<T> extends PrivateGinModule
{
    private final Class<T> param;
    private Class<? extends MyInterface<T>> implementation;

    public MyPrivateGinModule(Class<T> param)
    {
        this.param=param;
    }

    public MyPrivateGinModule<T> setImplementation(Class<? extends MyInterface<T>> implementation)
    {
        this.implementation=implementation;
        return this;
    }

    protected void configure()
    {
       ...
       bind(typeLiteral(MyInterface.class, param)).to(implementation);
       expose(typeLiteral(MyInterface.class, param));
       //typeLiteral is utility method which makes TypeLiteral<MyInterface<T>> during rebind phase using Types.newParameterizedType() and TypeLiteral.get()
    }
}

3. Install several instances of that module:

public class MyGlobalGinModule extends AbstractGinModule
{
    protected void configure()
    {
        install(new MyPrivateGinModule<Integer>(Integer.class).setImplementation(MyInterfaceIntegerImpl.class));// now we can @Inject MyInterface<Integer>
        install(new MyPrivateGinModule<String>(String.class).setImplementation(MyInterfaceStringImpl.class));// now we can @Inject MyInterface<String>
        install(new MyPrivateGinModule<Double>(Double.class).setImplementation(MyInterfaceDoubleImpl.class));// now we can @Inject MyInterface<Double>
    }
}

4. Compile the code.

What is the expected output? What do you see instead?

Each installed instance of MyPrivateGinModule generates fragments for 
dependencies defined inside - that's OK.
But also it generates fragments for all external dependencies (Service1 and 
Service2) which do not differ from one MyPrivateGinModule instance bindings to 
another.
That causes a lot of duplication in generated code and increases total size of 
compiled js-code.

Original issue reported on code.google.com by rx303...@gmail.com on 25 Sep 2014 at 9:32