I've inherited a Java (Maven) project at work. I'm not a Java developer, but the project is now mine, nonetheless. When I clone (a la git clone
) the repository, I notice the folder structure goes really deep before any .java files appear. For instance, the folder structure looks like this:
project_name
.git
.idea
src/
main/
java/
org/
bah/
co/
lab/
zeus/
apimanager/
RestClient.java
I've googled around, trying to find out why the folder structure goes so deep. After some research into Maven, my understanding is the default structure begins with /src/main/java. So, I'm curious why the previous (now incommunicado) developer structured this repo (and many others) like this. So as not to solicit opinion, please tell me: is there a technical reason the project is structured like this? There are literally no other .java files outside of the apimanager
folder, so what technical reason would there be to bury everything so deep?
Maven is a tool that has certain opinions on where things should go; a default configuration. You don't have to follow it, but not following this default configuration has three significant downsides:
To explain each layer:
src
Indicates that these are source files: Compiled and generated stuff should not be in here, and the entire src
tree should be in version control. Contrast to e.g. bin
or build
containing build artefacts, doc
containing documentation, and who knows what other directories you need for other relevant parts of a repo.
main
A project can consist of multiple separately buildable artefacts and 'kinds' of product. For example, most projects include a bunch of code that exists solely for testing purposes (the unit tests). They live in src/test
. The core product lives in main
.
You can also have for example separate sources for an installer perhaps (src/installer
), or a build plugin, or an annotation processor that needs to be built first and then it needs to be on classpath when compiling the main
project, etcetera.
java
There's such a thing as split language projects, where some of it is written in language A and some of it in language B. For its worth, I think this layer is bad design; A file ending in .java
gives away how one is to 'compile it', and this goes for just about every source file that needs a compiler applied to it: The extension says just as much as a folder name of java
ever could. To show you a common contrast: Many projects have src/main/resources
as well as src/main/java
: Resources are 'compiled' simply by copying them over: Imagine your app has a text file containing a list of all US states with all zipcodes used in each state. Or png
files with icon images for a GUI app. Such files are just as much part of your main application as the class files would be and should end up in the same place (inside the jar
file), but to 'compile' them, you just.. copy em, you don't run javac
to do this. That's what this level is about: What tool should be used to turn source files into distributable aspects?
co/lab/zeus/apimanager
This matches the java package structure. This is effectively a requirement applied by javac
itself. The reason to use such a deeply nested package structure is simply because packages serve as namespaces: If there is a conflicting fully qualified name, all hell breaks loose: Java simply cannot handle this. Hence, java programmers ensure that such conflicts never happen by using a 'reverse domain name' structure: You'd stick your project in that package if you own the zeus.lab.co
domain, thus ensuring nobody except other folks in your team who share control of that server could possibly be in conflict (and for those: They're in your team, talk to them to avoid conflict). For example, there are 3 different open source java projects all called spark. Had they all gone with package spark;
(and thus, src/main/java/spark/Main.java
as an example file), then for every java project you'd pick one of the 3: The other 2 you can never use in this project. Harsh, and pointless, which is why (almost) all java libraries use a reversed domain name as root package name, and then maven follows this package name in its directory structure because javac
makes life extremely difficult if you don't do that.
That gets us to project_name/src/main/java
.
org/bah
You made that up for hyperbole. Nobody hosts a proj on zeus.lab.co.bah.org
. But if they do: Talk to the management that decided to assign that whopper of a domain name to a team. It's on them, not on the author of this project.
Maven is a build and dependency management tool that helps develop your application and manage all the lifecycle of your development process such as build, compilation, packaging, testing, etc. through command lines. There is a convention on how a Maven project is structured:
└───maven-project
├───pom.xml
├───README.txt
├───NOTICE.txt
├───LICENSE.txt
└───src
├───main
│ ├───java
│ ├───resources
│ ├───filters
│ └───webapp
├───test
│ ├───java
│ ├───resources
│ └───filters
├───it
├───site
└───assembly
What is important to understand for the moment is the role a each files and folder and how to use Maven commands.
pom.xml
: this file contains the structure and the information of your project, and your dependencies (external jars). This file is used by the commands you execute in Maven
src/main/java
: contains your packages and your source code.
src/test/java
: contains your test code
In your case, the structure of your project is due to the package name. Here, the name is org.bah.co.lab.zeus.apimanager
and in Java a package is physically a nested group of folders. There is a package naming convention, but in most of the cases, it is up to you to choose the name you want to use.
As you are using IntelliJ IDEA, you can display your package with the options Compact Middle Packages.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With