tags:

views:

65

answers:

2

As my Maven project grows, I'm trying to stay on top of the project structure. So far, I have a nested directory layout with 2-3 levels, where there's a POM on each level with module entries corresponding to the directories at that level. POM inheritance (parent property) does not necessarily follow this, and is not relevant for the purpose of this question.

Now, while the nested structure seems pretty natural to Maven, and it's nice and clean as long as you are on one particular level, I'm starting to get confused by what I look at in my IDE (Eclipse and IntelliJ IDEA).

I had a look at the Apache Felix sources, and they have a pretty complex project in what seems to be a flat directory structure, so I'm wondering if this would be a better way to go.

What are some pros and cons for either approach that you have experienced in practice?

Note that this question (which I found meanwhile) seems to be very similar. I'll leave it to the community to decide whether this should be closed as a duplicate.

A: 

I vote for nesting. I'm using IDEA 9 which shows the nesting in the project pane, so the presentation mirrors your logical project structure. (This wasn't the case in 8.1 - it was flattened out.)

I prefer keeping things nested, especially if the names are very similar - makes navigation much easier when using a command prompt. I have a project with names like myapp-layer-component, so they all start with the same prefix, and many have the same -layer-, so using autocomplete on the commandline is next to useless. Separating these out into a nested structure is then much easier because each part of the name (appname, layer or component) is repeated just once at each level in the directory structure.

If building from the command line, it's much easier to build a subset of the project, e.g. if I'm working on the db model, then often I need to build all projects in that area. This is tricky to do when the files are flattened out - the only way I know is to use the -pl argument to maven and specify the proejcts to build. With the nested directories, I just cd to the db directory and run mvn.

For example, instead of

myapp-web-gui1
myapp-web-gui2
myapp-web-base
myapp-svc-clustered
myapp-svc-clustered-integrationtest
myapp-svc-simple
myapp-db-model
myapp-db-hibernate

We have the structure

\myapp
   \web
     \gui1
        pom.xml
     \gui2
        pom.xml  (other poms omitted to keep it short)
     \base
   \svc
      \clustered
      \clustered-it
      \simple
   \db
      \model
      \hibernate      

You could also add nesting for the integration tests, but this seems like driving the point too far.

With nesting, you also get all the benefits of inheritance (and some of it's pains...)

The only issue I've had with this is that the directory name doesn't match the artifact id. (I'm still using full artifactIds.) And so each project must explicitly define SCM paths, since these can no longer be inferred from the parent pom. Of course, each directory can be made the same as the artifactId, and then the SCM details can be inferred from the parent, but I found the long directory names a bit unwieldy.

mdma
How do you deal with the multiple semantics that could be, and often are, encoded in the directory tree, e. g. branches/tags in Subversion?
Hanno Fietz
Can you give another example, I'm afriad I don't quite get what you are asking.
mdma
There's several hierarchies in a large project, for example what belongs together in the VCS, what belongs together in a build, what belongs together in a deployment (zip etc), what a developer needs to have in the IDE for a particular task etc. These often overlap *mostly*, but very often *not quite*. This gets worse the more you reuse modules, which is an important reason to modularize in the first place.
Hanno Fietz
I've not encountered that problem. Our project structure is pulled straight out of SCM, as is. All projects are built by the build server (Hudson.) Deliverables, webapps, desktop apps with installers etc.. are separate projects that bring in what they need to build via dependencies. In the IDE, I can open all projects from a common root POM, or I can open up a subproject to get just that portion. If I need a cross-cutting slice, then I either manually add modules to a new IDEA project, or create a temporary maven pom to bring in the required modules. Reuse is rife and unproblematic. HTH
mdma
A: 

I use a kind of mixed approach. Things with distinct lifecycle (from a release and thus VCS point of view) are flat, things with the same lifecycle are nested. And I use svn:externals for the checkout. I wrote about this approach in this previous answer.

Pascal Thivent
That other answer is really good, thanks.
Hanno Fietz