Showing posts with label ejb. Show all posts
Showing posts with label ejb. Show all posts

Tuesday, June 1, 2010

Dependency Injection and OO

Once upon a time, there was Object-Orientation, and people liked it and wanted to do complex things with it. One idiom that was widely used was dependency injection:
class PaymentCard {
public boolean validateTransaction(Transaction t, Communicator c);
}
Here, a transaction (a different Object) is validated using some communication channel (a different object, being injected). The subclass could then just say

class VisaCard extends PaymentCard {
public boolean validateTransaction(Transaction t, Communicator c) {
super.validateTransaction(t, new VisaCommunicator());
}
}
Alas, the real world is not that easy. The VisaCommunicator is probably something that needs to be injected into VisaCard, or else it needs other injections like SerialCommunicator, EthernetCommunicator, RandomGenerator, CertificateHandler and whatnot. Pretty soon, the methods become huge.

"This is a bother", says everybody, and proceeds to move the injections into the constructor. However, it still means that to construct an object, you need to know what it and all objects it constructs needs injected.

"This breaks encapsulation", says everybody, and proceeds to make Dependency Injection frameworks where all these things are done automagically with annotations, reflections and all manner of other niftiness. Now several layers of reflection, lookup and wrapping is done for each object creation.

"This is slow", says everybody, and proceed to move the injection into "beans" that handle various layers of services: web service layer, business service layer, data access objects, ... The injections can now be done only when a new bean is needed, and since beans are stateless, they can be pooled and reused. Much faster. Scales nicely.

"This is not object-oriented", says I. My objects no longer have any significant functionality on them, since anything that requires injections (which turns out to be many things) must live in the beans. Code becomes spaghetti once again. However, these injections are almost all "static" injections - the objects injected are always the same class and have no state. So maybe each "OO class" (class that is actually object-oriented) could have an associated class that just holds its injections? It cannot be a static field, as they don't play well with beans. It should just be findable at construction time to be plugged into the object. Surely somebody has done this, I says, and wander off looking for a solution

Monday, September 28, 2009

Reasons I don't like EJB

At work, we've long since decided to use EJB3 for our main server system. As the conversion from old code goes along, I also learn some of the problems of EJB. I am more and more of the opinion that EJB3 is yet another over-engineered monstrosity as I've come to expect from Sun. Even with nifty annotations. But the worst part is that using EJB denies one access to a lot of the features of Java.
  • Package-level protection. Much as the package-level method protection scheme is inferior in Java (partly due to the lack of true subpackaging), when you switch to EJBs, you give up even that when you use EJBs. An EJB needs to implement an interface, and all other EJBs must get their dependencies through the interface. So unless you cast your injected bean to the implementation all the time, you cannot use package-level protection.
  • Object-orientation. Beans are singletons implemented with objects, their methods static for all practical purposes. Unless your bean is an entity (and thus subject to all the restrictions of being mapped to a database), you only have the one that's injected.
  • It's viral. Which is not so bad if you start out using it, but if you have a big old system it's difficult to gradually change over. Suddenly you find a cluster of classes that are unrelated to what you're doing, but you have to change them to EJBs because one of them calls a method in the class you actually want to change. And since EJB injection happens at runtime, it's tricky to determine if you've done it right. Even once you have all the EJBs injected correctly, if you miss somebody who makes an instance you'll get very subtle errors down the road.
  • EJB-injected objects are not the real objects, merely proxies implementing the interface (at least in some implementations). This means you can't do anything in the way of reflection beyond what the interface has; in particular, you cannot find annotations on the objects. This is particularly ironic with EJB3, which can be done entirely with annotations.
I'm sure more issues will pop up as the conversion goes along.