Un sistema puede hacer exactamente lo que se le pidió —cumplir todos sus requisitos funcionales— y aun así ser un fracaso: porque es lento, se cae cada semana, no resiste un ataque o cuesta una fortuna mantenerlo. Todo eso lo gobiernan los atributos de calidad, también llamados requisitos no funcionales. Son, en gran medida, lo que la arquitectura busca lograr: el "cómo de bien" frente al "qué hace". En esta lección aprenderás a identificarlos, a distinguirlos de los requisitos funcionales y, sobre todo, a especificarlos de forma medible mediante escenarios de calidad, porque un atributo que no se puede medir no se puede diseñar ni verificar.

Contenido

  1. Funcionales frente a no funcionales
  2. Catálogo de atributos de calidad
  3. El problema de los requisitos vagos
  4. Escenarios de calidad: cómo especificarlos
  5. Tácticas arquitectónicas para lograrlos
  6. Conflictos entre atributos

  1. Funcionales frente a no funcionales

Conviene tener clara la frontera desde el principio.

Tipo de requisito Responde a Ejemplo
Funcional ¿Qué hace el sistema? "El usuario puede transferir dinero entre sus cuentas"
No funcional (atributo de calidad) ¿Cómo de bien lo hace? "La transferencia se completa en menos de 2 segundos el 99% de las veces"

Los requisitos no funcionales también se conocen como atributos de calidad, NFR (Non-Functional Requirements) o -ilities en inglés (scalability, availability, etc.). Son responsabilidad directa de la arquitectura: la funcionalidad puede implementarse de muchas formas, pero solo algunas estructuras logran la disponibilidad o el rendimiento exigidos.

  1. Catálogo de atributos de calidad

Existen taxonomías formales (por ejemplo, la norma ISO/IEC 25010). A continuación, los atributos más relevantes en la práctica:

Atributo Definición breve Cómo se suele medir
Rendimiento Rapidez de respuesta y uso eficiente de recursos Latencia (ms), throughput (peticiones/s)
Escalabilidad Capacidad de crecer ante más carga Usuarios concurrentes soportados, coste por unidad de carga
Disponibilidad Proporción de tiempo operativo % de uptime (p. ej., 99,9%), MTBF, MTTR
Fiabilidad Funcionar correctamente sin fallos Tasa de errores, fallos por millón de operaciones
Seguridad Proteger datos y funciones de accesos indebidos Vulnerabilidades, cumplimiento de normativas
Mantenibilidad Facilidad de cambio y corrección Tiempo medio de implementar un cambio, complejidad
Testabilidad Facilidad de probar el sistema Cobertura, tiempo de la suite de pruebas
Usabilidad Facilidad de uso para el usuario final Tasa de tareas completadas, tiempo de aprendizaje
Observabilidad Capacidad de entender el estado interno desde fuera Cobertura de logs, métricas y trazas
Portabilidad Facilidad de mover el sistema a otro entorno Esfuerzo de migración

Nota sobre disponibilidad: el porcentaje de uptime tiene consecuencias muy concretas en tiempo de caída tolerado al año.

Disponibilidad Caída máxima al año (aprox.)
99% ("dos nueves") ~3,65 días
99,9% ("tres nueves") ~8,77 horas
99,99% ("cuatro nueves") ~52,6 minutos
99,999% ("cinco nueves") ~5,26 minutos

Cada "nueve" adicional dispara el coste y la complejidad. Por eso es un atributo que debe negociarse con el negocio, no fijarse al máximo "por si acaso".

  1. El problema de los requisitos vagos

Compara estas dos formas de expresar el mismo requisito:

  • Vago: "El sistema debe ser rápido."
  • Medible: "El 95% de las búsquedas de productos deben responder en menos de 300 ms con 1.000 usuarios concurrentes."

El primero es inútil: ¿rápido para quién, en qué operación, bajo qué carga, con qué objetivo? No se puede diseñar contra él ni verificar si se cumple. El segundo es medible, específico y verificable. La regla de oro es:

Un atributo de calidad que no es medible no es un requisito, es un deseo.

  1. Escenarios de calidad: cómo especificarlos

El SEI (Software Engineering Institute) propone los escenarios de calidad como forma estándar de especificar atributos no funcionales. Un escenario tiene seis partes:

Parte Significado Ejemplo (rendimiento)
Fuente del estímulo Quién/qué genera el evento Un usuario externo
Estímulo El evento que llega Lanza una búsqueda de productos
Artefacto Parte del sistema afectada El servicio de catálogo
Entorno Condiciones en que ocurre En hora pico, con 1.000 usuarios concurrentes
Respuesta Qué hace el sistema Devuelve los resultados de la búsqueda
Medida de la respuesta Criterio de éxito cuantificable En menos de 300 ms el 95% de las veces

Leído de corrido: "Un usuario externo lanza una búsqueda de productos en el servicio de catálogo en hora pico con 1.000 usuarios concurrentes; el sistema devuelve los resultados en menos de 300 ms el 95% de las veces."

Podemos representarlo de forma estructurada:

escenario_calidad:
  atributo: rendimiento
  fuente: usuario_externo
  estimulo: busqueda_de_productos
  artefacto: servicio_catalogo
  entorno: hora_pico_1000_usuarios_concurrentes
  respuesta: devolver_resultados_busqueda
  medida:
    metrica: tiempo_respuesta_ms
    objetivo: 300
    percentil: 95   # el 95% de las peticiones debe cumplir el objetivo

Este YAML formaliza el escenario para que pueda discutirse y verificarse. Lo importante no es el formato concreto, sino que cada escenario incluya las seis partes. El campo percentil: 95 es clave: especificar un percentil (P95, P99) en lugar de un promedio evita engaños, porque un promedio bajo puede esconder un pequeño porcentaje de peticiones desastrosamente lentas que arruinan la experiencia.

Un escenario de disponibilidad podría escribirse así:

escenario_calidad:
  atributo: disponibilidad
  fuente: nodo_del_sistema
  estimulo: caida_inesperada_de_una_instancia
  artefacto: servicio_de_pagos
  entorno: operacion_normal
  respuesta: redirigir_trafico_a_instancia_sana_sin_perdida_de_datos
  medida:
    objetivo_uptime: "99.9%"
    tiempo_recuperacion_max_segundos: 30

Aquí el estímulo no viene de un usuario, sino de un fallo interno (la caída de una instancia). La respuesta esperada es que el sistema se recupere automáticamente redirigiendo el tráfico, con un objetivo de disponibilidad del 99,9% y un tiempo de recuperación máximo de 30 segundos. Especificarlo así permite diseñar y probar la tolerancia a fallos de forma concreta.

  1. Tácticas arquitectónicas para lograrlos

Una táctica es una decisión de diseño que influye en un atributo de calidad concreto. Algunas habituales:

  • Rendimiento: caché, índices, balanceo de carga, procesamiento asíncrono.
  • Disponibilidad: redundancia, failover automático, health checks, circuit breakers.
  • Escalabilidad: escalado horizontal (más instancias), particionado de datos (sharding), colas para absorber picos.
  • Seguridad: autenticación y autorización, cifrado en tránsito y en reposo, principio de mínimo privilegio.
  • Mantenibilidad: bajo acoplamiento, alta cohesión, modularidad, pruebas automatizadas.
// Ejemplo de táctica de disponibilidad: un circuit breaker simplificado.
// Si un servicio dependiente falla repetidamente, dejamos de llamarlo un tiempo
// para no agotar recursos y dar margen a que se recupere ("fail fast").
public class CircuitBreaker {
    private int fallosConsecutivos = 0;
    private final int umbral = 5;          // a partir de 5 fallos, abrimos el circuito
    private boolean abierto = false;

    public Respuesta llamar(ServicioRemoto servicio) {
        if (abierto) {
            // Circuito abierto: no llamamos, devolvemos una respuesta de reserva.
            return Respuesta.degradada();
        }
        try {
            Respuesta r = servicio.invocar();
            fallosConsecutivos = 0;        // éxito: reiniciamos el contador
            return r;
        } catch (Exception e) {
            fallosConsecutivos++;
            if (fallosConsecutivos >= umbral) {
                abierto = true;            // demasiados fallos: abrimos el circuito
            }
            return Respuesta.degradada();
        }
    }
}

Este ejemplo Java implementa de forma muy simplificada el patrón circuit breaker (cortacircuitos), una táctica clásica de disponibilidad. La idea: si un servicio remoto falla umbral veces seguidas (fallosConsecutivos >= umbral), el circuito se "abre" (abierto = true) y dejamos de llamarlo, devolviendo una respuesta degradada inmediata en lugar de esperar a que vuelva a fallar. Esto evita que un servicio caído arrastre a todo el sistema (efecto dominó) y le da tiempo a recuperarse. En producción se usarían librerías maduras como Resilience4j, pero el concepto es este.

  1. Conflictos entre atributos

Los atributos de calidad casi nunca son independientes: mejorar uno suele perjudicar a otro. Por eso la arquitectura es el arte de los compromisos (que veremos en detalle en la siguiente lección).

Si mejoras... Puedes perjudicar... Motivo
Seguridad (más cifrado/validaciones) Rendimiento El cifrado y las comprobaciones consumen tiempo
Disponibilidad (más redundancia) Coste Más servidores y replicación cuestan dinero
Rendimiento (más caché) Consistencia Los datos en caché pueden quedar obsoletos
Escalabilidad (sistemas distribuidos) Mantenibilidad/simplicidad Lo distribuido es más complejo de operar y depurar

La conclusión práctica es que no existe la arquitectura "óptima" en abstracto: existe la arquitectura adecuada para un conjunto priorizado de atributos de calidad. Por eso el primer trabajo del arquitecto es lograr que el negocio priorice: ¿qué importa más, el coste o la disponibilidad?, ¿la velocidad o la consistencia perfecta?

Errores Comunes y Consejos

  • Dejar los NFR para el final. Los atributos de calidad deben capturarse al inicio, porque condicionan la estructura completa. Añadir disponibilidad a un sistema que no se diseñó para ella es carísimo.
  • Especificarlos de forma vaga. "Rápido", "seguro", "escalable" no son requisitos. Usa escenarios de calidad con medidas concretas.
  • Pedir el máximo en todo. Querer cinco nueves de disponibilidad, latencia mínima y coste mínimo a la vez es contradictorio. Hay que priorizar.
  • Usar promedios en lugar de percentiles. Un promedio oculta los casos peores. Mide P95/P99.
  • Consejo: convierte cada NFR en algo verificable. Si no sabes cómo medir que se cumple, reescríbelo hasta que puedas.

Ejercicios

Ejercicio 1. Reescribe el siguiente requisito vago en un escenario de calidad con sus seis partes: "El sistema de login debe ser seguro y rápido".

Ejercicio 2. Una tienda online exige 99,99% de disponibilidad. ¿Cuánto tiempo de caída al año tolera, aproximadamente? ¿Qué dos tácticas propondrías para alcanzarlo y qué atributo se vería perjudicado?

Ejercicio 3. Identifica el conflicto entre atributos en esta decisión: "Vamos a cifrar todos los datos en la base de datos y validar cada campo en tres capas distintas". ¿Qué atributo mejora y cuál se resiente?

Soluciones

Solución 1. Ejemplo de escenario para la parte de rendimiento del login: Fuente: un usuario registrado. Estímulo: envía sus credenciales. Artefacto: el servicio de autenticación. Entorno: operación normal con 500 usuarios concurrentes. Respuesta: valida las credenciales y devuelve un token de sesión. Medida: en menos de 500 ms el 99% de las veces. (Para la parte de seguridad se redactaría otro escenario aparte, p. ej.: ante 5 intentos fallidos en 1 minuto desde la misma IP, el sistema bloquea la cuenta y registra el evento de seguridad.)

Solución 2. El 99,99% tolera aproximadamente 52,6 minutos de caída al año. Tácticas posibles: redundancia con varias instancias en distintas zonas y failover automático con balanceador y health checks. El atributo perjudicado es principalmente el coste (más infraestructura y replicación), y secundariamente la complejidad/mantenibilidad operativa.

Solución 3. Mejora la seguridad (cifrado y validación exhaustiva). Se resiente el rendimiento: el cifrado/descifrado y la triple validación añaden latencia y consumo de CPU en cada operación. También puede afectar a la mantenibilidad si la validación está duplicada en tres capas sin una única fuente de verdad.

Conclusión

Has aprendido a distinguir requisitos funcionales de no funcionales, a manejar un catálogo de atributos de calidad, a especificarlos de forma medible con escenarios de calidad de seis partes, a aplicar tácticas para lograrlos y a reconocer que casi siempre entran en conflicto entre sí. Precisamente ese choque permanente entre atributos —disponibilidad contra coste, rendimiento contra consistencia— es el corazón del trabajo arquitectónico. En la siguiente lección abordaremos de frente cómo se toman esas decisiones difíciles: las decisiones arquitectónicas y los compromisos (trade-offs), incluyendo métodos formales de evaluación como ATAM.

Curso de Arquitectura de Aplicaciones

Módulo 1: Fundamentos de la Arquitectura de Aplicaciones

Módulo 2: Principios y Tácticas de Diseño

Módulo 3: Estilos y Patrones Arquitectónicos

Módulo 4: Arquitecturas Distribuidas y Microservicios

Módulo 5: Arquitecturas Dirigidas por Eventos y Mensajería

Módulo 6: Diseño Dirigido por el Dominio (DDD)

Módulo 7: Datos y Persistencia

Módulo 8: Arquitectura en la Nube y Despliegue

Módulo 9: Calidad, Seguridad y Observabilidad

Módulo 10: Evolución, Gobernanza y Casos Prácticos

© Copyright 2026. Todos los derechos reservados