TheNEXUS

1.7. Sammenligning af Maven med Ant

Forfatterne til denne bog har ingen interesse i at skabe en fejde mellemApache Ant og Apache Maven, men vi er også opmærksomme på, at de fleste organisationer er nødt til at træffe en beslutning mellem de to standardløsninger: Apache Ant og Apache Maven. I dette afsnit sammenligner og kontrasterer vi værktøjerne.

Ant udmærker sig ved byggeprocessen, det er et byggesystem modelleret efter makemed mål og afhængigheder. Hvert mål består af et sætinstruktioner, som er kodet i XML. Der er en copy opgave og enjavac opgave samt en jar opgave. Når du bruger Ant, forsyner du Antwmed specifikke instruktioner til at kompilere og pakke ditoutput. Se på følgende eksempel på en simpel build.xml-fil:

En simpel Ant build.xml-fil.

<project name="my-project" default="dist" basedir="."> <description> simple example build file </description> <!-- set global properties for this build --> <property name="src" location="src/main/java"/> <property name="build" location="target/classes"/> <property name="dist" location="target"/> <target name="init"> <!-- Create the time stamp --> <tstamp/> <!-- Create the build directory structure used by compile --> <mkdir dir="${build}"/> </target> <target name="compile" depends="init" description="compile the source " > <!-- Compile the java code from ${src} into ${build} --> <javac srcdir="${src}" destdir="${build}"/> </target> <target name="dist" depends="compile" description="generate the distribution" > <!-- Create the distribution directory --> <mkdir dir="${dist}/lib"/> <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file --> <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/> </target> <target name="clean" description="clean up" > <!-- Delete the ${build} and ${dist} directory trees --> <delete dir="${build}"/> <delete dir="${dist}"/> </target></project>

I dette enkle Ant-eksempel kan du se, hvordan du skal fortælle Antexactly hvad du skal gøre. Der er et kompileringsmål, som omfatter javacopgaven, der kompilerer kildekoden i mappen src/main/java til mappen thetarget/classes. Du skal fortælle Ant nøjagtigt, hvor din kilde er, hvor du ønsker, at den resulterende bytekode skal gemmes, og hvordan du skal pakke det hele i en JAR-fil. Selv om der er sket nogle nyere udviklinger, som hjælper med at gøre Ant mindre procedureteknisk, er en udviklers erfaring med Ant at kode et procedureteknisk sprog skrevet i XML.

Sammenlign det foregående Ant-eksempel med et Maven-eksempel. Hvis du i Maven vil oprette en JAR-fil fra en Java-kilde, skal du blot oprette en simpel pom.xml, placere din kildekode i${basedir}/src/main/java og derefter køre mvn install fra kommandolinjen. Eksemplet Maven pom.xml, der opnår de sammeresultater som den simple Ant-fil, der er anført i En simpel Ant build.xml-fil, er vist iA Sample Maven pom.xml.

A Sample Maven pom.xml.

<project> <modelVersion>4.0.0</modelVersion> <groupId>org.sonatype.mavenbook</groupId> <artifactId>my-project</artifactId> <version>1.0</version></project>

Det er alt, hvad du har brug for i din pom.xml. Hvis du kører mvn install fra kommandolinjen, vil du behandle ressourcer, kompilere kildekoden, udføre unittests, oprette en JAR og installere JAR’en i et lokalt repository til genbrug i andre projekter. Uden ændring kan du køre mvn siteog derefter finde en index.html-fil i target/site, der indeholderlinks til JavaDoc og et par rapporter om din kildekode.

Det er ganske vist det enkleste mulige eksempelprojekt, der ikke indeholder andet end noget kildekode og producerer en simpel JAR. Det er et projekt, der nøje følger Maven-konventionerne, og som ikke kræver nogen afhængigheder eller tilpasning. Hvis vi ville begynde at tilpasse opførslen, ville vores pom.xml vokse i størrelse, og i de største projekter kan man se samlinger af meget komplekse Maven POM’er, som indeholder en stor mængde plugin-tilpasninger og afhængighedserklæringer. Men selv når dit projekts POM-filer bliver mere omfattende, indeholder de en helt anden slags information end byggefilen for et projekt af samme størrelse, der bruger Ant. Maven POM’er indeholder deklarationer: “Dette er et JAR-projekt”, og “Kildekoden er i src/main/java”. Ant-byggefiler indeholder eksplicitte instruktioner: “Dette er et projekt”, “Kildekoden er i src/main/java”, “Kør javakode i denne mappe”, “Læg resultaterne i target/classes”, “Opret en JAR fra ….” osv. Hvor Ant skulle være eksplicit om processen, var der noget “indbygget” i Maven, der bare vidste, hvor kildekoden var, og hvordan den skulle behandles.

Den forskel mellem Ant og Maven i dette eksempel er:

  • Apache Ant

    • Ant har ikke formelle konventioner som f.eks. en fælles projektmappestruktur eller en standardadfærd. Du er nødt til at fortælle Ant præcis, hvor kilden skal findes, og hvor output skal placeres. Der er med tiden opstået uformelle konventioner, men de er ikke blevet kodificeret i produktet.
    • Ant er proceduremæssig. Du skal fortælle Ant præcis, hvad han skal gøre, og hvornår han skal gøre det. Du skal fortælle den, at den skal kompilere, derefter kopiere og derefter komprimere.
    • Ant har ikke en livscyklus. Du er nødt til at definere mål og målafhængigheder. Du er nødt til at knytte en sekvens af opgaver til hvert mål manuelt.
  • Apache Maven

    • Maven har konventioner. Den ved, hvor din kildekode er, fordi du har fulgt konventionen. Maven’s Compiler-plugin sætter bytekoden i target/classes, og den producerer en JAR-fil i target.
    • Maven er deklarativ. Det eneste, du skulle gøre, var at oprette en pom.xml-fil og lægge din kildekode i standardmappen. Maven tog sig af resten.
    • Maven har en livscyklus, som blev påkaldt, da du udførte mvn install. Denne kommando bad Maven om at udføre en række på hinanden følgende livscyklusfaser, indtil den nåede livscyklusfasen install. Som en sideeffekt af denne rejse gennem livscyklusen udførte Maven en række standard-plugin-mål, der gjorde ting som at kompilere og oprette en JAR.

Maven har indbygget intelligens om almindelige projektopgaver i form af Maven-plugins. Hvis du ønsker at skrive og udføre enhedstests, skal du blot skrive testene, placere dem i $${basedir}/src/test/java, tilføje en afhængighed med testområde, enten TestNG eller JUnit, og køre mvn test. Hvis du ønsker at distribuere en webapplikation og ikke en JAR, skal du blot ændre din projekttype til war og placere din docroot i${basedir}/src/main/webapp. Selvfølgelig kan du gøre alt dette medAnt, men du vil skulle skrive instruktionerne fra bunden. I Ant skal du først finde ud af, hvor JUnit JAR-filen skal være. Derefter skal du oprette en classpath, der indeholder JUnitJAR-filen. Derefter skal du fortælle Ant, hvor den skal lede efter testkildekode, skrive et mål, der kompilerer testkilden til bytekode, og udføre enhedstestene med JUnit.

Selv uden understøttende teknologier som antlibs og Ivy (selv med disse understøttende teknologier) har Ant fornemmelsen af at være en c`ustom proceduralbuild. Et effektivt sæt Maven POM’er i et projekt, der overholder Maven’s antagne konventioner, har overraskende lidt XML sammenlignet med Ant-alternativet. En anden fordel ved Maven er afhængigheden af Maven-plugins, der deles i vid udstrækning. Alle bruger Maven Surefire-plugin’et til enhedstest, og hvis nogen tilføjer understøttelse af et nyt rammeværk til enhedstest, kan du få nye muligheder i dit eget build ved blot at øge versionen af et bestemt Maven-plugin i dit projekts POM.

Det er ikke en binær beslutning om at bruge Maven eller Ant, og Ant har stadig en plads i et komplekst build. Hvis dit nuværende build indeholder en megettilpasset proces, eller hvis du har skrevet nogle Ant-scripts til at gennemføre en specifik proces på en specifik måde, som ikke kan tilpasses Maven-standarderne, kan du stadig bruge disse scripts med Maven. Ant er gjort tilgængelig som et centralt Maven-plugin. Brugerdefinerede Maven-plugins kan implementeres i Ant, og Maven-projekter kan konfigureres til at udføreAnt-scripts inden for Maven-projektets livscyklus.

Leave a Reply