I am the founder and lead developer of Hibernate Envers, a Hibernate core module, which provides entity versioning/auditing capabilities. I am also one of the co-founders of SoftwareMill, a company specializing in delivering customized software solutions (http://softwaremill.com, "Extraordinary software as a standard"), based on Java and JBoss technologies. After work, apart from being involved in development of Envers, I work on several small open source projects, like ElasticMQ (simple message queue written in Scala with an SQS interface), projects around static analysis (using JSR 308 - Typestate Annotations/ Checkers Framework and FindBugs), and some CDI/Weld (not always portable) extensions, like autofactories or stackable security interceptors. I am also interested in new JVM-based languages, especially with functional elements (like Scala, JRuby) and frameworks built using them (like Lift), as well as improving the ways we use Dependency Injection. Adam is a DZone MVB and is not an employee of DZone and has posted 52 posts at DZone. You can read more from them at their website. View Full User Profile

Frameworks vs Libraries as Inheritance vs Composition?

04.25.2012
| 7879 views |
  • submit to reddit

For quite some time inheritance was the dominant model of structuring programs in OO languages like Java. Very often it was used as a mechanism for reusing code – “common” functions where placed in an abstract class, so that subclasses can use them.

However, this often proves to be very limiting, as you can only inherit from a single class. The code becomes constrained and tied to one particular framework-specific class. Not to mention testing – such base classes often depend on outside state, making tests hard to setup.

That’s why nowadays time and again you can hear that you should prefer composition over inheritance (see for example this StackOverflow question). When using composition, you can leverage multiple re-usable chunks of code, and combine them in an arbitrary way. Also using IoC/Dependency Injection strongly favors composition.

I think the above inheritance-composition opposition strongly resembles the framework-library distinction. When using a framework, you are forced into a specific structure, where you must model your code in one specific way. Quite obviously it’s often hard or impossible to use two frameworks in one layer/module. That’s how hacks, ugly workarounds, reflection madness, etc. is born.

Libraries on the other hand (unless they are deliberately wrongly written), can be freely combined. Just like composition of classes, you can compose usage of many libraries in one module. Your code can be kept clean and only use the library functionality it really requires.

I’m not saying that frameworks are bad – just like inheritance, they may be very useful if used in the correct places. However, next time you put your code into a framework, maybe it’s better to think twice: can this functionality be implemented using composition, with the help of a library? Won’t this make my code cleaner and more maintainable?

Published at DZone with permission of Adam Warski, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Jilles Van Gurp replied on Thu, 2012/04/26 - 2:18am

The difference between inheritance and composition is the point in time when you fix the decision as to what to compose with or what to inherit from. With inheritance this is before compile time and with composition after compile time. The relation between a base class and its subclasses is compiled into the system. The relation between an object and is delegates is created at construction time.

So, basically inheritance relations are fixed earlier in time: you have to decide earlier. Minimum before you compile the software and realistically quite early in the development of the software. Worse, once you have inheritance relations, you need quite a bit of API compatibility breaking refactoring operations to convert them into delegation based relations. Generally pushing decisions for this type of stuff to a later point in time provides you with greater flexibility, which is a good thing given the amount of uncertainty that is typical during software development.

Another issue is that Java actually provides us with two inheritance mechanisms: interface extension and class extension. Most of the early framework designs did not really take that into account and were all about class extension and about languages that support multiple inheritance (e.g. C++, Smalltalk).

Both forms of extension are a way of expressing an is-a relation between two types. However, there is a subtle difference. With interfaces you are saying that class MyClass is a Foo. It is perfectly ok for MyClass to also be a Bar, and a Serializable, a YetAnother interface, etc. MyClass can implement many interfaces, but it can only extend one class. 

Both forms of inheritance complement each other. Typically, a good Java API defines any composition dependencies in terms of interfaces. Implementing the type is required, extending a base class of that type is optional. For example in the collections framework in Java you have Lists, Maps, and Sets, which are all interfaces. Generally something that needs a map has a property of that type, which allows the user of that class to inject any kind of implementation of that interface.

The inheritance based alternative would be to exend e.g. HashMap. Which removes that choice and probably results in a weird design where the extending class does all sorts of things that are completely unrelated to being a HashMap. This kind of cohesiveness problems are typical for class inheritance based designs. Good class design results in strongly cohesive classes where everything in the class has some close relation to each other. If you find a class that has multiple sets of cohesive functionality, you have a design problem that has known negative correlations to several of the 'ilities (maintainability, flexibility, understandability, etc.). In other words, having classes with poor cohesiveness in your software is not a good a thing. So, by extension (pun intended), class inheritance is a bad idea unless you can guarantee and preserve a high level of cohesiveness for both base class and any (future) sub classes. This is very hard.

In my personal experience, whenever class extension seemed convenient and I ended up using it, I almost always ended up regretting that decision at some point later in the evolution of the software. I've learned the hard way that class inheritance relations are brittle and tend to not survive the scrutiniy of refactorings and minor redesigns. So, as a form of optimization, I don't generally bother with class inheritance at all and refactor anything in sight that is based on inheritance, pretty much without a second thought. Often the intention of inheritance is merely to express is-a relations. You can do that just fine with interfaces. However, when is-a relations start to look more like has-a relations, composition and delegation are the only answers.

 

Jose Maria Arranz replied on Thu, 2012/04/26 - 2:19am

Meanwhile we are speculating in articles or thinking on the typical Hello World example of composition vs impl inheritance (where both solutions are basically the same in code and effectiveness) everything is fine.

But when it comes to real world problems, things are different, for instance try to convince to Android guys to provide an alternative solution instead implementation inheritance for instance to this class.

Christos Melas replied on Thu, 2012/04/26 - 7:54am

Interesting article, but as Jose mentioned in some cases you need classes to be part of a framework, i.e. via inheritance, so that they can be used by it and not to just use parts of a framework i.e. via composition.

Erwin Mueller replied on Mon, 2012/04/30 - 1:39am in response to: Jilles Van Gurp

Inheritance vs. composition is just simple: Inheritance is a "it is a" relationship, and composition is a "it uses that" relationship.

It's just that simple. For example, if you extend a JFrame, that new class "is a" JFrame. It have all the methods of JFrame and it behaves like a JFrame, short: it is a JFrame. But if you are using composition, your new class is a new class, that just is using the JFram. Why that is that hard to understand is beyond me.

That's why in 99% of the case inheritance is the wrong type to use. You can't just change later an Apple to a Peanut and expect that the rest of your program is working just as.

 Also inheritance is always public (expect in C++ where you actually have private super class). It's like to declare a bunch of methods and possible state public that is not related to your problem.

That's why I so much dislike the "classic" tutorial in Java:

class Foo extends JFrame {
... main(...) {
foo = new Foo();
foo.setVisible(true);
}

public Foo() {
add(new JButton(...));
...
}
}

There is no reason for Foo to be a JFrame. You just mixed the methods of JFrame, Window, Container, Component, etc. to your Foo class. Foo is not a new kind of JFrame, it's just using JFrame to display a window.

 

class Foo {
... main(...) {
foo = new Foo();
foo.openWindow();
}

public Foo() {
frame = new JFrame();
frame.add(new JButton(...));
...
}
public void openWindow() {
frame.setVisible(true);
}
}

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.