Descubre millones de libros electrónicos, audiolibros y mucho más con una prueba gratuita

Solo $11.99/mes después de la prueba. Puedes cancelar en cualquier momento.

Diseño de arquitecturas .NET orientadas a microservicios
Diseño de arquitecturas .NET orientadas a microservicios
Diseño de arquitecturas .NET orientadas a microservicios
Libro electrónico472 páginas4 horas

Diseño de arquitecturas .NET orientadas a microservicios

Calificación: 3 de 5 estrellas

3/5

()

Leer la vista previa

Información de este libro electrónico

La mejor arquitectura es aquella que resuelve su problema de software. Ahora, tiene a su disposición el manual con el que aprender a diseñar, de forma sencilla y autónoma, arquitecturas basadas en microservicios.

Gracias a este libro, dejará atrás los contratiempos al trabajar con monolitos, como el alto acoplamiento dentro de un mismo sistema o la baja escalabilidad al resolver con la misma arquitectura distintos problemas. Asimismo, aprenderá alternativas que le permitirán aplicar distintas soluciones a multitud de cuestiones y sabrá distinguir cuándo es mejor orientar su arquitectura a microservicios y cuándo mantener su monolito.

1.Conocerá los fundamentos de desarrollo .NET.
2.Construirá cada módulo de que se compone una arquitectura con .NET.
3.Aplicará seguridad a su arquitectura mediante la autenticación y autorización JWT.
4.Sabrá cuándo aplicar una arquitectura monolítica o una orientada a microservicios.
5.Será capaz de modelar arquitecturas limpias cumpliendo la regla de dependencia.
6.Diseñará una arquitectura de microservicios usando distintas tecnologías en cada una.
7.Aprenderá los distintos tipos de comunicación entre microservicios.

Además, tras su lectura, conseguirá emplear una arquitectura limpia que le permitirá abstrae del almacén de datos utilizado, separar responsabilidades, crear un código reutilizable y mantenible, dotar a su sistema de un nivel de seguridad basado en token JWT, aprender los patrones más utilizados, así como conocer las bondades del desarrollo .NET, entre muchas otras posibilidades.

Es el momento de dar rienda suelta a su creatividad y convertirse en el mejor arquitecto de software. Hágase con el libro, conozca los beneficios que aporta utilizar este tipo de arquitecturas y decida por sí mismo si debe o no aplicarlo.
Ramón Serrano Valero: Ingeniero Informático con un máster en Ingeniería de Desarrollo para Dispositivos Móviles y otro en Ciencia de Datos. A lo largo de sus más de 14 años de experiencia en desarrollo .NET, diseñando diferentes arquitecturas software para las distintas necesidades de los clientes y asesorando a otras empresas en la definición de arquitecturas, ha aprendido que no todas las empresas requieren una misma arquitectura y que, en ocasiones, no realizar una sobre ingeniería simplifica la solución, al evitar que crezca su complejidad más de lo necesario.
IdiomaEspañol
EditorialMarcombo
Fecha de lanzamiento12 ene 2022
ISBN9788426734471
Diseño de arquitecturas .NET orientadas a microservicios

Relacionado con Diseño de arquitecturas .NET orientadas a microservicios

Libros electrónicos relacionados

Programación para usted

Ver más

Artículos relacionados

Comentarios para Diseño de arquitecturas .NET orientadas a microservicios

Calificación: 3 de 5 estrellas
3/5

1 clasificación0 comentarios

¿Qué te pareció?

Toca para calificar

Los comentarios deben tener al menos 10 palabras

    Vista previa del libro

    Diseño de arquitecturas .NET orientadas a microservicios - Ramón Serrano Valero

    PRINCIPIOS SOLID

    Hemos ido introduciendo el concepto sin haber entrado en detalle, pero estos principios son bien conocidos y existe mucha literatura al respecto, que debemos leer. Los principios SOLID fueron una de las aportaciones del ingeniero de software Robert Cecil Martin, también conocido como Uncle Bob a la comunidad de artesanos del software, una serie de principios de diseño orientado a objetos, que todo desarrollador debería conocer y aplicar.

    Veamos una serie de ejemplos de implementación en .NET Core 5 y lenguaje C#, para llegar a entender mejor como aplicar estos principios en el mundo real.

    •SRP: Principio de responsabilidad única

    •OCP: Principio abierto/cerrado

    •LSP: Principio de sustitución Liskov

    •ISP: Principio de segregación de interfaz

    •DIP: Inversión de Dependencias

    Procede de uno de los principios de diseño orientado a objetos, basado en el desacoplamiento. En él se establece que módulos de nivel superior no deberían depender de otros de nivel inferior, sino que ambos deberían depender de abstracciones, es lo que se conoce como bajo acoplamiento, cuanto menor, mejor.

    Dicho de otro modo, las clases deberían desentenderse de la implementación concreta de una clase. ¿Cómo? Sirviéndose de abstracciones o interfaces haciendo uso de la inyección de dependencias.

    Esta definición en la teoría queda genial; sin embargo, hasta que no veamos un ejemplo práctico, costará comprenderlo.

    S: Principio de responsabilidad única (SRP)

    Es el primer principio de SOLID, en el que se defiende que una clase únicamente debe representar una única responsabilidad; para Robert C. Martin: Una clase únicamente debe tener una razón para cambiar.

    Es decir, no deberíamos tener una clase que realiza más de una acción, ¿cómo podemos lograr no infringir este principio?

    •Cuando encontremos más de un método público en la misma clase, es muy probable que dicha clase tenga más de una responsabilidad.

    •Cuando existan varios atributos de una clase en el que unos pocos siempre sean utilizados por una clase y el resto por otra distinta, esto implica que dicha clase podría haberse dividido en otras dos, separando responsabilidades.

    •Dificultad de testing sobre el método de una clase, puede causar que el método deba segmentarse.

    Una vez consigamos separar por responsabilidades, nuestro código incrementará la reutilización, pudiendo invocar desde múltiples servicios estas funcionalidades.

    Al tener clases más pequeñas, que únicamente realizan una responsabilidad, conseguimos reducir la duplicidad del código y ganamos en legibilidad, ¿no es genial?

    Veamos un ejemplo donde se infringe este principio [S5.3]; Tenemos una clase llamada UserRepositorySrpViolation, que podemos observar en la línea 5 del código. Esta clase posee dos métodos públicos, uno para registrar el usuario y otro método para enviar un email de bienvenida al usuario que se acaba de registrar.

    De modo que, tras registrar el usuario de manera satisfactoria en la base de datos, automáticamente se envía un email.

    Illustration

    Figura S5.3

    Illustration

    Figura S5.3.a

    Al disponer de dos métodos públicos en la misma clase, tenemos dos puntos de entrada a la clase y por tanto dos posibles responsabilidades, ello conduce al incumplimiento del principio [S5.3.a]. Pero…entonces… ¿existe alguna manera de evitar esto?

    La respuesta, como no podía ser de otra manera, es sí. Simplemente intentemos separar [S5.4] de la clase UserRepository el método que no pertenece al propio dominio de usuario, es decir, el envío de email SendWelcomeMessageToMail.

    Illustration

    Figura S5.4

    Para ello creamos una nueva clase notificadora de emails EmailSenderWelcomeMessage, que seguirá teniendo el mismo método antiguo de envío de emails.

    Posteriormente, en la clase UserRepository inyectamos la clase notificadora de emails que acabamos de crear a través de su constructor; de esta forma, podremos invocar el método de la instancia _emailSenderWelcomeMessage, por lo que seguiremos enviando el mismo email tras el registro de usuario.

    Illustration

    Figura S5.4.a

    Con esto hemos conseguido que UserRepository [S5.4.a] tenga una cohesión más alta y con una única responsabilidad. Por lo que ganamos en desacoplamiento.

    ¿Y cuál es la diferencia? La diferencia principal es que ahora ambas clases tienen una única responsabilidad, la clase repositorio de usuario únicamente posee un método de entrada y la clase envío de email también, con lo cual ganamos en legibilidad, testeo y reutilización, es decir, ambas clases tienen que hacer lo que han de hacer y nada más.

    Pero podemos ir un paso más allá y ganar en modularidad, la posibilidad de que varias clases puedan implementar el mismo método que defina su interfaz [S5.5].

    Illustration

    Figura S5.5

    Para ello, creamos una interfaz ISender, que implemente un método SendTo, así como dos clases SendWelcomeMessageByPushNotification, que envía una notificación push al móvil y SendWelcomeMessageByEmail, que envía un email al usuario registrado.

    Ambas clases implementan la interfaz ISender, lo cual nos permite ganar en modularidad y que podamos crear tantos tipos de mensajería como queramos, ya que cada clase implementará su forma de comunicación.

    Ahora ya únicamente en la clase UserRepositoryModular recibiremos por parámetro en el constructor una clase que implemente dicha interfaz, con lo cual, si le proporcionásemos la clase de envío de emails, la línea 17 de UserRepositoryModular, implementaría el envío definido en la clase SendWelcomeMessageByEmail; no obstante, si por el contrario, se inyectase la clase de notificaciones push, la línea 17, implementaría el envío push mediante el método SendTo. ¿Increíble las ventajas que puede traernos la modularidad?

    O: Principio abierto/cerrado (OCP)

    Este principio establece que nuestras clases deben ser abiertas para extensión, pero cerradas para modificación.

    Uno de los principales motivos es no romper aquello que ya funcionaba, por el simple hecho de haber introducido una nueva funcionalidad o simplemente cambio sobre la clase en cuestión.

    No cumplir este principio puede hacer que nuestro equipo de desarrollo entre en bucle de regresión tratando de probar casos de uso que con anterioridad al cambio las pruebas pasaban y posteriormente debemos volver a probarlas.

    Para no infringir este principio, la clave es evitar la dependencia de concreciones, es decir, clases concretas, abstraernos de su implementación. No modificar una clase ya implementada, se debe hacer extensible mediante la herencia, empleando para ello abstracciones como clases abstractas o interfaces.

    En otras palabras, no dependa en la implementación del método de una clase, de un tipo en concreto, dado que, si un día cambia su tipo o simplemente incorporamos uno nuevo, nos veríamos obligados a introducir múltiples condicionales if else o un switch case y, por tanto, estaríamos modificando la implementación del método incumpliendo el principio.

    Si conseguimos desarrollar desacoplando los métodos de la clase, de una implementación concreta, podremos incorporar nuevos casos de uso al extender su funcionalidad.

    Veamos con un ejemplo cómo se incumple este principio [S5.6]; disponemos de una tienda virtual, representada por la clase VirtualShop, que vende productos, inicialmente únicamente vendía bicicletas, representada por la clase BikePriceCalculator, de modo que se implementó proporcionando la concreción BikePriceCalculator como parámetro del método, para posteriormente realizar el cálculo del IVA del producto en sí, invocando su método CalculatePrice().

    Illustration

    Figura S5.6

    Posteriormente, la tienda virtual creció y vendía también otros productos como neumáticos para bicicletas, así que decidió crear un producto nuevo, WheelPriceCalculator [S5.7], para tal propósito.

    Illustration

    Figura S5.7

    Sin embargo, para que la clase VirtualShop pudiera calcular el nuevo precio del producto, al haber dependido de la concreción del producto bicicleta, nos vemos obligados a modificar dicho método porque no es capaz el método CalculateProductPrice de extender la funcionalidad para incorporar el nuevo producto sin modificar el método.

    Para solucionar el problema debemos depender de interfaces o clases abstractas, de modo que modifiquemos la clase de tienda virtual VirtualShopOCP para que sea abierta a extensión [S5.8].

    Para ello creamos la interfaz IShopProduct, declarando el método público de cálculo de precio. Posteriormente, las clases que teníamos de BikePriceCalculatorOCP, clase del producto bici y WheelPriceCalculatorOCP, clase del producto neumático, haremos que implementen ambos el método de la interfaz IShopProduct.

    Por último, cambiamos el parámetro de entrada del método de cálculo, CalculateProductPrice, que emplea la tienda, por una clase que cumpla la interfaz.

    Illustration

    Figura S5.8

    De esta forma, si un día queremos incorporar un nuevo producto para calcular su precio en tienda, bastará con crear una nueva clase para el nuevo tipo de producto, que implemente la interfaz IShopProduct. Con esto conseguimos que nuestra clase esté abierta a

    ¿Disfrutas la vista previa?
    Página 1 de 1