I recently joined a new Project, and as always one of my first tasks was to become familiar with the existing codebase.
In this JEE-Project, one of the most important things for me was to learn how the classes were distributed into different packages. Having this knowledge would mean that, even if I didn't know how something worked, I could easily know where to look and then learn how the code works.
In this blog post, I want to show two of the most commonly known architectural design patterns on how one could organize the code.
Or the horizontal approach.
Imagine a cake with multiple layers.
Each layer represents a package.
Each package contains exactly what this layer is responsible to do.
So imagine you organize your code into 4 Layers, let's say:
(this of course is not the most optimal way of organizing your layers and is only used for easy representation purposes)
We would have 4 layers, or 4 packages.
The UI is responsible for handling everything UI related. So this is where every UI class related to any feature would be created.
The same applies to the other three layers. Businesslogic is responsible for everything related to business-rules, DAO handles the Database-Access, Model contains for example the Object Relational Model for the underlying database.
If we would want to build an application that can create some tasks, and then list them, we could divide them accordingly into the 4 packages.
Adding new classes in such an environment is really easy.
For example, if someone would want to create a new Model-Class, he could simply do it by adding it to the Model package without thinking twice.
This also means that new team members will have an easy time learning on how to organize the code.
A big disadvantage for this approach is, that it is really hard to assess the complexity of a feature, because you don't know where a feature is or might be used, and what dependencies it might have to other features.
Also, think about encapsulation. Everything must be public.
The Businessrule probably has to access the DAO in some way.
But why can the UI also access the DAO? Because either only other DAO's can access my DAO, or everyone can.
Of course, this Argument only applies if you are still using Java8 like myself.
Else you could use Jigsaw (Java9 Module-System) to create modules.
Or the vertical approach.
Imagine a cake, with multiple slices.
Each slice represents a package.
Each package contains exactly what this feature is responsible to do.
So imagine our App-Example from before, if you would organize your code into a feature-like package structure, it could look like this.
In contrast to the Layer Architecture, you can actually use encapsulation in such a structure, as every Feature is encapsulated in his own package. Only the API's that really have to be public, can be public.
In modern architectures, it's very common to create micro services. With this structure already in place, it's really easy to extract existing features, into a micro service architecture.
Extandibility (if this is a word, it suits here):
If a feature needs to be extended by some functionality, you immediately know where you have to go, and in what context you will work.
You can also be more certain, that with changes to some features, you will probably not break the whole application by doing so, only the feature that you are working on.
Big Applications with lots of features, will quickly grow in not only their amount of classes, but also their amount of packages. On the one hand, it might be hard to keep track of all the features, but on the other hand it might also be easier to identify certain features, if the packages have more meaningful names than just their layer.
You actually have to know what you are doing. If this is a disadvantage or not, you should decide for yourself. But also think about new people joining the team. Instead of immediately having the right place for each class, they actually have to know what they are currently working on, to precisely choose the correct package for their new class.
So what should you choose for your Project?
As always it depends.
In general, and based on the amount of advantages I've listed for one of the patterns, I prefer the Feature Architecture. It gives you more stability in the way you are working. If you change a class, you don't actually have to do a regression test on the whole application (at least in theory).
But the Layer Architecture also has it's strengths. I imagine that in smaller projects, this kind of architecture would actually be beneficial, because you can get a faster overview of all your classes.
I would like to conclude by saying that neither of these solutions is the correct answer to all your problems. Each team should find out what kind of architecture fits for their requirements, or for their project.
In a lot of cases I've seen a combination of the two.
You could organize your classes into Feature-Packages (Feature Architecture), and in these packages you divide your classes into the layers (Layer Architecture).
Only the team can decide, what is good for it.