24.1 Objetivo del proyecto
Construiremos una aplicación que reciba una medición, compruebe su coherencia, la convierta a otra unidad compatible y genere un registro estructurado. No se trata solo de obtener un número: la herramienta debe explicar qué hizo y rechazar datos físicamente inválidos.
El resultado será una base extensible para incorporar nuevas magnitudes, unidades y reglas sin reescribir toda la interfaz.
24.2 Requisitos funcionales
- Ingresar valor, incertidumbre, unidad y cifras significativas.
- Elegir únicamente unidades compatibles con la magnitud.
- Convertir valores mediante una referencia interna.
- Propagar la incertidumbre a través de la conversión.
- Validar números, dominios físicos y coherencia del resultado.
- Mostrar un reporte legible y un objeto JSON reutilizable.
24.3 Requisitos de calidad
- Interfaz accesible mediante etiquetas y mensajes claros.
- Lógica independiente de la presentación.
- Datos originales preservados sin redondeos prematuros.
- Errores visibles, sin reemplazos silenciosos por cero.
- Diseño adaptable a pantallas pequeñas.
- Pruebas para ejemplos, límites y propiedades generales.
24.4 Diseño por capas
Catálogo
Define magnitudes, símbolos y transformaciones.
Dominio
Valida y convierte cantidades.
Presentación
Lee controles y muestra resultados.
Pruebas
Comprueba reglas y casos límite.
Esta separación evita que un cambio de estilo altere una equivalencia física y permite probar las funciones sin cargar el documento HTML.
24.5 Contrato de una medición
{
"value": 12.5,
"uncertainty": 0.1,
"unit": "ft",
"quantity": "length",
"significantDigits": 3
}La incertidumbre se interpreta aquí como estándar y no negativa. En una aplicación real convendría añadir fecha, instrumento, método, identificador y condiciones.
24.6 Catálogo de unidades
function linear(quantity, symbol, scale) {
return { quantity, symbol, scale,
toBase: value => value * scale,
fromBase: value => value / scale };
}
function affine(quantity, symbol, scale, offset) {
return { quantity, symbol, scale,
toBase: value => value * scale + offset,
fromBase: value => (value - offset) / scale };
}
const units = {
m: linear("length", "m", 1),
cm: linear("length", "cm", 0.01),
ft: linear("length", "ft", 0.3048),
degC: affine("temperature", "°C", 1, 273.15)
};
console.log("Unidades registradas:", Object.keys(units).join(", "));
console.log("12,5 ft =", units.ft.toBase(12.5), "m");
console.log("20 °C =", units.degC.toBase(20), "K");Las claves internas son estables; los símbolos pertenecen a la presentación. Las unidades lineales usan escala y las afines añaden un desplazamiento.
24.7 Conversión del valor
Antes de transformar se verifica que origen y destino existan y compartan magnitud. Para temperatura absoluta también se comprueba que el equivalente en kelvin no sea negativo.
24.8 Conversión de la incertidumbre
En una transformación lineal y = ax, la incertidumbre se convierte como u(y) = |a|u(x). Para una transformación afín y = ax + b, el desplazamiento b no influye:
Esta regla convierte una incertidumbre ya estimada; no incorpora automáticamente resolución, calibración u otras fuentes omitidas.
24.9 Reglas de validación
- El valor debe ser un número finito.
- La incertidumbre debe ser finita y mayor o igual que cero.
- Las cifras significativas deben ser enteras dentro del intervalo admitido.
- Las unidades deben existir y ser compatibles.
- El valor debe pertenecer al dominio físico de la magnitud.
- El resultado convertido también debe ser finito.
24.10 Aplicación integradora
Probá distintas magnitudes y observá el reporte de validación. El redondeo afecta la presentación; el objeto JSON conserva los valores numéricos calculados.
Conversor y validador de mediciones
Convierte valor e incertidumbre, verifica el dominio y construye un registro.
—
Validación
Registro generado
Este prototipo trabaja en el navegador y no envía ni almacena los datos ingresados.
24.11 Redondeo para presentación
El proyecto usa cifras significativas para mostrar el resultado, pero conserva el número completo en el registro. En informes metrológicos suele redondearse primero la incertidumbre a una o dos cifras significativas y luego el valor a la misma posición decimal.
La cantidad de dígitos elegida aquí permite experimentar; no sustituye una decisión basada en la incertidumbre y el propósito de la medición.
24.12 Mensajes útiles
“Error” informa muy poco. Un mensaje eficaz identifica el problema y su solución: “La incertidumbre debe ser mayor o igual que cero” o “La temperatura equivale a −2 K y está por debajo del cero absoluto”.
La validación debe aparecer junto al resultado y actualizarse cuando cambia la entrada.
24.13 Accesibilidad y uso con teclado
Cada control posee una etiqueta asociada, los resultados dinámicos usan una región anunciable y el estado no se comunica únicamente mediante color. Los elementos nativos conservan navegación con teclado y comportamiento familiar.
Una versión ampliada debería mover el foco al resumen de errores al enviar un formulario y relacionar cada mensaje con su campo mediante atributos ARIA.
24.14 Pruebas unitarias esenciales
const registry = {
m: { quantity: "length", toBase: x => x, fromBase: x => x },
ft: { quantity: "length", toBase: x => x * 0.3048, fromBase: x => x / 0.3048 },
s: { quantity: "duration", toBase: x => x, fromBase: x => x },
K: { quantity: "temperature", toBase: x => x, fromBase: x => x },
degC: { quantity: "temperature", toBase: x => x + 273.15, fromBase: x => x - 273.15 },
degF: { quantity: "temperature", toBase: x => (x - 32) * 5 / 9 + 273.15,
fromBase: x => (x - 273.15) * 9 / 5 + 32 }
};
function convert(value, source, target) {
const from = registry[source];
const to = registry[target];
if (!from || !to || from.quantity !== to.quantity) {
throw new Error("Magnitudes incompatibles");
}
return to.fromBase(from.toBase(value));
}
function validateUncertainty(value) {
if (!Number.isFinite(value) || value < 0) {
throw new Error("Incertidumbre no válida");
}
}
function assertClose(actual, expected, tolerance = 1e-12) {
if (Math.abs(actual - expected) > tolerance) {
throw new Error(`Esperado ${expected}; obtenido ${actual}`);
}
}
function assertThrows(operation) {
try { operation(); } catch { return; }
throw new Error("Se esperaba una excepción");
}
assertClose(convert(1, "ft", "m"), 0.3048);
assertClose(convert(0, "degC", "K"), 273.15);
assertClose(convert(32, "degF", "degC"), 0);
assertThrows(() => convert(1, "m", "s"));
assertThrows(() => validateUncertainty(-0.1));
console.log("Pruebas superadas: 5 de 5");
console.log("Conversión verificada: 1 ft =", convert(1, "ft", "m"), "m");assertClose compara con tolerancia para contemplar la representación binaria de punto flotante.
24.15 Pruebas de propiedades
- Convertir una unidad a sí misma conserva valor e incertidumbre.
- La ida y vuelta recupera el dato dentro de una tolerancia.
- La composición por una tercera unidad coincide con la conversión directa.
- Una conversión lineal nunca vuelve negativa una incertidumbre válida.
- Magnitudes incompatibles siempre son rechazadas.
24.16 Casos límite
Probá cero, números negativos permitidos, temperaturas cercanas a 0 K, incertidumbre cero, valores muy grandes y pequeños, coma decimal, campos vacíos e infinito. También conviene ensayar la misma unidad como origen y destino.
Un caso límite no es una rareza irrelevante: suele revelar supuestos que el código no hizo explícitos.
24.17 Persistencia e intercambio
El JSON generado puede enviarse a una API o almacenarse, pero requiere un esquema versionado. El receptor debe conocer la convención de unidades, el tipo de incertidumbre y la versión del catálogo.
JSON utiliza punto decimal en números. Las comas localizadas pertenecen a la interfaz, no al formato de intercambio.
24.18 Posibles ampliaciones
- Historial local y exportación CSV o JSON.
- Conversión de unidades compuestas mediante vectores dimensionales.
- Propagación de incertidumbres en fórmulas.
- Importación de certificados de calibración.
- Soporte multilingüe y alias de unidades.
- Pruebas automatizadas con un marco como Vitest.
24.19 Criterios de evaluación
| Aspecto | Evidencia esperada |
|---|---|
| Modelo | Valor, unidad, magnitud e incertidumbre explícitos. |
| Conversión | Factores y transformaciones correctos. |
| Validación | Rechazo de entradas y dominios inválidos. |
| Calidad | Funciones separadas, nombres claros y sin duplicación. |
| Pruebas | Casos normales, límites y propiedades. |
| Interfaz | Resultados comprensibles, accesibles y adaptables. |
24.20 Desafíos finales
- Agregá volumen y comprobá que galón estadounidense e imperial tengan claves distintas.
- Permití ingresar una lista de mediciones y convertir media y desviación estándar.
- Implementá redondeo de valor e incertidumbre a la misma posición decimal.
- Exportá el registro con fecha, instrumento y versión del catálogo.
- Escribí una prueba que recorra automáticamente todas las unidades y compruebe ida y vuelta.
24.21 Síntesis del curso
A lo largo del curso distinguimos magnitudes, dimensiones, unidades y sistemas; utilizamos el SI, notación científica y análisis dimensional; estudiamos instrumentos, errores, incertidumbres, repeticiones, propagación, calibración y trazabilidad.
El proyecto integra esas ideas en software: cada número conserva contexto, cada conversión valida dimensiones y cada resultado comunica su alcance. Medir bien y programar bien comparten una misma disciplina: hacer explícitos los supuestos.
24.22 Ideas para recordar
- Un conversor correcto comienza con un modelo de magnitudes, no con una colección de fórmulas aisladas.
- Valor, unidad, incertidumbre y contexto forman una medición.
- Validar antes de calcular evita resultados numéricos sin sentido físico.
- La presentación se redondea; el dato interno conserva precisión.
- Las pruebas y los mensajes de error son parte del resultado científico.
Con este proyecto queda completado el curso de Magnitudes, Unidades y Sistemas de Medición.