TL; DR - Sto provando a progettare una struttura dati ottimale per definire le unità all'interno di un'unità di misura.
Un Unit of measure
è essenzialmente un value
(o quantità) associato a unit
. Le unità SI hanno sette basi o dimensioni. Vale a dire: lunghezza, massa, tempo, corrente elettrica, temperatura, quantità di sostanza (moli) e intensità luminosa.
Questo sarebbe abbastanza semplice, ma ci sono un certo numero di unità derivate e tariffe che usiamo frequentemente. Un esempio di unità combinata sarebbe il Newton: kg * m / s^2
e un tasso di esempio sarebbe tons / hr
.
Abbiamo un'applicazione che fa molto affidamento sulle unità implicite. Incorporeremo le unità all'interno del nome della variabile o della colonna. Ma questo crea problemi quando abbiamo bisogno di specificare un'unità di misura con unità diverse. Sì, possiamo convertire i valori in input e display ma questo genera un sacco di codice di sovraccarico che vorremmo incapsulare all'interno della sua stessa classe.
Esistono numerose soluzioni su codeplex e altri ambienti collaborativi. La concessione di licenze per i progetti è gradevole, ma il progetto di solito finisce per essere troppo leggero o troppo pesante. Stiamo dando la caccia al nostro unicorno di "giusto".
Idealmente, potrei definire una nuova unità di misura usando qualcosa del genere:
UOM myUom1 = new UOM(10, volts);
UOM myUom2 = new UOM(43.2, Newtons);
Naturalmente, utilizziamo un mix di unità Imperial e SI in base alle esigenze dei nostri clienti.
Abbiamo anche bisogno di mantenere questa struttura di unità sincronizzata con una futura tabella di database in modo da poter fornire lo stesso grado di coerenza anche all'interno dei nostri dati.
Qual è il modo migliore per definire le unità, le unità derivate e le tariffe che dobbiamo utilizzare per creare la nostra classe di unità di misura? Potrei vedere usando una o più enumerazioni, ma potrebbe essere frustrante per altri sviluppatori. Un singolo enum sarebbe enorme con oltre 200 voci, mentre più enumerazioni potrebbero essere confuse basandosi su unità SI contro unità imperiali e ulteriore suddivisione basata sulla categorizzazione dell'unità stessa.
Esempi di enum che mostrano alcuni dei miei dubbi:
myUnits.Volt
myUnits.Newton
myUnits.meterSIUnit.meter
ImpUnit.foot DrvdUnit.Newton
DrvdUnitSI.Newton
DrvdUnitImp.FtLbs
Il nostro set di unità in uso è ben definito ed è uno spazio finito. Abbiamo bisogno della capacità di espandere e aggiungere nuove unità o tariffe derivate quando abbiamo la domanda dei clienti per loro. Il progetto è in C # anche se penso che gli aspetti di progettazione più ampi siano applicabili a più lingue.
Una delle librerie che ho visto consente l'immissione di unità in forma libera tramite stringa. La loro classe UOM ha poi analizzato la stringa e inserito le voci di conseguenza. La sfida con questo approccio è che costringe lo sviluppatore a pensare e ricordare quali sono i formati di stringa corretti. E corro il rischio di un errore / eccezione di runtime se non aggiungiamo ulteriori controlli all'interno del codice per convalidare le stringhe che vengono passate nel costruttore.
Un'altra libreria essenzialmente ha creato troppe classi con le quali lo sviluppatore avrebbe dovuto lavorare. Insieme a un UOM equivalente ha fornito un DerivedUnit
e RateUnit
e così via. Essenzialmente, il codice era eccessivamente complesso per i problemi che stiamo risolvendo. Quella libreria essenzialmente consentirebbe qualsiasi: qualsiasi combinazione (che è legittima nel mondo delle unità) ma siamo felici di risolvere il nostro problema (semplificare il nostro codice) non consentendo ogni possibile combinazione.
Altre librerie erano ridicolmente semplici e non avevano nemmeno considerato il sovraccarico dell'operatore, ad esempio.
Inoltre, non sono preoccupato per i tentativi di conversioni errate (ad esempio: volt in metri). Gli sviluppatori sono gli unici che accederanno a questo livello a questo punto e non abbiamo necessariamente bisogno di proteggere da questi tipi di errori.