Rethinking modularity: Introducing TrueVFS Profiles

In modern software design, modularity is a primary concern in order to provide a sustainable, extensible architecture which is composed of reusable software components.

Hence, TrueZIP 7 already employs the (in)famous three-tier architecture pattern with several modules within each tier. However, not all modules are well-cut and so some modules are rather coarse-grained while others are too thin to be useful. For example, if you add the TrueZIP Driver ZIP to your class path, then without customization your application would detect the canonical file extensions for the ZIP, JAR, ODF and SFX file formats even though you might only need to support the ZIP file format.

So when designing TrueVFS I considered this lesson and reshaped the module system (while retaining the three-tier architecture). The result is much more fine-grained: While TrueZIP is composed of 14 modules, TrueVFS is composed of 32 modules (not counting non-code modules and four spin-off code modules of the TrueCommons project)! This massive increase partly results from assigning one module for each archive file system type. For example, if you add the TrueVFS Driver ZIP to your class path, then your application would detect the canonical file extension for the ZIP file format only.

However, modularity comes at a price: While fine-grained modules certainly foster reusability, actually reusing them gets harder because you need to satisfy all their dependencies. Maven’s integrated dependency management certainly helps here, but declaring dozens of dependencies in a POM ain’t fun no more! Because I want to apply the KISS principle by applying the Convention-over-Configuration design paradigm, I needed to solve this puzzle. The solution is surprisingly simple…

Introducing TrueVFS Profiles

A TrueVFS Profile is simply an aggregator POM (i.e. of type pom) which bundles some dependencies on other TrueVFS modules in order to serve a typical use case. An application could then declare a single all-in-one dependency on this profile rather than declaring the complete set of dependencies. This best practice is explained in Maven: The Complete Reference). Here’s an example:

<dependency>
    <groupId>net.java.truevfs</groupId>
    <artifactId>truevfs-profile-default</artifactId>
    <version>0.9.1</version>
    <type>pom</type>
</dependency>

Note the type pom in this declaration! Currently, TrueVFS defines three profiles for typical use cases:

  1. TrueVFS Profile Base: Provides a fully functional stack of modules with the …
  2. TrueVFS Profile Default: Extends the TrueVFS Profile Base with the…
  3. TrueVFS Profile Full: Extends the TrueVFS Profile Default with the …

Customizing a Profile

Customizing a profile is easy: Say you want to use the TrueVFS Profile Base with the TrueVFS Driver ZIP.RAES. Simply edit your POM to contain this:

<dependency>
    <groupId>net.java.truevfs</groupId>
    <artifactId>truevfs-profile-base</artifactId>
    <version>0.9.1</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>net.java.truevfs</groupId>
    <artifactId>truevfs-driver-zip-raes</artifactId>
    <version>0.9.1</version>
    <scope>runtime</scope>
</dependency>

Likewise, you can exclude a dependency of a profile. Say you want to use the TrueVFS Profile Default without the TrueVFS Driver ZIP.RAES. Then edit your POM to contain this:

<dependency>
    <groupId>net.java.truevfs</groupId>
    <artifactId>truevfs-profile-default</artifactId>
    <version>0.9.1</version>
    <type>pom</type>
    <exclusions>
        <exlusion>
            <groupId>net.java.truevfs</groupId>
            <artifactId>truevfs-driver-zip-raes</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Conclusion

Fine-grained TrueVFS modules enable users to select the file system drivers their application should support simply by composing the class path. TrueVFS profiles then help to keep the class path configuration in the POM at bay.

Enjoy!