jeudi 28 février 2019

De la génération du code à la génération des applications (2/3) : la génération du code

La génération du code est le point fort des EDI. Ces dernier vise à traduire des actions visuelles pour générer un code correct. Cela s'ajout à un ensemble d'outil de gestion des projets et d'édition du code (coloration, auto-complétion, etc.) (point discuté ici).
Dans cet exemple, je vais illustrer cette caractéristique principal des EDI. Pour faire, il n'y a pas mieux que travailler sur des composants graphiques où l'action visuelle est plus parlante. Ainsi, je vais commencer par créer un nouveau projet et par créer une JFrame. Je vais garder en esprit que NetBeans "génère automatiquement" une méthode main pour chaque JFrame.




NetBeans utilise GroupLayoutManager comme LayoutManager par défaut pour gérer le positionnement des éléments. Cela nous donne l'avantage pour gérer d'une façon très souple le positionnement des éléments, néanmoins, cela limite la portabilité de notre code pour d'autres éditeurs.
Ajoutons quelques composants pour voir le code généré :


L'outil nous permet de voir et de modifier toutes les propriétés des composants manipulés. Il nous donne aussi la possibilité de changer des éléments basiques du génération du code tels que les nomes des variables :


Jetons un coup d'oeil sur le code généré :

    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        lblMessage = new javax.swing.JLabel();
        txtMessage = new javax.swing.JTextField();
        btnDisplay = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        lblMessage.setText("Message : ");

        txtMessage.setText("Message to display");

        btnDisplay.setText("Diplay");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(85, 85, 85)
                        .addComponent(lblMessage)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(txtMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(161, 161, 161)
                        .addComponent(btnDisplay)))
                .addContainerGap(71, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(53, 53, 53)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblMessage)
                    .addComponent(txtMessage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(30, 30, 30)
                .addComponent(btnDisplay)
                .addContainerGap(173, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>

Nous voyons que le code généré est un peu lourd, c'est à cause de LayoutManager utilisé.
Nous pouvons changer le LayoutManager en toute simplicité et sans modifier le code directement. Il suffit de faire un clique droit sur l'objet de la JFrame dans le navigateur et de choisir le nouveau LayoutManager de la liste qui s'affiche en pointant "Set Layout" :


Revenant à notre code :

    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        lblMessage = new javax.swing.JLabel();
        txtMessage = new javax.swing.JTextField();
        btnDisplay = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(null);

        lblMessage.setText("Message : ");
        getContentPane().add(lblMessage);
        lblMessage.setBounds(85, 55, 77, 15);

        txtMessage.setText("Message to display");
        getContentPane().add(txtMessage);
        txtMessage.setBounds(174, 53, 155, 19);

        btnDisplay.setText("Diplay");
        getContentPane().add(btnDisplay);
        btnDisplay.setBounds(161, 102, 78, 25);

        pack();
    }// </editor-fold>  

Ainsi, nous pouvons contrôler facilement le code généré à un niveau très bas et avec toute la liberté, mais, un certain niveau de connaissance et de compréhension du code généré est nécessaire.


dimanche 24 février 2019

Oracle JET : des composants et non pas une framework

Le développement frontend repose principalement sur des framework JS. Ces frameworks peuvent imposer l'architecture à suivre mais aussi le style de développement à suivre, et la question qui vient à l'esprit d'un minimaliste est : Existe-t-il une solution plus légère ? Comment développer ("prototyper") en frontend en utilisant JS sans avoir à faire appel à une framework ?

Cette question me vient toujours à l'esprit à chaque fois que j'essaie de faire une démo rapide et je me trouve déboguer un code JS perdant ainsi un temps précieux en classe.

Ces derniers jours, je me suis retourné vers une technologie (si on peut dire) Oracle à laquelle j'ai tourner le dos depuis longtemps. C'est Oracle JET (Oracle JET). Comme étant intéressé exclusivement par Java et à la limite J2EE (maintenant EE4J), je n'ai pas pas trop concentré sur les autres technologies Oracle. Aujourd'hui, je me suis retourné pour voir est ce que je pourrais trouver une réponse à ma question.

Est-ce que Oracle JET est bel et bien la réponse à la question que j'ai posée ? Oui et Non.

Oui, parce que à la base, Oracle JET est un ensemble de composants et non pas une framework (selon l'explication). Vous pouvez suivre toujours vos propres méthodes, architectures et approches de développement et au même temps avoir une large gamme de composants que vous pouvez intégrer facilement à votre application (liste).

Non, pour les raisons suivantes :

  • Oracle JET est basé sur un grand nombre de librairies JS et bien sûre sur Node. Malgré la facilité d'utilisation, le tout doit être à jour et l'outil effectue (presque) à chaque fois des actions de téléchargement; cela devient (avec un peu d'exagération de ma part) inutilisable dans un contexte d'enseignement.
  • Le code généré par l'outil ojet-cli est incroyablement grand puisque il intègre le tout, non pas seulement les composants que vous voulez utilisés, par conséquent, un grand travail de nettoyage est nécessaire avant le déploiement (cela reste toujours acceptable dans le cadre d'un prototype).
Pour l'installation, c'est très simple (Command Line Tool):

npm install -g @oracle/ojet-cli

Mais malheureusement, ce n'est jamais aussi simple que ça.
Premièrement, n'oubliez pas de donner le droit d’administrateur à la commande (sudo).

Deuxièmement, si Node n'est pas à jour, alors vous risquez d'avoir des erreurs de syntaxe sur le code généré. L'erreur qui m'est arrivée :

$ ojet build
/home/tarek/JavaPlayground/firstJet/MyFirstJET/node_modules/winston/lib/winston.js:11
const { warn } = require('./winston/common');
      ^

SyntaxError: Unexpected token {
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:374:25)
    ...

Comme vous voyez, cette erreur n'a rien à voir avec Oracle JET mais avec "winston", et à vrai dire, je n'ai jamais entendu parlé de ce "winston" avant ce message d'erreur. Une erreur commune qui nécessite la mise à jour de Node (l'issue). Là c'est pas aussi simple aussi (propositions "théorique", et n).

npm peut rendre npm inutilisable (Oui, apparemment ça arrive)
Ensuite, il faut une installation presque manuelle pour mettre à jour Node et pour récupérer npm qui a tenté de mettre à jour Node.

Une fois tous les problèmes sont résolus, l'application fonctionne à merveille.