98 votes

Qu'est-ce que l'initialisation paresseuse et pourquoi est-elle utile ?

Qu'est-ce que l'initialisation paresseuse des objets ? Comment s'y prendre et quels en sont les avantages ?

125voto

Bevan Points 20976

L'initialisation paresseuse est une optimisation des performances qui consiste à différer la création d'objets (potentiellement coûteux) jusqu'à ce que vous en ayez réellement besoin.

Un bon exemple est de ne pas créer une connexion à la base de données dès le départ, mais seulement juste avant d'avoir besoin d'obtenir des données de la base.

La raison principale est que (souvent) vous pouvez éviter de créer complètement l'objet si vous n'en avez jamais besoin.

43 votes

Cela devrait aller sans dire, mais juste au cas où il l'aurait manqué : La raison pour laquelle il s'agit d'une optimisation est que vous vous rendez souvent compte que vous n'avez pas besoin de faire la création du tout, et parce que vous pouvez économiser un travail lorsque l'ordinateur est déjà occupé jusqu'à un moment où il est moins occupé.

0 votes

Bon commentaire. J'ai modifié la réponse pour intégrer votre point.

0 votes

Un très bon (et différent) cas d'utilisation/raison de l'utiliser Lazy est affiché dans la question SO suivante : stackoverflow.com/a/15894928/4404962 cette suggestion a résolu exactement ce que nous avions besoin de résoudre - en utilisant Lazy comme principal responsable

65voto

Michael Points 34110

Comme d'autres l'ont mentionné, l'initialisation paresseuse consiste à retarder l'initialisation jusqu'à ce qu'un composant ou un objet soit utilisé. Vous pouvez considérer l'initialisation paresseuse comme un application en cours d'exécution de la Le principe du YAGNI - " You ain't gonna need it "

Les avantages de l'initialisation paresseuse du point de vue des applications sont que les utilisateurs n'ont pas à payer le temps d'initialisation pour des fonctionnalités qu'ils n'utiliseront pas. Supposons que vous deviez initialiser chaque composant de votre application dès le départ. Cela pourrait créer un temps de démarrage potentiellement long - les utilisateurs devraient attendre des dizaines de secondes ou de minutes avant que votre application soit prête à être utilisée. Ils attendent et paient pour l'initialisation de fonctionnalités qu'ils n'utiliseront peut-être jamais ou pas tout de suite.

Au contraire, si vous reportez l'initialisation de ces composants au moment de l'utilisation, votre application démarrera beaucoup plus rapidement. L'utilisateur devra toujours payer le coût de démarrage lorsqu'il utilisera d'autres composants, mais ce coût sera amorti sur toute l'exécution du programme et non condensé au début, et l'utilisateur pourra associer le temps d'initialisation de ces objets aux fonctionnalités qu'il utilise.

0 votes

Dommage que je ne puisse donner que +1 ! Bon raisonnement, BTW.

3 votes

YAGNI signifie "vous n'en aurez pas besoin [la fonctionnalité, le code]". L'initialisation paresseuse est une optimisation qui est une fonctionnalité en soi. Je dirais plutôt que cela s'applique dans l'autre sens : à moins que vous ne soyez sûr d'avoir besoin de l'initialisation paresseuse, ne l'utilisez pas, YAGNI.

23voto

Justin Niessner Points 144953

L'initialisation paresseuse est le concept qui consiste à différer la création d'un objet jusqu'à sa première utilisation. S'il est utilisé correctement, il peut entraîner des gains de performance significatifs.

Personnellement, j'ai utilisé l'initialisation paresseuse lors de la création de mon propre ORM (hand-rolled) en .NET 2.0. Lors du chargement de mes collections à partir de la base de données, les éléments réels de la collection étaient initialisés paresseusement. Cela signifie que les collections étaient créées rapidement, mais que chaque objet n'était chargé que lorsque j'en avais besoin.

Si vous êtes familier avec le modèle Singleton, vous avez probablement déjà vu l'initialisation paresseuse en action.

public class SomeClassSingleton
{
    private static SomeClass _instance = null;

    private SomeClassSingleton()
    {
    }

    public static SomeClass GetInstance()
    {
        if(_instance == null)
            _instance = new SomeClassSingleton();

        return _instance;
    }
}

Dans ce cas, l'instance de SomeClass n'est pas initialisée avant que le consommateur SomeClassSingleton n'en ait besoin.

0 votes

Supprimez le paramétrage explicite de la variable privée à 'null' pour améliorer encore un peu plus la vitesse ;). De toute façon, c'est redondant.

0 votes

Bon point, SomeClassSingleton doit être une classe égale ou inférieure à SomeClass.

0 votes

Je ne sais pas si quelqu'un lit les vieilles réponses mais je suppose que la méthode privée statique get instance devrait être publique ?

7voto

Dolphin Points 2694

En termes informatiques généraux, l'évaluation paresseuse consiste à différer le traitement d'un élément jusqu'à ce que vous en ayez réellement besoin. L'idée principale étant que vous pouvez parfois éviter des opérations coûteuses s'il s'avère que vous n'en avez pas besoin, ou si la valeur change avant que vous ne l'utilisiez.

Un exemple simple de ceci est System.Exception.StackTrace. Il s'agit d'une propriété de type chaîne sur une exception, mais elle n'est pas réellement construite tant que vous n'y accédez pas. En interne, elle fait quelque chose comme :

String StackTrace{
  get{
    if(_stackTrace==null){
      _stackTrace = buildStackTrace();
    }
    return _stackTrace;
  }
}

Cela vous évite d'avoir à appeler buildStackTrace jusqu'à ce que quelqu'un veuille voir ce que c'est.

Les propriétés sont un moyen de fournir simplement ce type de comportement.

2 votes

C'est vrai, mais je ne vois pas pourquoi vous partageriez une référence à une exception entre plusieurs fils de discussion de toute façon.

4voto

Rakesh Kumar Points 31

L'initialisation paresseuse d'un objet signifie que sa création est différée jusqu'à sa première utilisation. (Pour ce sujet, les termes initialisation paresseuse et instanciation paresseuse sont synonymes). L'initialisation paresseuse est principalement utilisée pour améliorer les performances, éviter les calculs inutiles et réduire les besoins en mémoire du programme. Il s'agit des scénarios les plus courants :

Lorsque vous avez un objet dont la création est coûteuse, et que le programme risque de ne pas l'utiliser. Par exemple, supposons que vous ayez en mémoire un objet Client dont la propriété Commandes contient un grand tableau d'objets Commandes qui, pour être initialisé, nécessite une connexion à une base de données. Si l'utilisateur ne demande jamais à afficher les commandes ou à utiliser les données dans un calcul, il n'y a aucune raison d'utiliser la mémoire du système ou les cycles de calcul pour les créer. En utilisant Lazy pour déclarer l'objet Orders pour une initialisation paresseuse, vous pouvez éviter de gaspiller des ressources système lorsque l'objet n'est pas utilisé.

Lorsque vous avez un objet dont la création est coûteuse, et que vous voulez reporter sa création jusqu'à ce que d'autres opérations coûteuses aient été effectuées. Par exemple, supposons que votre programme charge plusieurs instances d'objets lorsqu'il démarre, mais que seules certaines d'entre elles sont nécessaires immédiatement. Vous pouvez améliorer les performances de démarrage du programme en reportant l'initialisation des objets qui ne sont pas nécessaires jusqu'à ce que les objets nécessaires aient été créés.

Bien que vous puissiez écrire votre propre code pour effectuer une initialisation paresseuse, nous vous recommandons d'utiliser plutôt Lazy. Lazy et ses types connexes prennent également en charge la sécurité des fils et fournissent une politique cohérente de propagation des exceptions.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X