This post is in response to On using containers as objects.
First of all, dispatching calls to different services based on runtime conditions is something that is needed all the time. The example explained on the code reef might not speak to everybody, though. Example scenarios of every-day use include :
- You need to change the behavior of a payment system depending on the environment. Obviously, you cannot use the real bank service for development, so you need to switch between a DevelopmentPaymentFakeSystem and a RealWorldBankPaymentSystem implementation depending on a runtime condition (the environment on which the application is deployed)
- You need to activate debug features (IE browser check pass-through in development mode, etc)
Obviously, every programming problem can be solved by adding spaghetti code that adds a few conditions here and there in your real services. But the rest of this post assumes that for testability and maintainability reasons, you are implementing the features as different services : the fake payment system, and the real world payment system
The idea suggested by the aforementionned blog post is to use a front-service that will deleguate to the right implementation (real vs fake) based on a runtime condition (deployment). Even though the idea of doing that is brilliant, I would tend to think that the provided implementation is assuming a broken, half-implemented IoC container.
Indeed, by using a framework such as Spring :
- The Spring container can directly be used as a service locator (just implement ApplicationContextAware, and spring will inject you the service locator). So, no need to create your own implementation of the container (you could always implement ApplicationContextAware later if you need to switch to a different container, as this is just an interface)
- There is actually no need to use the IoC container as a service locator: the dispatcher service can be declared in the IoC container and one can inject it the different implementations using the IoC mechanisms. This can be accomplished using several techniques : name-based wiring (or the @Autowired annotation coupled with @Qualifier), tag-based wiring (you can now tag implementations based on some logical semantic, and then use @Autowired complemented with @Qualifier to get the right instance), or you can just have all implementations of a given interface directly injected to you so you can do your runtime logic to determine the right object (once again, the magical @Autowired annotation is your friend, just declare an array of the given type and @Autowired it! )
Sure, there are advantages of abstracting the container, but sping provides so much goodness that it’s pretty sad to avoid making use of it, or mirroring its features in custom code !
Thats pretty cool, I didnt know about the Qualifier annotation. Its a shame that I cant find that functionality in Windsor.
Thanks for the poste!