Está en la página 1de 9

Inyección de Dependencias (DI) en ASP.

NET Core, mejores


prácticas para escribir código reutilizable, escalable y
desacoplado
Los Desarrolladores de Software siempre estamos en busca de una forma
reutilizable para resolver un problema común y para lograrlo es necesario recurrir a
estándares como lo son los patrones de diseño de Software. Antonio Leiva define un
patrón de diseño como una forma de solucionar un problema que se puede extraer,
explicar y reutilizar en múltiples ámbitos.
Inyección de Dependencias es un patrón de diseño de software que nos permite
desarrollar componentes acoplados libremente o desacoplados para obtener como
resultado la fácil gestión de cambios a futuro, implementación fácil de pruebas
unitarias, factoría para emitir instancias de clases, prevención de fugas de memoria,
entre otros.
DI proporciona un mecanismo para la construcción de gráficos de dependencia
independientes de las definiciones de clase, aplicando esta técnica nuestras clases
van a depender de interfaces y no de implementaciones, esto se relaciona
directamente con el primero de los 5 principios para desarrollar software de calidad,
haciendo referencia a SOLID y el principio de responsabilidad única.
Por su parte ASP.NET Core nos permite la utilización del patrón de diseño Inyección
de Dependencias sin la necesidad de utilizar librerías de terceros para lograrlo,
además ASP.NET Core provee un Contenedor de Inversión de Controles (IoC)
quien es el encargado de proveer las instancias de los tipos los cuales le decimos
en el inicio de la Aplicación (Startup).
Para este post utilizaremos un proyecto WebApi de .NET Core 3.0, utilizaré los
mismos modelos, base de datos en memoria y estructura del proyecto de mi post
anterior titulado Base de Datos en memoria con ASP.NET Core 3.0 MVC + Entity
Framework Core.

Vamos a Visual Studio Comunity 2019.


Inicialmente visualizamos el archivo HomeController.cs, este código utiliza un
servicio para mostrar un listado de Albumes y su relación con Artista, mediante
Entity Framework Core. Por el momento no estamos pensando en inyección de
dependencias.
El servicio utiliza el Contexto de Datos para traer el listado de la Base de Datos.
La clase contexto WebApiDbContext posee una sobreescritura del método
OnConfiguring para enviarle la configuración de la base de datos en memoria y el
método constructor está sobrecargado.
El resultado es el siguiente:

Analicemos el código anterior, como punto principal vemos que funciona, pero
nuestro controlador crea y depende directamente de la instancia de la clase
AlbumesService, las dependencias de código son problemáticas y deben evitarse,
¿por qué? supongamos que queremos reemplazar la implementación de
AlbumesService, debería modificar el controlador también y esto en un proyecto
grande representa problemas porque puede que olvide modificar diferentes
controladores que utilicen el mismo servicio y el funcionamiento del sistema seria
inconsistente. Un problema más en este código podría ser que si AlbumesService
tuviera alguna dependencia esta debe ser configurada en el controlador o clase que
utilice el servicio de Albumes. Por otra parte, esta implementación como se
encuentra en este momento dificultaría la realización de pruebas unitarias debido a
que sería difícil probar componentes que no están desacoplados y no hay manera
de pasarle un servicio fake porque se está utilizando el servicio de forma explícita
como una instancia directa.

Ahora abordemos la problemática y solucionemos mediante


Inyección de Dependencias.
Pensemos en Inyección de Dependencias, como primer paso debemos utilizar una
interface que nos permita abstraer la implementación de dependencias, vamos a
relacionarla con el servicio Albumes.

El siguiente paso es decirle al servicio de Albumes que implemente la interface


IAlbumesService.
Ahora debemos registrar el servicio en el Contenedor de servicios integrados
IServiceProvider que nos proporciona ASP.NET Core, los servicios son registrados
en el método ConfigureServices de la clase Startup de la aplicación, una vez
definido el servicio debemos registrarlo.

Observemos que para este escenario estamos utilizado el método AddTransient


para indicar la interface para el servicio y su implementación, esto hace referencia al
ciclo de vida de los servicios que viven en el contenedor. Dentro del contenedor que
nos provee ASP.NET Core existen 3 ciclos de vida básicos los cuales podemos
utilizar para inicializar las dependencias desde nuestro contenedor.
 Transient: Se crean cada vez que se solicitan desde el contenedor de
servicios. Esta vida útil funciona mejor para servicios ligeros y sin estado.
 Scoped: Se crean una vez por solicitud del cliente (conexión). Se utiliza
cuando queremos servir la misma instancia dentro del mismo contexto de una
petición HTTP, pero diferente entre distintos contextos HTTP.
 Singleton: Se crean la primera vez que se solicitan o cuando Startup.
ConfigureServices se ejecuta y se especifica una instancia con el registro
del servicio. Cada solicitud posterior utiliza la misma instancia.
Para el paso anterior hay otra alternativa por la que podemos optar, personalmente
me gusta la siguiente alternativa que nos recomienda Microsoft, consiste en separar
todos los servicios en una clase static dentro de un método que recibe como
parámetro el IServiceCollection y lo retorna con los servicios ya registrados y
unificados para después inyectar todo en el método ConfigureServices, creamos
una carpeta llamada Middleware este nombre es arbitrario y dentro una clase
llamada IoC que hace referencia al Contenedor de Inversión de Control.

Ahora invocamos el método AddDependency en el método ConfigureServices en


la clase Startup.cs

Seguidamente vamos al controlador a cambiar esa instancia explicita que teníamos


con AlbumesService y la modificaremos pensando en inyectar dependencias,
observemos que ahora en lugar de instanciar AlbumesService tenemos una
propiedad de lectura que además es una interface IAlbumesService y en ningún
momento la inicializamos nosotros, inyectamos la dependencia en el método
constructor y quien se encarga de instanciar el servicio es el contenedor, he aquí la
razón de agregar las dependencias en el método ConfigureServices de la clase
Startup.
Ahora compilamos, ejecutamos y vamos a la ruta de nuestro WebApi desde
Postman y podemos observar que este código funciona, el resultado es el mismo
cierto, pero en el estado actual en el que se encuentra nuestro código es mejor,
debido a que abordamos las problemáticas anteriormente mencionadas.

En conclusión la técnica de Inyección de Dependencias nos ayuda a escribir código


reutilizable debido a que el servicio no se instancia en ningún controlador ni en otra
clase que lo utiliza podemos reutilizarlo en N cantidad de controladores y clases que
necesitemos, ya que la lógica está encapsulada dentro de un servicio, además es
escalable y mantenible, podemos modificar la lógica del servicio sin afectar otras
partes de nuestro sistema y evitar inconsistencias lógicas, además el código está
desacoplado por lo que fácilmente podemos comprobar el correcto funcionamiento
de un fragmento de código en específico.
Link al repositorio en GitHub:
https://github.com/EbarriosCode/DependencyInjectionDotNetCore3.0

También podría gustarte