Familiarisation with Modularity concept in Java & .Net

Familiarisation with Modularity concept in Java & .Net
Familiarisation with Modularity concept in Java & .Net

Following the numerous redundant and rebutting arguments being actively made on modularity for Java, over the last decade. Finally, it is now being considered by the future JVM-based languages also, such as Scala.

Modularity is one of the intrinsic milestones in the evolution of Java. Throughout the JSR 277, now depreciated, to the recognition of JSR 291, and the currently developing JSR 294, modularity allows us to distinguish between the versions effectively.

What do you mean by modularity?

Modularity is one of the extensive concepts of software development that implies that the software product can be disintegrated into individual modules that are developed in an isolated fashion. Later, these modules are integrated by adding standardised interfaces to allow modules to communicate among themselves for triggering one-another.

The concept of Modules in Java and .Net is analogous to the concept of separation of concerns between objects in object-oriented programming languages, while Modules work on a wider scale. Specifically, the segmentation of a system into modules facilitates the minimisation of coupling, which results in easier to maintain code.

During the design phase, Modules were not included in Java, except for packages that are likened to Modula-3 modules in the introduction. But now multiple de facto modules are present in the Java community. Any given Java library in action can be considered as a module, including Log4J, Hibernate, or Tomcat.

Conventionally, both open-source applications, as well as closed-source applications, are linked to one or multiple dependencies that come with certain external libraries. These external libraries are transitively dependant on several other libraries. Modularity is one of the centres of modern software engineering-to be more specific, any kind of engineering.

What do you mean by a module?

The Dictionary definition of a module says that it is “one of a set of separate parts that, when combined, form a complete whole”. Typically, Modularity is an extended concept. When it comes to the software terminology, module indicates creating and implementing a programme or a computing system as several unique modules, instead of a unified, monolithic design.

To establish communication between modules a standardised interface is used. Division of the software ecosystem into saturated segments constructs distinct modules, which helps in reducing coupling to a greater extend, optimises software development and reduces the overall system and space complexity.

This facilitates independent testing of modules during all the phases of the software development lifecycle and accelerates the software testing and debugging process. As, if the modules have low coupling, they can be tested parallelly, and parallel development efforts can be taken, while a sprint or project.

Main characteristics of a module:

  • A module provides an optimum level of abstraction of the implementation details from the consumer of the services. This allows us in preserving the patent of the source code.
  • A module offers single or numerous related services clubbed as a set through a standard interface. An interface adds to the reusability of the module and makes it easily replaceable.

Prime benefits of modularity:

  • Reusability: If you create a module once, you can use it at multiple places. This eliminates the need of writing boilerplate/redundant codes.
  • Parallel Testing and Execution: If the project is modularised, multiple teams can work in parallel. Testing of modules becomes, more specific, isolated, handy, and time-saving. Different modules can be at the different stages of the Software Development Life Cycle and later, these can be integrated to build the final product.
  • Improves Stability: Any amendment or adaptation in a module is confined to a smaller area, and it remains abstracted from the users. This facilitates product testing in a reduced time span.

Logical and Physical modules:

When it comes to any software application, the modular design is created logically by clubbing functions and services together as modules, such that an optimum balance of cohesion and coupling is maintained between modules.

This is usually the result of the application of Software Architecture principles on the problem statement. For instance, if you intend to create a Ticket Booking application, the following three modules on a specific area of the solution can be used.

Image Source: HackerNoon

Furthermore, the software of this application can be designed with the help of modules. Working software (application binaries) can be modularised in one of the two possible ways mentioned below:

Option One:
There is a unified executable file that contains all the modules. Although the modules may be segregated internally in the distinct source tree of the application, they exist as one unified executable file physically.

Image Source: HackerNoon

Option Two:
Each module is considered to be a library and all the specific applications use these libraries. Libraries are kept isolated from the main application and are built and released separately.

Image Source: HackerNoon

Most of us are familiarised with the modular approach mentioned in the first option. Option one successfully provides the entire range of above-mentioned key benefits of modularity.

Pre-required platform capabilities

Based on the programming language, being used that is Java or .Net, the pre-requisites for modularity support changes. For creating a software application with option two kinds of modularity, a platform needs to have at least the following capabilities:

  • Including Versioning: If all the modules are versioned separately and sequentially, each module can evolve independently without intervening in the other modules that depend on it.
  •  Up to Java 8: Doesn’t support versioning.
  •  Java 9 and above: Doesn’t support versioning.
  • .Net: Supported by adding CLR. The manifest contains the version of each Assembly, along with the version of each dependency. During execution, the version of the corresponding dependency is tallied with the version at the project build. By making a strong-named assembly, version enforcement can be done, although this is optional.
  • Dependency Discovery: After any module has stated its dependencies, the platform is supposed to explore those dependencies (modules or libraries) during the execution time, load them and allocate them.
  • Up to Java 8: By configuration.
    Classpath configuration is set-up in numerous ways. Class files are tracked using the classpath configurations set-up earlier.
  • Java 9 and above: By configuration.
    Module path configuration is set-up in numerous ways. Modules are tracked using the module path configurations set-up earlier.
  • .Net: By convention. It is highly optimised by CLR, as it looks up for dependencies in pre-defined places by using the probing strategy. The target folder usually includes the same folder as the application or its sub-folders.
  • Encapsulation: It is present in each module at subsequent levels. This ensures that the user is only familiar with the standard public interface and the internal details are abstracted. Programmers are not allowed to build dependency on “details”, such that details can be changed without any interruption. For example,in a logging library, com.mylogger.api.The logger is a public interface and com.mylogger.service.impl.FileLogger is the class implementing logging to file. Users of the logging library should be allowed to access FileLogger so that FileLogger can be altered without interrupting any dependant application.
  • Up to Java 8 – It is possible only if the whole module uses a unified package. Public access should be allowed if you want to access type outside the package. But, this technique is not feasible as making the type -“public” can lead to a lot of vulnerabilities in the system.
  • Java 9 and above -Supported by JPMS. With the help of modules, only selected packages can be exported. The entire range of packages become internal to a module, you cannot even access the public types externally.
    For example:
module com.AndroidCodingNinjas{
exports com.AndroidCodingNinjas.api.service;
}
  • .Net – It is partially supported in .Net. The “internal” access modifier in C# is used for access within the assembly. “internal” is supported by the C# compiler but not enforced by Reflection APIs, such that the leaves types with “internal” access modifier are used outside the Assembly using Reflections without any restrictions.
  • Dependency Management: Due to the existence of transitive dependencies between the modules, there should be an option, such that, each module can declare its dependencies.
  • Up to Java 8: JVM has no knowledge about dependencies. It traditionally tries to locate the class file with the help of the classpath and it fails, if not found. Tools like Maven and Gradle used to manage builds are used for handling dependencies. Once the build has been created successfully, the metadata of dependencies is dropped and JVM has no knowledge of dependencies explicitly.
  • Java 9 and above: Supported by JPMS. Each Module declares the other modules it is dependent on. The JVM creates a graph and adds an edge between each related module; the build fails if any if the module is not found in the graph.
    For example:
module com.AndroidCodingNinjas{
  requires com.JavaCodingNinjas;
}
  • .Net: It is supported by .Net Runtime (CLR). The manifest of the .net assembly contains data about the dependencies. This information is required by the CLR for checking the integrity of dependencies and discovering them.

If you have read between the lines, you might have inferred that many features of modules are not supported by Java 8 and below versions. Therefore, for a better experience update your Java library to 9s, prior to including modules.

Furthermore, advent is going at a high pace where modularity is concerned. The JSR 294 mailing list is to be launched soon; it allows developers to create a module system which can be defined efficiently in the Java Language Specification itself.

Want to understand the difference between Java and JavaScript, take a look.

By Vanshika Singolia