To download the app, visit: [tulip](https://<span translate=).co/library/apps/unit-converter--temperature/">Library
In questo articolo, Tamás, uno dei nostri sviluppatori della libreria, illustra le scelte di sviluppo alla base dell’app “Convertitore di unità: Temperatura”, disponibile nella libreria.
Perché ho utilizzato un elenco di oggetti invece di una tabella
Ciao, sono Tamás di Tulip.
Per questo componente, ho deciso di utilizzare un elenco di oggetti memorizzati come valori predefiniti delle variabili, poiché il set di dati cambia raramente e non richiede una gestione basata su tabelle.
In questo caso, i fattori di conversione della temperatura e gli offset sono relazioni matematiche statiche. Non richiedono modifiche in fase di esecuzione, aggregazioni o query relazionali. Per questo motivo, ho deliberatamente evitato di utilizzare una tabella. Invece:* Memorizzo le definizioni di conversione all’interno di una variabile* La variabile viene inizializzata con valori predefiniti* L’elenco di oggetti fornisce una visualizzazione dei dati strutturata e leggibile* Non è richiesta alcuna logica di aggregazione delle tabelle
Questo approccio mantiene il componente leggero e autonomo.
Perché non una tabella?
L’uso di una tabella comporterebbe:* La necessità di aggiungere una tabella aggiuntiva all’app* La necessità di creare una query su quella tabella* La necessità di configurare la logica di aggregazione per quella query* La necessità di aggiungere e mantenere quella query e l’aggregazione all’interno dell’app
Per un set di dati che cambia raramente, tale sovraccarico è superfluo.
Memorizzando le definizioni di conversione come valori predefiniti all’interno di una variabile:* Il componente diventa completamente portabile* Copiando l’app si copia anche la struttura dei dati* Non è richiesta alcuna dipendenza esterna
L’elenco degli oggetti offre una visione chiara e strutturata degli attributi correlati (inputUnit-targetUnit, fattore, offset) senza richiedere una logica relazionale.
Principio di progettazione: logica protetta, configurazione flessibile
Il componente è stato progettato secondo un principio fondamentale:
La logica di base non dovrebbe mai richiedere modifiche.
A tal fine, ho introdotto variabili interne al componente e le ho contrassegnate con un trattino basso iniziale (ad esempio, _temperatureInputUnit). Queste variabili con trattino basso fungono da interfacce interne stabili su cui la logica di base protetta può fare affidamento.
Compromesso: l’uso di variabili interne richiede due piccoli trigger di configurazione:* 01 – CONFIG URENTE: FASE DI INGRESSO mappa le fonti esterne nelle variabili interne* 03 – CONFIG URENTE: FASE DI USCITA mappa il risultato interno alla destinazione desiderata
Ciò aggiunge un sottile livello di configurazione attorno al motore protetto, ma mantiene intatto il trigger MAGIC e ne facilita il copia/incolla.
Opzione alternativa
Un approccio più semplice — ma meno gestibile — consisterebbe nell’inserire direttamente i riferimenti esterni nell’espressione principale (ad esempio, utilizzando una variabile dell’app o un segnaposto table record field in linea).
Ciò evita i trigger di configurazione aggiuntivi, ma riduce la portabilità e rende più difficile il riutilizzo poiché ogni copia richiede la modifica della logica di base.
Per la distribuzione dei componenti, il modello di interfaccia con variabili interne è più facile da gestire: gli input e gli output vengono configurati ai bordi, mentre il motore di calcolo rimane stabile e protetto.
Il trigger MAGIC esegue una ricerca e applica una trasformazione affine:
risultato = (valore × fattore) + offset
Poiché le definizioni di conversione sono centralizzate nell’elenco degli oggetti interni, il trigger può gestire più casi senza modifiche.
In questa implementazione:* Sono supportati °C, K e °F* Tutte le combinazioni 3×3 sono predefinite* La logica determina dinamicamente il fattore e l’offset corretti
Lo sviluppatore dell’app deve solo:1. Configurare le fonti di input2. Configurare la destinazione di output
Nessuna riscrittura di formule. Nessuna modifica della logica condizionale. Nessuna modifica strutturale.
Perché questa soluzione è scalabile
Questa struttura consente di:* Aggiungere nuove unità estendendo l’elenco degli oggetti* Mantenere inalterato il motore di calcolo* Mantenere la coerenza architettonica tra le app* Riutilizzare rapidamente il codice in più progetti
Il componente separa:* La configurazione delle fonti dati (fase di input)* La logica di esecuzione (MAGIC)* L’instradamento dei risultati (fase di output)
Questa separazione garantisce che il sistema sia sicuro, prevedibile e scalabile.
Analisi del trigger – Come funziona il MAGIC (espressione)
Il trigger MAGIC protetto è implementato come una singola espressione:(@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 livello generale, questa espressione esegue tre passaggi:
1. Costruisce la chiave di ricerca
La chiave viene costruita dinamicamente a partire dalle variabili di input configurate:
unità_di_ingresso-unità_di_destinazione
Ad esempio:
°C-°F
Ciò garantisce che la logica rimanga generica e funzioni per tutte le combinazioni supportate.
2. Risoluzione del fattore e dell’offset dall’elenco degli oggetti
L'espressione risolve il fattore e l'offset in un unico passaggio:* map_to_text_list(..., 'inputUnit-targetUnit') crea al volo l'elenco delle chiavi di ricerca.* array_index_of(...) individua l’indice della chiave corrispondente.* array_value_at_index(...) utilizza tale indice per estrarre i valori corrispondenti dagli elenchi del fattore e dell’offset.
La scelta progettuale chiave in questo caso è quella di comporre array_index_of(...) direttamente con map_to_text_list(...). Ciò evita di memorizzare un elenco di chiavi intermedio in una variabile separata. L’elenco di ricerca viene invece generato inline e utilizzato immediatamente per recuperare sia il fattore che l’offset all’interno di un’unica espressione.
Ciò mantiene il trigger MAGIC autonomo e riduce la superficie di configurazione, pur continuando a comportarsi come una ricerca strutturata, senza richiedere una tabella o una logica di aggregazione.
3. Applicare la trasformazione affine
Una volta determinati il fattore e l’offset corretti, viene applicato il calcolo:
risultato = (valore × fattore) + offset
Poiché la logica di ricerca è basata su indici e guidata dai dati, il trigger non richiede ramificazioni condizionali né strutture switch-case.
Perché è stata scelta questa struttura
- Evita la logica condizionale hardcoded.
- Si adatta in modo naturale all'aggiunta di nuove combinazioni di unità.
- Mantiene il calcolo interamente basato sui dati.
- Mantiene un'unica espressione protetta invece di più trigger.
Questo design mantiene il componente deterministico, estensibile e al riparo da modifiche accidentali alla logica.
Estensione con nuove unità
Per aggiungere una nuova unità, estendere _temperatureConversionDefaults aggiungendo una nuova voce che includa:* inputUnit-targetUnit (chiave)* fattore* offset
Una volta che la nuova mappatura è presente nell’elenco degli oggetti, il trigger MAGIC protetto può risolverla automaticamente: non sono necessarie modifiche alla logica di base.
Gestione degli errori (modello di ricerca sicuro)
Il trigger MAGIC include un rilevamento esplicito degli errori per garantire un'esecuzione sicura quando non viene trovata una coppia di conversione. Anziché affidarsi a un risultato vuoto, il trigger controlla direttamente l’indice di ricerca:
ARRAY_INDEX_OF( MAP_TO_TEXT_LIST(_temperatureConversionDefaults, 'inputUnit-targetUnit'), _temperatureInputUnit + '-' + _temperatureTargetUnit )
Se l’indice restituito è pari a -1, non esiste alcuna regola di conversione corrispondente.
Flusso di esecuzione: 1. Azzerare _temperatureConversionResult all’inizio del trigger. 2. Se l’indice di ricerca = -1 → non eseguire il calcolo. 3. Altrimenti → eseguire il calcolo e memorizzare il risultato.
La fase OUTPUT verifica quindi:
Se _temperatureConversionResult è vuoto → visualizza un messaggio di errore.
Esempio di messaggio:
"Nessuna regola di conversione trovata per la coppia di unità selezionata. Verificare il formato delle unità (°C, K, °F) e che la coppia esista in _temperatureConversionDefaults."
Ciò garantisce:• Che non rimangano valori obsoleti da esecuzioni precedenti • Che non venga tentato alcun calcolo senza una regola valida • Che l’utente riceva un messaggio di errore chiaro e utilizzabile
La logica di base rimane protetta e invariata, garantendo al contempo un comportamento deterministico e sicuro.
Perché non utilizzare array separati per chiavi, fattori e offset?
Un approccio alternativo sarebbe stato quello di memorizzare:* Le chiavi di ricerca in un array* I fattori in un altro array* Gli offset in un terzo array
Sebbene ciò funzionerebbe tecnicamente, comporterebbe un rischio strutturale: la relazione posizionale tra gli array deve rimanere sempre perfettamente allineata.
Se l’ordine di un array cambiasse e quello degli altri no, la relazione chiave–fattore–offset verrebbe compromessa in modo silenzioso, generando conversioni errate.
Memorizzando gli attributi correlati insieme in un elenco di oggetti, ogni voce mantiene i valori di inputUnit-targetUnit, fattore e offset raggruppati in modo logico. Ciò riduce il rischio di disallineamento e rende la struttura più sicura e più facile da mantenere.
Partecipa
Entra a far parte della comunità per condividere miglioramenti, proporre nuove unità, segnalare problemi o discutere le scelte architetturali.
