matsim-org / matsim-code-examples

A repository containing code examples around MATSim
GNU General Public License v3.0
75 stars 173 forks source link

Guice Bindings in DefaultMobsimModule #1125

Closed Janekdererste closed 1 month ago

Janekdererste commented 1 month ago

The DefaultMobsimModule below, has different code paths for different implementations of the mobsim. I would like to understand, why the QSimModule is installed but the other modules are injected using `bindMobsim().to(...)?

Maybe @kainagel remembers why?

public class DefaultMobsimModule extends AbstractModule {
    @Override
    public void install() {
        if (getConfig().controller().getMobsim().equals(ControllerConfigGroup.MobsimType.qsim.toString())) {
            install(new QSimModule());
//            bind(  RelativePositionOfEntryExitOnLink.class ).toInstance( () -> 1. );
        } else if (getConfig().controller().getMobsim().equals(ControllerConfigGroup.MobsimType.JDEQSim.toString())) {
            bindMobsim().to(JDEQSimulation.class);
            //            bind(  RelativePositionOfEntryExitOnLink.class ).toInstance( () -> 0. );
        } else if (getConfig().controller().getMobsim().equals(ControllerConfigGroup.MobsimType.hermes.toString())) {
            bindMobsim().toProvider(HermesProvider.class);
        } else if (getConfig().getModule(ExternalMobimConfigGroup.GROUP_NAME) != null
                && ((ExternalMobimConfigGroup)getConfig().getModule(
                ExternalMobimConfigGroup.GROUP_NAME)).getExternalExe() != null) {
            bindMobsim().to(ExternalMobsim.class);
            // since we do not know what the external mobsim does here, we leave it open, which should force the user to fill this with meaning.  ???  kai,
            // nov'19
        }

        install(new MobsimScopeEventHandlingModule());
    }
//    public interface RelativePositionOfEntryExitOnLink{
//        double get() ;
//    }
}
sebhoerl commented 1 month ago

Just a quick guess: The QSimModule has various subordinate AbstractQSimModule that are bound when the moduel is installed. And they, traditionally contain various asEagerSingleton. So if the QSimModule would be installed by default, all these object trees would be generated by default, even though they may never be used. This is especially tricky if certain components in the scenario etc. are maybe not even there because one just wants to set up an injector without a QSim. So I would assume that it was easier to do it this way than to resolve all the unneeded eager bindings.

kainagel commented 1 month ago

@michaz (if he reads this) should know better than me. My own guess is that installing the QSim is more involved (i.e. needs several bindings), and so they are grouped into a separate AbstractModule. (In my understanding, nested installs do not have any meaning ... the bindings are all at the same level.) Could as well move the other bindings into Modules of their own. I don't think that this has anything to do with eager singletons; in fact, every time I see them I try to replace them by in( Singleton.class ) scope.

But maybe I am misunderstanding your question, sorry.

Janekdererste commented 1 month ago

Thanks for your answers, I think this goes into the right direction. With your remarks, I can now see, that the QSimModule eventually also calls bind(Mobsim.class).to(QSim.class), which is what the others are essentially doing. I guess this also means that the other Mobsim implementations are less configurable and have to be used as is.