Composite Oriented Programming With Qi4j

9. June, 2011

Qi4j LogoComposite oriented programming (COP) addresses one of the short comings of OO: That the meaning of an object depends on the context.

In most OO languages today, it’s hard to change the type of an object. Actually, Object Oriented Programming should be called Class Oriented Programming because the class (the type) is the┬ácore feature which we use to build application.

But in the real world, objects can have several types. This isn’t polymorphism. It means that COP allows you use the data in an instance within the context of several classes.

For example, in Java, we have two methods which should be context sensitive: toString() and equals(). When I call toString(), I want a certain conversion but that can change depending on in which context I call it. In a debugger, I might want all fields. In the debug log, I might just want the name. In the UI, I will want a nice, user-configurable conversion.

equals() is a similar beast. Different contexts need different equals() methods that work on the same instance. For example in Hibernate, equals() should use the business key. Which is stupid: As soon as a primary key is assigned to the instance, it would be much faster and precise to use that to check for equality. But if you write a tool to compare graphs, your needs will be vastly different.

DI and IoC tools try to fill the similar gaps: At a certain point in time, your code needs a service and you can’t know ahead of time which implementation will be executing the service. While that works somewhat, it’s just a workaround for a fundamental flaw in todays OO languages: Type rules, instances are part of the problem.

Qi4j tries to solve this fundamental problem. Instead of writing huge classes that do everything, the application is created from small building blocks.

The typical case is names. A lot of instances have a name. Instead of writing this code once and using it everywhere, 10 lines of code are copied into every class: The field definition, getter and setter. And maybe you want to set the name from the constructor, so you need 8 more lines (one default constructor and one with the name parameter).

In Qi4j, you define this once. After that, you just add “extends NamedObject” in all the places where you need it. Almost no duplication. Since NamedObject is just an interface, you can collect several of these building blocks in your entity.