IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Tests et Performance Java Discussion :

[Sonar] Comment corriger un "Avoid instantiating objects in loops" ?


Sujet :

Tests et Performance Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    406
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 406
    Par défaut [Sonar] Comment corriger un "Avoid instantiating objects in loops" ?
    Bonjour à tous,

    J'utilise Sonar (version 2.2) et j'ai un nombre important de violations intitulées "Avoid instantiating objects in loops" mais je n'ai aucune idée de comment les corriger.
    J'instancie mes objets dans une boucle car j'ai besoin de créer un nouvel objet à chaque itération de boucle.

    Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    List liste = null;
    for (int i = 0; i < limite; i++) {
        liste = new ArrayList();
    }
    Pour faire sauter la violation, je ne peux pas réutiliser ma liste comme ci-dessous car j'ai besoin à chaque itération de boucle d'une nouvelle liste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    List liste = new ArrayList();
    for (int i = 0; i < limite; i++) {
        liste.clear();
        liste.setObjet();
        ...
    }
    Auriez-vous des idées pour corriger ce type de violations ?

    Une idée comme ça, est-ce que le design pattern fabrique pourrait m'aider ?

  2. #2
    Membre confirmé
    Homme Profil pro
    Dev
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Par défaut
    Bonjour

    Dans ton code la variable list est affecté au début de chaque itération de la boucle , et elle ne doit pas être lu en dehors de la boucle.


    Ici la durée de vie de ta variable est équivalent à un parcours de ta boucle , Dans ces cas là ,il est conseillé en général de la déclarer dans la boucle, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for (int i = 0; i < limite; i++) {
       ArrayList liste = new ArrayList();
    ...
    }
    Dans ton exemple ,où tu utilise une ArrayList qui posséde un clear , il vaut mieux faire comme tu la écris dans ton code pour des questions de performance ( Tu créera et détruira moins d’objet ... ).

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    406
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 406
    Par défaut
    Citation Envoyé par miaous Voir le message
    Ici la durée de vie de ta variable est équivalent à un parcours de ta boucle , Dans ces cas là ,il est conseillé en général de la déclarer dans la boucle, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for (int i = 0; i < limite; i++) {
       ArrayList liste = new ArrayList();
    ...
    }
    Cela ne fait pas sauter la violation Sonar . De plus, pour des problèmes de performances, n'est-ce pas encore pire de créer l'objet dansl a boucle en plus de l'instancier ? C'est pourquoi j'ai sorti la création de l'objet de la boucle.

    Citation Envoyé par miaous Voir le message
    Dans ton exemple ,où tu utilise une ArrayList qui posséde un clear , il vaut mieux faire comme tu la écris dans ton code pour des questions de performance ( Tu créera et détruira moins d’objet ... ).
    Ou quoi ? Quelle est la deuxième solution que tu préconises ?

    Mon exemple n'est pas assez parlant. En voici un nouveau avec une méthode qui supprime des utilisateurs en base de données (seulement les utilisateurs cochés dans un tableau par l'utilisateur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    /**
    * Supprime les utilisateurs cochés dans le tableau par l'utilisateur.
    * 
    * @param utilisateursCoches
    *                       les utilisateurs cochés à supprimer            
    */
    public void suppressionUtilisateurs(List<UtilisateurBean> utilisateursCoches) {
    	UtilisateurDTO utilisateurASupprimer = null;
    	for (UtilisateurBean util : utilisateursCoches) {
    		// On crée l'élément à supprimer
    		utilisateurASupprimer = new UtilisateurDTO();
    		utilisateurASupprimer.setUser(util.getUser());
    		utilisateurASupprimer.setNom(util.getNom());
    		utilisateurASupprimer.setPrenom(util.getPrenom());
     
                    // Supprime l'utilisateur en base
                    supprimerUtilisateur(utilisateurASupprimer);
    	}
    }
    Ici, je suis obligé d'instancier l'utilisateur à supprimer dans la boucle et Sonar me sort donc une violation de type "Avoid instantiating objects in loops" sur la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    utilisateurASupprimer = new UtilisateurDTO();
    Comment puis-je dans ce cas éviter la violation Sonar ?

  4. #4
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Citation Envoyé par womannosky Voir le message
    Comment puis-je dans ce cas éviter la violation Sonar ?
    Comme ceci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void suppressionUtilisateurs(List<UtilisateurBean> utilisateursCoches) {
    	UtilisateurDTO utilisateurASupprimer = new UtilisateurDTO();
    	for (UtilisateurBean util : utilisateursCoches) {
    		utilisateurASupprimer.setUser(util.getUser());
    		utilisateurASupprimer.setNom(util.getNom());
    		utilisateurASupprimer.setPrenom(util.getPrenom());
     
                    // Supprime l'utilisateur en base
                    supprimerUtilisateur(utilisateurASupprimer);
    	}
    }

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    406
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 406
    Par défaut
    Bonjour Hervé et merci pour la réponse.

    Ce code fonctionnerait si je supprimais directement les utilisateurs en base de données. Cependant, je garde ces objets (utilisateurs) dans une autre liste par la suite avant de tous les supprimer (l'une de mes contraintes). Si j'utilisais ce code, j'aurais dans ma liste tous les mêmes objets égaux. Leur user, prénom et nom serait ceux du dernier utilisateur parcouru dans la boucle "for" (puisque je modifie les références des objets à chaque itération).

    Ma question s'en détache : Est-il possible de ne pas créer l'objet utilisateur dans la boucle "for" si je dois garder ces utilisateurs par la suite ?
    J'ai l'impression que la réponse à cette question devient de plus en plus évidente, cela doit être "non".

  6. #6
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Citation Envoyé par womannosky Voir le message
    Ce code fonctionnerait si je supprimais directement les utilisateurs en base de données. Cependant, je garde ces objets (utilisateurs) dans une autre liste par la suite avant de tous les supprimer.
    En effet, c'est problématique
    Bon, si c'est juste pour contourner Sonar, et dans l'hypothèse où cet outil ne fait pas une analyse statique "trop" approfondie, je propose ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public void suppressionUtilisateurs(List<UtilisateurBean> utilisateursCoches, UtilisateurDTOFactory utilisateurDTOFactory) {
    	for (UtilisateurBean util : utilisateursCoches) {
    		UtilisateurDTO utilisateurASupprimer = utilisateurDTOFactory.newInstance();
    		utilisateurASupprimer.setUser(util.getUser());
    		utilisateurASupprimer.setNom(util.getNom());
    		utilisateurASupprimer.setPrenom(util.getPrenom());
     
                    // Supprime l'utilisateur en base
                    supprimerUtilisateur(utilisateurASupprimer);
    	}
    }
     
    public interface UtilisateurDTOFactory {
    	UtilisateurDTO newInstance();
    }
     
    ...
     
    gestionnaireUtilisateurs.suppressionUtilisateurs(utilisateursCoches, new UtilisateurDTOFactory() {
    	public UtilisateurDTO newInstance() {
    		return new UtilisateurDTO();
    	}
    });
    voire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    private UtilisateurDTOFactory utilisateurDTOFactory; // injecté par Spring par exemple
     
    public void suppressionUtilisateurs(List<UtilisateurBean> utilisateursCoches) {
    	for (UtilisateurBean util : utilisateursCoches) {
    		UtilisateurDTO utilisateurASupprimer = utilisateurDTOFactory.newInstance();
    ...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 21/07/2006, 15h50
  2. [MFC] Comment corriger ces fuites de mémoire
    Par Philippe320 dans le forum MFC
    Réponses: 8
    Dernier message: 07/03/2006, 13h50
  3. [FTP] comment corriger une boucle infinie ?
    Par sofybj dans le forum Langage
    Réponses: 8
    Dernier message: 08/11/2005, 14h49
  4. Comment corriger le bug de RightClickSelect du treeview de Delphi 7 ?
    Par bambino3996 dans le forum Composants VCL
    Réponses: 2
    Dernier message: 01/08/2005, 13h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo