Monday, October 28, 2024

Técnicas Avanzadas de Manejo de Excepciones

En aplicaciones modernas y empresariales, el manejo básico de excepciones no siempre es suficiente para gestionar situaciones complejas, como la integración de múltiples servicios o la necesidad de mantener la estabilidad en sistemas distribuidos. Este capítulo presenta técnicas avanzadas de manejo de excepciones, incluyendo la creación de excepciones personalizadas, el encadenamiento de excepciones con InnerException, y patrones avanzados como Retry, Circuit Breaker, y el uso eficiente de herramientas de logging.

5.1 Creación de Excepciones Personalizadas

El uso de excepciones personalizadas es útil cuando necesitas representar errores específicos del dominio de tu aplicación. En lugar de utilizar excepciones genéricas, crear una excepción personalizada mejora la legibilidad del código y proporciona más contexto al manejar errores en situaciones concretas.

Ejemplo de Excepción Personalizada:

Uso de la Excepción:

Las excepciones personalizadas te permiten capturar y comunicar errores que están directamente relacionados con la lógica del negocio, lo que facilita la depuración y el mantenimiento.

5.2 Encadenamiento de Excepciones con InnerException

El encadenamiento de excepciones con InnerException permite conservar el contexto original de un error mientras se lanza una nueva excepción en niveles superiores. Esto es útil cuando quieres proporcionar más información sobre el fallo en una capa superior sin perder detalles sobre la excepción original.

Ejemplo:

Cuando capturas la excepción en una capa superior, puedes acceder a InnerException para obtener detalles del error original:

Este enfoque proporciona un contexto completo del error, lo que facilita la depuración en sistemas complejos con múltiples capas de abstracción.

5.3 Patrón Retry (Reintento)

El patrón Retry es útil para manejar errores transitorios, como fallos en la red o en la base de datos. En lugar de fallar inmediatamente, el sistema intenta repetir la operación varias veces antes de darla por fallida.

Ejemplo de Implementación de Retry:

5.4 Uso de Librerías para Reintentos

Librerías como Polly en .NET facilitan la implementación de políticas avanzadas para reintentos y retrocesos exponenciales. Polly permite definir políticas reutilizables para manejar fallos comunes de manera eficiente.

Ejemplo con Polly:

5.5 Patrón Circuit Breaker

El patrón Circuit Breaker es útil para prevenir que un sistema siga intentando operaciones fallidas repetidamente, lo que podría sobrecargar un servicio o recurso. Este patrón desactiva temporalmente las llamadas a un servicio después de varios fallos consecutivos, dándole tiempo para recuperarse.

Ejemplo de Polly con Circuit Breaker:

El Circuit Breaker asegura que no se sobrecargue un sistema o recurso cuando ocurren fallos repetidos.

5.6 Logging Detallado y Análisis

El registro detallado de excepciones es crítico en sistemas empresariales y distribuidos. Utilizar herramientas de logging como Serilog o NLog te permite capturar detalles sobre excepciones en diferentes capas del sistema, facilitando la resolución de problemas.

Ejemplo con Serilog:

El registro adecuado de excepciones proporciona visibilidad de los errores, especialmente en sistemas distribuidos donde el problema puede no estar localizado en un solo componente.

5.7 Manejo de Excepciones en Código Asíncrono

En entornos asíncronos, el manejo de excepciones puede ser más complejo debido al uso de async y await. Es crucial capturar las excepciones que ocurren dentro de las operaciones asíncronas para evitar que la aplicación falle sin advertencia.

Ejemplo de Manejo Asíncrono:

El uso de await permite capturar excepciones dentro de las operaciones asíncronas de manera similar a las operaciones sincrónicas, asegurando que cualquier error sea gestionado correctamente.


5.8 Conclusión

Las técnicas avanzadas de manejo de excepciones permiten que las aplicaciones sean más robustas, escalables y mantenibles. Desde el uso de excepciones personalizadas hasta la implementación de patrones como Retry y Circuit Breaker, estas técnicas aseguran que los sistemas puedan manejar errores de manera eficaz sin comprometer la estabilidad. Además, el uso de herramientas de logging y el manejo adecuado de excepciones asíncronas son esenciales para identificar y resolver problemas en tiempo real en entornos empresariales complejos.

Sunday, October 27, 2024

Errores Comunes en el Manejo de Excepciones

El manejo de excepciones es una práctica esencial para asegurar la estabilidad y resiliencia de una aplicación, pero su implementación incorrecta puede llevar a problemas de rendimiento, complejidad en el código y dificultades en el mantenimiento. Este capítulo analiza algunos de los errores más comunes en el manejo de excepciones y cómo evitarlos para mejorar la calidad y eficacia de las aplicaciones.

4.1 Uso Excesivo de Excepciones para el Flujo de Control

Uno de los errores más comunes es utilizar excepciones para controlar el flujo lógico de un programa, en lugar de emplearlas solo para errores inesperados. Esto ocurre cuando los desarrolladores lanzan excepciones en lugar de emplear condiciones y verificaciones previas para validar el estado.

Ejemplo Incorrecto:

Mejor Práctica: Usar condiciones de control en lugar de excepciones para situaciones predecibles.

4.2 Captura de Excepciones Demasiado Generales

Capturar excepciones usando bloques catch demasiado generales (catch (Exception ex)) puede hacer que el código capture errores inesperados, ocultando posibles problemas y dificultando la depuración.

Ejemplo Incorrecto:

Mejor Práctica: Capturar excepciones específicas siempre que sea posible, para gestionar cada tipo de error de manera adecuada.

4.3 Ignorar Excepciones sin Registrar o Notificar

Ignorar excepciones en el código sin registrar el error ni notificar al usuario puede llevar a que el programa falle sin una explicación, y a que los desarrolladores no tengan visibilidad de lo que ocurrió.

Ejemplo Incorrecto:

Mejor Práctica: Registrar las excepciones y, si es relevante para el usuario, mostrar un mensaje de error amigable.

4.4 No Liberar Recursos en el Bloque finally

Es común que los recursos, como conexiones a bases de datos, archivos o memoria, no se liberen adecuadamente si ocurre una excepción. Esto puede llevar a fugas de recursos y problemas de rendimiento.

Ejemplo Incorrecto:

Mejor Práctica: Usar el bloque finally o estructuras using en C# para garantizar que los recursos se liberen.

4.5 No Lanzar Excepciones Específicas o Útiles

Lanzar excepciones genéricas, como Exception, dificulta el diagnóstico de errores, ya que no proporciona información detallada sobre la causa específica del problema.

Ejemplo Incorrecto:

Mejor Práctica: Lanzar excepciones específicas, como ArgumentOutOfRangeException, que proporcionen más contexto sobre el error.

5.6 Uso Inapropiado de Excepciones Personalizadas

Crear excepciones personalizadas innecesariamente puede incrementar la complejidad del código y hacer que el manejo de errores sea más difícil de entender y mantener. Las excepciones personalizadas solo deberían usarse cuando el problema es específico de la aplicación y no puede ser cubierto adecuadamente por una excepción existente en .NET.

Ejemplo Incorrecto:

Mejor Práctica: Usar excepciones personalizadas solo cuando aporten valor adicional, como información contextual específica o soluciones específicas de la aplicación.

5.7 Ignorar la Propiedad InnerException

Cuando se manejan excepciones que se derivan de otros errores, es común que los desarrolladores ignoren la propiedad InnerException. Esto hace que se pierda información valiosa sobre el error original que desencadenó la excepción.

Mejor Práctica: Siempre verificar InnerException para obtener el contexto completo de la excepción.

5.8 Conclusión

El manejo de excepciones efectivo es crucial para la estabilidad de una aplicación. Evitar estos errores comunes y aplicar buenas prácticas ayuda a los desarrolladores a mejorar el rendimiento y la claridad de su código, garantizando que las excepciones se gestionen de manera apropiada y que el programa sea más fácil de mantener y depurar. Con estas bases sólidas, los desarrolladores pueden abordar técnicas avanzadas de manejo de excepciones en los capítulos siguientes.

Comprendiendo las Excepciones

Para manejar las excepciones de manera efectiva, es esencial comprender a fondo qué son, cómo funcionan y cómo se diferencian de otros tipos de errores. Las excepciones en C# son eventos imprevistos que pueden interrumpir el flujo normal de un programa y ocurren cuando se presentan situaciones anormales en tiempo de ejecución. Este capítulo se centra en explicar cómo funcionan las excepciones en C# y cómo el lenguaje facilita su manejo para construir aplicaciones más robustas.

3.1 ¿Qué es una Excepción?

En términos simples, una excepción es una condición que surge cuando el programa encuentra un error o situación que no puede gestionar automáticamente. Las excepciones son clases que heredan de la clase base Exception en C#, lo que les permite contener información detallada sobre el error, como el tipo de excepción, el mensaje de error y una traza de pila.

Las excepciones en C# permiten que el flujo del programa se transfiera a bloques de código específicos para manejar el problema de manera controlada, en lugar de que el programa falle abruptamente.

3.2 Jerarquía de Excepciones en C#

La clase Exception en C# es la clase base de todas las excepciones, y muchas otras excepciones derivan de ella. Conocer la jerarquía de excepciones ayuda a identificar y manejar los errores de manera más precisa y específica.

  • System.Exception: Clase base de todas las excepciones en .NET.
    • System.SystemException: Clase base de excepciones lanzadas por el sistema.
      • System.NullReferenceException: Ocurre cuando se intenta acceder a un objeto nulo.
      • System.IndexOutOfRangeException: Generada cuando un índice está fuera de los límites de una colección.
      • System.InvalidOperationException: Señala que una operación no es válida en el estado actual del objeto.

Las excepciones personalizadas también se pueden definir heredando de Exception, lo que permite a los desarrolladores manejar situaciones específicas de sus aplicaciones.




3.3 Propiedades de una Excepción

Cada excepción en C# contiene propiedades que proporcionan información útil sobre el error:

  • Message: Contiene un mensaje descriptivo sobre el error.
  • StackTrace: Proporciona una traza de pila del error, indicando el punto exacto donde ocurrió la excepción.
  • InnerException: Permite encapsular excepciones dentro de otras, útil para rastrear errores complejos.
  • Source: Informa sobre el origen de la excepción en el código.

Ejemplo de uso de propiedades:

3.4 Tipos Comunes de Excepciones en C#

Entender los tipos de excepciones más comunes en C# permite anticiparse a errores frecuentes y diseñar soluciones de manejo adecuadas:

  • NullReferenceException: Ocurre cuando se intenta acceder a un miembro de un objeto que es null.
  • FormatException: Lanzada cuando una conversión de tipo no es válida (por ejemplo, intentar convertir un string a número).
  • InvalidOperationException: Señala que la operación no es válida en el contexto actual.
  • DivideByZeroException: Ocurre cuando se intenta dividir un número entre cero.

Cada tipo de excepción proporciona información específica, facilitando a los desarrolladores la creación de bloques catch específicos para manejar cada situación.

3.5 Excepciones Personalizadas

En muchos casos, las excepciones estándar no son suficientes para cubrir necesidades específicas de una aplicación. Crear excepciones personalizadas permite manejar escenarios propios del negocio o de la lógica de la aplicación. Para definir una excepción personalizada, se crea una nueva clase que hereda de Exception.

Ejemplo de excepción personalizada en C#:

Luego, esta excepción personalizada puede lanzarse y capturarse en el código como cualquier otra:

Las excepciones permiten mejorar la legibilidad del código al separar la lógica de manejo de errores del flujo principal, y además:

  • Facilitan la depuración y el mantenimiento.
  • Permiten centralizar el manejo de errores, proporcionando una única fuente de control para errores específicos.
  • Hacen que el código sea más resiliente al permitir que el programa continúe su ejecución después de manejar el error adecuadamente.

3.7 Buenas Prácticas en el Manejo de Excepciones

  • Evitar el uso excesivo de excepciones: Usar excepciones solo para situaciones excepcionales y no como parte del flujo normal del programa.
  • Especificidad en el manejo de excepciones: Capturar excepciones específicas siempre que sea posible, en lugar de capturar todas las excepciones genéricas.
  • Usar finally para liberar recursos: El bloque finally permite limpiar recursos como archivos o conexiones de red, asegurando que se liberen correctamente independientemente de si ocurrió una excepción.

3.8 Conclusión

Las excepciones en C# proporcionan una manera eficaz de manejar errores de tiempo de ejecución. Este capítulo explicó la naturaleza de las excepciones, su jerarquía y cómo implementar excepciones personalizadas para escenarios específicos. Con una base sólida en el funcionamiento de las excepciones, los desarrolladores pueden aplicar técnicas más avanzadas de manejo de errores para mejorar la estabilidad y la robustez de sus aplicaciones.

Saturday, October 26, 2024

Tipos de Errores

El manejo de errores en programación es crucial para construir aplicaciones robustas y confiables. Entender los distintos tipos de errores que pueden surgir ayuda a los desarrolladores a anticiparse y aplicar estrategias adecuadas para prevenirlos o gestionarlos. En C# y en otros lenguajes, los errores se pueden categorizar principalmente en errores de sintaxis, errores de tiempo de ejecución y errores lógicos. Cada uno tiene sus propias características y métodos de resolución.

2.1 Errores de Sintaxis

Los errores de sintaxis son aquellos que ocurren cuando el código escrito no cumple con las reglas gramaticales del lenguaje de programación. Estos errores son detectados por el compilador o el entorno de desarrollo antes de que el programa se ejecute. Por ejemplo, en C#, omitir un punto y coma (;) al final de una línea de código o utilizar un nombre de variable no válido generará un error de sintaxis.

Ejemplo de error de sintaxis en C#:

Para evitar errores de sintaxis, es importante seguir las reglas de sintaxis del lenguaje y utilizar herramientas de desarrollo que resaltan los errores automáticamente.

2.2 Errores de Tiempo de Ejecución

Los errores de tiempo de ejecución son aquellos que no se detectan durante la compilación, sino que ocurren mientras el programa se está ejecutando. Estos errores pueden ser el resultado de condiciones inesperadas, como intentar dividir por cero, acceder a un índice fuera de los límites de una matriz o intentar leer un archivo inexistente. Las excepciones en C# permiten gestionar estos errores de forma controlada, evitando que el programa se detenga abruptamente.

Ejemplo de error de tiempo de ejecución en C#:

Para manejar estos errores, los desarrolladores pueden usar bloques try-catch que capturan la excepción y permiten ejecutar acciones específicas, como mostrar un mensaje de error al usuario o intentar una operación alternativa.

2.3 Errores Lógicos

Los errores lógicos ocurren cuando el programa compila y se ejecuta sin problemas, pero los resultados obtenidos no son los esperados debido a una falla en la lógica del código. Estos errores son difíciles de detectar, ya que el compilador o el entorno de ejecución no pueden identificarlos automáticamente. En muchos casos, los errores lógicos ocurren debido a errores en el flujo de control, condiciones incorrectas o cálculos mal implementados.

Ejemplo de error lógico en C#:

Para evitar errores lógicos, es esencial revisar cuidadosamente la lógica del código, realizar pruebas exhaustivas y, cuando sea posible, implementar pruebas unitarias que validen el comportamiento esperado del programa.

2.4 Otros Tipos de Errores

Además de los tres tipos principales, existen otros errores específicos que también pueden afectar la estabilidad de una aplicación:

  • Errores de Concurrencia: Surgen en aplicaciones multihilo donde dos o más hilos intentan acceder a los mismos recursos de forma simultánea, lo que puede causar inconsistencias.
  • Errores de Memoria: Pueden ocurrir cuando hay fugas de memoria o cuando un programa intenta acceder a una región de memoria no permitida.
  • Errores de Comunicación: Son comunes en aplicaciones distribuidas donde pueden fallar las conexiones de red, los tiempos de respuesta de los servidores, entre otros.

2.5 Conclusión

Comprender los distintos tipos de errores permite a los desarrolladores aplicar prácticas de programación y técnicas de manejo de excepciones adecuadas en cada caso. Al identificar y categorizar los errores de manera correcta, se pueden reducir los problemas durante el desarrollo y mejorar la calidad del software final. Este conocimiento es clave para el resto de los capítulos, donde exploraremos técnicas específicas para manejar cada tipo de error y garantizar que el programa funcione de forma segura y predecible.

Este capítulo establece la base para manejar distintos tipos de errores y proporciona una perspectiva sobre la importancia de categorizarlos y prevenirlos para un desarrollo más robusto.

Friday, October 25, 2024

Introducción al manejo de excepciones en C#

El manejo de excepciones es un pilar fundamental en el desarrollo de software robusto y confiable, especialmente en aplicaciones empresariales y sistemas críticos. En C# y el ecosistema .NET, el manejo de excepciones permite a los desarrolladores anticiparse a los errores en tiempo de ejecución y controlarlos de forma que el sistema pueda seguir funcionando sin interrupciones abruptas o fallas inesperadas. A través de este introbook, "Manejo de Excepciones en C#", se exploran en profundidad los conceptos, técnicas y buenas prácticas para gestionar errores de manera eficaz y profesional.

¿Por qué es importante el manejo de excepciones?

En el contexto de .NET y C#, las excepciones son eventos imprevistos que ocurren durante la ejecución de un programa, como intentos de acceso a recursos no disponibles, errores de lógica o problemas de comunicación en aplicaciones distribuidas. Sin un manejo adecuado, estos problemas pueden resultar en bloqueos de la aplicación o pérdida de datos. Un manejo efectivo de excepciones no solo garantiza que el programa maneje estos fallos de forma controlada, sino que también mejora la experiencia del usuario y facilita el mantenimiento del código. Ejemplo: Imagínese un programa que intenta leer un archivo. Si el archivo no existe, en lugar de permitir que el programa se detenga bruscamente, el manejo de excepciones permite al sistema capturar este error y notificar al usuario que el archivo no fue encontrado.

Este introbook ofrece una guía estructurada para los desarrolladores, abordando desde los fundamentos del manejo de excepciones hasta técnicas avanzadas y estrategias de prevención. Cada capítulo contiene ejemplos de código en C# que ilustran los conceptos clave, permitiendo al lector ver cómo aplicar las prácticas recomendadas directamente en sus proyectos .NET.

¿Qué aprenderás en este introbook?

En el transcurso de los capítulos, exploraremos los siguientes temas:

  • Conceptos básicos de excepciones y errores: qué son, cómo se generan y qué estructuras de código se utilizan para controlarlos.
  • Errores comunes y cómo evitarlos: prácticas que suelen ser problemáticas y cómo un diseño adecuado puede evitarlas.
  • Técnicas avanzadas: métodos para personalizar la gestión de excepciones, como la creación de excepciones personalizadas y el encadenamiento de errores.
  • Depuración y registro de errores: estrategias para rastrear y registrar errores, facilitando el diagnóstico y solución de problemas.
  • Prevención de errores: prácticas de código de alta calidad que minimizan la aparición de excepciones y problemas en producción.

Público objetivo

Este introbook está diseñado para desarrolladores de nivel intermedio a avanzado en C# y .NET que buscan profundizar en el manejo de excepciones. También es útil para ingenieros de software interesados en mejorar la estabilidad y robustez de sus aplicaciones mediante prácticas efectivas de control de errores.

Cómo utilizar este introbook

Cada capítulo está estructurado para que pueda leerse de manera secuencial o consultarse de forma independiente según las necesidades del lector. Los ejemplos de código en C# están diseñados para ser prácticos y reutilizables, permitiendo que el lector los adapte a sus propios proyectos. Además, se incluyen consejos y trucos para mejorar la calidad del código y promover un enfoque preventivo en lugar de reactivo al manejo de errores.

Exception Handling Dealing with Errors - Sunil Kumar Saini


Guide to the Software Engineering Body of Knowledge v4.0

 

Monday, October 14, 2024

Servidores de configuración

Sesión 6: 1h30m

Recomendaciones para implementar SAGA

Sesión 5: 4h37m30s

Tenga en cuenta los puntos siguientes al implementar el patrón de saga:

  • El patrón de saga inicialmente puede ser desafiante, ya que requiere una neuva forma de pensar sobre cómo coordinar una transacción y mantener la coherencia de los datos para un proceso empresarial que abarque varios microservicios.
  • El patrón de saga es especialmente difícil de depurar y la complejidad crece a medida que los participantes aumentan.
  • NO SE PUEDEN REVERTIR LOS DATOS porque los participantes de la saga confirman los cambios en sus bases de datos locales.
  • La implementación debe ser capaz de controlar un conjunto de posibles errores transitorios y proporcionar idempotencia para reducir los efectos secundarios y garantizar la coherencia de los datos. La idempotencia significa que la misma operación se puede repetir varias veces sin cambiar el resultado inicial.
  • Es mejor implementar la observabilidad para supervisar y realizar un seguimiento del flujo de trabajo de la saga.
  • La falta de aislamiento de los datos de los participantes impone desafíos de durabilidad. La implementación de la saga debe incluir contramedidas para reducir las anomalías.

Pueden producirse las siguientes anomalías si no se toman las medidas adecuadas:
  • Pérdida de actualizaciones, cuando un patrón de saga escribe sin leer los cambios realizados por otro patrón de saga.
  • Lecturas de datos sucios, cuando una transación o una saga lee las actualizaciones realizadas por una saga que todavía no ha completado dichas actualizaciones.
  • Lecturas aproximadas/no repetibles, cuando diferentes pasos de la saga leen datos diferentes porque se produce una actualización de datos entre las lecturas.
Entre las contramedidas sugeridas para reducir o evitar anomalías se incluyen:
  • El bloqueo semántico, un bloqueo de nivel de aplicaicón en el que una transacción de compensable de una saga utiliza un semáforo para indiciar que hay una actualización en curso.
  • Las actualizaciones conmutativas que se pueden ejecutar en cualquier orden y generar el mismo resultado.
  • Visión pesimista, es posible que una saga lea datos sucios mientras otra saga ejecuta una transacción compensable para revertir la operación. La visión pesimista reordena la saga para que los datos subyacentes se actualicen en una transacción reintentable, lo que elimina la posibilidad de una lectura de datos sucios.
  • El valor de relectura comprueba que los datos no se hayan modificado y, a continuación, actualiza el registro. Si el registro ha cambiado, los pasos se anulan y la saga puede reiniciarse.
  • Un archivo de versión registra las operaciones en un registro a medida que llegan y las ejecuta en el orden correcto.
  • Por valor usa el riesgo empresarial de cada solicitud para seleccionar dinámicamente el mecanismo de simulataneidad. Las solicitudes de bajo riesgo favorecen a las sagas, mientras que las solicitudes de alto riesgo favorencen a las trancciones distribuidas.
Cuando usar SAGA
  • Use el patrón de SAGA cuando necesite:
    • Garantizar la coherencia de los datos en un sistema distribuido sin acoplamiento estricto.
    • Revertir o compensar si se produce un error en una de las operaciones de la secuencia.
  • El patrón de saga es menos adecuado para:
    • Transacciones estrechamente acopladas
    • Transacciones de compensación que se producen en participantes anteriores.
    • Dependencias cíciclicas.

Thursday, October 10, 2024

¿Por qué es tan demandado el perfil de Full Stack Developer?


El perfil de Full-Stack Developer ha ganado una gran popularidad en los últimos años, y con justa razón. Las empresas valoran a los desarrolladores que tienen la capacidad de gestionar tanto el front-end (interfaz de usuario) como el back-end (lógica del servidor y bases de datos). Sin embargo, aunque este perfil es altamente demandado, también conlleva ciertos desafíos que conviene analizar. A continuación, exploramos tanto las ventajas que hacen tan atractivo este rol, como las desventajas que pueden surgir al desempeñarlo.

Ventajas

  • Versatilidad y Flexibilidad: La habilidad de un Full-Stack Developer para trabajar en ambas partes de una aplicación lo convierte en un profesional sumamente versátil. Puede moverse fácilmente entre el desarrollo de la interfaz de usuario y la lógica del servidor, lo que lo hace adecuado para una amplia gama de proyectos. En un mercado que demanda adaptabilidad, esta es una ventaja crucial que posiciona al desarrollador Full-Stack como una pieza valiosa en cualquier equipo.
  • Reducción de Costos para las Empresas: Contratar a un solo desarrollador Full-Stack, en lugar de varios especialistas en front-end y back-end, puede representar una importante reducción de costos para las empresas, especialmente las startups o pequeñas empresas que no pueden permitirse equipos grandes. El Full-Stack Developer puede abordar todas las capas de una aplicación, reduciendo la necesidad de múltiples contrataciones y facilitando la coordinación de tareas.
  • Visión Integral del Proyecto: Gracias a su conocimiento de todas las capas del desarrollo, un Full-Stack Developer tiene una visión completa de cómo funciona una aplicación. Esto le permite tomar decisiones informadas sobre la arquitectura y el diseño del sistema, lo que facilita la creación de soluciones más coherentes y optimizadas. Además, puede identificar y solucionar problemas más rápidamente, ya que comprende tanto la interacción entre el front-end y el back-end como los puntos críticos de cada área.
  • Adaptabilidad a Metodologías Ágiles: Los Full-Stack Developers encajan bien en equipos que siguen metodologías ágiles, donde la flexibilidad y la rapidez en la entrega de resultados son clave. Al ser capaces de abordar distintas tareas y cambiar de rol dentro del ciclo de vida del desarrollo, contribuyen a mantener los proyectos ágiles y en constante progreso.
  • Mayor Autonomía y Responsabilidad: Los Full-Stack Developers tienen la capacidad de llevar proyectos desde la concepción hasta la entrega final. Esta autonomía les permite asumir mayor responsabilidad en las decisiones técnicas y estratégicas. Además, su perfil es ideal para liderar equipos pequeños o startups, donde se necesitan desarrolladores multifacéticos que puedan enfrentar diversos desafíos sin depender de otros especialistas.

Desventajas

  • Riesgo de Superficialidad: Aunque un Full-Stack Developer domina múltiples áreas del desarrollo, existe el riesgo de que su conocimiento sea superficial en comparación con un especialista que se enfoque solo en el front-end o el back-end. En proyectos que requieren un alto grado de especialización en una tecnología específica (por ejemplo, optimización avanzada de bases de datos o interfaces gráficas muy complejas), un Full-Stack Developer podría enfrentar dificultades para profundizar en áreas especializadas.
  • Sobrecarga de Tareas: Debido a que los Full-Stack Developers manejan varias partes del proyecto, a menudo se ven abrumados por la cantidad de responsabilidades que asumen. Esta sobrecarga puede llevar a tiempos de entrega más largos o una calidad de código inferior si no se gestionan correctamente las expectativas y los plazos. Para algunos desarrolladores, el hecho de estar constantemente cambiando entre front-end y back-end puede ser agotador y afectar la productividad a largo plazo.
  • Dificultad para Mantenerse al Día con las Tecnologías: El desarrollo tecnológico avanza rápidamente, tanto en el front-end como en el back-end, lo que exige a los Full-Stack Developers mantenerse actualizados en una amplia gama de tecnologías. Esto puede ser un reto, ya que es difícil estar al día con todas las innovaciones en ambas áreas. Por ejemplo, mientras que un especialista front-end puede estar completamente actualizado con los últimos cambios en Angular o React, un Full-Stack Developer tiene que dividir su tiempo entre esas tecnologías y las novedades en bases de datos, servidores, o frameworks de back-end.
  • Falta de Profundización en Roles Complejos: En entornos de desarrollo más complejos, como grandes corporaciones o proyectos que requieren una infraestructura muy robusta, puede que el perfil Full-Stack no sea suficiente. A menudo, estas organizaciones necesitan especialistas que tengan un conocimiento profundo en áreas críticas como la escalabilidad de bases de datos, la optimización de servidores o la experiencia de usuario avanzada, donde los Full-Stack Developers pueden quedar rezagados frente a los especialistas.
  • Expectativas altas por parte de las empresas: Aunque las empresas valoran la versatilidad de un Full-Stack Developer, esto a menudo viene con expectativas elevadas. A veces se espera que estos desarrolladores sean expertos en todas las áreas del desarrollo, lo que puede ser irrealista. Si bien es posible que tengan un buen nivel de competencia en diversas tecnologías, es poco probable que puedan igualar el nivel de profundidad que un especialista puede ofrecer en un área específica. Esto puede generar presión y estrés, ya que el desarrollador podría sentir que nunca alcanza las expectativas del empleador.

Wednesday, October 9, 2024

Breve historia de .NET y su ecosistema



.NET, creado por Microsoft, ha sido uno de los pilares en el desarrollo de software desde principios de los 2000. Lo que comenzó como un marco de trabajo para facilitar la creación de aplicaciones en Windows ha evolucionado para ser una plataforma abierta, flexible y multiplataforma. Esta es una breve historia que abarca sus hitos clave y la expansión de su ecosistema.

Nacimiento y primeras versiones de .NET (2000-2015)

El proyecto .NET fue presentado por Microsoft a finales de los años 90 y se lanzó oficialmente como .NET Framework 1.0 en 2002. Esta versión inicial tenía como objetivo proporcionar una plataforma unificada para el desarrollo de aplicaciones de escritorio y web sobre Windows. Sus principales componentes incluían:
  • Common Language Runtime (CLR): Un entorno de ejecución que permitía que diferentes lenguajes, como C#, Visual Basic y F#, pudieran trabajar juntos.
  • Base Class Library (BCL): Un conjunto de bibliotecas que facilitaba el acceso a funcionalidades comunes (manejo de archivos, entrada/salida, gráficos, etc.).
En sus primeras versiones, .NET era exclusivo de Windows y destacaba por su integración con el sistema operativo, lo que lo hizo muy popular para el desarrollo de aplicaciones empresariales.

El ecosistema original

El éxito temprano de .NET se basó en su capacidad para abarcar varios tipos de desarrollo:
  • ASP.NET: Introducido en la versión inicial, permitía a los desarrolladores crear aplicaciones web dinámicas usando lenguajes como C# o VB.NET.
  • Windows Forms y WPF (Windows Presentation Foundation): Estas tecnologías permitían crear aplicaciones de escritorio con interfaces gráficas avanzadas.
  • ADO.NET: Simplificaba el acceso a bases de datos, una herramienta clave para aplicaciones empresariales.
Durante más de una década, .NET siguió siendo la solución predominante para desarrolladores de aplicaciones de Windows, con cada nueva versión del Framework añadiendo más capacidades.

La revolución de código abierto y multiplataforma: .NET Core (2016)

El siguiente gran cambio en la historia de .NET vino con el lanzamiento de .NET Core en 2016. Este marco fue desarrollado desde cero con varias mejoras clave:
  • Multiplataforma: A diferencia del .NET Framework, .NET Core se diseñó para ejecutarse en Windows, Linux y macOS, ampliando significativamente el alcance de la plataforma.
  • Código abierto: Microsoft liberó el código de .NET Core en GitHub, lo que permitió a la comunidad de desarrolladores participar activamente en su evolución.
  • Optimización para la nube: .NET Core estaba diseñado pensando en la eficiencia y el rendimiento, convirtiéndose en una opción ideal para aplicaciones basadas en microservicios y en la nube.
Este cambio de enfoque hizo que .NET fuera competitivo en nuevos escenarios de desarrollo, como aplicaciones web modernas y microservicios en entornos cloud, utilizando tecnologías como contenedores Docker.

La unificación: .NET 5, .NET 6, .NET 7 y .NET 8

En 2020, Microsoft unificó .NET Framework y .NET Core en una única plataforma con el lanzamiento de .NET 5, eliminando la confusión entre diferentes versiones y creando una experiencia coherente para el desarrollo de aplicaciones. Las siguientes versiones han continuado esta evolución:
  • .NET 6 (2021): Marcó el primer lanzamiento de soporte a largo plazo (LTS) bajo esta nueva unificación, con mejoras en rendimiento y soporte para aplicaciones web, móviles y de escritorio.
  • .NET 7 (2022): Introdujo mejoras en rendimiento y nuevas capacidades en inteligencia artificial y Machine Learning.
  • .NET 8 (2023): Continuó optimizando la plataforma, especialmente en integración con la nube y tecnologías como Blazor para el desarrollo web interactivo.

El ecosistema moderno de .NET

Hoy en día, .NET es una plataforma que no solo abarca aplicaciones web y de escritorio, sino que también ofrece soporte para una variedad de escenarios:
  • Desarrollo web con ASP.NET Core y Blazor: ASP.NET Core se ha convertido en una plataforma potente para el desarrollo web, mientras que Blazor permite crear aplicaciones web interactivas usando C# en lugar de JavaScript.
  • Desarrollo móvil con Xamarin y .NET MAUI: Xamarin, y más recientemente .NET MAUI (Multi-platform App UI), permiten crear aplicaciones móviles para iOS y Android desde una base de código compartida.
  • Integración con la nube: La integración con Azure facilita el despliegue y la gestión de aplicaciones .NET en entornos de nube.

El futuro de .NET

El ecosistema de .NET sigue evolucionando con cada nueva versión. Las áreas emergentes incluyen el desarrollo de aplicaciones inteligentes con inteligencia artificial y Machine Learning, así como la creación de soluciones más robustas y escalables para la nube. Además, la comunidad de desarrolladores de .NET sigue creciendo, impulsando la innovación y manteniendo el marco al día con las demandas de la industria.


En resumen, la historia de .NET refleja la capacidad de la plataforma para adaptarse a los cambios en el panorama tecnológico. Desde sus comienzos como un marco centrado en Windows, hasta su evolución hacia una plataforma moderna, abierta y multiplataforma, .NET sigue siendo una opción poderosa y flexible para el desarrollo Full-Stack.

Tuesday, October 8, 2024

Requisitos previos

Para obtener el máximo provecho de este libro, es recomendable que los lectores cuenten con algunos conocimientos básicos en las siguientes áreas:

C#

  • Familiaridad con la sintaxis básica y los conceptos fundamentales de la programación orientada a objetos (POO), como clases, objetos, herencia, y polimorfismo.
  • Entender la estructura de una aplicación .NET y cómo se utilizan las bibliotecas y paquetes NuGet.

HTML/CSS

  • Conocimiento básico de HTML para estructurar el contenido de las páginas web.
  • Comprensión de CSS para aplicar estilos y diseño a las aplicaciones, incluyendo conceptos como selectores, propiedades, y modelos de caja.
  • Familiaridad con la creación de diseños responsivos utilizando técnicas como Flexbox o Grid.

JavaScript

  • Comprensión de la sintaxis básica de JavaScript y su uso en la manipulación del DOM (Document Object Model).
  • Conocimiento de conceptos como variables, funciones, eventos y promesas.
  • Familiaridad con la interacción entre JavaScript y las APIs.

Bases de datos

  • Conocimientos básicos sobre qué son las bases de datos y su importancia en las aplicaciones web.
  • Comprensión de conceptos fundamentales como tablas, registros, consultas SQL y operaciones CRUD (Crear, Leer, Actualizar, Eliminar).
  • Familiaridad con al menos un sistema de gestión de bases de datos, preferiblemente SQL Server, aunque también puede ser útil conocer otros como MySQL o MongoDB.


Si bien tener estos conocimientos previos será beneficioso, no te preocupes si no eres un experto en cada área. Este libro incluirá explicaciones y ejemplos que te ayudarán a fortalecer tus habilidades y entender cómo se integran estos conceptos en el desarrollo Full-Stack con .NET y Angular.

¿Por qué elegir .NET y Angular para el desarrollo Full-Stack?

La elección de .NET y Angular para el desarrollo Full-Stack no es casualidad. .NET es una plataforma robusta, rápida y multiplataforma, ideal para construir aplicaciones web escalables y eficientes. Su soporte a largo plazo, la amplia comunidad de desarrolladores, y la integración con herramientas como Azure lo convierten en una opción excelente para el Back-End.

Por otro lado, Angular es uno de los frameworks de Front-End más populares y mantenidos por Google. Permite la creación de aplicaciones de una sola página (SPA) con una estructura modular, asegurando una experiencia de usuario fluida y eficiente. Además, Angular y ASP.NET Core se integran fácilmente, lo que hace que sean una combinación poderosa para desarrollar aplicaciones Full-Stack modernas.

Elegir .NET y Angular te permitirá beneficiarte de un stack tecnológico con soporte empresarial, alta demanda en el mercado y una comunidad activa que respalda su evolución constante.


Links:

¿Qué significa ser un .NET Full-Stack Developer?

Ser un desarrollador Full-Stack implica tener la capacidad de trabajar en todos los aspectos del desarrollo de software, desde el diseño de interfaces de usuario hasta la creación y gestión de la lógica del servidor, bases de datos y APIs. Un .NET Full-Stack Developer no solo domina el desarrollo Back-End utilizando tecnologías como ASP.NET Core y Entity Framework, sino que también es capaz de construir interfaces de usuario interactivas y dinámicas utilizando frameworks Front-End como Angular.

Este conjunto de habilidades te permite ser más versátil en el mercado laboral, pudiendo trabajar en cualquier parte del proceso de desarrollo o asumir proyectos de manera integral.

    Propósito del libro y a quién está dirigido

    Este libro está diseñado para desarrolladores de software que desean impulsar su carrera en el mundo del desarrollo Full-Stack utilizando las tecnologías .NET y Angular. Ya sea que estés comenzando tu camino como desarrollador o que ya tengas experiencia en uno de los lados (Front-End o Back-End), este libro te guiará para adquirir un conjunto completo de habilidades Full-Stack, permitiéndote construir aplicaciones web robustas y escalables desde cero.

    El propósito es proporcionarte una base sólida en el ecosistema .NET y Angular, mientras aprendes las mejores prácticas para la creación de aplicaciones web modernas. Está dirigido tanto a estudiantes y desarrolladores principiantes, como a profesionales con experiencia en desarrollo Back-End o Front-End que buscan dominar el otro lado del stack y ser capaces de entregar soluciones completas.

    Monday, October 7, 2024

    Implementación genérica del patrón SAGA a un proceso

    Sesión 5: 4h33m

    Patrón SAGA

    • Reemplaza una transacción distribuida con una saga
      • Divide la transacción en muchas solicitudes
      • Rastrea cada solicitud
      • ACID: compromiso de atomicidad
      • Descrito por primera vez en 1987
    • También es un patrón de gestión de fallas
      • Qué hacer cuando falla un servicio
      • Compensar solicitudes
    • Implementación: considerar lo siguiente:
      • SAGA Log
      • Coordinador de ejecución de saga (SEC)
      • Solicitudes y compensación de solicitudes





     


    Patrón SAGA implementación

    • Servicio que inicia la saga
      • Envía la solicitud de saga al registro de saga
    • Saga Log
      • Servicio con una base de datos
    • SEC
      • Interpreta y escribe en el registro
      • Envía solicitudes de saga
      • Envía solicitudes de compensación de saga
      • Recuperación: estado seguro vs estado inseguro
    • Solicitudes de compensación
      • Enviar en caso de error para todas las solicitudes completadas
      • Idempotente (fácil con REST)
      • Cada uno se envía de cero a muchas veces


    Friday, October 4, 2024

    Patrón SAGA Orchestration

    Sesión 5: 4h23m

    Nota: Cuando se hagan aplicaciones distribuidas no necesariamente se necestian APIs HTTP, también puede haber Listeners de los microservicios. En tu microservicio puedes tener una parte de exposición y  una parte de listeners. En la nube los listeners se trabajan con workers (Azure Function, Lambda Function). En caso onpremise sería en una consola o servicio windows.

    SAGA - Orquestación

    Para abordar la complejidad del patrón SAGA, es bastante normal agregar un administador de procesos como administrador. El administrador de procesos es responsable de escuhar eventos y activar puntos finales. Volviendo a la muestra anterior, en lugar de que el servicio de pedido, el servicio de stock y el servicio de envío tengan que escucharse entre sí, implementamos una "gestión de procesos" y estos 3 servicios escucharán esto.

    Flujo de SAGA-Orchestration

    1. El servicio de pedidos crea un registro de pedido de la base de datos con el estado "Verificando".
    2. El servicio de pedidio Solicita al Orquestador iniciar la "Transacción de pedido".
    3. El Orquestador envía un "Comando de actualización de stock" al servicio de stock.
    4. El servicio de stock actualiza el número del producto solicitado en la base de datos.
    5. El servicio de sotck respondeal Orquestador con el mensaje "Stock actualizado correctamente".
    6. El Orquestador envía un "Comando de actualización de pedidos" al servicio de pedidos con información de que el stock ya se actualizó correctamente. 
    7. Actualización del servicio de pedidos. Registro de pedidos en la base de datos con el estado "Envío".
    8. El Orquestador envía un "Comando de envío de registro" al servicio de envío.
    9. El servicio de envío inserta un nuevo registro en la base de datos de envíos.
    10. El servicio de envío responde al Orquestador con el mensaje "El envío se ha registrado correctamente".
    11. El Orquestador envía un "Comando de actualización de pedido" al servicio de pedidos ycon información de que el envío ya se actualizó correctamente.
    12. El servicio de pedidos actualiza el registro de pedidos en la base de datos con el estado "Finalizar".




    Flujo de Rollback en SAGA-Orchestration (Escenario 1)

    Hay un error con el servicio Stock

    1. El servicio de pedidos crea un registro de pedido en la base de datos con el estado "Verificando".
    2. El servicio de pedido Solicita al Orquestador iniciar la "Transacción de pedido".
    3. El Orquestador cenvía un "Comando de actualización de stock.
    4. El servicio de stock actualiza el número del producto solicitando en la base de datos. Pero hay un error.
    5. El servicio de stock responde con el mensaje "Agotado" al Orquestador.
    6. El Orquestador envía un "Comando de orden de reversión" al servicio de pedidos con información de que Stock falló en la actualización.
    7. El servicio de pedidos actualiza el regisgtro de pedidos en la base de datos con el estado "Error".


    Hay un error con el servicio de envío.
    1. El servicio de envío responde con el mensaje "Error al registrar envío" al Orquestador.
    2. El Orquestador envía un "Comando de pedido de reversión" al servicio de pedidos con información de que el servicio de envío fallo en el registro.
    3. El servicio de pedidos actualiza el registro de pedidos en la base de datos con el estado "Error".
    4. El Orquestador envía un "Comando de reversión de stock" al servicio de stock con información de que el servicio de envío falló en el registro.
    5. El servicio de stock actualiza el número del peroducto.


    Flujo de SAGA-Orchestration

    Un formar estándar de modelar una SAGA-Orchestrator es una máquina de estado donde cada transformación corresponde a un comando o mensaje. Las máquinas de estado son un excelente patrón para estructurar un comportamiento bien definido ya que son fáciles de implementar.

    Puede utilizar servicios en la nube que pueden ayudarle, por ejemplo:
    https://theburningmonk.com/2017/07/applying-the-saga-pattern-with-aws-lambda-and-step-functions/
    https://www.freecodecamp.org/news/an-introduction-to-azure-durable-functions-patterns-and-best-practices-b1939ae6c717/


    Ventajas y desventajas de SAGA Orchestration

    Fácil de mantener todo el flujo de trabajo en un solo lugar. Orquestador. Evita las dependencias cíclicas entre servicios. Todos los servicios solo se comunican con el Orsquestador. La complejidad de la transcción sigue siendo lineal cuando se agregan nuevos pasos.

    Sin embargo, para lograr las ventajas anteriores, debe diseñar un orquestador inteligente. Además, tener demasiada lógica en el orquestador podría llevar a difucultades en el mantenimiento.




    Cuando el código funciona, pero no tiene tests: ¿y ahora qué?

    Seguramente te ha pasado alguna vez. Te dan acceso al repositorio de un nuevo proyecto. Lo abres con curiosidad, esperas encontrar una estru...