How a great package structure can make a great application
Tags: java, architecture, informationhiding, packagebycomponent
Published: 2018-10-10 07:38:46

---
title: How a great package structure can make a great application
published: true
description: The way we arrange classes into packages has a great impact on the overall design of the application. This post describes how to arrange your code for best maintainability.
tags: java,architecture,information hiding,package by component
---

In this post I will give you some _simple_ advice that, when followed carefully, will immediately lead to an easy to maintain and scalable architecture of your Java application. While this post is dedicated to Java the concepts will equally apply to other languages that allow to arrange code in packages.

One could write books of how to achieve good architecture (and people did) but you need a better architecture right now and are short of time - and so am I - so let's jump into it. Everything I'm going to tell you now boils down to this single most important advice:

> Use _package private_ scope liberally

If you do, this solves so many problems at once that, once you got used to it, you will hopefully be as amazed as I was when I realized how valuable this advice is. Let me explain this in detail.

In bigger applications the key to maintainability is to keep _coupling_ of the 
application's single components under control. This assumes that your application must actually be structured into components in the first place. If it is not, you probably alreay experienced some kind of _inter-package-dependency-hell_ with package cycles and the alike (the good ol' _big ball of mud_).

> Dependency is the key problem in software development at all scales (_Kent Beck_)

Java provides the concept of _packages_ to structure your code into components. But experience taught me that most times, a single component is spread across multiple packages. This happens when programmers choose their packages under _technical_ aspects. For example if you have a package `org.domain.app.controllers` where all your controllers live and another package `org.domain.app.services` where all your services live you have a technical package structure. In this scenario, possibly unrelated classes are located near to each other in the same package while related classes are located far away. 

> _Locality of related code is a key aspect of having code that is easy to reason about_

Because your related classes, which together solve a certain domain specific problem are located in different packages, they all have to be _public_ in order to work together. By choosing to not place related classes into the same package you open yourself up to all the evil of having certain classes used in places where you don't want them to be used.

If upfront you chose a _domain_ or _feature_ related package structure there were an easy soultion to avoid this problem in the first place:

> Give as many as possible classes the _package private_ scope

Actually you should, by default, make every class _package private_ and only broaden its scope if necessary. After some time you will develop a bad feeling whenever you see something beeing _public_ - and this is a good thing. It makes you think explicitly about the public interface of your package. Following this advice you will automatically create packages with following characteristics:
* high cohesion: everything in the package is kind of related to the other things. The locality of related code will make it easy to reason about.
* low coupling to other packages: because there is only a minimal public interface of your package

While these are good things you will also experience that your packages grow bigger and bigger up to a size that make you feel uncomfortable. 

![No packages - No cycles](https://thepracticaldev.s3.amazonaws.com/i/k4r03z4fbqiwgxbd6izm.jpg)

If you feel your package is growing too big that is a clear sign that there might be a better domain specific cut. In this situation you should review and question the whole purpose of the current package. In my experience you run into the following cases:
1. Your original feature got undermined by unrelated code which actually serves a different feature.
2. As time passed, the requirements for the original feature changed that much that the original structure does not fit sufficiently anymore. It might also well be possible that the feature did not change, but your understanding of it did while you were coding it.

Most times the first case is simple to solve. If you are really in a situation where mostly unrelated code slipped into your feature package it should be pretty easy to isolate it and move it into its own package. 

If isolating smaller parts is not that easy you might be subject to the second case. This is where the sorcery of _package private_ reached its limits and you will have to do actual work. You are now up to some refactoring on package level - that is you need to split your current package into multiple new ones which better suit the requirements of the domain problems you are trying to solve. This is most likely not solvable by only moving some classes between packages but might require actual code changes. 

But because everything related is so near together and you know that most things are not used outside the package this gives you great confidence while refactoring.

![unit tests](https://thepracticaldev.s3.amazonaws.com/i/67q07eyq8e3sd0n8p31v.jpg)

Have you ever wondered what the _unit_ in unit testing is? You might have come across test suites where a test class exists for every production class. If so you most likely experienced that your unit tests are not very robust. They break easily if you adjust the implementation class even if you actually preserved behavior correctly. That is because _unit_ does not mean _class_. _Unit_ pertains to all the code you want to test in isolation in order to solve a domain specific problem. _Unit_ means _feature_ and feature, in our case, means the public interface of your package.

> _Don't write a test class for every production class. Write a test class for every feature_

Doing so loosely couples your test code to the production code in the same way your production code is loosely coupled to other packages. You can freely change all the implementation details (like, even delete classes) behind the public interface without breaking your tests. That is the very meaning of _information hiding_.

To summarize, by using package private scope liberally you get (for free!)
* high cohesion within your packages
* low coupling between packages
* a durable architecture because of well defined interfaces between components/packages
* code that is easier to reason about
* a good hint of what you should test in order to achieve more robust unit tests

And again: you get this for simply leaving out the `public` modifier in you class declarations! Whenever you feel the need to create a new class, make it package private and place it into the package where, from a domain or feature point of view, you think it fits best. This puts you in a position where you can evolve your package layout carefully over time.

**Addendum**
The attentive reader might have noticed the following: the above tips on structuring your packages is actually the same advice we followed along for decades on class level. It is undisputed that it is best practice to keep helper methods _private_ in order to have a well defined public interface. If _"dependency is a problem at all scales"_ it is likely and expectable that the solutions for managing dependency look similar at all scales too.


More information:
* Simon Brown on 'package by component': http://www.codingthearchitecture.com/2015/03/08/package_by_component_and_architecturally_aligned_testing.html
* https://github.com/olivergierke/moduliths (A spring Boot extension which tries to enforce this way of structring your application)
* Somthing about to DDD