Pregunta

I have been working with Ninject to implement an application using dependency injection. I feel like I have a pretty thorough understanding of the concepts and have really liked the loosely coupled and testable architecture that the application has achieved using DI. I am struggling with one specific type of service, however, and am looking for insight into whether I am doing something wrong or if others have ran across the same thing.

Basically, I end up with some services/classes (a pretty small number) that have no other services depending on them. Because of this, the class never gets instantiated even though it is required to since it performs a useful role in the application. As an example, say I have an IMonkeyRepository service and an IMonkeyPopulator service. Assume the IMonkeyPopulator service really has no public API, and its sole responsibility (following the Single Responsibility Principle) is to discover monkeys on the network and populate the IMonkeyRepository with them. This service depends on the IMonkeyRepository and perhaps some other service(s) to handle its interaction with the network (configuration data for ports and addresses, for example). However, the IMonkeyPopulator has no public API, its just an empty interface.

Is this a bad design or some sort of code smell that I'm missing? I could obviously move this functionality into the repository itself but that seems like a violation of SRP to me (the repository has useful access functions, etc., and could actually be populated by multiple services). Some approaches that I've considered or tried but am not happy with are:

  1. Make the service have a single public method, such as Start, that must be called for it to begin work. This has the drawback of needing to determine a somewhat arbitrary spot in the system to make this call.
  2. Bind the service to a constant that I instantiate when the Ninject kernel is created. This requires that I understand that no one is dependent on this service so it must be handled specially, which seems wrong.
  3. Add some members to the service and make a GUI somewhere in my application that reads these values (such as status of the service, etc.). Obviously, having to add a GUI to my application that is only there for this reason is quite silly (although at times useful for debugging, etc.).

Any thoughts or guidance?

¿Fue útil?

Solución

You say that the IMonkeyPopulator depends on the IMonkeyRepository, but it seems like that should be the other way around? It sounds like your IMonkeyRepository depends on, and consequently may need to be injected with, an IMonkeyPopulator. If you also inject some other service fine, but internally, the IMonkeyRepository could tell the IMonkeyPopulator to "start" so that there's actually something in the repository? I might be misunderstanding the problem though... maybe I shouldn't be monkeying around so much :/

Otros consejos

Your IMonkeyPopulator is therefore some kind of ActiveObject which listens on a tcp connection in the background and writes that data into the repository. I would say from an application perspective that active object has to be started and stopped because you don't want to start the tcp connection in the constructor. So you can use the OnActivation and OnDeactivation methods on the binding to start and stop the service like so:

 This.Bind<IPopulatorService>().To<>().OnActivation((c, i) => i.Start()).OnDeactivation((c, i) => i.Stop())

But still someone in your application has to fetch/get the IPopulatorService in order to get it instantiated in your application. I usually use the bootstrapper pattern here http://www.appccelerate.com/bootstrapper.html in order to achive this.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top