views:

348

answers:

2

Hi, what is the advantage of using @configurable compared to on bean that not managed by bean doing di by applicationcontext.getbean? any anyone list pro and cons?

+6  A: 

Doing applicationContext.getBean() completely defeats the purpose of dependency injection because you're not longer injecting dependencies. An application context XML file is fine. Annotation based configuration (auto-wiring) is also fine. This way you may as well be doing:

Service service = new Service();

or worse:

Service service = ServiceLocator.locate("service");

Both of which make your code hard to test.

cletus
@cletus, can you comment on using applicationcontextaware in this article http://tinyurl.com/ycrdnsa compared with traditional way of application.getbean ?
cometta
Why do you say `Service service = ServiceLocator.locate("service")` is worse than `Service service = new ServiceImpl()` (I'm assuming that's what you meant; otherwise DI is pointless anyway)? I'm using service locators extensively throughout the code; I'd probably go mad directly injecting services into every UI page. Locator implementations are easily pluggable (context-based vs mocked); I honestly don't see how using locators makes testing any harder.
ChssPly76
it makes it harder if they are not easily pluggable. it sounds like they are pluggable in *your* implementation
matt b
@matt b - that's like saying "it's harder to test if you code to concrete implementations instead of interfaces". It's not like I came up with some magical code; service Locator pattern is well documented, Spring provides its own implementation to boot.
ChssPly76
A: 

I'm going to get -20 for this. Even the infamous Martin Fowler who invented this horrendous name of 'Dependency Injection' didn't think it's better for testing:

http://martinfowler.com/articles/injection.html

A common reason people give for preferring dependency injection is that it makes testing easier. The point here is that to do testing, you need to easily replace real service implementations with stubs or mocks. However there is really no difference here between dependency injection and service locator: both are very amenable to stubbing. I suspect this observation comes from projects where people don't make the effort to ensure that their service locator can be easily substituted. This is where continual testing helps, if you can't easily stub services for testing, then this implies a serious problem with your design.

Here are my objections:

  1. DI turns implementation dependency into interface dependencies. Your class is polluted with setters that shouldn't been there otherwise. Yes the real checkout process depends on credit card service, mail service, database service and who-knows-what tomorrow, but we shouldn't advertise those dependencies. They are ad-hoc, on-demand, not interface-worthy. Maybe next month the whole checkout process reduces to just a REST call.

  2. Performance. Services are usually not needed outside one method. DI requires at least a field variable for each service, and it is referenced as long as the host object is alive. If a service has per-client states this is very bad. I'm not a performance sensitive guy, but this feels just wrong.

  3. Coding for production environment made harder. Think how much more boiler plate code you added to use DI, everytime you need a service. All in the name of making testing easier. First of all - what?! Production is the 1st priority; testing should work for it and with it, not the other way around. Testing is not a religion, people! Focus on production environment, worry about testing later. Second - is testing really easier now?

  4. In testing you only have to mock a few services which are heavy and involve out-of-VM activities. With service locator, you have a test configuration containing those mock services, and you are done. Your checkout process can be tested without any hassle, as well as all classes that depend on those services. In DI, you have to manually manage those dependencies, in each unit test. -But! But with DI you have the flexibility of providing different mock mail services for different test units now! Oh good for you!

  5. "DI encourages a uniform way of service configuration" - only if you use the same framework. Actually it has nothing to do with DI; a framework enforces one way of configuration, you can argue as well that Spring encourages a uniform way of service locating. When a framework become widely used, it can become a de facto standard therefore make different developers talk to each other easier - only because the network effect, not for anything inherently good in its design choice.

In Conclusion, it is bad for design, bad for performance, bad for production, bad for testing and irrelevant for setting standards. What is it good for? It's like a lot of dumb rules and conventions established long ago of questionable origins, but we still follow them blindly everyday. That's what makes the society go around.

irreputable
good comments ,dude !
cometta
Setters are optional (ie auto-wiring). Without them you can't put in a mock object to actually test your code with so the choice is testability vs boilerplate setters? Seriously? Your views on the performance impacts of DI are, at best, naive. I don't know if you'll get -20 for this answer... well I can't speak for the other -18.
cletus
performance: I usually don't count bytes and milliseconds, but declaring an object outside the scope it is used makes me uncomfortable. only if the DI framework can inject service into a method local variable! wait it already exists, it's called service locator.
irreputable
well, all 5 points are wrong. Perhaps you just haven't worked enough with a DI framework. And, btw, some of them seem to be against object composition as a principle.. this should hint you it is wrong ;)
Bozho