Modules   «Prev  Next»

Java Modules Conclusion

What is modularity in Java? To some, it is a principle for development: programming to interfaces and hiding the details of implementations. This is the school of encapsulation. To others, it's about leaning hard on class loaders to provide dynamic execution environments. This is the school of isolation. To still others, it's about artifacts, repositories, and tooling. This is the school of configuration. Individually, these perspectives are valid, but they feel like pieces of a larger story that is not quite clear. If a developer knows that some portion of their code is for internal use only, why can't they hide a package as easily as hiding a class or a field?
Question: If code can be compiled and run only in the presence of its dependencies, why don't those dependencies flow smoothly from compilation to packaging to installation to execution? If tools work only when presented with pristine self-describing artifacts, how can anyone reuse older libraries that are just plain JAR files?

Modules are a first-class feature of the Java platform

Java 9 offers a coherent story for modularity by introducing modules as a first-class feature of the Java platform. As previously mentioned, a module is a set of packages designed for reuse. This simple concept has a powerful impact on how code is
  1. developed,
  2. deployed, and
  3. run.
The longstanding mechanisms for promoting and controlling reuse in Java
  1. interfaces,
  2. access control,
  3. JAR files,
  4. class loaders,
  5. dynamic linking
all work better when packages are placed into modules.


Clarify Structure

First, modules clarify the structure of a program in a way that other mechanisms cannot. Many developers will be surprised that their code is not as well structured as they thought. For example, a codebase spread across multiple JAR files has a good chance of cycles between classes in different JAR files, but cycles between classes in different modules are forbidden. One of the motivations for investing in the modularization of a codebase is the knowledge that, once complete, there will not be any backsliding into the ball of mud that cyclic dependencies allow. Developing with modules also leads to programming with services, which reduce coupling and increase abstraction even further.

Second, modules create a sense of responsibility for code in a way that other mechanisms cannot. A developer who exports packages from a module is making a commitment to a stable API, and even the name of the module itself is part of the API. A developer who bundles too much functionality into a single module will cause that module to drag in a large number of dependencies that are irrelevant for any single task. Anyone who reuses the module will realize its nature even if its internals are hidden. Developing with modules encourages every developer to think about the stability and cohesiveness of their code.
It turned out that modularizing the JDK was challenging because some well-known libraries derived their power from trying to ignore the very encapsulation that the module system applied to the modules of the JDK. This tension in the design of Java 9 had no easy academic answers. In the end, a strong cycle of feedback from the community led to the module system offering developers a variety of levers and dials, so that modularized platform code can enjoy truly strong encapsulation while modularized application code can enjoy strong enough encapsulation.

A module system works best when it works for everyone. The more developers who create modules today, the more developers who will create modules tomorrow. But what about developers who have not created their modules yet? It is no exaggeration to say that Java 9 is just as concerned about the code that is not in modules as about the code that is. The only developer who should modularize a codebase is its author, so until that happens, the module system has to provide a way for code in modules to reach out to code not in modules.