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?
CodePudding user response:
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:
- You do have to then configure maven to tell it about the alternative choices you made. Maven does not make this easy.
- Other java programmers generally assume the defaults. If you have a good reason to deviate, go for it, but 'I do not like it' is not a good reason, as it'll be pointlessly increasing the learning curve.
- The maven developers chose this structure as default for a reason. If you think it's a dumb reason, that's certainly possible and you may even be right, but then you're using a build tool written by folks who, (judging the book by its cover a little bit), according to you, make boneheaded choices about sane defaults. That's not a great place to be.
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.
CodePudding user response:
Maven is a build and dependency management tool that helps develop your application and manage all the lifecycle of your developement process such as build
, compilation
, packaging
, testing
etc... throught command lines.
There is 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 de structure and the informations 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 on 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
.