Mise en cache via ||= lorsque la valeur peut être nil ou false

Comme nous l’avons vu dans cet article, il est facile et intéressant de mettre le résultat de l’appel d’une méthode en cache localement dans l’instance d’un objet. Ceci permet de n’exécuter la méthode qu’une seule fois, et de pouvoir récupérer le résultat autant de fois que nécessaire.

class MyObject
  def heavy_method
    @heavy_method_cache ||= begin
      # Ici on fait les actions gourmandes
    end
  end
end

Mais lorsque la valeur retournée par méthode peut prendre les valeurs nil ou false, l’opérateur d’affectation ||=, qui est un opérateur logique, agirait incorrectement et déclencherait l’exécution du block begin...end à chaque appel de la méthode.

Détecter si la variable d’instance est définie

Afin d’éviter ce problème, il faut complexifier légèrement le code de la méthode :

class MyObject
  def heavy_method
    # Retourne le cache si il existe
    if instance_variable_defined? '@heavy_method_cache'
      return @heavy_method_cache 
    end

    # Premier appel : remplie le cache
    @heavy_method_cache = begin
      # Ici on fait les actions gourmandes
    end
  end
end

On s’est débarrassé de l’opérateur d’affectation ||=, puisque l’on utilise à la place la méthode instance_variable_defined?. Comme son nom l’indique, cette méthode va retourner une valeur booléenne indiquant si la variable d’instance @heavy_method-cache est définit ou non. Lors du premier appel de la méthode ce n’est pas le cas, l’exécution est passée à la deuxième partie de la méthode, et le résultat est stocké dans la variable d’instance.

Lors des exécutions suivantes, comme la variable d’instance @heavy_method-cache est définit, et même si elle a une valeur false ou nil, celle ci est retournée sans faire appel au reste de la méthode.

Newsletter

Publié par

Benj

Artisan du web à plusieurs facettes, du développement à la gestion de produits complexes en passant par le pilotage de projets internationaux.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

un × deux =