Patrón de Carga Diferida: Inicialización diferida

Esta entrada es la parte 1 de 4 en la serie Patrón de Carga Diferida

El patrón de carga diferida es una técnica para mejorar la performance utilizada en casos en que nos encontramos con que no todas las características de un programa son usadas durante su ejecución o para distribuir los tiempos de carga, cuando estos son muy grandes, durante la ejecución para poder mejorar los tiempos de respuesta al iniciar.

Hay cuatro formas comunes de implementar la carga diferida: inicialización diferida, proxy virtual, fantasma y value holder.

Inicialización diferida

Esta técnica implica la inicialización del contenedor del recurso como nulo, o equivalente en el lenguaje, y recién realizar la carga en el momento de su primer uso.

Por ejemplo, establecer el identificador de la conexión al servidor de bases de datos como null y al momento de realizar una consulta, verificar si la conexión está inicializada o hace falta establecerla.

Algunas consideraciones que es necesario tener en cuenta al utilizar este patrón son:

  • Es necesario que cada vez que vayamos a usar el recurso del que estamos difiriendo su inicialización verifiquemos que haya sido cargado. Si bien a nivel performance no debería influir, si puede ser fuente de otros errores por olvido o por tener código duplicado.
  • Como en cualquier otro método de carga diferida, nos podemos encontrar conque el recurso no existe o no está accesible. Además, si toma mucho tiempo cargarlo, la ejecución del programa se puede ver interrumpida.
<?php

class BBDD {
  private $user;
  private $pass;
  private $host;
  private $name;

  private $connection;

  function __construct( $user, $pass, $host, $name ) {
    $this->user = $user;
    $this->pass = $pass;
    $this->host = $host;
    $this->name = $name;

    $this->connection = null;
  }

  function conectar() { /***/ }

  function query( $sql ) {
    if ($this->connection == null)
      $this->conectar();

    /***/
  }
}

 

Patrón de Carga Diferida: Proxy Virtual

Esta entrada es la parte 2 de 4 en la serie Patrón de Carga Diferida

El patrón de carga diferida es una técnica para mejorar la performance utilizada en casos en que nos encontramos con que no todas las características de un programa son usadas durante su ejecución o para distribuir los tiempos de carga, cuando estos son muy grandes, durante la ejecución para poder mejorar los tiempos de respuesta al iniciar.

Hay cuatro formas comunes de implementar la carga diferida: inicialización diferida, proxy virtual, fantasma y value holder.

Proxy virtual

Esta técnica implica la creación de un contenedor con la misma interfaz que el recurso original que carga el mismo cuando se realiza el primer llamado a uno de sus métodos.

Por ejemplo, una galería con cientos de imágenes que crea los objetos que representan todas las imágenes al iniciar el programa pero estos recién leerán la imagen del disco cuando tengan que dibujarla.

Algunas consideraciones que es necesario tener en cuenta al utilizar este patrón son:

  • Dependiendo del lenguaje de implementación y el tamaño de la clase puede terminar siendo un código engorroso y repetitivo con un montón de métodos públicos que únicamente llamen al loader.
  • La carga del recurso es transparente. A los efectos del resto del programa se hace al momento de crear el objeto.
  • Como en cualquier otro método de carga diferida, nos podemos encontrar conque el recurso no existe o no está accesible. Además, si toma mucho tiempo cargarlo, la ejecución del programa se puede ver interrumpida.
public class Image {

  public Image(filename) {
    /* Ahora cargaría la imagen desde el disco */
  }
  
  public void draw() { /***/ }
}

public class ImageProxy {
  private String filename;
  private Image image;

  public ImageProxy( filename ) {
    this.filename = filename;
  }

  public void draw() {
    if (this->image == null) {
      this.image = new Image(this.filename)
    }

    this.image.draw();
  }
}

 

Patrón de Carga Diferida: Fantasma

Esta entrada es la parte 3 de 4 en la serie Patrón de Carga Diferida

El patrón de carga diferida es una técnica para mejorar la performance utilizada en casos en que nos encontramos con que no todas las características de un programa son usadas durante su ejecución o para distribuir los tiempos de carga, cuando estos son muy grandes, durante la ejecución para poder mejorar los tiempos de respuesta al iniciar.

Hay cuatro formas comunes de implementar la carga diferida: inicialización diferida, proxy virtual, fantasma y value holder.

Ghost

Esta técnica implica la creación del recurso pero con una cantidad mínima de información y diferir el resto de la carga hasta que sea necesario.

Por ejemplo, al presentar un listado inicializamos el objeto con la información mínima para mostrar (por ejemplo un título o una descripción) y al hacer click en un ítem recién cargamos el resto del objeto para poder acceder a la información completa.

Algunas consideraciones que es necesario tener en cuenta al utilizar este patrón son:

  • Como la carga se realiza en dos tramos, puede que cuando hagamos la carga inicial el objeto esté disponible y cuando querramos obtener el resto de la información no.
  • Para que tenga sentido usar este patrón la carga mínima tiene que ser considerablemente más chica que la carga total del recurso sino el overhead por realizar dos accesos puede terminar haciendo todo el proceso menos eficiente.
function Documento(id) {
  var self = this;

  $.get('/get_preview/' + id, function (response) {
    self.title = response.title;
    self.path = response.path;
  });

  function mostrar_documento() {
    $.get('/get/' + id, function (response) {
      self.data = response.data;
      console.log(self.data);
    });
  }
}

var documentos = [
  new Documento(1),
  new Documento(3),
  new Documento(4),
];

documentos.forEach( function(e) {
  $('body').append( function(html, index) {
    var $item = $('<p><strong>' + e.id + ': ' + e.title + '</strong>');
    $item.click( this.mostrar_documento() );
  });
});

Patrón de Carga Diferida: Value Holder

Esta entrada es la parte 4 de 4 en la serie Patrón de Carga Diferida

El patrón de carga diferida es una técnica para mejorar la performance utilizada en casos en que nos encontramos con que no todas las características de un programa son usadas durante su ejecución o para distribuir los tiempos de carga, cuando estos son muy grandes, durante la ejecución para poder mejorar los tiempos de respuesta al iniciar.

Hay cuatro formas comunes de implementar la carga diferida: inicialización diferida, proxy virtual, fantasma y value holder.

Value Holder

Esta técnica implica la utilización de un objeto cuyo tiempo de carga es menor y que reemplaza al objeto original hasta que sea necesario su carga.

Por ejemplo, la utilización de una imagen con pocos colores y de muy  pequeño tamaño (un logo en escala de grises) que se utiliza en los sitios webs con muchas fotos en vez de la foto original hasta que esta es cargada.

Es necesario que el value holder esté optimizado al máximo, si termina siendo menos o igual de eficiente que cargar el objeto original el método pierde sentido.

<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">
document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  }
});

Fuente:  Lazy Loading Images and Video