A „Tömeg” mértékegység-átváltó letöltéséhez látogasson el ide: [tulip](https://<span translate=).co/library/apps/unit-converter--mass">Library
A Térfogat-átváltó letöltéséhez látogasson el ide: [tulip.co/library/apps/unit-converter--volume">Library](https://<span translate=)
Ebben a cikkben Tamás, az egyik könyvtárfejlesztőnk, bemutatja a könyvtárban elérhető Mértékegység-átváltó építőelem-alkalmazás fejlesztése során hozott döntéseket.
Miért használtam objektumlistát táblázat helyett
Sziasztok, Tamás vagyok a Tulip-tól.
Amikor elkészítettem ezt az egységátalakító komponenst, az egyik első architektúrai döntésem az volt, hogy nem használok táblázatot. Ehelyett úgy döntöttem, hogy mindent objektumlistákban tárolok, amelyeket alapértelmezett komponensváltozókként inicializáltam.
Az indoklás egyszerű volt: az egységátváltás ebben a kontextusban matematikai állandóként viselkedik, nem pedig operatív adatként. A kapcsolatok tisztán szorzó jellegűek, ritkán változnak, és nem igényelnek futásidejű szerkesztést, összesítést, szűrést vagy relációs lekérdezéseket. Egy táblázat bevezetése a következőket jelentette volna: * további infrastruktúra létrehozása és karbantartása, * lekérdezések és aggregations konfigurálása, * egy újabb függőségi réteg hozzáadása minden olyan alkalmazáshoz, amely a komponenst használja.
Ez növelte volna a komplexitást anélkül, hogy javította volna a képességeket.
Ezért ehelyett az adatkészleteket közvetlenül a komponensbe ágyaztam:* Kanonikus alapadatkészletek: * _lengthToBaseDefaults * _massToBaseDefaults * _volumeToBaseDefaults
- Szinonima-szótárak:
- _lengthUnitAliases
- _massUnitAliases
- _volumeUnitAliases
Mindkettő alapértelmezett változóértékként létezik. Ezáltal a komponens:* Hordozható* Önálló* Determinisztikus* Könnyen másolható az alkalmazások között
Ha az adatkészlet konstansként viselkedik, inkább a komponensen belül védem meg, mintsem külsővé tegyem.
Miért nem táblázat?
Egy táblázatalapú megoldás olyan strukturális függőséget vezetne be, amelyet ez a probléma nem indokol.
Az egységdefiníciók nem tranzakciós adatok. Strukturális definíciók. Operatív rekordként kezelni őket aránytalan lenne a problémához képest.
Célom itt az architektúra arányossága volt: csak annyi infrastruktúrát használni, amennyire a probléma valóban szükség van.
Tervezési elv: védett logika, rugalmas konfiguráció
Ez a komponens két alapgondolatot követ:1. Kanonikus alapnormalizálás 2. Bemeneti tolerancia szinonima-feloldás révén
Szándékosan elválasztottam a matematikai igazságot a felhasználói rugalmasságtól.* A kanonikus alapadatkészletek határozzák meg a matematikai összefüggéseket.* A szinonima-szótárak határozzák meg, hogy a rugalmas felhasználói beviteleket hogyan értelmezzük.
Mindkét réteg a tervezés része – nem utólagos kiegészítés.
A kanonikus alapmodellben minden egységet egy-egy referenciaegységhez rendelnek a saját tartományán belül. Minden átváltás ezen a referencián keresztül történik. Ez egy normalizációs útvonalat hoz létre, és garantálja, hogy minden egység ugyanazt a matematikai horgonypontot használja.
Tartományi alapegységek
Kifejezetten rögzítettem az alapegységeket területenként:* Hossz → m* Tömeg → kg* Térfogat → L
Ezek tudatos döntések voltak:* Iparági szabványok.* Minimalizálják a kerekítési eltéréseket.* A rendszert intuitívvá teszik a mérnökök számára.
Kanonikus egységkulcsok (támogatott egységek)
Minden alias-leképezésnek ezekre a kanonikus kulcsokra kell feloldódnia.
- Tömeg (alap: kg) µg, mg, g, kg, t, lb, oz
- Hossz (alap: m) mm, cm, m, km, in, ft, yd, mi
- Térfogat (alap: L) ml, cl, µl, mm3, cm3, l, m3, fl_oz_us, pt_us, qt_us, gal_us
Minden tartománynak megvan a saját alapadat-objektumlistája. Minden bejegyzés meghatározza egy mértékegységet és annak factorToBase értékét.
Az átváltás mindig ugyanazt a mintát követi:* Bemenet → Alap* Alap → Cél
Nincs elágazás. Nincs párok karbantartása.
Védett belső interfész
A véletlen logikai módosítások elkerülése érdekében elkülönítettem a magváltozókat:* _inputValue* _inputUnit* _targetUnit* _conversionResult
A magmotor kizárólag ezektől függ.
Két vékony konfigurációs réteg veszi körül:* 01 – FELHASZNÁLÓI KONFIGURÁCIÓ: BEMENETI SZAKASZ A külső forrásokat belső változókhoz rendeli.* 03 – FELHASZNÁLÓI KONFIGURÁCIÓ: KIMENETI SZAKASZ A kiszámított eredményt kifelé továbbítja.
Ez stabilan tartja a számítási magot, miközben rugalmas integrációt tesz lehetővé.
A trigger lebontása – Hogyan működik a MAGIC?
A védett MAGIC trigger két logikai műveletet hajt végre: 1. Az egységszinonimák feloldása 2. A kanonikus alapnormalizálás alkalmazása
Alias-feloldó réteg
Minden tartomány rendelkezik szinonimaszótárral, például:* _lengthUnitAliases
Minden objektum a következőket tartalmazza: * nyers * kanonikus
Példa:{ "nyers": "mm", "kanonikus": "mm" }{ "nyers": "milliméter", "kanonikus": "mm" }{ "nyers": "m³", "kanonikus": "m3" }Ez lehetővé teszi, hogy több írásmód is egyetlen kanonikus kulcshoz legyen hozzárendelve. Fontos, hogy nem duplikáltam a bejegyzéseket az alapadatkészletben. A szinonima réteg kizárólag azért létezik, hogy felszívja a bemeneti változékonyságot anélkül, hogy megsokszorozná a matematikai definíciókat.
Kanonikus alapképlet
A kanonikus egységek meghatározása után a képlet a következő:eredmény = bemenetiÉrték × factorToBase(kanonikusBemenet) ÷ factorToBase(kanonikusCél)
Példa egy triggerre (hosszúsági tartomány)
(@Variable._inputValue * array_value_at_index( map_to_number_list(@Variable._lengthToBaseDefaults , 'factorToBase'), array_index_of( map_to_text_list(@Variable._lengthToBaseDefaults , 'unit'), array_value_at_index( map_to_text_list(@Variable._lengthUnitAliases , 'canonical'), array_index_of( map_to_text_list(@Variable._lengthUnitAliases , 'raw'), @Variable._inputUnit ) ) ) ))/array_value_at_index( map_to_number_list(@Variable._lengthToBaseDefaults , 'factorToBase'), array_index_of( map_to_text_list(@Variable._lengthToBaseDefaults , 'unit'), array_value_at_index( map_to_text_list(@Variable._lengthUnitAliases , 'canonical'), array_index_of( map_to_text_list(@Variable._lengthUnitAliases , 'raw'), @Variable._targetUnit ) ) ))Szerkezetileg ez egy réteges logika:* A nyers értékek feloldása → kanonikus értékek* A kanonikus értékek feloldása → tényezők* Normalizálás az alapegység segítségével
Bonyolultnak tűnik, de szándékosan inline kódként írtuk, hogy a motor önálló maradjon, és elkerüljük a köztes állapotokat.
Miért választottuk ezt a szerkezetet?
Három garanciát akartam:* Nincs páros robbanás* Nincs kerekítési eltérés a több útvonal miatt* Nincs trigger-átírás az egységek kiterjesztésekor
A kanonikus alapmodell mindhármat biztosítja számomra. Amikor új egységet adok hozzá, pontosan egy factorToBase bejegyzést adok hozzá. A motor nem változik. Amikor új írási formátumot támogatok, pontosan egy alias bejegyzést adok hozzá. A matematika nem változik. Ez az elválasztás a legfontosabb architektúrai döntés.
Több területen való újrafelhasználás: ugyanaz a motor, különböző adatkészletek
Egy másik tudatos döntés: a motor logikája domain-független. A hossz, a tömeg és a térfogat ugyanazt a strukturális triggert használja. Csak az adatkészlet változik. Ahelyett, hogy három különböző konvertert építettem volna, egy kanonikus motort építettem, és hagytam, hogy az adatkészlet határozza meg a domaint. Ez csökkenti a kognitív terhelést, és előre jelezhetővé teszi a komponensek viselkedését.
Miért skálázható ez?
A skálázás az adatkészlet szintjén történik. Az egységek hozzáadása nem igényli: * a kiváltó kifejezések módosítását, * feltételes elágazások hozzáadását, * a logika duplikálását.
Az algoritmus stabil marad. Az adatkészlet fejlődik.
A komponens kiterjesztése
Új kanonikus egység hozzáadása
- Bővítse a megfelelő _ToBaseDefaults adatkészletet.
- Adja hozzá az egységet és a factorToBase-t.
- A trigger-t hagyja érintetlenül.
Új írási formátum hozzáadása
- Bővítse ki a megfelelő _UnitAliases szótárat.
- Adja hozzá a raw-t és a hozzá tartozó kanonikus kulcsot.
- Hagyja érintetlenül az alapadatállományt.
Ez szándékos volt: felhasználóbarát rugalmasságot akartam anélkül, hogy megsokszoroznám a matematikai definíciókat.
Hibakezelés (biztonságos keresési minta)
Két hibahely lehetséges: 1. A „raw” egység nem található az alias szótárban. 2. A kanonikus egység nem található az alapadatkészletben.
Ha bármelyik keresés sikertelen, a számítás nem kerül végrehajtásra.
Ez garantálja: * Nincsenek elavult értékek * Nincsenek észrevétlen számítási hibák * Determinisztikus viselkedés
Miért nem külön tömbök az egységeknek és a tényezőknek?
Az egységek és a tényezők külön tömbökben való tárolása pozíciós függőségi kockázatot jelentene. Ha az egyik lista sorrendje megváltozik, a másiké pedig nem, a rendszer észrevétlenül meghibásodik. Azáltal, hogy az egységeket és a factorToBase-t együtt tárolom strukturált objektumokon belül, kiküszöböltem ezt a strukturális sebezhetőséget.
Alapfilozófia
Ez a komponens szándékosan egyszerű felépítésű és szigorú viselkedésű.* A matematikai műveletek központosítottak.* A motor védett.* A rugalmasság a perifériákon érvényesül.
Úgy terveztem meg, hogy a logika idővel stabil maradjon, miközben a támogatott mértékegység-készlet biztonságosan bővülhessen. A motor nem változik. Az adatkészlet bővül.
Csatlakozz
Csatlakozz a közösséghez, hogy megoszthasd a fejlesztéseket, javasolhass további mértékegységeket, jelentethess hibákat, vagy megvitathasd az architektúrával kapcsolatos döntéseket
