Retour aux projets
PubliéAcadémique

Alexandria

Une application de gestion de bibliothèque complète.

Publié mai 20257 min de lecture

🎯 Le Contexte & L'Objectif

Écran d'accueil de l'application Alexandria
Écran d'accueil de l'application Alexandria

Alexandria — en référence à la célèbre bibliothèque d'Alexandrie — est née d'un projet universitaire en semestre 6 à l'ESIGELEC. Le cahier des charges était clair : concevoir une application capable de gérer l'intégralité du cycle de vie d'une bibliothèque, depuis le catalogue des ouvrages jusqu'au suivi des prêts par usager.

L'application devait prendre en charge cinq entités métier — usagers, livres, auteurs, genres et prêts — avec pour chacune les opérations classiques de création, consultation, modification et suppression. Les données devaient être persistées dans une base Oracle fournie par l'école, et l'ensemble des interactions tracé dans un fichier de log horodaté. Enfin, le projet exigeait la génération d'un fichier de résultats statistiques ainsi qu'une requête personnalisée affichée directement dans l'interface.

Plutôt que de me limiter au strict minimum, j'ai fait le choix de développer une interface graphique complète en Java Swing, en allant au-delà du cahier des charges sur plusieurs aspects : gestion des prêts en bonus, sécurisation des entrées, composants réutilisables et architecture pensée pour être maintenable.


🛠️ Ma Contribution & Mon Rôle

J'ai réalisé ce projet intégralement seul, de la modélisation de la base de données jusqu'à l'interface utilisateur finale.

Liste des usagers avec actions rapides
Liste des usagers avec actions rapides
Fenêtre d'actions sur un usager (modification, suppression)
Fenêtre d'actions sur un usager (modification, suppression)
Vue détaillée d'un usager et ses prêts en cours
Vue détaillée d'un usager et ses prêts en cours
  • Modélisation et base de données : conception du schéma relationnel Oracle, écriture des procédures et fonctions SQL pour les opérations CRUD, et mise en place de RAISE_APPLICATION_ERROR pour remonter des erreurs métier explicites côté Java.
  • Couche d'accès aux données (DAO) : implémentation de cinq DAO (Usager, Livre, Auteur, Genre, Prêt) communiquant avec la base via JDBC, avec des jointures optimisées pour éviter les requêtes en cascade.
  • Interface graphique Swing : développement de l'ensemble des fenêtres de gestion — listes scrollables, formulaires d'ajout/modification/suppression avec validation, modales de confirmation et vue détaillée par entité (un usager affiche ses prêts en cours, par exemple).
  • Architecture UI : mise en place d'un système d'héritage de formulaires (BaseFormFrameObjectForm → formulaires spécifiques) et de composants réutilisables (ButtonComponent, FormComponent, ListComponent) pour factoriser le code et accélérer le développement.
  • Fonctionnalités bonus : histogramme du nombre d'usagers par année de naissance (composant HistogramPanel peint à la main), génération d'un fichier de résultats statistiques, et système de logging complet via un LogManager singleton.

💻 Stack Technique

  • Langage : Java — imposé par le cadre académique, mais pleinement exploité avec l'héritage, le polymorphisme et les design patterns (DAO, Singleton, Template Method).
  • Interface graphique : Swing — la bibliothèque native de Java pour le desktop. Malgré sa réputation de lourdeur, j'ai réussi à obtenir une interface propre et cohérente grâce à un système de composants modulaires.
  • Base de données : Oracle (instance de l'ESIGELEC) — accédée via JDBC avec des PreparedStatement pour se prémunir contre les injections SQL.
  • Librairies tierces : JDatePicker pour la sélection de dates dans les formulaires, JUnit pour les tests unitaires.

⚙️ Architecture & Défis Techniques

Gestion du catalogue de livres
Gestion du catalogue de livres
Gestion des auteurs
Gestion des auteurs
Gestion des genres
Gestion des genres
Liste des prêts en cours
Liste des prêts en cours
Actions sur les prêts (retour, prolongation)
Actions sur les prêts (retour, prolongation)

Un système de formulaires génériques par héritage

Le projet gère cinq entités, chacune avec trois opérations (ajout, modification, suppression). Sans précaution, cela représente quinze formulaires quasi identiques avec beaucoup de code dupliqué. Pour éviter cela, j'ai conçu une hiérarchie de classes :

  • BaseFormFrame gère le squelette commun à tout formulaire (layout, boutons, messages d'erreur).
  • Chaque entité possède une classe ObjectForm intermédiaire (ex : LivreForm, UsagerForm) qui définit la validation des champs.
  • Les formulaires concrets (LivreAddForm, LivreModifyForm, LivreDeleteForm) héritent de leur ObjectForm et ne redéfinissent que le strict nécessaire : les champs à afficher et l'action principale.

Ce pattern m'a permis de produire quinze formulaires fonctionnels tout en gardant un code lisible et facilement extensible.

Sécurisation côté SQL et côté Java

Plutôt que de laisser Java gérer seul la validation, j'ai mis en place une double couche de protection :

  • Côté Oracle : des procédures stockées avec RAISE_APPLICATION_ERROR renvoient des codes et messages d'erreur explicites (ex : tentative de suppression d'un auteur encore référencé par un livre).
  • Côté Java : les SQLException sont interceptées et les messages personnalisés sont affichés à l'utilisateur via des popups, avec un fallback sur les erreurs natives Oracle si aucune procédure personnalisée n'est en jeu.

Cette approche garantit que la base de données reste cohérente quoi qu'il arrive, même si l'application venait à être modifiée ou étendue par un autre développeur.

Affichage dynamique des listes

Chaque entité est présentée dans une liste scrollable construite via un composant ListComponent qui génère dynamiquement des lignes avec les données et les boutons d'action (voir, modifier, supprimer). Lors d'un ajout, d'une modification ou d'une suppression, la liste se rafraîchit automatiquement sans rechargement de la fenêtre — un détail qui améliore sensiblement l'expérience utilisateur.

Visualisation de données : l'histogramme

Requête personnalisée — histogramme des usagers par année de naissance
Requête personnalisée — histogramme des usagers par année de naissance
Génération du fichier de résultats statistiques
Génération du fichier de résultats statistiques

Pour la requête personnalisée demandée par le cahier des charges, j'ai développé un composant HistogramPanel qui dessine un diagramme en barres directement via l'API Graphics de Java. L'histogramme affiche le nombre d'usagers par année de naissance, avec des barres dimensionnées dynamiquement et des labels lisibles. Ce composant est entièrement peint à la main, sans librairie de graphiques externe.


🚀 Résultats & Impact

  • Couverture fonctionnelle : les cinq entités sont entièrement gérables via l'interface, avec toutes les opérations CRUD et les vues détaillées associées.
  • Au-delà du cahier des charges : la gestion des prêts (ajout bonus), l'histogramme personnalisé, la protection contre les injections SQL et le système de composants réutilisables dépassent les exigences initiales du projet.
  • Traçabilité : chaque action utilisateur est enregistrée dans un fichier de log horodaté, conformément aux spécifications.
  • Robustesse : la validation des entrées côté Java et les procédures SQL sécurisées empêchent les états incohérents dans la base de données.
  • Note obtenue : 20/20 — le projet a été évalué sur la qualité du code, le respect du cahier des charges et les fonctionnalités bonus apportées.

💡 Ce que j'ai appris

Ce projet a été ma première vraie confrontation avec Swing, et je comprends maintenant pourquoi le framework a la réputation d'être fastidieux. La création de composants graphiques demande beaucoup de code boilerplate, et le positionnement des éléments via GridBagLayout n'est pas toujours intuitif. Malgré cela, le fait de tout construire à la main m'a donné une compréhension solide du fonctionnement interne d'une interface graphique : gestion des événements, cycles de rendu, imbrication de panels.

Si c'était à refaire, plusieurs améliorations s'imposeraient :

  • Singletoniser la connexion : actuellement, chaque DAO instancie sa propre connexion à la base, ce qui est inutilement coûteux.
  • Améliorer l'UX des formulaires : ne pas fermer la fenêtre après une erreur de saisie, et ajouter des boutons "Retour" plutôt que de forcer l'utilisateur à utiliser la croix.
  • Étendre les tests : la couverture JUnit est minimale et mériterait d'être renforcée, notamment sur la couche DAO.
  • Généraliser davantage l'architecture UI : le pattern d'héritage des formulaires pourrait être poussé plus loin pour réduire encore la duplication entre les entités.