5. Características del software: complejidad, cambio e invisibilidad

5.1 Introducción

El software tiene características particulares que lo diferencian de otros productos construidos por las personas. No se desgasta como una máquina, no puede verse completo de una sola mirada, puede modificarse muchas veces y suele representar reglas, procesos y decisiones de una organización.

Estas características explican por qué desarrollar software es difícil. Muchas veces los problemas no aparecen por falta de conocimiento de un lenguaje de programación, sino porque el sistema crece, cambia, se integra con otros sistemas y acumula decisiones que no son visibles para todos.

En este tema estudiaremos tres características centrales: complejidad, cambio e invisibilidad. Comprenderlas permite entender mejor la necesidad de aplicar Ingeniería de Software.

5.2 El software es complejo

La complejidad del software no se debe solamente a que haya muchas líneas de código. También aparece por la cantidad de relaciones entre partes, reglas, datos, usuarios, permisos, interfaces, errores posibles, tecnologías e integraciones.

Un sistema puede tener miles de elementos que interactúan entre sí. Una modificación en una regla de negocio puede afectar una pantalla, una API, una base de datos, un reporte, una prueba automatizada y una integración externa.

La complejidad aumenta cuando el sistema debe responder a muchas situaciones distintas:

  • Usuarios con distintos permisos.
  • Datos válidos, inválidos, incompletos o históricos.
  • Reglas de negocio con excepciones.
  • Distintos dispositivos, navegadores o sistemas operativos.
  • Integraciones con servicios externos.
  • Condiciones de error, lentitud o desconexión.
  • Versiones diferentes del mismo producto.
Idea clave: el software es complejo porque combina muchas reglas y relaciones invisibles que deben comportarse correctamente al mismo tiempo.

5.3 Complejidad esencial y complejidad accidental

No toda la complejidad tiene el mismo origen. Podemos distinguir entre complejidad esencial y complejidad accidental.

Tipo Significado Ejemplo
Complejidad esencial Proviene del problema que el sistema debe resolver. Un sistema de impuestos debe contemplar muchas reglas legales reales.
Complejidad accidental Proviene de decisiones técnicas, herramientas, organización deficiente o código innecesariamente difícil. Una regla simple está duplicada en diez archivos y cada copia funciona distinto.

La Ingeniería de Software no puede eliminar la complejidad esencial sin cambiar el problema. Pero sí puede reducir la complejidad accidental mediante buen diseño, modularidad, pruebas, documentación y refactorización.

5.4 Señales de complejidad mal gestionada

Cuando la complejidad no se administra, el proyecto empieza a mostrar síntomas claros:

  • Cada cambio requiere revisar demasiados archivos.
  • El equipo tiene miedo de modificar partes del sistema.
  • Una corrección provoca fallas en funcionalidades no relacionadas.
  • Solo una persona entiende una sección crítica del código.
  • Las reglas de negocio están mezcladas con detalles de interfaz o base de datos.
  • Las pruebas son difíciles de escribir o no existen.
  • El tiempo de desarrollo aumenta aunque las funcionalidades parezcan simples.

Estas señales indican que el sistema necesita más orden interno, no solamente más esfuerzo.

5.5 El software cambia constantemente

Otra característica fundamental del software es su tendencia al cambio. A diferencia de muchos productos físicos, el software puede modificarse después de entregado, y esa posibilidad genera expectativas: los usuarios esperan mejoras, correcciones y adaptaciones.

Los cambios pueden aparecer por muchos motivos:

  • Nuevas necesidades de usuarios.
  • Cambios en reglas de negocio.
  • Modificaciones legales o administrativas.
  • Nuevos dispositivos o navegadores.
  • Integración con otros sistemas.
  • Corrección de defectos.
  • Mejoras de rendimiento o seguridad.
  • Actualización de tecnologías y dependencias.

Por eso, un sistema debe pensarse para evolucionar. No se trata de anticipar todos los cambios posibles, sino de evitar diseños que hagan demasiado costoso cualquier cambio razonable.

5.6 Tipos de cambios en el software

Los cambios no siempre tienen la misma finalidad. Algunos corrigen problemas, otros adaptan el sistema y otros agregan valor.

Tipo de cambio Propósito Ejemplo
Correctivo Corregir defectos encontrados. Arreglar un cálculo incorrecto en una factura.
Adaptativo Ajustar el sistema a cambios del entorno. Modificar una integración porque cambió una API externa.
Perfectivo Mejorar funcionalidades, rendimiento o experiencia. Agregar filtros avanzados a un reporte usado diariamente.
Preventivo Reducir riesgos futuros y facilitar mantenimiento. Refactorizar un módulo antes de agregar nuevas reglas.

5.7 El costo del cambio

Modificar software puede ser barato o muy costoso según cómo esté construido. Si el sistema tiene responsabilidades separadas, pruebas y documentación útil, un cambio puede realizarse con confianza. Si el sistema está desordenado, cada cambio se vuelve riesgoso.

El costo del cambio depende de factores como:

  • Claridad de los requisitos.
  • Diseño interno del sistema.
  • Acoplamiento entre módulos.
  • Cantidad y calidad de pruebas.
  • Documentación disponible.
  • Conocimiento del equipo.
  • Dependencias con sistemas externos.
  • Deuda técnica acumulada.

Una meta importante de la Ingeniería de Software es mantener el costo del cambio dentro de límites razonables.

5.8 El software es invisible

El software no puede observarse completo como se observa un edificio, una máquina o un plano físico. Podemos ver pantallas, diagramas, código, bases de datos o documentación, pero ninguna de esas representaciones muestra todo el sistema de una vez.

Esta invisibilidad hace difícil responder preguntas como:

  • ¿Qué partes del sistema dependen de esta regla?
  • ¿Qué ocurre si cambia este dato?
  • ¿Qué funcionalidades usan este módulo?
  • ¿Dónde se valida esta condición?
  • ¿Qué camino sigue una solicitud desde la interfaz hasta la base de datos?
  • ¿Qué errores pueden aparecer en una integración?

Como no podemos ver el sistema completo de forma directa, necesitamos modelos, diagramas, documentación, pruebas, trazabilidad y herramientas de análisis.

5.9 Representaciones del software

Para trabajar con algo invisible, usamos representaciones. Cada una muestra una parte del sistema y oculta otras.

Representación Qué ayuda a ver Límite
Código fuente La implementación concreta. Puede ser demasiado detallado para entender el sistema completo.
Diagramas Estructura, comportamiento, relaciones o flujos. Son simplificaciones y pueden quedar desactualizados.
Documentación Decisiones, reglas, instrucciones y contexto. Depende de que se mantenga útil y vigente.
Pruebas Comportamientos esperados y casos importantes. No muestran todos los escenarios posibles.
Logs y métricas Comportamiento del sistema en ejecución. No explican por sí solos todas las causas.

5.10 El software no se desgasta, pero se deteriora

Un programa no se gasta por ejecutarse muchas veces. Si el mismo código se ejecuta con las mismas condiciones, no debería fallar por desgaste físico. Sin embargo, el software puede deteriorarse de otra manera.

Ese deterioro ocurre cuando el entorno cambia o cuando se acumulan modificaciones sin suficiente cuidado. Por ejemplo:

  • Una biblioteca queda obsoleta.
  • Un sistema operativo cambia una configuración.
  • Una API externa modifica su contrato.
  • Se agregan parches rápidos que duplican lógica.
  • Se postergan refactorizaciones necesarias.
  • Se pierden conocimientos sobre decisiones antiguas.

Por eso, aunque el software no se desgaste físicamente, puede volverse más difícil de mantener y menos adecuado para su contexto.

5.11 El software depende de su entorno

Un sistema no vive aislado. Depende de hardware, sistema operativo, bases de datos, navegadores, redes, servicios externos, usuarios, reglas legales, procesos de negocio y otros sistemas.

Cuando el entorno cambia, el software puede necesitar adaptación. Por ejemplo, una aplicación que funcionaba correctamente puede presentar problemas si cambia la versión del navegador, si aumenta mucho la cantidad de usuarios o si una integración externa empieza a responder de otra manera.

Esta dependencia del entorno obliga a pensar en compatibilidad, monitoreo, actualización, pruebas en distintos ambientes y gestión de configuración.

5.12 Consecuencias para el desarrollo

Las características vistas tienen consecuencias directas en la forma de trabajar:

Característica Problema que genera Prácticas que ayudan
Complejidad Es difícil comprender todas las relaciones del sistema. Modularidad, arquitectura, revisión de código y pruebas.
Cambio Los requisitos y el entorno evolucionan constantemente. Diseño mantenible, control de versiones, automatización y gestión de alcance.
Invisibilidad No se puede ver el sistema completo de una sola mirada. Diagramas, documentación, trazabilidad, métricas y modelos.
Dependencia del entorno El sistema puede fallar aunque el código no haya cambiado. Gestión de configuración, monitoreo y pruebas en ambientes representativos.
Deterioro por evolución Los cambios acumulados pueden volver el sistema difícil de mantener. Refactorización, gestión de deuda técnica y mejora continua.

5.13 Ejemplo: una aplicación de comercio electrónico

Imaginemos una tienda en línea. Al principio puede parecer simple: mostrar productos, agregar al carrito y pagar. Pero rápidamente aparecen muchas condiciones:

  • Productos con variantes de talle, color y stock.
  • Promociones que dependen de fechas, categorías o usuarios.
  • Impuestos según ubicación.
  • Pagos aprobados, rechazados o pendientes.
  • Envíos con distintos proveedores.
  • Devoluciones, cupones y facturación.
  • Usuarios invitados, registrados y administradores.

La complejidad surge por la combinación de reglas. El cambio aparece cuando se agregan promociones, medios de pago o nuevas políticas. La invisibilidad aparece porque ninguna pantalla muestra todas las relaciones internas del sistema.

5.14 Errores comunes al ignorar estas características

Cuando no se reconocen estas propiedades del software, suelen cometerse errores como:

  • Tratar cambios importantes como si fueran simples ajustes de código.
  • No documentar decisiones porque "el código ya lo muestra todo".
  • Agregar funcionalidades sin revisar el diseño general.
  • No escribir pruebas porque el sistema parece funcionar manualmente.
  • Subestimar integraciones con sistemas externos.
  • Permitir que una solución rápida se convierta en estructura permanente.
  • No reservar tiempo para mantenimiento y refactorización.

La Ingeniería de Software ayuda a reconocer estos riesgos antes de que se transformen en problemas difíciles de corregir.

5.15 Qué debes recordar de este tema

  • El software es complejo por la cantidad de reglas, relaciones, datos e integraciones que contiene.
  • Existe complejidad esencial del problema y complejidad accidental creada por malas decisiones.
  • El software cambia porque cambian usuarios, reglas, tecnología, entorno y necesidades.
  • El costo del cambio depende de la calidad del diseño, las pruebas, la documentación y el conocimiento del equipo.
  • El software es invisible: necesitamos representaciones para comprenderlo y comunicarlo.
  • Aunque no se desgaste físicamente, puede deteriorarse por cambios mal gestionados y obsolescencia.
  • Estas características justifican la necesidad de aplicar prácticas de Ingeniería de Software.

5.16 Conclusión

El software es difícil de desarrollar no solo porque requiere programar, sino porque combina complejidad, cambio e invisibilidad. Estas características hacen que los sistemas puedan volverse difíciles de entender, modificar y mantener si no se trabajan con método.

Para quien comienza, la idea principal es esta: la Ingeniería de Software existe porque el software cambia, crece y no puede comprenderse completamente sin modelos, prácticas y acuerdos de trabajo.

En el próximo tema estudiaremos a los actores interesados: usuarios, clientes, equipo y organización, para comprender quiénes influyen en un proyecto de software y por qué sus necesidades pueden ser distintas.