November 22, 2010

A Logical Ordering of Import Statements

Originally published 3 Mar 2006

Do you care about the order of your Java import statements?  Well, maybe not, but I do.  The reason is because I like to do a visual check of my dependencies.  According to the Acyclic Dependencies Principle, there should be no cycles in packages.  Robert Martin wrote here, "Remember that the prime motivation for using Object Oriented Design is to manage module dependencies."  One way I check my dependencies is by scanning the import statements of a class or interface to make sure it depends on other, appropriate classes and interfaces.

The rule I use is that you can go up a package hierarchy and over to the right, but you can’t go down or to the left.  (Props go to Michael Gaffney for working with me to come up with this rule years ago).  Over to the right?  I’m working in the context of a layered architecture and when I say “over to the right,” I’m talking about something like this:

presentation -> business -> persistence -> general utilities

So starting on the left, dependencies flow to the right.  You wouldn't want to go back to the left.  That would introduce a cycle.  Also, within a layer, you could go up the package hierarchy, but you wouldn't want to go down.

Here’s an example.  Suppose I’m developing a web application and I’m working on a class in the presentation layer.  I might have something like (contrived):

package com.mycompany.myapp.web.struts;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.mycompany.myapp.utils.SomeUtil;
import com.mycompany.myapp.domain.SomeDomainObject;
import com.mycompany.myapp.domain.SomeOtherDomainObject;
import com.mycompany.myapp.web.SomethingHigher;
import com.mycompany.myapp.web.utils.SomethingToTheRightWithinModule;

Now, ideally, I’d like to list those imports in the exact opposite order.  That way, I could start at the package statement and look down and make sure the imports flow in an acceptable, directed acyclic graph kind of order, following the rule above.  In fact, I used to list them in this order, but everybody else lists them in an order more like the above, and so, I accepted defeat and now follow suit.  I just start at the bottom and look up.

I only care about ordering among packages here.  I don’t try to list the imports in dependency order among classes at the same package level.  That would be crazy.  However, I am strict within the layer of the class I’m working with.  In the example, that would be the web layer.  I’m looking at a class in ...web.struts and I want to make sure that I’m going to the right first, then up, all within com.mycompany.myapp.web in an appropriate package order.

Once I’m past the web layer, I loosen up.  I just want to make sure all the imports for the next layer are grouped together, and so on.  So in the example, all the domain imports would be together, then all the utils, and so on, all the way up to java.util.

You can set up this ordering standard in Eclipse under the Organize Imports preference.

How else could you check your dependencies?  There are useful tools out there like JDepend, and I use them.  But I still like this import ordering practice.  I typically do the manual scan right before check in time.

No comments:

Post a Comment