Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Java Platform Module System (JPMS): Introduzione

Introduzione al concetto di modularità in Java (Java Platform Module System), una delle innovazioni più importanti per questo linguaggio.
Introduzione al concetto di modularità in Java (Java Platform Module System), una delle innovazioni più importanti per questo linguaggio.
Link copiato negli appunti

Il JPMS (progetto Jigsaw) è l'innovazione più importante di Java 9.
Sua base è il concetto di modulo con cui dar vita ad applicazioni modulari,
che offre benefici in termini di produttività e manutenibilità.

Ma cos'è un modulo? in Java le classi vengono
organizzate in package seguendo il principio Object Oriented di alta coesione. Essa porta a definire classi
con metodi legati al raggiungimento di specifiche funzionalità, per cui la classe è progettata, e ad organizzare
in un insieme classi che concorrono in modo diverso o complementare ad offrire il medesimo servizio.

In un package possiamo trovare le classi per manipolare stringhe e caratteri, in un altro classi per
gestire numeri e calcoli. La modularità utilizza il concetto base di package
aggiungendo un più alto livello di aggregazione basato sul loro uso.

Un modulo è quindi un'aggregazione di package relazionati nella quale
è possibile inserire risorse di altra natura (immagini, XML..). Ogni modulo
è dotato di un descrittore che specifica:

  • nome del modulo;
  • moduli dai quali dipende (dipendenze);
  • package resi esplicitamente disponibili o non disponibili ad altri moduli;
  • servizi che offre e usa;
  • a quali altri moduli rende possibile la reflection.

Il descrittore risiede nel file module-info che contiene la dichiarazione
del modulo. Ogni dichiarazione inizia con la keyword module seguita dal nome
del modulo e da parentesi graffe. Ciò che è inserito tra le parentesi
rappresenta il corpo del modulo:

module modulename {
      //body
     }

Nel corpo del modulo possiamo inserire direttive per agire sugli aspetti prima elencati.
Con requires, seguita dal nome di un modulo,
specifichiamo le sue dipendenze. Essa consente di utilizzare
la keyword static per indicare che la dipendenza è richiesta in compilazione e non a runtime. Un aspetto molto
interessante legato a tale direttiva è la implied readability. Possiamo specificarla facendo seguire a
requires la keyword transitive seguita dal nome di un modulo. Con essa intendiamo dire che un modulo A che richieda l'uso
del modulo B diventa dipendente anche dal modulo transitive C dichiarato in B.

Consideriamo il modulo
java.desktop che dichiara requires transitive java.xml: ogni modulo A che legge java.desktop
deve leggere anche java.xml. Supponiamo che in A si usi un metodo di una classe all'interno del modulo java.desktop che ritorni un tipo
creato con una classe del modulo java.xml, il codice di A diventa automaticamente dipendente di java.xml.

Senza requires transitive nella dichiarazione di java.desktop la compilazione di A
non sarebbe possibile a meno di una dichiarazione esplicita della dipendenza java.xml in A.

In un modulo in genere non si vuole rendere pubblici tutti i package, ci possono essere infatti package
destinati solo ad uso interno. La keyword esports permette di specificare quali package
sono visibili ad altri moduli. Quando un package di A è visibile ad un altro modulo B il codice di B
può accedere a quanto dichiarato public nel package di A.

Un modulo può utilizzare specifici servizi divenendo un service consumer, cioè un oggetto di classe che implementa
l'interfaccia, o estende la classe astratta, specificata con la direttiva uses:

module it.html.module {
        exports it.html.spi
        uses it.html.spi.IProblemProvider;
       }

In questo caso il modulo esporta il package it.html.spi contenente l'interfaccia IProblemProvider e la sua classe
Problem. Ciò abilita moduli che implementano IProblemProvider ad accedere all'implementazione fornita
dal modulo.

uses indica che in it.html.module vengono usati oggetti di classi che implementano l'interfaccia
IProblemProvider, tale aspetto fa del modulo un service consumer.

L'uso di un servizio da parte di un modulo avviene tramite reflection.
Utilizzando la direttiva provides...with un modulo può diventare fornitore di servizi. Con essa specifichiamo
un'interfaccia, o una classe astratta, nella sezione provides indicando la sua implementazione nella parte with:

module it.mycustom.module {
        requires it.html.convertitore;
        provides it.html.convertitore.spi.IConvertitore
            with com.mymodule.ConvertitoreImpl
       }

it.mycustom.module dichiara la dipendenza da it.html.convertitore implementando
la sua interfaccia (IConvertitore) presente nel package it.html.convertitore.spi. L'implementazione è la classe
ConvertitoreImpl del package com.mymodule (modulo it.mycustom.module).

Le direttive opens, opens .. to ed open sono utili invece
per l'accessibilità dei package verso altri moduli. Utilizzando opens, seguita dal nome di un package del modulo,
stiamo dicendo che le classi public (ed i loro campi e metodi public e protected) all'interno del package
sono accessibili in altri moduli soltanto a runtime, consentendo l'accesso con reflection a tutti i tipi all'interno delle classi
del package.

opens..to consente di specificare i moduli verso i quali quanto detto precedentemente è possibile.
In un modulo potremmo dichiarare qualcosa come opens mypackage to module1,module2 per indicare che il package
è accessibile con le modalità indicate da open ai soli module1 e module2. Se invece tutti i package di un modulo devono
essere accessibili a runtime e via reflection agli altri moduli, è possibile aprire totalmente un modulo con open
a livello di dichiarazione di modulo:

open module it.mycustom.module {
          ..
       }

Ti consigliamo anche