Especificación de estructuras de datos y programas
Este artículo es una explicación de conceptos sobre la especificación de estructuras de datos y programas, incluyendo preguntas de examen, componentes clave y etiquetas.
En resumen
Las estructuras de datos se describen formalmente mediante modelos, tipos, invariantes y esquemas. Las estructuras de programas se precisan a través de interfaces, precondiciones y postcondiciones, estados y flujo de control. El objetivo es lograr software inequívoco, verificable y mantenible.
Descripción técnica compacta
Especificación de datos
- Modelos: modelo ER o diagrama de clases UML
- Cardinalidades, claves, normalización (hasta 3NF)
- Reglas como invariantes
- Datos en interfaces legibles por máquina: JSON Schema (o DDL/XML Schema)
Especificación de programas
- Módulos/APIs con firmas
- Contratos de error
- Diseño por Contrato: precondición, postcondición, invariante
- Comportamiento: máquinas de estado, diagramas de actividad/secuencia
- Precisión: OCL (Object Constraint Language)
Las especificaciones sirven como base para validación automática, generación de stubs y Contract Tests.
Puntos clave para examen
- Cardinalidades/claves correctas: Los modelos de datos deben definir claves únicas y relaciones correctas entre entidades. Las cardinalidades mal definidas conducen a datos inconsistentes o consultas erróneas.
- JSON Schema para validación de entrada: JSON Schema describe estructuras permitidas y rangos de valores para datos JSON. Con él puedes verificar automáticamente las entradas antes de procesarlas y rechazar datos defectuosos.
- Precondiciones/postcondiciones y casos de error: Diseño por Contrato formula obligaciones para quien llama y quien es llamado. Las precondiciones deben cumplirse antes de la llamada, las postcondiciones después. Los casos de error se definen explícitamente como excepciones.
- Modelos de estado para transiciones permitidas: Los diagramas de estado muestran en qué estados puede encontrarse un objeto y qué transiciones están permitidas. Esto evita cambios de estado inválidos, como reenviar un pedido cancelado.
- Derivación de casos de prueba (clases de equivalencia/valores límite): Los casos de prueba se pueden desarrollar deliberadamente a partir de especificaciones. Las invariantes y condiciones generan clases de equivalencia, las claves y valores límite generan datos de prueba concretos.
- Versionado, migración y deprecación: Los esquemas e interfaces cambian con el tiempo. El versionado semántico, las notificaciones de deprecación y las rutas de migración ayudan a introducir cambios de forma controlada.
- Seguridad: validación, permisos y campos de auditoría: Las especificaciones deben incluir aspectos de seguridad. Esto incluye validación de entrada, derechos de acceso y registro de quién cambió qué datos y cuándo.
Componentes clave
- Tipo de dato abstracto + rango de valores - Un tipo de dato abstracto define los valores posibles y operaciones de una estructura de datos. El rango de valores especifica qué entradas son válidas, como números positivos o cadenas que coinciden con ciertos patrones.
- Modelo de estructura (ER/clase) - Un modelo ER o diagrama de clases UML describe las entidades, sus atributos y relaciones. El modelo de estructura es la base para bases de datos y modelos de objetos.
- Cardinalidades + formas normales - Las cardinalidades indican cuántas entidades están conectadas entre sí. Las formas normales reducen redundancias y previenen anomalías al insertar, modificar o eliminar datos.
- Esquema de datos (JSON Schema) - JSON Schema es una descripción legible por máquina de datos JSON. Especifica tipos, campos obligatorios, rangos de valores y patrones, y permite validación automática.
- Contrato de API + códigos de error - Un contrato de API describe interfaces, parámetros, valores de retorno y casos de error. Los códigos de error y mensajes ayudan a quien llama a identificar problemas y tratarlos correctamente.
- Diseño por Contrato - Diseño por Contrato define precondiciones, postcondiciones e invariantes. Garantiza que quien llama y quien es llamado cumplan sus acuerdos y facilita la búsqueda de errores.
- Modelos de estado/proceso - Los modelos de estado muestran estados permitidos y transiciones. Los modelos de proceso como diagramas de actividad describen flujos y decisiones dentro de la lógica del programa.
- Reglas de calidad (RNF) - Los requisitos no funcionales como rendimiento, seguridad o disponibilidad se establecen como reglas de calidad. Complementan la especificación funcional con criterios medibles.
- Derivación de pruebas (Contract/Property) - Los casos de prueba se pueden derivar de especificaciones. Los Contract Tests verifican contratos de interfaz, los Property-based Tests verifican propiedades generales como invariantes.
- Concepto de versión/migración - Los cambios en esquemas o APIs deben versionarse. Un concepto de migración describe cómo se transfieren datos existentes y clientes a nuevas versiones.
Ejemplo práctico (Pedido)
JSON Schema (extracto como texto)
type: object
required: id, kundeId, positionen, gesamt
properties:
id: string (pattern ^ORD-[0-9]{6}$)
gesamt: number (minimum 0)
positionen: array (minItems 1)
Invariantes OCL (en sentido)
context Bestellung inv SummeStimmt:
gesamt = sum(positionen.preis * positionen.menge)
context Bestellung inv PositiveMengen:
forAll(positionen, menge > 0)
Contrato de servicio (pseudocódigo)
interface BestellService
legeBestellungAn(warenkorb)
precondición:
warenkorb.positionen no vacío y warenkorb.gesamt > 0
postcondición:
result.status = ANGELEGT y result.gesamt = warenkorb.gesamt
casos de error:
UngültigeDaten, ZahlungAbgelehnt
Ventajas y desventajas
Ventajas
- Comunicación inequívoca
- Validación automatizable
- Mayor verificabilidad y menos errores de integración
Desventajas
- Esfuerzo inicial
- Mantenimiento de versiones/migraciones
- Riesgo de formalismo excesivo
Preguntas típicas de examen (con respuesta breve)
- ¿Modelo ER vs diagrama de clases? ER para datos/persistencia, clase para tipos + operaciones.
- ¿Para qué sirven las invariantes? Reglas que siempre deben cumplirse.
- ¿Cómo surgen las pruebas a partir de la especificación? Precondiciones/invariantes → clases de equivalencia/valores límite.
- ¿Cómo se versionan esquemas de forma segura? Semver, cambios incompatibles = Mayor, deprecación + migración.
Estrategia de aprendizaje
- Introducción conceptual: Modela un pequeño dominio como una biblioteca o tienda en línea como diagrama de clases. Deduce un JSON Schema y algunas invariantes.
- Método de profundización: Formula precondiciones, postcondiciones y casos de error para una función existente. Escribe casos de prueba con clases de equivalencia y valores límite.
- Entrenamiento enfocado en examen: Practica la distinción entre modelo ER y diagrama de clases, así como la notación correcta de invariantes y transiciones de estado.
- Prevención de errores: Mantén las especificaciones actualizadas. Cuando el sistema cambia, también deben actualizarse el modelo, esquema y contratos, de lo contrario se crea deuda técnica.
Ejercicio 1: JSON Schema para un pedido
Un pedido tiene un ID en formato ORD- más seis dígitos, una ID de cliente, al menos una posición y un monto total que debe ser mayor o igual a cero. JSON Schema establece estas reglas de forma formal y puede verificar la entrada automáticamente.
Ejemplo práctico 2: Invariantes OCL para una orden
Una orden tiene la invariante de que el monto total debe corresponder a la suma de todas las líneas. Otra invariante establece que cada cantidad debe ser positiva. Estas invariantes se pueden trasladar a pruebas.
Ejemplo práctico 3: Design by Contract para un servicio de pedidos
La función crearPedido requiere como precondición un carrito no vacío con un monto total positivo. Como postcondición se establece que el pedido tenga el estado CREADO y el monto sea correcto. Los casos de error, como datos inválidos o pago rechazado, se mencionan explícitamente.
Ejercicio 1: Elegir el tipo de modelo
Deseas documentar la estructura de datos para una base de datos relacional. ¿Qué modelo es más apropiado, ER o diagrama de clases?
Solución: El modelo ER es más apropiado porque representa entidades, atributos y relaciones para el diseño de bases de datos. Un diagrama de clases se enfoca más en tipos, operaciones y herencia.
Ejercicio 2: Derivar una invariante
Una línea de pedido tiene los atributos precio y cantidad. Formula una invariante significativa.
Solución: Una invariante significativa es cantidad > 0 y precio >= 0. Ambas deben cumplirse siempre para que la línea sea válida.
Ejercicio 3: Explicar un modelo de estados
Un pedido puede tener los estados CREADO, PAGADO, ENVIADO y CANCELADO. ¿Qué transiciones tienen sentido y cuáles no?
Solución: Las transiciones sensatas son CREADO → PAGADO, PAGADO → ENVIADO y CREADO → CANCELADO. No tienen sentido ENVIADO → CREADO o CANCELADO → ENVIADO, porque violarían el flujo de negocio.
Análisis del tema
- Núcleo técnico: Descripción formal de datos y comportamiento. Las especificaciones establecen qué datos son permitidos y cómo debe comportarse el sistema. Los modelos, esquemas y contratos son los instrumentos centrales.
- Desafíos de implementación: Balance entre precisión y practicidad. Las especificaciones demasiado formales son costosas de mantener, las imprecisas llevan a malentendidos. El nivel de detalle adecuado depende del proyecto.
- Implicaciones de seguridad: Validación y derechos como parte de la especificación. La validación de entrada, control de acceso y pistas de auditoría deben considerarse desde la especificación para no olvidarlos en la implementación.
- Obligaciones documentales: Modelos, esquemas y contratos como documentación del proyecto. Las especificaciones son componentes vinculantes de la documentación del proyecto. Ayudan a alinear requisitos entre área comercial, desarrollo y pruebas.
- Evaluación económica: Esfuerzo de especificación versus ahorro por menos errores. Una buena especificación cuesta tiempo al principio, pero evita errores costosos y correcciones en fases posteriores. La validación automatizable y la derivación de pruebas aumentan el valor.



