In Java when you add a new method to an interface, you break all your clients.... Since changing interfaces breaks clients you should consider them as immutable once you've published them. --Erich Gamma
NoSuchMethodError
--Java VM, all too frequently
The two quotes above are problems of interface evolution. The first one suggests a real problem in Java's interface approach. At least one master designer is reluctant to use them, and indeed Gamma has gone on the praise Eclipse's replacement of Java interfaces by descriptors written in XML. There is an implicit put down here: Java's interfaces are bad enough that master designers write their interfaces in a separate language.
The second quote shows up all too frequently on Scala Bazaars. People independently post compiled jar's onto a bazaar, and all too frequently we discover that different versions of compiled jars are incompatible with each other. Their interfaces have shifted and are no longer compatible.
Both of these problems are caused by interface evolution. Either you get stuck with a bad interface, or you improve the interface and break compatibility.
There is a lot that can be done to ease the pain of interface evolution. One tool in the tool box is to extend the idea of deprecation into transition checking. With this approach, you step into interface evolution carefully, and you have a checker to help you decide when to take the plunge and make an API-breaking change. I will be talking about this approach at the end of the month at the Workshop on Library-Centric Software Development:
Spoon, S. Alexander. Anti-Deprecation: Towards Complete Static Checking for API Evolution. Workshop on Library-Centric Software Development (LCSD) 2006. (extended version with proofs)
Abstract: API evolution is the process of migrating an inter-library interface from one version to another. Such a migration requires checking that all libraries which interact through the interface be updated. Libraries can be updated one by one if there is a transition period during which both updated and non-updated libraries can communicate through some transitional version of the interface. Static type checking can verify that all libraries have been updated, and thus that a transition period may end and the interface be moved forward safely. Anti-deprecation is a novel type-checking feature that allows static checking for more interface evolutions periods. Anti-deprecation, along with the more familiar deprecation, is formally studied as an extension to Featherweight Java. This formal study unearths weaknesses in two widely used deprecation checkers.