Erreurs de programmation

Problèmes dans le code Java

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Chaque erreur est humaine. Celle commise en programmation Java. Cependant, il vaut mieux les éviter afin de ne pas mettre en péril notre application web. Voici un article consacré à des fautes de programmation Java commises très souvent.

Erreurs de programmation Java

  1. Faire attention aux blockages des Threads

    L'une des choses à faire est de se demander comment l'application va se comporter dans la situation où un Thread sera bloqué. Cela évitera les problèmes de défaillance de la machine virtuelle Java.

    Supposons qu'on a développé une application qui se connecte à d'autres sites internet pour récupérer certaines informations via une méthode synchronisée. En occurrence, il est intéressant de se poser la question suivante : "Quelle influence aura l'indisponibilité d'un site sur l'exécution du programme ?". Et la conséquence peut être tragique. Ce problème, en absence d'un timeout de connexion, peut provoquer le dead lock du Thread. Quant à lui, il peut causer la surchauffe du JVM et le plantage de l'application en question.

  2. Mauvaise pratique d'utilisation du "=="

    Souvent dans les langages de bas niveau, le signe "==" détermine si les deux éléments sont égaux. En Java aussi, mais il se réfère à des instances et non pas à ses valeurs. On constate cela sur cet exemple :

    public class IsEqualTest {
        public static void main(String args[]) {
            String s1 = new String("a");
            String s2 = new String("a");
            System.out.println("s1 == s2 ? " + (s1 == s2));
            System.out.println("s1 and s2 values are equal ? " + s1.equals(s2));
        }
    }
    

    Ce code retourne :

    s1 == s2 ? false
    s1 and s2 values are equal ? true
    

  3. L'ignorance de l'importance du rôle des Exceptions

    Les exceptions jouent un rôle fondamental en Java. Elles permettent à notre application de gérer les situations imprévues. Bien souvent couplées avec un système des logs, elles rendent le suivi d'erreurs beaucoup plus facile.

    Il est donc très important de ne pas les négliger. Et parfois on peut trouver l'instruction try-catch avec le contenu du block catch vide. Même si l'on est flemmard, il faut éviter de pratiquer cette méthode qui n'aide en aucun cas dans une bonne maintenabilité de l'application.

    Une autre chose très importante est l'exactitude des exceptions. En fait, plusiers implémentations de la classe java.lang.Exception existent. Elles s'adaptent à la plupart des situations qu'on peut rencontrer pendant le développement. Donc au lieu d'écrire un code généraliste, il vaut mieux privilégier la version plus exacte - même si elle est plus longue. Il arrive aussi que les messages captés ne soient pas explicites ou qu'ils ne contiennent pas le message d'exception. L'illustration sur l'exemple ci-dessous :

    public class ExceptionsTest {
        public static void main(String args[]) {
          String[] stringArray = new String[2];
            stringArray[0] = "a";
            stringArray[1] = "b";
            Detailed d1 = new Detailed(null, stringArray);
            d1.doSubstring();
            d1.getElement(2);
            NotDetailed nd1 = new NotDetailed(null, stringArray);
            nd1.doSubstring();
            nd1.getElement(2);
        }
    }
    
    abstract class ExceptionsExemple {
        protected String testString;
        protected String[] arrayString;
      
        public ExceptionsExemple(String t, String[] arr) {
            testString = t;
            arrayString = arr;
        }
    
        public void doSubstring() {
            try {
                testString.substring(0, 3);
            } catch (NullPointerException ne) {
                System.out.println("NullPointerException occured on doSubstring() : " + ne.getMessage());
            } catch (Exception e) {
                System.out.println("Exception occured on doSubstring() : " + e.getMessage());
            }
        }
    
        public String getElement(int key) {
            try {
                return arrayString[key];
            } catch (ArrayIndexOutOfBoundsException ae) {
                System.out.println("ArrayIndexOutOfBoundsException occured on getElement() : " + ae.getMessage());
            } catch (Exception e) {
                System.out.println("Exception occured on getElement() : " + e.getMessage());
            }
            return null;
        }
    }
    
    class Detailed extends ExceptionsExemple {
        public Detailed(String t, String[] arr) {
            super(t, arr);
        }
    }
    
    class NotDetailed extends ExceptionsExemple {
        public NotDetailed(String t, String[] arr) {
          super(t, arr);
        }
    
        public void doSubstring() {
            try {
                testString.substring(0, 3);
            } catch (Exception e) {
                System.out.println("Exception occured on doSubstring()");
            }
        }
    
        public String getElement(int key) {
            try {
                return arrayString[key];
            } catch (Exception e) {
                System.out.println("Exception occured on getElement()");
            }
            return null;
        }
    }
    

    L'exécution de ce code retournera :

    NullPointerException occured on doSubstring() : null
    ArrayIndexOutOfBoundsException occured on getElement() : 2
    Exception occured on doSubstring()
    Exception occured on getElement()
      
  4. Eviter évitable - limiter les exceptions captées

    Comme on a vu précédemment, les exceptions sont bien utiles. Cependant, il faut faire en sorte de les avoir le moins possible.

    L'une des exceptions la plus courante est NullPointerException. Elle se produit quand on se réfère (via une méthode par exemple) à un objet inexistant. Plusieurs moyens existent pour éviter NullPointerException en Java. Ici, on peut mentionner la plus fréquente qui est une vérification simple if (object != null).

    Une autre exception fréquente est ArrayIndexOutOfBoundsException. Elle apparaît dès qu'on essaie d'accéder à un élément du tableau inexistant. On peut imaginer que notre tableau contient 10 éléments (dernière clé est 9, vu qu'on commence à compter à partir de 0). Si l'on tente de retrouver son dixième élément ([10]), on aura droit à ArrayIndexOutOfBoundsException.

  5. La non fermeture de toute type de connexions

    Java et ses librairies permettent de se connecter quasiement à tout. Cependant, il faut garder en tête un point important qui est la clôture de ces connexions. Cette procédure décharge l'application et garantit une cohérence de son fonctionnement.

    La clôture des connexions peut être effectuée via l'instruction try-catch-finally où dans le dernier block (finally) on ferme la connexion en question.

    Cette problématique peut concerner par exemple une base de données qui accepte le nombre de connexions limité.

  6. Conversions incorrectes

    Les conversions entre types primitifs en Java sont possibles grâce à tout un système de parse. Cependant, il y a une règle d'or à retenir pour toute opération de ce type. La valeur convertie ne peut pas contenir les espaces blanches. Regardons cet exemple pour bien comprendre le principe :

    public class BadConversion {
        public static void main(String[] args) {
            String stringEx = "32 ";
            try {
                int stringInt = Integer.parseInt(stringEx);
                System.out.println("String => int = " + stringInt);
            } catch (NumberFormatException e) {
                System.out.println("NumberFormatException when trying to convert String to int " + e.getMessage());
            }
            try {
                int stringInt = Integer.parseInt(stringEx.trim());
                System.out.println("String => int = " + stringInt);
            } catch (NumberFormatException e) {
                System.out.println("NumberFormatException when trying to convert String to int " + e.getMessage());
            }
        }
    }
    

    On verra le résultat suivant :

    NumberFormatException when trying to convert String to int For input string: "32 "
    String => int = 32
    

    Comme on peut le constater, la chaîne de caractères contenant une espace, ne s'est pas convertie correctement en un entier.

Bartosz KONIECZNY Standards du codage

Une question ? Une remarque ?

*

*

Un conseil PHP

Utiliser XPath pour calculer le nombre d'apparitions d'un élément.

XPath est un langage qui sert à se déplacer au sein d'un document XML. Il contient beaucoup de fonctionnaltiés utilies lors de l'analyse de ces documents. Par exemple, pour voir le nombre d'apparition d'un tag, il suffit d'utiliser la méthode count et placer comme son paramètre le chemin vers les éléments à calculer. Imaginons qu'on veut calculer le nombre de noeds d'erreur. En PHP cela va se présenter ainsi :

// $this->xpath is the instance of DOMXPath
echo (int)$this->xpath->evaluate("count(/error)");