¿Qué es la inicialización diferida de objetos? ¿Cómo lo haces y cuáles son las ventajas?
83
La inicialización diferida es una optimización del rendimiento en la que aplaza la creación de objetos (potencialmente costosa) hasta justo antes de que realmente la necesite.
Un buen ejemplo es no crear una conexión de base de datos por adelantado, sino solo justo antes de que necesite obtener datos de la base de datos.
La razón clave para hacer esto es que (a menudo) puede evitar crear el objeto por completo si nunca lo necesita.
Lazy
se publica en la siguiente pregunta SO: stackoverflow.com/a/15894928/4404962 esta sugerencia resolvió exactamente lo que necesitábamos resolver, usandoLazy
como principal claveComo han mencionado otros, la inicialización diferida retrasa la inicialización hasta que se utiliza un componente u objeto. Puede ver la inicialización diferida como una aplicación en tiempo de ejecución del principio YAGNI - "
You ain't gonna need it
"Las ventajas desde la perspectiva de la aplicación de la inicialización diferida son que los usuarios no tienen que pagar el tiempo de inicialización por funciones que no usarán. Suponga que debe inicializar todos los componentes de su aplicación por adelantado. Esto podría generar un tiempo de inicio potencialmente largo: los usuarios tendrían que esperar decenas de segundos o minutos antes de que la aplicación esté lista para usarse. Están esperando y pagando por la inicialización de funciones que tal vez nunca usen o no usen de inmediato.
En cambio, si pospone la inicialización de esos componentes hasta el momento de su uso, su aplicación se iniciará mucho más rápido. El usuario aún tendrá que pagar el costo de inicio cuando use otros componentes, pero ese costo se amortizará durante la ejecución del programa y no se condensará al principio, y el usuario puede asociar el tiempo de inicialización de estos objetos con las características que son. utilizando.
fuente
La inicialización diferida es el concepto de aplazar la creación de un objeto hasta que el objeto se utilice por primera vez. Si se usa correctamente, puede resultar en ganancias significativas en el rendimiento.
Personalmente, he usado Lazy Initialization al crear mi propio ORM hecho a mano en .NET 2.0. Al cargar mis colecciones desde la base de datos, los elementos reales de la colección se inicializaron de forma diferida. Esto significaba que las colecciones se creaban rápidamente, pero cada objeto se cargaba solo cuando lo necesitaba.
Si está familiarizado con el patrón Singleton, probablemente también haya visto la inicialización perezosa en acción.
public class SomeClassSingleton { private static SomeClass _instance = null; private SomeClassSingleton() { } public static SomeClass GetInstance() { if(_instance == null) _instance = new SomeClassSingleton(); return _instance; } }
En este caso, la instancia de SomeClass no se inicializa hasta que el consumidor SomeClassSingleton la necesita por primera vez.
fuente
En términos informáticos generales, "evaluación perezosa" significa diferir el procesamiento de algo hasta que realmente lo necesite. La idea principal es que a veces puede evitar operaciones costosas si resulta que no lo necesita o si el valor cambia antes de usarlo.
Un ejemplo simple de esto es System.Exception.StackTrace. Esta es una propiedad de cadena en una excepción, pero en realidad no se crea hasta que accede a ella. Internamente hace algo como:
String StackTrace{ get{ if(_stackTrace==null){ _stackTrace = buildStackTrace(); } return _stackTrace; } }
Esto le ahorra la sobrecarga de llamar a buildStackTrace hasta que alguien quiera ver qué es.
Las propiedades son una forma de proporcionar simplemente este tipo de comportamiento.
fuente
Aquí puede leer sobre la inicialización diferida con código de muestra.
fuente
La inicialización diferida de un objeto significa que su creación se pospone hasta que se utiliza por primera vez. (Para este tema, los términos inicialización diferida y creación de instancias diferida son sinónimos). La inicialización diferida se utiliza principalmente para mejorar el rendimiento, evitar cálculos innecesarios y reducir los requisitos de memoria del programa. Estos son los escenarios más comunes:
Cuando tiene un objeto que es costoso de crear y es posible que el programa no lo utilice. Por ejemplo, suponga que tiene en la memoria un objeto Cliente que tiene una propiedad Pedidos que contiene una gran variedad de objetos Pedido que, para inicializarse, requiere una conexión a la base de datos. Si el usuario nunca solicita mostrar los pedidos o utilizar los datos en un cálculo, entonces no hay razón para utilizar la memoria del sistema o los ciclos de cálculo para crearlos. Al utilizar Lazy para declarar el objeto Orders para la inicialización diferida, puede evitar el desperdicio de recursos del sistema cuando no se utiliza el objeto.
Cuando tiene un objeto que es costoso de crear y desea posponer su creación hasta que se hayan completado otras operaciones costosas. Por ejemplo, suponga que su programa carga varias instancias de objetos cuando se inicia, pero solo algunas de ellas son necesarias de inmediato. Puede mejorar el rendimiento de inicio del programa aplazando la inicialización de los objetos que no son necesarios hasta que se hayan creado los objetos necesarios.
Aunque puede escribir su propio código para realizar la inicialización diferida, le recomendamos que utilice Lazy en su lugar. Lazy y sus tipos relacionados también admiten la seguridad de subprocesos y proporcionan una política de propagación de excepciones coherente.
fuente
//Lazy instantiation delays certain tasks. //It typically improves the startup time of a C# application. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LazyLoad { class Program { static void Main(string[] args) { Lazy<MyClass> MyLazyClass = new Lazy<MyClass>(); // create lazy class Console.WriteLine("IsValueCreated = {0}",MyLazyClass.IsValueCreated); // print value to check if initialization is over MyClass sample = MyLazyClass.Value; // real value Creation Time Console.WriteLine("Length = {0}", sample.Length); // print array length Console.WriteLine("IsValueCreated = {0}", MyLazyClass.IsValueCreated); // print value to check if initialization is over Console.ReadLine(); } } class MyClass { int[] array; public MyClass() { array = new int[10]; } public int Length { get { return this.array.Length; } } } } // out put // IsValueCreated = False // Length = 10 // IsValueCreated = True
fuente
Como lo que he entendido acerca de lazy init hasta ahora, es que el programa no carga / solicita todos los datos una vez. Espera su uso antes de solicitarlo, por ejemplo. un servidor SQL.
Si tiene una base de datos con una tabla grande unida con una gran cantidad de subtablas y no necesita que los detalles se unan desde las otras tablas a menos que vaya a "editar" o "ver detalles", entonces Lazy Init. ayudará a la aplicación a ir más rápido y primero "cargar de forma diferida" los datos detallados necesarios.
En SQL o LINQ puede establecer esta "configuración" en su modelo de base de datos pr. elemento de datos.
¿Espero que esto tenga algún sentido para tu pregunta?
Un cliente web (por ejemplo, un navegador) hace lo mismo. Las imágenes se "cargan en forma diferida" después del HTML y AJAX también es una "especie de inicio diferido" si se usa correctamente.
fuente
Los ejemplos de bases de datos que se han mencionado hasta ahora son buenos, pero no se limitan solo a la capa de acceso a datos. Puede aplicar los mismos principios a cualquier situación en la que el rendimiento o la memoria puedan ser un problema. Un buen ejemplo (aunque no .NET) es Cocoa, donde puede esperar hasta que el usuario solicite una ventana para cargarla (y sus objetos asociados) desde la plumilla. Esto puede ayudar a mantener el uso de la memoria bajo y acelerar la carga inicial de la aplicación, especialmente cuando se habla de cosas como las ventanas de Preferencias que no serán necesarias hasta más adelante, si es que alguna vez lo hacen.
fuente