How to program object-oriented with a DI framework? [duplicate]

Possible Duplicate:
Does “Inversion of Control” promote “Anemic Domain Model”?

My impression is that projects using a DI framework like Spring or Guice tend to lose their object orientation and degenerate to a purely procedural design:

  1. DI not only centralizes the question of which implementation of an object to use but also manages the life-cycle of these objects. Many OO design patterns, however, rely on the ability of business logic to wire objects. I wouldn’t know, for example, how to implement a Strategy Pattern in Spring because the decision which of the concrete strategies to use, is statically determined by the configuration of the application instead of a piece of code. Same goes for decorator, composite, observer, …

  2. The reason above leads to a design where functionality and data are separated. Because you don’t want to let the DI container decide when data is created, you split any code off the data in order to have only this part managed by the DI container. This is contrary to the idea of OO where code and data should reside together in one unit. This breaks the encapsulation of data because all fields of the data “beans” are exposed by public getters and setters.

  3. You can’t use polymorphism anymore because code is not linked to its data anymore and the “virtual functions” can’t work. This leads to those instanceof cascades that we all know we shouldn’t use. Also, we lose all those designs that rely on polymorphism.

  4. The DI container will inject managed beans only in objects which are also managed by it. So you can’t mix managed beans and normal objects because there can’t be any “non-managed gaps” in the reference chain of managed beans. So once you started with DI, you need to put all other code under the control of the DI container and you can’t use normal objects anymore. I suppose that this is the reason why the separation of code and data is done so rigorously in DI projects.

I see that there are reasons why to use DI but is it really worth giving up so much? Don’t people care about OO? Apart from this article, I can’t find any discussions on this topic.

Or is it just me who doesn’t understand how to do this properly? Any ideas how the four points above can be tackled with?

Appendix 1: Explanation of strategy pattern

I refer to the example here. Let’s assume there’s a DI version of it where all implementations of Strategy and the Context are injected to StrategyExample. Then StrategyExample doesn’t decide anymore which Strategy to inject into Context but the configuration would have already decided which implementation to inject into Context. So yes, DI heavily applies the Strategy Pattern. But it always does so statically.

3

DI not only centralizes the question of which implementation of an
object to use but also manages the life-cycle of these objects. Many
OO design patterns, however, rely on the ability of business logic to
wire objects. I wouldn’t know, for example, how to implement a
Strategy Pattern in Spring because the decision which of the concrete
strategies to use, is statically determined by the configuration of
the application instead of a piece of code. Same goes for decorator,
composite, observer, …

That’s simply not true. I think strategy is a prime example for one pattern that actually benefits from DI and is by itself (with or without container) the prototype of DI. You can export as many strategies as you like and pick the one that you want in your business logic. Also, no one, I repeat nothing and no one stops you from instantiating a known strategy by yourself to override the strategy that was injected.

The reason above leads to a design where functionality and data are
separated. Because you don’t want to let the DI container decide when
data is created, you split any code off the data in order to have only
this part managed by the DI container. This is contrary to the idea of
OO where code and data should reside together in one unit. This breaks
the encapsulation of data because all fields of the data “beans” are
exposed by public getters and setters.

I see your point but you can easily resolve this by using a factory pattern. In the simplest way, you can instantiate your object yourself and then have it built up and wired by the factory (calling and hiding the container’s implementation).

You can’t use polymorphism anymore because code is not linked to its
data anymore and the “virtual functions” can’t work. This leads to
those instanceof cascades that we all know we shouldn’t use. Also, we
lose all those designs that rely on polymorphism.

I totally don’t see your point here. Dependency Injection done right is a really good example for the power of polymorphism by itself.

The DI container will inject managed beans only in objects which are
also managed by it. So you can’t mix managed beans and normal objects
because there can’t be any “non-managed gaps” in the reference chain
of managed beans. So once you started with DI, you need to put all
other code under the control of the DI container and you can’t use
normal objects anymore. I suppose that this is the reason why the
separation of code and data is done so rigorously in DI projects.

Yes, but this can easily be resolved with a factory approach. You totally can build software that runs with or without a DI container by using a simple factory.

8

I don’t think DI throws OO principles out the window; in may ways, DI is dependent on them.

I’ll keep this answer generic, since most DI frameworks borrow very heavily from one another. The concepts are similar, though some frameworks have features that others don’t. I will assume, however, that the framework accepts external configuration that is read at runtime (like XML or properties file(s)), possibly in addition to compile-time configuration (like attributes).

In a DI world, you become more heavily dependent on interfaces and composition. For example, say your application needs to get a price of a product, and that price might come from a CSV file, or a database, or a REST service. You can define the interface as something like

public interface PricingService {
  public int getPrice(String productId);
}

with implementations

public class FilePricingService implements PricingService {
  public void setParser(Parser parser) { ... } // and getter
  public void setPriceFile(File file) { ... }  // and getter

  private Map<String, Integer> prices;
  public void init() {
    getParser().parse(getPriceFile());
     prices = ...;
  }

  public int getPrice(String productId) {
    return prices.get(productId);
  }
}

A decent DI system would be able to introspect the property types of this object, and call the setters with the appropriate objects. When an object is first referenced, the framework looks up all of the depended-upon objects, and calls the object’s init() method if it has one. For example, a property file based configuration (just to make the example simpler) may look like:

# Application.properties
class=...
pricingService=CSVPricingService

# CSVPricingService.properties
class=FilePricingService
parser=CSVParser # defined elsewhere
priceFile=/path/to/prices.csv

# XMLPricingService.properties
class=FilePricingService
parser=XMLParser # defined elsewhere
priceFile=/path/to/prices.xml

So at runtime, the configuration can be changed without having to recompile anything. The framework knows that the FilePricingService is expecting priceFile t be a File, so it invokes its own converters to automagically create a File from the filename that was provided. It knows that Parser is not a simple type, so it assumes this is a reference to another DI-managed component, and looks up that component. This is especially handy if you don’t have the source to the components you want to use. Extending the example:

public class RESTPricingService implements PricingService {
  public void setEndpointURL(URL endpoint) { ... }

  public int getPrice(String productId) { ... }
}

etc. The idea is that wherever something needs a PricingService, it doesn’t have to care what the implementation class is. Say you had a requirement drop on you that says “pick the lowest price from two different CSV files and the REST service”. The only additional code you’d have to write is a composition class that uses these other existing pricing services:

public class LowestPricingService implements PricingService {
  public void setPricingServices(List<PricingService> services) { ... }

  public int price(String productId) {
    int lowestPrice = Integer.MAX_VALUE;
    for(PricingService s : getPricingServices()) {
      int p = s.getPrice(productId);
      if(p < lowestPrice) {
        lowestPrice = p;
      }
    }
  }
}

And you can create a configuration file that looks like

# FileOnePricingService.properties
class=FilePricingService
parser=CSVParser
file=/path/to/file/one.csv

# FileTwoPricingService.properties
class=FilePricingService
parser=CSVParser
file=/path/to/file/two.csv

# RESTPricingService.properties
class=RESTPricingService
endpointURL=https://example.com/price

# FilesAndRESTPricingService.properties
class=LowestPricingService
pricingServices=FileOnePricingService,FileTwoPricingService,RESTPricingService

and tell the application to use that FilesAndRESTPricingService in its configuration.

This system is dependent on many OO priciples. Polymorphism/inheritance, encapsulation, etc., are all in use here. Java makes some of this a lot more verbose, with boilerplate getters and setters everywhere, but that’s a deficiency of the language, not of the DI pattern. (Imagine a Java with macros that allow you to say { property File theFile; } which would create the getter/setter code).

The benefit of using a DI system like this is the framework handles a lot of the configuration for you. A good DI system would also provide a way for you to inspect the runtime configuration of the objects via some UI. At runtime, if you needed to change the list of PricingServices, for example, the framework UI should be able to show you all of the registered implementations, and let you change their dependencies on the fly.

Systems like this exist, and have existed for over a decade, in real-world production settings.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật