I'm going to take a quick first cut at this (great Q BTW!):
Would imposing a structure on the large project (i.e. into smaller
sub-projects) slow the compiler down?
Not by enough that it matters, the overhead is actually in Maven invocations.
Also, I have a slight concern on what impact this might have editing
time in IDEs (we principally use Intellij). Intellij seems to build
each project in turn through the dependency tree - i.e. if C depends
on B depends on A, and I change A, it won't try to build B unless A
compiles, and so on. Arguably that's advantageous, but I have found
that if - for example, I change an interface in A that is widely used
in B and C, it takes some time to fix all the errors from that
change...
Different IDEs have their different strengths with regards to Maven bindings and dependency management. The current state of play seems to be that it mostly just works on the latest Eclipse, Netbeans and IntelliJ - but you will have to teach your developers the emergency double whammy of "Refresh source files from disk and rebuild all related maven projects".
I find I'm having to do that less and less these days though. Having an SSD drive makes a massive difference here BTW.
snip factory classes paragraphs
Dependency management is incredibly important, regardless of what technology (Maven/Ivy/whatever) use use to help you implement it.
I'd start by getting the extensive reporting out of the Maven dependency plugin and take stock of what you've got. Generally speaking you set the dependency in the dependency management of the POM as high up the food chain as possible, but no higher. So if two of your submodules use an external dependency, then haul that into their parent POM and so on and so forth.
Upgrading external JARs should always be done as a proper mini-project. Evaluate why you're upgrading, alter source code to take advantage of any new features/bug fixes etc. Just bumping the version without this analysis and work will get you into trouble.
So, in general, my questions are:
Does anyone have any experience of breaking up large projects? Are there any >tips/tricks that you would be willing to share?
- Interfaces and Dependency injection are your friend.
- Michael Feather's book on dealing effectively with legacy code is a must read.
- Integration tests are your friend
- Splitting the sub projects into foo-api (interfaces only!) and foo-core and having modules only depend on the foo-api helps a great deal and enforces separation
- Jboss Modules and/or OSGi can help enforce clean separation
What impact did this have on your development and build times?
Very minor impact on dev and build times - a massive gain in time for our overall continuous delivery pipeline.
What advice could you offer on structuring such a break-up of such a project?
Do the little things right and the big things tend to fall out cleanly afterwards. So split things off bit by bit - don't do a massive restructure of the whole lot unless you've got a high percentage of coverage with your integration tests.
Write integration tests before the split - you should more or less get the same result(s) after the split.
Draw diagrams of the modularity you have now and where you want to get to. Design intermediate steps.
Don't give up - some Yak shaving now builds the foundation for being able to "rapidly build and refactor without fear" Shameless plug -> from Ben and I's The Well-Grounded Java Developer.
Best of luck!
You will have "trunk", now called "master", you will have "branches" now called "heads" and you will have "tags", still called "tags", but they won't be folders, they will be "refs", labels to revisions that live in separate namespace inside the repository.
Subversion and Git have different ways to do branching. The basic subversion model is to have a directory tree with single global timeline and if you want to branch, you copy a subtree in another directory.
On the other hand Git has a directory tree with revisions that each defines it's parents, but each revision can have multiple parents (a merge) and multiple children (branches). So instead of having directories for branches, you get independently created revisions. The "refs" are just names associated with latest revision for given "branch".
This difference is fundamental to distributed version control. Git (and other distributed systems) does not have any central authority to keep the history linear, so revisions can be created independently on multiple repositories without knowing about each other and the system has to accommodate them. It turns out the generalization makes branching and merging a lot easier in general.
Note, that in Git, revisions are not on any branch. They just are and branches contain them. But once branch is merged, or proves to be dead alley, you can just delete the "ref" pointing to it and forget about it altogether (if you discard old trials, they will be garbage-collected eventually with git gc
). This helps you avoid getting swamped in old experiments nobody remembers what they were about anymore.
Best Answer
You have 2 options:
configuration
,project1
andproject2
are on the same directory level and each one could be a git repository. When buildproject1
orproject2
you run the maven command fromproject1
orproject2
level and maven will try to fetch the parent (configuration) from maven repository not from parent directory. You should pay attention to versions. I would recommend inproject1
orproject2
to keep a reference to a parent (configuration) with a release version.To make a release you have to do it in 2 steps: release configuration first and release project second. Project1 and project2 can evolve independently and doesn't have to have the same configuration version as a parent.
Just for special cases when you want to have both configuration and projects as SNAPSHOT versions, in project1 or project2 you can use the
<relativePath>
tag inside<parent>
tag to point to your local path of configuration. I don't recommend this because will create problems on development environment (at least for me in Eclipse)I apologize for my English. [1]: http://git-scm.com/book/en/Git-Tools-Submodules