Showing posts with label Software Construction. Show all posts
Showing posts with label Software Construction. Show all posts

Friday, April 4, 2025

Querido Developer, ¿estás probando lo suficiente tu código?

Como developers, estamos entrenados para resolver problemas, construir funcionalidades y entregar valor rápido. Pero hay un aspecto esencial del desarrollo que muchas veces ignoramos o subestimamos: las pruebas de software.

En este artículo, quiero hablarte como colega. Vamos a reflexionar juntos sobre por qué las pruebas no son una carga, sino una de las mejores herramientas que tenemos para escribir mejor código, evitar dolores de cabeza y ganar confianza en nuestras entregas.


La importancia de las pruebas dentro del proceso de desarrollo de software

Las pruebas no son una fase final ni un "extra" que solo se hace si queda tiempo. Son una parte fundamental del ciclo de desarrollo.

Cuando probamos nuestro código, no solo estamos verificando que una función devuelva el valor esperado. Estamos:

  • Confirmando que el sistema cumple con los requisitos.
  • Validando que los cambios no rompan lo que ya funcionaba.
  • Previniendo bugs antes de que lleguen a producción.
  • Reduciendo el costo de mantenimiento a futuro.

Probar es una forma de cuidar nuestro trabajo. De blindar nuestras soluciones frente a cambios, errores humanos y condiciones inesperadas. Es escribir con visión de futuro.

Entonces… si sabemos que las pruebas son clave, ¿por qué a veces las evitamos?


¿Por qué los developers no siempre invierten suficiente tiempo en pruebas?

La realidad es que sí hacemos pruebas, pero muchas veces de forma informal o superficial. Hacemos una prueba manual, o ejecutamos el programa “a ver si funciona”, y seguimos adelante. ¿Te suena?

Las razones por las que no escribimos suficientes pruebas son conocidas:

  • Presión por entregar rápido.
  • Plazos ajustados que nos hacen pensar que “ya habrá tiempo para testear después”.
  • Falta de cultura de calidad dentro del equipo o la empresa.
  • Desconocimiento o poca práctica con herramientas de testing.

El problema es que esta lógica termina saliendo cara. Porque lo que no se prueba hoy, se rompe mañana. Y cuando se rompe en producción, el costo es mayor: horas extra, bugs urgentes, pérdida de confianza, estrés...

Por eso es importante entender qué tipo de pruebas existen y cuál es nuestro rol como developers en cada una.


Tipos de pruebas en el desarrollo de software

No todas las pruebas son iguales. Cada tipo cumple una función específica dentro del desarrollo:

Cada una de estas pruebas aporta valor en un nivel distinto del sistema. Como developers, no podemos esperar que QA cubra todo. Tenemos una responsabilidad clara sobre las pruebas unitarias e integración, que son las que nos permiten desarrollar con confianza.

Y si además logramos automatizarlas, el beneficio se multiplica.


¿Qué es la automatización de pruebas y por qué deberías aplicarla?

La automatización de pruebas consiste en escribir scripts o casos de prueba que se ejecutan automáticamente, en lugar de hacerlos a mano cada vez.

Esto permite:

  • Ejecutar pruebas en segundos (ideal para integración continua).
  • Detectar errores al instante después de cada cambio.
  • Asegurar que el código nuevo no rompa el sistema existente.
  • Ahorrar tiempo en tareas repetitivas.

Antes, todas las pruebas eran manuales. Hoy, con herramientas como xUnit, NUnit, Selenium o Postman, podemos automatizar casi todo.

Pero cuidado: automatizar no significa automatizar todo. Acá es donde entra un concepto clave en el mundo del testing...


La pirámide de testing: cómo decidir qué pruebas automatizar

La pirámide de testing es un modelo que nos guía sobre cuántas pruebas hacer y de qué tipo. Su idea central es: las pruebas más baratas y rápidas deben ser las más numerosas.


  • Las pruebas unitarias (base de la pirámide) son fáciles de escribir, rápidas de ejecutar y muy efectivas para detectar errores en funciones pequeñas.
  • Las pruebas de servicio o integración validan cómo interactúan los módulos, APIs, o servicios entre sí.
  • Las pruebas de UI son necesarias, pero frágiles, lentas y difíciles de mantener. Se deben hacer con moderación.

Este enfoque no solo mejora la eficiencia, también reduce el tiempo de feedback y mantiene tu sistema saludable en el tiempo.

Y aquí viene otra gran pregunta...


¿Dónde terminan las pruebas del developer y empiezan las del tester?

En realidad, no hay una línea tan clara. QA y desarrollo deberían trabajar juntos, no como dos mundos separados.

  • Los developers escribimos pruebas que aseguran que el código hace lo que esperamos.
  • El equipo de QA verifica que el sistema responde correctamente ante escenarios reales, errores de usuario, condiciones extremas.

Si no escribimos nuestras pruebas, el equipo QA pasa más tiempo encontrando errores básicos en vez de enfocarse en casos más complejos y valiosos.

Colaborar con QA desde el inicio del proyecto mejora los entregables, evita malentendidos y crea una cultura de calidad compartida.


¿Qué es una estrategia de pruebas y por qué deberías tener una?

Una estrategia de pruebas es el plan que define cómo vamos a probar nuestro software. Y no debería ser un documento oculto o algo que solo define QA.

Definir una buena estrategia de pruebas implica responder a estas preguntas:

  • ¿Qué tipos de pruebas vamos a hacer? (unitarias, integración, UI…)
  • ¿Cuántas pruebas vamos a tener? (basado en riesgo o cobertura)
  • ¿Quién las va a hacer? (Dev, QA, ambos)
  • ¿Cuándo se van a ejecutar? (CI/CD, antes del release, por sprint)
  • ¿Con qué herramientas? (xUnit, Cypress, Postman, Playwright, etc.)
  • ¿Cuál será la arquitectura de pruebas? (estructura de carpetas, mocks, inyección de dependencias, base de datos en memoria, etc.)

Una estrategia clara nos da foco, reduce el retrabajo y permite mantener una cobertura saludable sin duplicar esfuerzos.

Lectura recomenda: Definición de la estrategia de pruebas

Conclusión: probar es parte de tu trabajo, no una tarea secundaria

Como developers, no solo estamos para escribir código que compila. Estamos para crear soluciones robustas y mantenibles.

Probar tu código no es una pérdida de tiempo. Es la mejor forma de proteger tu trabajo, tu tiempo y la calidad del producto.


✅ Acciones concretas que puedes aplicar hoy

  • Empieza por lo básico: agrega pruebas unitarias a tu próxima función.
  • Incorpora las pruebas en tu flujo diario: que no sean una fase separada.
  • Automatiza con herramientas simples: empieza con xUnit o NUnit.
  • Habla con QA: alinear expectativas y compartir estrategia de pruebas.
  • Construye o mejora la estrategia de testing de tu equipo.


¡Gracias por llegar hasta aquí!


Sunday, March 30, 2025

Inyección de dependencias

¿Qué es Inyección de Dependencias?

Inyección de Dependencias (en inglés Dependency Injection, DI), es un patrón de diseño de software usado en la Programación Orientada a Objetos.

Permite desarrollar componentes desacoplados permitiendo una fácil gestión de cambios a futuro, implementación de pruebas unitarias, factoría para creación de instancias, prevención de fugas de memoria, entre otros.

Conceptos


  • Inversión de Dependencia (ID)
    • Principio de Diseño: Las clases de alto nivel no deberían depender de clases de bajo nivel; ambas deberían depender de abstracciones (interfaces o clases abstractas). 
    • Objetivo: Reducir el acoplamiento entre clases para mejorar la modularidad y facilitar la mantenibilidad y la extensibilidad del código.
  • Inyección de Dependencia (DI)
    • Patrón de Diseño: Una forma de implementar la inversión de control donde las dependencias (objetos) son proporcionadas a una clase en lugar de ser creadas por la clase.
    • Métodos: Las dependencias pueden ser inyectadas a través de constructores, métodos setter o directamente en propiedades.
  • Inversión de control (IoC)
    • Principio General: Refiere a invertir el control del flujo del programa, delegándolo a un contenedor o framework externo.
    • Implementación: Se logra mediante técnicas como la inyección de dependencia.
    • Efecto: Las dependencias entre componentes se gestionan externamente en lugar de que cada componente gestione sus propias dependencias.



Tipos de inyección de dependencias en .NET


Uso de Transient

Crea y comparte una instancia del servicio cada vez que la aplicación lo solicite. El componente se puede agregar como transitorio utilizando el método AddTransient() para IServiceCollection




Uso de Scoped

Se crea una vez por alcance y se implementa utilizando el método AddScoped(). La mayoría de las veces, el alcance se refiere a la duración de una solicitud http.



Uso de Singleton

Crea y comparte una única instancia del componenete a lo largo de la vida de la aplicación. El componente se puede agregar como singleton utilizando el método AddSingleton() para IServiceCollection.



Beneficios

  • Aplicación de bajo acoplamiento.
  • En caso de cualquier cambio en la implementación del servicio, simplemente cambie el nombre del archivo servicio o Implementación en el archivo program.cs.
  • No más cambios en ninguna clase del controlador.
  • Facilita la vida del desarrollador





Monday, March 3, 2025

Integrando el Versionamiento en la Arquitectura Empresarial

En el ámbito empresarial moderno, la Arquitectura Empresarial (AE) se presenta como un marco fundamental que alinea los procesos de negocio con las capacidades tecnológicas, asegurando que las inversiones en tecnología respalden eficazmente los objetivos estratégicos de la organización. Dentro de este contexto, la gestión adecuada de los activos tecnológicos es esencial para mantener la competitividad y eficiencia operativa.​


Activos Tecnológicos en la Arquitectura Empresarial

Los activos tecnológicos comprenden todos los recursos de tecnología de la información que una organización utiliza para operar y alcanzar sus metas. Estos incluyen:​
  • Hardware: Servidores, computadoras, dispositivos de red y otros equipos físicos.​
  • Software: Aplicaciones internas, sistemas operativos y herramientas de productividad.​
  • Datos: Bases de datos, registros de clientes y cualquier información digital relevante.​
  • Infraestructura de Red: Conectividad interna y externa, incluyendo internet y redes privadas.​
  • Propiedad Intelectual Digital: Patentes, licencias y derechos de autor en formato digital.
La AE proporciona una visión integral de cómo estos activos interactúan y se integran con los procesos de negocio, facilitando una gestión más efectiva y alineada con la estrategia corporativa. ​

La Práctica del Versionamiento en la Gestión de Activos Tecnológicos

El versionamiento es una práctica técnica que implica el seguimiento y control de las diferentes versiones de los artefactos de software o ítems de configuración dentro de un sistema. Esta práctica es esencial para mantener la integridad y continuidad operativa, permitiendo a las organizaciones:​
  • Rastrear Cambios: Identificar qué modificaciones se realizaron, cuándo y por quién.​
  • Revertir Errores: Volver a versiones anteriores en caso de fallos o problemas.​
  • Facilitar la Colaboración: Permitir que múltiples equipos trabajen simultáneamente sin conflictos.
El control de versiones coordina todos los cambios en un proyecto de software, al rastrear de manera efectiva los cambios en los archivos de origen, los diseños y todos los activos digitales necesarios para un proyecto y los metadatos relacionados. ​


Artefactos que un Desarrollador debe Considerar para el Versionamiento

Para implementar un control de versiones efectivo, los desarrolladores deben considerar una variedad de artefactos, incluyendo:​
  1. Código Fuente: Los archivos que contienen las instrucciones de programación de las aplicaciones.​
  2. Archivos de Configuración: Documentos que establecen parámetros y ajustes para diferentes entornos (desarrollo, pruebas, producción).​
  3. Documentación: Manuales de usuario, guías de instalación y cualquier material que acompañe al software.​
  4. Scripts de Base de Datos: Instrucciones para la creación, modificación y gestión de bases de datos.​
  5. Pruebas Automatizadas: Casos de prueba que aseguran la funcionalidad y calidad del software.​
  6. Infraestructura como Código (IaC): Archivos que describen la configuración de la infraestructura, permitiendo su gestión y despliegue automatizado.​
  7. Dependencias y Librerías: Módulos externos o paquetes que la aplicación requiere para funcionar correctamente.
Estos artefactos, al ser versionados, garantizan que cualquier cambio sea registrado y pueda ser gestionado de manera eficiente, reduciendo riesgos y mejorando la calidad del producto final.​

Conclusión

La integración de prácticas de versionamiento en la gestión de activos tecnológicos es fundamental para el éxito de la Arquitectura Empresarial. Al asegurar que cada componente tecnológico esté debidamente controlado y alineado con los objetivos estratégicos, las organizaciones pueden adaptarse mejor a los cambios del mercado, mejorar su eficiencia operativa y mantener una ventaja competitiva sostenible.​

¡Gracias por llegar hasta aquí!

Friday, February 28, 2025

Control de versiones en scripts de migración de bases de datos

Introducción

El desarrollo de software es un proceso en constante evolución, donde los cambios son esenciales para mejorar los sistemas y adaptarse a un entorno tecnológico dinámico. Sin embargo, gestionar estas modificaciones de manera efectiva es un desafío, ya que cualquier alteración no planificada puede comprometer la estabilidad, seguridad o eficiencia de una aplicación. Para enfrentar este reto, el control de versiones se ha convertido en una práctica fundamental, permitiendo a los equipos registrar cambios, mantener un historial preciso y colaborar de forma estructurada mediante herramientas como Git. Esto asegura la coherencia del código fuente y facilita su mantenimiento y evolución.

En el caso de las bases de datos, la gestión del cambio presenta desafíos únicos, ya que almacenan información crítica y cualquier modificación puede afectar la integridad de los datos. A diferencia del código fuente, que puede reemplazarse fácilmente, las bases de datos requieren estrategias bien planificadas para evitar pérdidas de información, garantizar la compatibilidad con versiones anteriores y sincronizar cambios sin interrumpir la operatividad del sistema. En este artículo, se analizará la importancia del control de versiones en los scripts de migración de bases de datos, los principales desafíos que implica y las mejores prácticas para asegurar estabilidad, seguridad y escalabilidad.


Versionado de Base de Datos mediante scripts de migración

Los scripts de migración de bases de datos son archivos que contienen instrucciones SQL diseñadas para modificar la estructura, los datos o la configuración de una base de datos de manera incremental y controlada. Estos scripts permiten realizar cambios como:

  • Creación, modificación o eliminación de tablas.
  • Adición o eliminación de columnas.
  • Alteración de índices, restricciones y llaves foráneas.
  • Inserción, actualización o eliminación de datos estáticos.
  • Cambios en procedimientos almacenados, funciones y triggers.
  • Creación de Jobs o Tareas Programadas.
  • Cambios en permisos y seguridad.
  • Creación de scripts de reversión para cada migración.

Por ejemplo, un script de migración que define la creación de una nueva tabla Users podría ser de la siguiente manera:

-- V1__Create_Users_Table.sql
CREATE TABLE Users (
    Id INT PRIMARY KEY,
    Name VARCHAR(100),
    Email VARCHAR(100) UNIQUE,
    CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
);

El control de versiones en bases de datos busca gestionar cambios de manera estructurada, evitando inconsistencias entre entornos (desarrollo, prueba, producción). Los scripts de migración son una parte clave de este proceso, ya que:

  1. Documentan los cambios: Cada script representa una versión específica de la base de datos, facilitando el seguimiento del historial de modificaciones.
  2. Permiten la replicación de cambios en distintos entornos: Aseguran que todos los desarrolladores y servidores utilicen la misma versión de la base de datos.
  3. Facilitan el rollback: En caso de errores, los scripts de migración pueden incluir scripts de reversión para volver a una versión anterior.
  4. Se integran con herramientas de versionado y CI/CD: Herramientas como Flyway, Liquibase, Entity Framework Core Migrations, entre otras, permiten aplicar estos scripts de manera ordenada y automatizada.

El uso de scripts de migración es una estrategia esencial para mantener la coherencia y estabilidad de las bases de datos a medida que evolucionan junto con el software. Sin embargo, gestionar estos cambios manualmente puede volverse complejo, especialmente en proyectos grandes con múltiples desarrolladores y entornos.

Para abordar este desafío, existen herramientas especializadas que automatizan la gestión de migraciones y garantizan que los cambios se apliquen de manera ordenada y reproducible. Entre las soluciones más utilizadas en el ecosistema de desarrollo encontramos Flyway y Entity Framework Core Migrations, dos enfoques que facilitan el versionado de bases de datos, cada uno con características y beneficios específicos.


Flyway y Entity Framework Core Migrations: Herramientas para el versionado de bases de datos

El control de versiones en bases de datos no solo requiere una estrategia bien definida, sino también herramientas que faciliten la aplicación y gestión de cambios de manera eficiente y segura. Flyway y Entity Framework Core Migrations (EF Core Migrations) son dos de las soluciones más utilizadas en el mundo del desarrollo, cada una con un enfoque distinto para gestionar la evolución de la base de datos.

Flyway: Migraciones mediante scripts SQL

Flyway es una herramienta de control de versiones de bases de datos que permite gestionar cambios mediante scripts SQL escritos manualmente. Se basa en un enfoque migration-based, lo que significa que los cambios se aplican secuencialmente a través de scripts versionados.

¿Cómo funciona Flyway?
  1. Los desarrolladores crean scripts de migración con cambios específicos en SQL.
  2. Flyway detecta y aplica los scripts en orden secuencial, registrando cada cambio en una tabla especial (flyway_schema_history).
  3. Los cambios se propagan automáticamente a diferentes entornos (desarrollo, prueba, producción).

Ejemplo de script de migración en Flyway:
-- V1__Create_Users_Table.sql
CREATE TABLE Users (
    Id INT PRIMARY KEY,
    Name VARCHAR(100),
    Email VARCHAR(150) UNIQUE,
    CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
);

Ejemplo de comando para ejecutar la migración:
flyway migrate

Ventajas de Flyway
  • Independiente del lenguaje de programación (compatible con .NET, Java, Python, etc.).
  • Permite escribir migraciones en SQL puro, dando control total sobre los cambios.
  • Historial de cambios claro y replicable en múltiples entornos.
  • Integración sencilla con CI/CD (Jenkins, GitHub Actions, Azure DevOps, etc.).
Desventajas de Flyway
  • Requiere escribir los scripts SQL manualmente, lo que puede ser más tedioso para equipos sin experiencia en bases de datos.
  • No genera automáticamente los scripts a partir del modelo de datos, como lo hace EF Core Migrations.
¿Cuándo usar Flyway?
  • Cuando se necesita control total sobre los cambios en la base de datos.
  • Si la base de datos es compartida entre múltiples aplicaciones o equipos.
  • En proyectos que no dependen exclusivamente de .NET y requieren una solución universal.

Entity Framework Core Migrations: Migraciones Code-First

Entity Framework Core Migrations (EF Core Migrations) es la herramienta nativa de .NET y Entity Framework Core para gestionar cambios en la base de datos mediante el enfoque Code-First. En este caso, los cambios en la base de datos se generan a partir del modelo de datos en C#, sin necesidad de escribir scripts SQL manualmente.

¿Cómo funciona EF Core Migrations?
  1. El desarrollador modifica las clases del modelo de datos en C# (ejemplo: agregar una nueva propiedad a una entidad).
  2. Se genera automáticamente un script de migración con el siguiente comando: 
    dotnet ef migrations add AddBirthdateToUsers

  3. Se aplica la migración a la base de datos con el comando:
    dotnet ef database update

  4. EF Core se encarga de ejecutar los cambios en SQL, sin necesidad de escribir los scripts manualmente.

Ejemplo de modelo de datos en C#:
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public DateTime Birthdate { get; set; } // Nuevo campo agregado
}

Ejemplo de migración generada automáticamente por EF Core:
ALTER TABLE Users ADD COLUMN Birthdate DATE;


Ventajas de EF Core Migrations
  • Automatiza la generación de scripts SQL, reduciendo la carga de trabajo del desarrollador.
  • Se integra perfectamente con .NET y Entity Framework Core.
  • Permite realizar migraciones sin escribir SQL manualmente, facilitando la gestión del esquema de la base de datos.
Desventajas de EF Core Migrations
  • Está altamente acoplado a .NET y Entity Framework Core.
  • Puede generar scripts SQL no óptimos en bases de datos grandes o complejas.
  • No es ideal para bases de datos compartidas con otras aplicaciones que no usan EF Core.
¿Cuándo usar EF Core Migrations?
  • En proyectos .NET que usan Entity Framework Core y siguen el enfoque Code-First.
  • Cuando se quiere minimizar la necesidad de escribir SQL manualmente.
  • Si la base de datos solo es utilizada por la aplicación .NET y no requiere cambios gestionados por otros equipos.


Conclusión

El desarrollo de software requiere que tanto el código como la base de datos evolucionen de manera estructurada para adaptarse a nuevas necesidades sin comprometer la integridad del sistema. A diferencia del código fuente, donde los cambios son más manejables, cualquier modificación en una base de datos debe gestionarse cuidadosamente mediante un sistema de versionado. Herramientas como Flyway y Entity Framework Core Migrations facilitan este proceso, ofreciendo enfoques distintos según el contexto del proyecto. Más allá de la elección de herramientas, es crucial adoptar una cultura de disciplina y control en la gestión de cambios, ya que un sistema de versionado adecuado no solo garantiza estabilidad y seguridad, sino que también permite escalar y evolucionar el software de manera eficiente.


¡Gracias por llegar hasta aquí!


Webgrafía: