:: Enseignements :: ESIPE :: E4INFO :: 2026-2027 :: Java Avancé ::
![[LOGO]](http://monge.univ-eiffel.fr/ens/resources/mlv.png) | TP noté intermédiaire de Java Avancé 2026 - 2027 |
Le but de ce TP noté est d'implanter une petite application permettant de gérer
les emprunts d'une bibliothèque et de calculer les éventuelles pénalités de retard.
Vos sources Java produites pendant l'examen devront être placées sous le répertoire EXAM
de votre compte ($HOME) (qui est vide dans l'environnement de TP noté).
Sinon, elles ne seront pas récupérées.
Vous avez le droit de lire le sujet jusqu'au bout, cela vous donnera une bonne idée de là où on veut aller !
Exercice 1 - Library
Notre bibliothèque propose des livres, des magazines et des bandes dessinées.
Les adhérents peuvent emprunter des documents pendant une durée maximale de
15 jours.
Au-delà de cette durée, l'adhérent doit payer une pénalité pour chaque
jour de retard.
Les pénalités journalières sont fixées par la bibliothèque (pour le moment) :
- Un livre : 5 euros par jour ;
- Un magazine : 2 euros par jour ;
- Une bande dessiné : 3 euros par jour
On souhaite tout d'abord modéliser les documents et emprunts de notre bibliothèque.
Un document est soit un livre avec un titre (Book(title)), soit un magazine
avec un titre (Magazine(title)) soit une bande dessinée avec un titre
(Comic(title)).
Un emprunt (Loan) est caractérisé par le nom de l'adhérent
(member de type String) qui emprunte le document,
un document et la date à laquelle le document a été emprunté
(borrowedOn de type LocalDate).
Une classe Library contient la liste des emprunts et permet
d'ajouter de nouveaux emprunts.
Les tests JUnit 5 de cet exercice sont
LibraryTest.java.
Note : comme on utilise les tests unitaires JUnit sans Maven, dans la configuration de votre projet, il faut ajouter
la librairie JUnit 5, soit à partir du fichier
LibraryTest.java, en cliquant sur l'annotation
@Test et en sélectionnant le quickfix "Fixup project ...", soit en sélectionnant les "Properties" du projet
(avec le bouton droit de la souris sur le projet) puis en ajoutant la librairie JUnit 5 (jupiter) au ClassPath.
-
Dans le package fr.uge.loanlibrary,
créer les classes dont vous avez besoin pour modéliser les emprunts.
Créer également une classe Library permettant de stocker
les emprunts.
Elle doit proposer les méthodes :
addLoan(Loan loan) qui ajoute un emprunt et loans()
qui renvoie la liste des emprunts.
Vérifier que les tests marqués "Q1" passent.
-
Dans Library, déclarer trois constantes correspondantes
aux pénalités journalières (des entiers longs pour représenter les valeurs en euro).
Écrire une méthode d'aide
lateFee(Loan loan, LocalDate date) qui calcule le montant
de la pénalité associée à un emprunt à une date donnée.
Cette méthode doit être testable par les tests, mais ne pas
faire partie de l'API.
Exemple d'utilisation : si un emprunt a été effectué le 1er juin, il n'y a
aucune pénalité le 16 juin : les quinze jours d'emprunt sont encore
écoulés exactement. Le 17 juin, un jour de retard est facturé.
Écrire ensuite la méthode publique
lateFeeForMember(String member, LocalDate date)
qui calcule la somme des pénalités dues par un adhérent.
Pour calculer les pénalités, on peut soit utiliser le polymorphisme
soit utiliser le pattern matching.
Avant de programmer, expliquez en commentaire laquelle des deux approches
vous semble la plus adaptée ici et pourquoi.
Implanter l'approche retenue, sachant que l'on vous demande d'utiliser
la programmation impérative.
Note: pour calculer le nombre de jours entre deux dates,
on peut utiliser ChronoUnit.DAYS.between(startDate, endDate).
Vérifier que les tests marqués "Q2" passent.
-
Commenter le code la méthode lateFeeForMember précédente.
Réécrire une nouvelle implantation de la méthode lateFeeForMember en utilisant un Stream.
Note: attention à ne pas faire de boxing inutile,
vous serez sévèrement sanctionné sur ce point.
Vérifier que les tests marqués "Q3" passent.
-
On souhaite maintenant pouvoir effectuer différentes recherches dans
la bibliothèque sans pour autant multiplier le nombre de méthodes spécialisées.
C'est à dire, au lieu d'avoir une méthode findLoansByMember, findLoansByDate,
etc. On cherche à écrire une seule méthode findLoans(???)
qui prend en paramètre la recherche exacte que l'on veut faire.
Ajouter à Library la méthode findLoans
qui renvoie la liste des emprunts correspondant à la recherche.
Note: L'implémentation doit utiliser un Stream.
Vérifier que les tests marqués "Q4" passent.
-
Une recherche peut être décrite par plusieurs conditions.
Par exemple, on peut vouloir trouver les emprunts d'Alice qui
correspondent à un certain type de document.
On souhaite donc ajouter la méthode findAllLoans(???)
qui prend une liste de critère de recherche
et renvoie les emprunts qui vérifient tous les critères.
Implémenter findAllLoans.
Note: en termes d'implantation,
Attention à ne parcourir la liste des emprunts qu’une seule fois.
Vérifier que les tests marqués "Q5" passent.
-
On souhaite maintenant pouvoir produire des statistiques sur les emprunts,
dans notre cas, deux statistiques.
On souhaite tout d'abord connaître le nombre d'emprunts pour chaque
type de document.
Pour cela, ajouter une classe DocumentKind ayant les valeurs BOOK,
MAGAZINE et COMIC.
Écrire une méthode : countByDocument()
qui renvoie une Map contenant pour chaque type de document,
le nombre d'emprunts correspondants (un entier long).
Si un type de document n'a pas d'emprunt, il ne doit pas être présent dans la Map.
Ajouter ensuite une méthode borrowDaysByDocument(date) permettant de calculer,
pour chaque type de document, la somme des jours d'emprunts.
Vérifier que les tests marqués "Q6" passent.
-
On souhaite généraliser les deux méthodes précédentes et écrire une méthode
statsByDocument(???) qui permet d'effectuer n'importe quelles statistiques
par type de document.
Mettre en commentaire le code des méthode countByDocument() et borrowDaysByDocument(date).
Puis réimplanter celles-ci en utilisant une méthode statsByDocument() intermédiaire.
Vérifier que les tests marqués "Q7" passent.
-
Les pénalités définies comme constantes dans Library sont
pratiques, mais elles ne permettent pas de calculer les pénalités
avec une autre politique tarifaire.
On souhaite donc ajouter une surcharge de
lateFeeForMember qui reçoit en dernier paramètre (fees)
une table associant chaque type de document (DocumentKind) à une pénalité journalière.
Ajouter la méthode lateFeeForMember(member, date, fees)
Réfléchissez à ne PAS dupliquer le code existant, mais à comment faire
pour factoriser le code correctement.
Réfléchissez également au comportement à adopter lorsqu'un DocumentKind
n'a pas de pénalité journalière définie.
Vérifier que les tests marqués "Q8" passent.
© Université de Marne-la-Vallée