danilo.pianini@unibo.itgianluca.aguzzi@unibo.itangelo.filaseta@unibo.itCompiled on: 2025-12-05 — versione stampabile
nos esse quasi nanos gigantium humeris insidentes Bernardo di Chartres
Tutto il software moderno dipende da altro software!
java.* e javax.*)Tutto il software che costruiamo e usiamo dipende da altro sofware
$\Rightarrow$ Le applicazioni hanno un albero di dipendenze!
Proviamo a costruire una semplice applicazione che:
Una possibile soluzione: https://github.com/APICe-at-DISI/sample-gradle-project/blob/master/src/main/java/it/unibo/sampleapp/SimplerRateAMovie.java
È stata sfruttata una libreria per OMDB
Ma a sua volta, questa libreria usa librerie che usano librerie…
+--- com.omertron:API-OMDB:1.5
| +--- commons-codec:commons-codec:1.10
| +--- org.apache.commons:commons-lang3:3.4
| +--- com.fasterxml.jackson.core:jackson-core:2.8.7
| +--- com.fasterxml.jackson.core:jackson-annotations:2.8.7
| +--- com.fasterxml.jackson.core:jackson-databind:2.8.7
| | +--- com.fasterxml.jackson.core:jackson-annotations:2.8.0
| | \--- com.fasterxml.jackson.core:jackson-core:2.8.7
| +--- org.slf4j:slf4j-api:1.7.24
| \--- org.yamj:api-common:2.1
| +--- org.apache.httpcomponents:httpclient:4.5.3
| | +--- org.apache.httpcomponents:httpcore:4.4.6
| | +--- commons-logging:commons-logging:1.2
| | \--- commons-codec:commons-codec:1.9
| \--- org.slf4j:slf4j-api:1.7.24
Le dipendenze indirette (dipendenze di dipendenze) sono dette transitive
In progetti non giocattolo, le dipendenze transitive sono la maggioranza
Gestire il classpath diventa molto difficile! Ogni libreria va:
L’applicazione di prima viene lanciata con:
java -cp "build/classes/java/main:lib/API-OMDB-1.5.jar:lib/jool-0.9.14.jar:lib/logback-classic-1.4.1.jar:lib/api-common-2.1.jar:lib/slf4j-api-2.0.2.jar:lib/httpclient-4.5.3.jar:lib/commons-codec-1.10.jar:lib/commons-lang3-3.4.jar:lib/jackson-databind-2.8.7.jar:lib/jackson-core-2.8.7.jar:lib/jackson-annotations-2.8.7.jar:lib/logback-core-1.4.1.jar:lib/httpcore-4.4.6.jar:lib/commons-logging-1.2.jar" it.unibo.sampleapp.SimplerRateAMovie
Ci servirebbe uno strumento capace di:
Per farlo, però, abbiamo bisogno di conoscere qualche archivio ("repository") di librerie, e di sapere come reperirle, ossia conoscere il loro nome e versione…
Al compilatore Java e alla JVM (a differenza di quello che accade con altri linguaggi) è ignoto il concetto di “libreria”. L’unica astrazione che abbiamo in mano è quella di classpath, ma è troppo grezza!
Quando Java ha preso piede, è stato necessario sopperire a questa mancanza. Un particolare build system, Apache Maven, ha elaborato una propria convenzione per i nomi, divenuta oggi sostanzialmente standard (qualunque build system per Java la adotta).
Una libreria Java in formato compatibile con Maven si compone di:
it.unibo, com.google, io.githubcommons-math, guava, junit-jupiter-assertions-jvm., -, o + (solitamente numeri e punti)
1.0, 1.0.1, 2.3.5-beta4, 28ae10dd, 4.0.2-alpha+28ae10ddPer riferirsi ad una libreria specifica, si usa la sintassi: groupId:artifactId:version
com.google.guava:guava:32-jreit.unibo.alchemist:alchemist-api:25.0.1Ora sappiamo come si chiamano, ma non dove trovarle…
Assieme alla convenzione per i nomi, Maven definì un repository (archivio) dove i creatori di software Java open source potessero:
La disponibilità e la possibilità di riuso ha consentito la nascita dell’“ecosistema” Java, rendendolo uno dei linguaggi/piattaforme di più ampio successo di sempre.
Sappiamo dove trovare le librerie e come riferirle, ma ci serve ancora uno strumento per:
Gradle consente di gestire le dipendenze, specificando:
In Gradle è possibile “puntare” ad archivi di librerie specificandolo in un blocco repositories
Per dire a Gradle di:
è sufficiente configurare build.gradle.kts come segue:
plugins { java } // Carica il necessario per Java
repositories { mavenCentral() } // Configura Gradle per cercare e scaricare da Maven Central
Siamo pronti per importare le librerie che vogliamo! Dobbiamo solo:
groupId, artifactId, e version
com.omertron:API-OMDB:1.5Gradle consente di (costringe a) dire chiaramente “a cosa serve” una certa libreria. Noi vedremo solo alcuni degli scope disponibili:
implementation: la libreria ci serve sia per compilare che per eseguire la nostra applicazione
testImplementation: la libreria ci serve per compilare ed eseguire i test
testRuntimeOnly: la libreria ci serve per eseguire i test (sarà nel -cp di java), ma non per compilarli (non sarà nel -cp di javac)Una volta identificata la libreria
com.omertron:API-OMDB:1.5e scelto lo scope che vogliamo usare
implementationPossiamo semplicemente configurare Gradle per importarla dentro il blocco dependencies:
plugins { java } // Carica il necessario per Java
repositories { mavenCentral() } // Configura Gradle per cercare e scaricare da Maven Central
dependencies {
implementation("com.omertron:API-OMDB:1.5")
}
Quando lanceremo il task compileJava, Gradle si occuperà di:
Google Guava (https://github.com/google/guava)
Apache Commons (https://commons.apache.org)
Static Logger Facade for Java (SLF4J) (http://www.slf4j.org)
println)Esiste una lista, costantemente manutenuta, che elenca le più comuni, diffuse e stabili librerie per una pletora di usi: https://bit.ly/awesome-java
Alcune librerie sono costruite come Framework, ossia come ossature di applicazioni, pensate per velocizzare la costruzione di un certo tipo di software
Uno degli scopi del progetto di OOP è quello di misurare se siate bravi designer, ma per farlo è necessario che il design della vostra applicazione l’abbiate fatto voi e non chi ha costruito il framework.
Vi raccomandiamo quindi di evitare i framework! O, al più, usarli solo dopo che il progetto è avviato come semplice libreria (non semplice e non sempre possibile)
danilo.pianini@unibo.itgianluca.aguzzi@unibo.itangelo.filaseta@unibo.itCompiled on: 2025-12-05 — versione stampabile