Sponsored Link •
Erich Gamma lept onto the software world stage in 1995 as co-author of the best-selling book Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley, 1995) . This landmark work, often referred to as the Gang of Four (GoF) book, cataloged 23 specific solutions to common design problems. In 1998, he teamed up with Kent Beck to produce JUnit , the de facto unit testing tool in the Java community. Gamma currently is an IBM Distinguished Engineer at IBM's Object Technology International (OTI) lab in Zurich, Switzerland. He provides leadership in the Eclipse community, and is responsible for the Java development effort for the Eclipse platform .
On October 27, 2004, Bill Venners met with Erich Gamma at the OOPSLA conference in Vancouver, Canada. In this interview, which will be published in multiple installments in Leading-Edge Java on Artima Developer, Gamma gives insights into software design.
Bill Venners: In the introduction of the GoF book, you mention two principles of reusable object-oriented design. The first principle is: "Program to an interface, not an implementation." What's that really mean, and why do it?
Erich Gamma: This principle is really about dependency relationships which have to be carefully managed in a large app. It's easy to add a dependency on a class. It's almost too easy; just add an import statement and modern Java development tools like Eclipse even write this statement for you. Interestingly the inverse isn't that easy and getting rid of an unwanted dependency can be real refactoring work or even worse, block you from reusing the code in another context. For this reason you have to develop with open eyes when it comes to introducing dependencies. This principle tells us that depending on an interface is often beneficial.
Bill Venners: Why?
Erich Gamma:Once you depend on interfaces only, you're decoupled from the implementation. That means the implementation can vary, and that's a healthy dependency relationship. For example, for testing purposes you can replace a heavy database implementation with a lighter-weight mock implementation. Fortunately, with today's refactoring support you no longer have to come up with an interface up front. You can distill an interface from a concrete class once you have the full insights into a problem. The intended interface is just one 'extract interface' refactoring away.
So this approach gives you flexibility, but it also separates the really valuable part, the
design, from the implementation, which allows clients to be decoupled from the
implementation. One question is whether you should always use a Java
interfaces for that. An abstract class is good as well. In fact, an abstract
class gives you more flexibility when it comes to evolution. You can add new behavior
without breaking clients.
Bill Venners: How's that?
Erich Gamma: In Java when you add a new method to an
interface, you break all your clients. When you have an abstract class, you
can add a new method and provide a default implementation in it. All the clients will
continue to work. As always there is a trade-off, an interface gives you freedom with
regard to the base class, an abstract class gives you the freedom to add new methods later.
It isn't always possible to define an interface in an abstract class, but in the light of
evolution you should consider whether an abstract class is sufficient.
Since changing interfaces breaks clients you should consider them as immutable once
you've published them. As a consequence when adding a new method to an interface you
have to do so in a separate interface. In Eclipse we take API stability seriously and for
this reason you will find so called I*2 interfaces like
IWorkbenchPart2 in our APIs. These interfaces add methods to the
Since the additions are done in separate extension interfaces you do not break the clients.
However, there is now some burden on the caller in that they need to determine at run-
time whether an object implements a particular extension interface.
Another lesson learned is that you should focus not only on developing version one, but to also think about the following versions. This doesn't mean designing in future extensibility, but just keeping in mind that you have to maintain what you produce and try to keep the API stable for a long time. You want to build to last. That's been an important theme of Eclipse development since we started. We have built Eclipse as a platform. We always keep in mind as we design Eclipse that it has to last ten or twenty years. This can be scary at times.
We added support for evolution in the base platform when we started. One example of
this is the
IAdaptable interface. Classes implementing this interface can
be adapted to another interface. This is an example of the Extension Object pattern,. 
Bill Venners: It's funny nowadays we're so much more advanced, but when we say build to last, we mean ten or twenty years. When the ancient Egyptians built to last, they meant...
Erich Gamma: Thousands of years, right? But for Eclipse, ten to twenty years, wow. Quiet honestly, I don't envision a software archeologist finding an Eclipse installation stored somewhere on a hard disk in ten or twenty years. I really mean that Eclipse should still be able to support an active community in ten or twenty years.