Interfaces in your faces

What’s wrong with the following code? (Other than the fact that I wrote it):

public void someMethod() {
   ArrayList someList = new ArrayList();
   ImportantObject important = createOrGetImportantObject();
      someList.add( someThirdMethod() );
   important.useList( someList );

youThere’s alot wrong with it. But I wanna talk about the first obvious thing that jumps out at me, the type declaration. By the way, hi I’m Cliff and you’re here because the hairs on your chin look similar to the picture to the right. (…and that means either your Gillette no longer works or you have a higher than average aptitude for solving complicated problems and applying sophisticated algorithms to computer processes which results in more heat emitted from your skull which causes resident follicles to migrate southward where climates are generally cooler.) Chances are you know enough about Java or O-O to know what a concrete type declaration is versus an interface type declaration. However, do you regularly make a habit of declaring most of your variables as an interface type? Also are you aware of how important interfaces are for quality software? Do you know when it’s appropriate to use or declare a concrete?

Do you?
This is the part where I climb atop a soap box and babble for a while about something that struck a chord with me while I perform my daily programming tasks. Truth be told, I’m no expert on any subject and much of what you read here should be taken with a grain of salt. (followed by a fifth of gin chased by a 22oz bottle of beer.) But, BUT I tell you, what I have to say today could change your life. It could cause you to yield to others in traffic, tithe at your local church, and/or reduce your overall cholesterol intake by a certain magnitude. What I have to say today is relative. It’s religious as much as it’s good practice. I’ll begin with the moral and then fill in the details, “unless you’re absolutely positively at the mercy of a terrorist weilding a weapon of mass destruction or on a downward spiraling plane headed for certain disaster, use an interface.”

Why is it such a big deal to some people to use interfaces? Why is it such a big deal to others to avoid an interface? Those who are new to Java or OO as well as many who have used it for a while miss the concept behind interfaces. These people view interfaces as obstructive nuisances that impede a fluent development cycle. These are also the same people who have not gotten full use out of the tools available in their IDE many which include refactoring shortcuts and hotkeys. Then there are others who are reading right now and feel like I’m scratching that itch imposed by a fellow co-worker of the former type. These people know exactly where I’m heading with the text I fill this page with. These people have been in the game for a while and have actually been able to use the code they’ve written three months ago for a completely unfathomable purpose. These people come in all different shapes and sizes but typically resemble the picture above. These are my homies. (Honestly I don’t believe in stereotypes and most programmers (at least nowadays) don’t wear long beards or pocket protectors. We’ve actually evolved into a more handsome species capable of being cool and bugging out. Check out my mug shot above, that should show you how how attractive we’ve become.)

Enough Dumb Talk! Get To The Point!
I gathered you here today from far and distant regions of our planet to inform you (or in many cases remind you) what interfaces can buy. In the simplest case you have the ease of refactoring. Here’s a breif example of what you can expect:

public void someMethod() throws AnOffTheHookException {
   HashMap map = new HashMap();
   //add some stuff
   for(Map.Entry entry : map.entrySet()) { /* do something clever */ }

On the second time around (you’re revisiting the code) let’s pretend you want the map to be sorted. Now what happens?

public void someMethod() throws AnOffTheHookException {
   HashMap map = new TreeMap();
   //add some stuff
   for(Map.Entry entry : map.entrySet()) { /* do something clever */ }

Compile error!!! (Or if you live in the 21st century, editor squiggly line indicators around the 1st assignment in the method.) But that’s too easy right? C’mon nobody would change just the right hand of the assignment and try to compile. The more likely situation is:

public void someMethod() throws AnOffTheHookException {
   TreeMap map = new TreeMap();
   //add some stuff
   for(Map.Entry entry : map.entrySet()) { /* do something clever */ }

See? No type incompatibility drama. Everything is nice and neat and you can shove those interfaces to Hell because they do nothing! But missing the point is what this article is all about. You see I did something clever in the code that we glossed over. I added stuff to the map. Now lets say that it is a lot of work coming up with the stuff we put into the map, I’m thinking several lines riddled with JDBC and/or XML. Let’s also make the situation more realistic by pretending the need for a sorted map came after an initial dozen rounds refactoring of the “add some stuff” code. By this time “add some stuff” has been moved into another method and finally into a set of delegate objects that each remember the Map’s origin. These delegates say stuff like, “I grew up with that HasMap back in 03′ when we had some crazy wild times smoking prepared statements, convertin’ BigDecimals, and catching SQLExceptions!” in other words they have methods that look like this:
public void backflipWithDB2ComplexityAndLoadMap(HashMap map, ResultSet someunneccessaryParamDueToPoorDesign) {}
And there’s a couple of them. Furthermore each helper object got a record deal and blew up like MC Hammer getting calls from all over the place. Now lets try to introduce our TreeMap! See where I’m going with this? If not just imagine a huge collection of method calls all asking for and/or returning HashMaps. Now imagine cherry-picking these method calls one at a time trying to change the parameter and return types to TreeMap. Then imagine trying to go back and use a map from a 3rd party API after you painfully make the first global change.

How does this happen? Well because we didn’t use the Map interface to declare our variable we automatically “told” every one who uses the variable all of its dirty secrets. It’s the equivalent of passing the variable around naked. As we moved the code around and refactored we end up propagating the concrete type to parameters lists and return types. Had we used the Map interface instead (putting clothes on our variable) we could then use an old thing that works like a Map without touching any additional code. It just makes sense to use an interface.

Even when you use interfaces they don’t help unless you use them for most of your types. To explain I’ll give a recent example of what I ran into:

public interface Row {
/** Iterates the row instance returning a list of columns **/
public ArrayList getCols() ;

The above signature was found heavily used through the system by our only implementation that spoke JDBC to a database in a lower level. When we saw the need to introduce a new implementation that used record streaming or data pipelining from the DB the natural thing to do was write a List implementation that was actually connected to or delegated calls to an internal JDBC ResultSet. (I’m sorry, that’s too many syllable crammed together. Let me simply state it as we tried to turn a ResultSet into a List and return it.) We were stuck with about 475,373,595,698 touch points of impossible to test code in need of refactoring just to introduce our change. Had the original (idiot) author (me) of the method only declared a return type to be the List interface instead of the more concrete (like my head) ArrayList type the change could have been quietly slipped underneath all 475,373,595,698 touch points avoiding the horrible never dying zombie Find/Replace dialog introduced in a more recent version of Idea. (That’s a whole ‘nother story that I’ll rap to you about in the future!)

What else can I use interfaces for?
You can use an interface when you want to work in parallel with another developer. The interface becomes the contract between you two. You would have a conversation like:

You: Why don’t we build the Inventory Receiving software together. You do the UI while I work on the backend.
Him: That’s great since I love playing with Swing! How should it work?
You: We can start by giving the warehouse a screen to enter pallets numbers on. Then when the number is entered a full list of expected products and quantities should show.
Him: Perfect, I’ll give you a pallet number as an “int” and you can return a list of product objects. It can look like this:
public interface Receiver {
List receivePallet(int number);
You: I’ll get to work right away! I got everything I need.
Him: Me too!

Then at the conclusion when your bars are green and product management has signed off on his UI the pieces can be glued together with little worries of compatibility because you both worked off of a common interface.Also you avoid the need to step on each others toes; you writing or accepting Swing components and him assembling JDBC statements. Life is good.

Another good use for interfaces is (and most important) in unit tests. In fact I found that if you write your unit test against a concrete object then you’ve written throw-away code, both in the unit test and in the concrete implementation. All unit tests should start with an interface. They should also no nothng about how the implementation comes into existance if at all possible. I started writing my unit tests as abstract classes and I found that helps keep me focused on how the object is used instead of how it is written. In all cases you should not write any code until you have a firm design. Guessing at the design fools you into thinking you have the right design, but if you’re not using your design before you’ve written it then is the wrong designe in most cases. Writing a unit test is your opportunity to use your code before you write it. It sounds and feels awkward initially but it becomes addictive once you do it a few times. Also you should pay attention to the “intentions” or “quick fixes” features in both Idea and Eclipse respectively. Combined with a properly written unit test they are a way of getting your IDE to write 80% of your implementation for you keeping you even more focused on how the object is used from the outside.

So in summary interfaces let you:

  • Refactor without problems
  • switch the implementation with little if any touch points
  • work in parallel with another
  • focus on how your objects are used instead of how they are written

That said when in doubt, use an interface. This message was brought to you by…

Juxy the XSLT unit testing, poly-urathene based paint thinning, magic creme facial hair removing, anti-theft adulterous spouse catching product. Get your copy in stores today!
…and also by…
Maven2 why maintain your build system when someone else can do it for you?
…brought to you in part by…
Rory because the world needed another short, opinionated, big nosed, and drug free man of somewhat French descent….
…and also by…
Groovy, the agile dynamic language for the VM that will make you feel retarded for buying that Ruby/Rails book on Amazon. I mean, honestly, who wants to learn yet another language, API stack, deployment solution, and methodology just to write DSLs and use closures when you have all of those goodies and more linked right into the JVM?

5 thoughts on “Interfaces in your faces

  1. I agree with Merlyn – interfaces for unit testing is brilliant. In fact, for UIs, we move all logic out of the UI layer into a presentation layer. (Model-View-Presenter pattern) The presentation layer simply has an interface to the UI, allowing you to fully test your UI logic without having a real UI in place.

    Interfaces also seperate dependencies nicely, as you mention. If a Joe Developer needs a piece of code from Sally Developer, he can just use an interface to code against it, allowing him to continue work while Sally builds the really implementation.

  2. Merlyn/Judah,

    I totally agree and I thought I hinted at that same point once or twice in my topic. As a matter of fact my last point is directly tied to the idea of unit testing the right way. I still wanna post a piece on BDD with J-Unit to further drive the point home.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s