mercredi 28 août 2019

Exemple d’utilisation d’Apache Freemarker : Génération du code

Pourquoi générer du code Java

Java est relativement lourd comme langage; il est très strict mais très efficace. Des fois, on n’a pas le temps (ou ils suffit être comme moi, un peu féniant) pour tout écrire, alors, on fait appel à nos outils pour générer une partie du code. A ce niveau, les différents IDE possèdent tous des outils pour générer les constructeurs et les Setters et Getters et bien d’autres parties de nos classes Java.
Dans cet exemple, je vais compter sur un "template engine" pour générer le code des Java Beans. J’ai choisi comme exemple Apache Freemarker. Je n’ai aucune idée sur les autres "template engines".

Apache Freemarker

Je reprends le diagramme donné par Apache pour expliquer le principe d’un "template engine" :



ce qui est important à noter est l’affirmation ( ici ):

Anything not an FTL tag or an interpolation or comment is considered
static text and will not be interpreted by FreeMarker; it is just
printed to the output as-is.

Par conséquent, Freemarker peut être utilisé pour générer n’importe quel format texte.

L’exemple

Dans cet exemple, j’ai tenté de générer le code d’un Java Bean.

La spécification JavaBeans de Oracle définit les composants de type
JavaBeans comme « des composants logiciels réutilisables manipulables
visuellement dans un outil de conception ».

Ils sont utilisés pour encapsuler plusieurs objets dans un seul objet :
le « bean » (ou haricot en français). Le « bean » regroupe alors tous
les attributs des objets encapsulés, et peut définir d'autres attributs
si besoin. Ainsi, il représente une entité plus globale que les objets
encapsulés de manière à répondre à un besoin métier.

Pour cela, j’ai défini deux classes comme modèle :

public class Variable {

    String variableName;
    String variableType;

}

Et

public class Bean {

    public String beanName;
    public List<Variable> attributes;

}

Ainsi, un Bean peut être créé facilement. A titre d’exemple, si je veux un Bean "User" avec trois attributs : id, userName et password, il suffit un petit bout de code comme le suivant :

Bean user = new Bean();
user.setBeanName("User");
user.setAttributes(new ArrayList<>());
user.getAttributes().add(new Variable("id", "int"));
user.getAttributes().add(new Variable("userName", "String"));
user.getAttributes().add(new Variable("password", "String"));

Par la suite, il fallait créer une petite template avec un constructeur vide et l’ensemble des Setters et Getters :

public class ${bean.beanName} {

 public ${bean.beanName}(){
 }

<#list bean.attributes as attribut>;
 ${attribut.variableType} ${attribut.variableName};

 public void set${attribut.variableName?cap_first}(${attribut.variableType} value){
  ${attribut.variableName} = value;
 }

 public ${attribut.variableType} get${attribut.variableName?cap_first}(){
  return ${attribut.variableName};
 }

</#list>
}

Par la suite, il ne reste qu’jouter le Bean au modèle, puis passer ce dernier à la template chargé pour générer le code nécessaire :

public static void createBean(Configuration cfg, String templateName, Bean bean) throws MalformedTemplateNameException, TemplateException, ParseException, IOException{

        Map root = new HashMap();
        root.put("bean", bean);
        Template template = cfg.getTemplate(templateName);
        Writer out = new OutputStreamWriter(new  FileOutputStream(new File(bean.getBeanName() + ".java")));
        template.process(root, out);

}

Le résultat est bien le fichier source attendu pour le Bean décrit.

En effet, l’outil est très simple à utiliser au point où je me suis amusé à ajouter une template qui génère une fenêtre avec les champs nécessaires. La tâche est loin d’être finie (adapter les champs de saisi selon les types de données), mais le début était très simple.

Vous pouvez trouver le code exemple ici.
Vous pouvez trouver la version PDF de ce post ici.

samedi 24 août 2019

Nitrite, un petit SGBD NoSQL : l'équivalent de Sqlite pour le NoSQL

Le NoSQL "désigne une famille de systèmes de gestion de base de données (SGBD) qui s'écarte du paradigme classique des bases relationnelles. L'explicitation du terme la plus populaire de l'acronyme est Not only SQL (« pas seulement SQL » en anglais) même si cette interprétation peut être discutée" (Wikipedia)

Le non respect du paradigme traditionnel veut dire, principalement, le non respect des formes normales et plus particulièrement la première forme normale, ainsi, une propriété peut avoir plusieurs valeurs à un instant donné (tableau de valeurs simples et/ou être composée). L'objectif n'est pas la composition, autrement, les SGBD Objets deviendraient suffisants. L'objectif est d'éviter l'opération de jointure.

Par exemple, si nous possédons trois tables :

  • Utilisateur : qui compte 10.000 enregistrements (lignes),
  • Lien_Amitie : qui compte  1.000.000 d'enregistrements (chaque utilisateur possède 100 amis en moyenne),
  • Publication : qui compte 10.000.000 enregistrements (1.000 publications per utilisateur en moyenne)
Pour afficher le fil d'actualité, il faut faire une jointure entre Utilisateur et Lien_Amitie pour trouver les amis et une jointure entre Lien_Amitite et Publication pour récupérer les publications des amis. Sur des fichiers de cette taille, les requêtes deviendront très vite coûteuses en temps d'exécution. Imaginez maintenant des systèmes avec 1 million, 10 millions ou 100 millions d'utilisateurs.

Néanmoins, la plus part des SGBD NoSQL sont conçus pour supporter une grande quantité de données, ainsi, le passage d'un modèle conceptuel qui cite "table", "propriété", "association", "clé" se trouve face à des termes comme "cluster", "noeud", "réplication" et d'autres notions relatives au "big data". Par conséquent, ils ne sont pas adapté à des applications de petite taille (mono utilisateur, mobile, etc.).

La solution peut être Nitrite (NoSQL Object -> NO2) : l'équivalent du Sqlite dans le monde NoSQL. Il s'agit un SGBD NoSQL de petite taille. Son noyau permet de faire les opérations de base CRUD. Nitrite est doté aussi d'un ensemble d'outils qui permettent son extension pour supporter plusieurs langages, la réplication des données, la visualisation des données et autres.

J'ai testé Nitrite en suivant son manuel d'utilisation. L'objectif était de créer une seule Collection (l'équivalent d'une table) pour stocker un seul type d'objets (une seule classe dans le modèle de données). J'ai essayé de créer deux projets :

  • Un projet Maven tel que recommandé par l'auteur : un premier teste rapide dans lequel je ne m'attendais pas d'avoir des problèmes et effectivement, le teste a passé sans problèmes.

  • Un projet ordinaire (sans passer par Maven) : l'idée est de voir à quel point c'est simle d'ajouter Nitrite à projet existant.

Après, le teste je peux résumer on avis en points forts et faibles :

Points forts


  • Documentation claire : la documentation est disponible, des fois au format AsciiDoc, et, à mon avis, elle est suffisante pour apprendre les bases.
  • L'outil tient sa promesse : il est simple, rapide en développement, le nommage des fonctions et des classes est très efficace et très parlant.
  • Une classe de Collection générique est déjà disponible et permet de cacher les notions internes telles que la notion du Document ce qui facilite encore l'apprentissage et l'utilisation de l'outil.

Points faibles

  • L'utilisation de Maven est (presque) obligatoire : même avec un temps de construction d'environ 1 minute et 34 secondes, l'autre option (gérer les dépendances manuellement) est (presque) impossible. La plus part des dépendances de Nitrite sont à leur tour des projets Maven sur GitHub, ainsi, il faut les télécharger et les construire manuellement.

  • Le nombre de dépendances : à mon avis, avoir un grand nombre de dépendances ne peut qu'être un inconvénient majeur. En plus, la plus part de ces dépendances ne sont pas supportés par des fondations ou des entreprises, ainsi, si une de ces dépendances est abandonnée, on est obligé de continuer sa maintenance au niveau local. Sur ce point, je trouve SmallSQL plus avantageux.
  • L'outil ne supporte pas le langage SQL : malgré que, par définition, ce n'est pas nécessaire, p)lsuieurs SGBD NoSQL ajoute le support du (ou d'une partie du) langage SQL pour faciliter l'interrogation. Malheureusement, ce n'est pas le cas de Nitrite.
Finalement, je conseille tout intéressé par les SGBD NoSQL de jeter un coup d'oeil sur Nitrite et de voir les possibilités qu'il offre.

Vous pouvez trouver une version PDF de ce post ici.