1

I'm learning AutoFac. I like the idea of modules. From my understanding, I could for example create a module that registers some part of my application dependencies to the container to create some abstraction above it. However, I don't really know what to do in situations where I have multiple modules.

  1. First thing is, should I create a seperate LoggerModule just to do this:

    builder.RegisterType<'MyLogger>().As<'ILogger>();

Or should it be put drectly in composition root? The question comes from my confusion if it's a good idea to register modules (higher abstraction) and services (lower abstraction) on the same level of composition root. Should modules be created only for services that use many dependencies, to make the registration simpler on the composition root level?

  1. Another thing: What about my other modules that register services that require ILogger? Should I just assume that ILogger is already registered and just c.Resolve<'ILogger>() or should I register it again so that every module has all needed dependencies registered?

  2. Can I create a module that registers other modules?

I tried to look for answers to these, but I found only topics that were close, but not really about my issue.

Loreno
  • 668
  • 8
  • 26

1 Answers1

2

Think of modules as vehicles for configuration, not as components of your application. They exist to setup the container with the components your application will depend upon. With this in mind:

  1. Sure. There's no reason why a module shouldn't exist for a single purpose (such as to configure logging in the container). Oftentimes, however, logging is such a fundamental service that it's usually "built-in" at the root (or shell) of the application.
  2. Other components should just assume that logging is available and that it's someone else's responsibility to configure it. This is the essence of dependency injection - if the required services are not available your app can't run.
  3. This is technically possible, but I wouldn't do it. Try to think of modules as being self-contained and not directly dependent on each other. It's possible in complex applications that the order in which modules are loaded at startup is important, but I consider that an implementation detail that shouldn't affect architectural abstractions.
lesscode
  • 6,221
  • 30
  • 58
  • Thank you for this valuable input. About 3rd point: I can imagine a situation where some component has lots of dependencies, so I will create a module for it. But one of its dependencies also has lots of its own dependencies. In such case it becomes confusing on which level I should actually load the latter module. In composition root? Well, this module will be used only by the first, bigger module. In this case, I think I could load the second module in the first one. What do you think? – Loreno Feb 06 '19 at 08:17
  • If you're finding that you have too many dependencies, you probably need to split your classes/projects down further. The more you split them down into their real components, the easier it will be to see "why" you do it. (In answer to your original point). Its such a difficult question to give a full answer to without really understanding what your code/solution looks like. But your basic premise is to aim for High Cohesion, Low Coupling.. You can find further reading here: https://thebojan.ninja/2015/04/08/high-cohesion-loose-coupling/ – Robert Perry Feb 06 '19 at 09:19
  • @Loreno It seems like you're still conflating modules with components to some degree (eg _"this module will only be used by the first, bigger module"_). The number of dependencies between components is not the best criteria by which you decide to arrange your modules - it's more about cohesion and separation (as suggested by Robert). The order of loading modules I mentioned is purely a technical concern (eg. logging will be used by most modules as they are loaded, so if logging is configured by a module, that one will have to load first). – lesscode Feb 06 '19 at 19:32
  • @lesscode Does an order of loading modules have any significance? Loading does not yet mean actually creating the dependencies, so as long as I don't create actual instances I can register dependencies in any order. About second thing, I understand what you try to say, but I think that modules also are some kind of components, but just more high-level ones. In my application, I create modules that group dependencies that always are instantiated together. If I have 4 services following same interface and a factory that can create all of them - I will add them all to one module – Loreno Feb 07 '19 at 07:28
  • Order of loading modules is only an issue for certain, narrow, technical reasons, in complex applications (like the logging scenario in my prior comment). Your scenario of having related services in a single module is perfectly fine and appropriate - but you should avoid making modules directly dependent upon other modules (or even know that they exist). Any "communication" between modules should happen only through (injected) dependencies between components (i.e. shared abstractions), in keeping with the Dependency Inversion Principle. – lesscode Feb 07 '19 at 16:51