Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the point of a deep folder structure in Java (Maven)?

Tags:

java

maven

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?

like image 553
Robert Simpson Avatar asked Oct 19 '21 21:10

Robert Simpson


2 Answers

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.

like image 74
rzwitserloot Avatar answered Oct 19 '22 23:10

rzwitserloot


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.

like image 42
Harry Coder Avatar answered Oct 20 '22 01:10

Harry Coder