Convertidor de unidades: Temperatura

Prev Next

To download the app, visit: [tulip](https://<span translate=).co/library/apps/unit-converter--temperature/">Library

En este artículo, uno de nuestros desarrolladores de la biblioteca, Tamás, explica las decisiones de desarrollo que hay detrás de la aplicación «Convertidor de unidades: Temperatura», disponible en la biblioteca.

Por qué utilicé una lista de objetos en lugar de una tabla

Hola, soy Tamás, de Tulip.

Para este componente, decidí utilizar una lista de objetos almacenada como valores de variables predeterminados, ya que el conjunto de datos rara vez cambia y no requiere una gestión basada en tablas.

En este caso, los factores de conversión de temperatura y las compensaciones son relaciones matemáticas estáticas. No requieren edición en tiempo de ejecución, agregación ni consultas relacionales. Por eso, evité deliberadamente utilizar una tabla. En su lugar:* Almaceno las definiciones de conversión dentro de una variable* La variable se inicializa con valores por defecto* La lista de objetos proporciona una vista de datos estructurada y legible* No se requiere ninguna lógica de agregación de tablas

Este enfoque mantiene el componente ligero y autónomo.

¿Por qué no una tabla?

El uso de una tabla supondría:* La necesidad de añadir una tabla adicional a la aplicación* La necesidad de crear una consulta sobre esa tabla* La necesidad de configurar la lógica de agregación para esa consulta* La necesidad de añadir y mantener también esa consulta y esa agregación dentro de la aplicación

Para un conjunto de datos que rara vez cambia, esa sobrecarga es innecesaria.

Al almacenar las definiciones de conversión como valores por defecto dentro de una variable:* El componente se vuelve totalmente portátil* Al copiar la aplicación también se copia la estructura de datos* No se requiere ninguna dependencia externa

La lista de objetos ofrece una vista clara y estructurada de los atributos relacionados (inputUnit-targetUnit, factor, offset) sin necesidad de lógica relacional.

Principio de diseño: lógica protegida, configuración flexible

El componente se diseñó siguiendo un principio clave:

La lógica central nunca debe requerir modificaciones.

Para respaldar esto, introduje variables internas del componente y las marqué con un guión bajo al principio (por ejemplo, _temperatureInputUnit). Estas variables con guión bajo actúan como interfaces internas estables en las que puede basarse la lógica central protegida.

Compensación: el uso de variables internas requiere dos pequeños desencadenantes de configuración:* 01 – CONFIGURACIÓN DEL USUARIO: LA ETAPA DE ENTRADA asigna fuentes externas a variables internas* 03 – CONFIGURACIÓN DEL USUARIO: LA ETAPA DE SALIDA asigna el resultado interno al destino deseado

Esto añade una ligera capa de configuración alrededor del motor protegido, pero mantiene intacto el disparador MAGIC y facilita el copiar y pegar.

Opción alternativa

Un enfoque más sencillo —aunque menos fácil de mantener— consistiría en pegar referencias externas directamente en la expresión principal (por ejemplo, utilizando una variable de la aplicación o un marcador de posición « table record field » en línea).

Esto evita los desencadenadores de configuración adicionales, pero reduce la portabilidad y dificulta la reutilización, ya que cada copia requiere editar la lógica central.

Para la distribución de componentes, el patrón de interfaz de variables internas es más fácil de gestionar: las entradas y salidas se configuran en los extremos, mientras que el motor de cálculo permanece estable y protegido.

El disparador MAGIC realiza una búsqueda y aplica una transformación afín:

resultado = (valor × factor) + desplazamiento

Dado que las definiciones de conversión están centralizadas en la lista de objetos internos, el disparador puede gestionar múltiples casos sin necesidad de modificaciones.

En esta implementación:* Se admiten °C, K y °F* Las tres combinaciones 3×3 están predefinidas* La lógica resuelve dinámicamente el factor y el desplazamiento correctos

El desarrollador de la aplicación solo tiene que: 1. Configurar las fuentes de entrada 2. Configurar el destino de salida

Sin reescribir fórmulas. Sin editar la lógica condicional. Sin cambios estructurales.

Por qué es escalable

Esta estructura permite:* Añadir nuevas unidades ampliando la lista de objetos* Mantener intacto el motor de cálculo* Mantener la coherencia arquitectónica entre aplicaciones* Reutilizar rápidamente el código en múltiples proyectos

El componente separa:* La configuración de la fuente de datos (etapa de entrada)* La lógica de ejecución (MAGIC)* El enrutamiento de resultados (etapa de salida)

Esta separación mantiene el sistema seguro, predecible y escalable.

Desglose del desencadenador: cómo funciona MAGIC (expresión)

El disparador MAGIC protegido se implementa como una única expresión:(@Variable._temperatureInputValue * array_value_at_index( map_to_number_list(@Variable._temperatureConversionDefaults , 'factor'), array_index_of( map_to_text_list(@Variable._temperatureConversionDefaults , 'inputUnit-targetUnit'), @Variable._temperatureInputUnit + '-' + @Variable._temperatureTargetUnit )))+array_value_at_index( map_to_number_list(@Variable._temperatureConversionDefaults , 'offset'), array_index_of( map_to_text_list(@Variable._temperatureConversionDefaults , 'inputUnit-targetUnit'), @Variable._temperatureInputUnit + '-' + @Variable._temperatureTargetUnit ))A grandes rasgos, esta expresión realiza tres pasos:

1. Crear la clave de búsqueda

La clave se construye dinámicamente a partir de las variables de entrada configuradas:

unidad_de_entrada-unidad_de_destino

Por ejemplo:

°C-°F

Esto garantiza que la lógica siga siendo genérica y funcione para todas las combinaciones admitidas.

2. Resolver el factor y el desplazamiento a partir de la lista de objetos

La expresión resuelve el factor y el desplazamiento en una sola pasada:* map_to_text_list(..., 'inputUnit-targetUnit') crea la lista de claves de búsqueda sobre la marcha.* array_index_of(...) encuentra el índice de la clave coincidente.* array_value_at_index(...) utiliza ese índice para extraer los valores correspondientes de las listas de factor y desplazamiento.

La decisión clave de diseño aquí es combinar array\_index\_of(...) directamente con map\_to\_text\_list(...). Esto evita almacenar una lista de claves intermedia en una variable separada. En su lugar, la lista de búsqueda se genera en línea y se utiliza inmediatamente para recuperar tanto el factor como el desplazamiento dentro de una única expresión.

Esto mantiene el disparador MAGIC autónomo y reduce la superficie de configuración, al tiempo que sigue comportándose como una búsqueda estructurada, sin necesidad de una tabla ni de lógica de agregación.

3. Aplicar la transformación afín

Una vez determinados el factor y el desplazamiento correctos, se aplica el cálculo:

resultado = (valor × factor) + desplazamiento

Dado que la lógica de consulta se basa en índices y está orientada a los datos, el disparador no requiere ramificaciones condicionales ni estructuras «switch-case».

Por qué se eligió esta estructura

  • Evita la lógica condicional codificada de forma rígida.
  • Se adapta de forma natural cuando se añaden nuevas combinaciones de unidades.
  • Mantiene el cálculo totalmente basado en los datos.
  • Mantiene una única expresión protegida en lugar de múltiples desencadenadores.

Este diseño hace que el componente sea determinista, extensible y esté a salvo de modificaciones accidentales de la lógica.

Ampliación con nuevas unidades

Para añadir una nueva unidad, amplíe _temperatureConversionDefaults añadiendo una nueva entrada que incluya:* inputUnit-targetUnit (clave)* factor* offset

Una vez que la nueva correspondencia existe en la lista de objetos, el disparador protegido MAGIC puede resolverla automáticamente; no se requieren cambios en la lógica central.

Gestión de errores (patrón de búsqueda segura)

El disparador MAGIC incluye una detección explícita de fallos para garantizar una ejecución segura cuando no se encuentra un par de conversión. En lugar de basarse en un resultado en blanco, el disparador comprueba directamente el índice de búsqueda:

ARRAY_INDEX_OF( MAP_TO_TEXT_LIST(_temperatureConversionDefaults, 'inputUnit-targetUnit'), _temperatureInputUnit + '-' + _temperatureTargetUnit )

Si el índice devuelto es igual a -1, no existe ninguna regla de conversión que coincida.

Flujo de ejecución: 1. Borrar _temperatureConversionResult al inicio del disparador. 2. Si el índice de búsqueda = -1 → no realizar el cálculo. 3. En caso contrario → calcular y almacenar el resultado.

A continuación, la etapa OUTPUT comprueba lo siguiente:

Si _temperatureConversionResult está en blanco → mostrar un mensaje de error.

Ejemplo de mensaje:

«No se ha encontrado ninguna regla de conversión para el par de unidades seleccionado. Comprueba el formato de las unidades (°C, K, °F) y que el par exista en _temperatureConversionDefaults».

Esto garantiza:• Que no queden valores obsoletos de ejecuciones anteriores • Que no se intente realizar ningún cálculo sin una regla válida • Que el usuario reciba un mensaje de error claro y que permita actuar

La lógica central permanece protegida y sin cambios, al tiempo que sigue ofreciendo un comportamiento determinista y seguro.

¿Por qué no utilizar matrices separadas para claves, factores y compensaciones?

Un enfoque alternativo habría sido almacenar:* Las claves de búsqueda en un array* Los factores en otro array* Las compensaciones en un tercer array

Aunque esto funcionaría técnicamente, introduciría un riesgo estructural: la relación posicional entre los arrays debe permanecer siempre perfectamente alineada.

Si el orden de una matriz cambiara y el de las demás no, la relación clave-factor-desplazamiento se rompería de forma silenciosa, lo que daría lugar a conversiones incorrectas.

Al almacenar los atributos relacionados juntos en una lista de objetos, cada entrada mantiene sus valores de «inputUnit-targetUnit», factor y desplazamiento agrupados de forma lógica. Esto reduce el riesgo de desalineación y hace que la estructura sea más segura y fácil de mantener.

Participa

Únete a la comunidad para compartir mejoras, proponer unidades adicionales, informar de problemas o debatir decisiones arquitectónicas.