Java 9, the most recent major Java release, added strong encapsulation to the module system. This seemingly small addition has major implications for improving software development efforts – the module system offers additional support for SOLID development.
When to Use Modules
There are a couple of reasons why it makes sense to choose modules during development. Many Java development houses select Spring or Spring Boot just to satisfy the “D” in SOLID development. If a Java project only requires Dependency Injection, Java 9 can do this without any additional frameworks. Spring, and occasionally Spring Boot, require configuration files to map Java class implementation to interfaces. Creating these configuration files can be tedious. Modules do not require the same configuration files, which saves development time and, therefore, money. Modules also support the “S” in SOLID development. Software developers can decompose a monolithic Java application into many single-purpose modules. Properly architected applications using SOLID principles and modules can yield applications that are easier to maintain than if the application were a monolith, which again saves money.
If you’d like to get started with an example implementation, download the code located on Github here. Edit the build script variables as necessary to match your file system and then run it. The output of the main class will display. Notice that the main class only imports interfaces Coffee and CoffeeService to achieve its goal. Further inspection shows that interfaces are encapsulated inside of their own modules, com.example.coffee and com.example.coffeeservice. Implementation files are in different modules, com.example.coffee.impl and com.example.coffeeservice.impl.
Modularization requires a module-info.java file for each module. Compare the module-info.java files inside of com.example.coffee and com.example.coffee.impl for guidance on the visibility keywords required for separating interfaces from implementation.
It is important to point out the ServiceLoader class in the main class. The ServiceLoader is the class responsible for resolving the implementation files. Given an interface, the ServiceLoader can return an Iterable containing the files that implement the interface. The desired implementation is selected from the Iterable.
It makes sense to select Java modules over Spring or Spring Boot if you just need a lightweight system for SOLID development. UDig has a crew of excellent Java developers that are skilled in everything from Spring Boot to Adobe Experience Manager and can be a great resource for your next Java project.