:: Enseignements :: Master :: M1 :: 2014-2015 :: Design Pattern ::
[LOGO]

Je loggue, tu loggues, ...




Exercice 1 - Mon logger à moi

Un des principaux sports en Java est de se ré-écrire sa propre bibilothèque de logger, car les bibliothèques java.util.logging, Apache Common logging, Apache Log4j, Apache Log4j2, Tiny Log, Android Log et QOS Logback sont vraiment pas terribles.

Votre entreprise, elle aussi atteinte du syndrome NIH, utilise la classe suivante

Bien sûr, elle ne permet de logguer des messages que sur la sortie d'erreur standard mais nous allons améliorer cela.

  1. On souhaite aussi pouvoir logger des messages dans un fichier, on se propose donc d'écrire une classe PathLogger qui prend un Path à la construction, ouvre un BufferedWriter sur un fichier et écrit les logs dedans.
    Ecrire la classe PathLogger.
    Note: Il existe une méthode Files.newBufferedWriter !
    Note 2: pensez qu'il faut pouvoir fermer le fichier ouvert, si le logger n'est plus utilisé; et sans perdre de logs.
  2. En tant que développeur, on souhaite pouvoir manipuler indifféremment un SystemLogger ou un PathLogger à travers la même API.
    Faite les changements qui s'impose.
  3. On peut remarquer que créer plusieurs instances de SystemLogger est un peu idiot, on pourrait partager la même instance.
    Quel design pattern doit-on utiliser dans ce cas ?
    Faites les changements qui s'impose dans la classe SystemLogger.
  4. Votre chef à écrit le code suivant:
    		    public class Foo {
    		      ...
    		      private static final PathLogger logger = new PathLogger(Paths.get("log.txt"));
    		    }
    		  
    Et le code ne compile pas car il manque la gestion des exceptions d'entrée/sortie.
    Au lieu de devoir gérer les exceptions dans un bloc statique, il vous demande d'écrire du code qui essaye de creér un PathLogger et s'il n'y arrive pas pour cause d'exceptions, renvoie un SystemLogger à la place.
    Bien sûr ce code devra pouvoir être appelé avec des fichiers de log différents.
    Quel design pattern doit on mettre en oeuvre ici ?
    Ecrire le code correspondant.
    1. On souhaite pouvoir filtrer les logs du PathLogger, c-a-d afficher les logs qui sont plus grands ou plus petits qu'un certain Level.
      Comment doit-on faire ?
      Implanter la solution retenue.
      PS: pour plus de flexibilité on representera le fait de choisir si on affiche un Level ou non par un Predicate<Level> pour ne pas hardcoder le choix d'un Level dans le code.
    2. On veut aussi permettre de filtrer les logs sur le SystemLogger et plus généralement sur n'importe quel logger.
      Expliquer pourquoi utiliser une classe abstraite qui contient un Predicate pour partager le code ne marche pas ici ?
    3. Comment le design pattern Proxy permet de résoudre le problème ?
      Modifier votre code pour implanter ce design pattern.
    4. En fait, dans 90% des cas, on ne rend pas la classe du proxy publique.
      Expliquer pourquoi et comment un utilisateur va utiliser la classe ?
      Faire les changements qui s'imposent dans le code.
  5. Enfin, on souhaite pouvoir créer un loggeur qui affiche ses logs et sur la console et dans un fichier.
    Comment doit-on implanter un tel logger ?
    Ecrire le code correspondant.
Pour préparer les questions de la prochaine séance, il vous est demandé d'étudier le design pattern Flyweight. Pour commencer, vous pouvez lire les articles suivants :