Faceți cunoștință cu Bond, Microsoft Bond - Un nou cadru de serializare a datelor
Publicat: 2022-03-11Microsoft Bond este un nou cadru de serializare pentru date schematizate creat de Microsoft.
Să recapitulăm unde serializarea datelor este folosită cel mai mult:
- Persistența datelor în fișiere, fluxuri, NoSQL și BigData.
- Transmiterea datelor în rețele, IPC etc.
În mod obișnuit, aceste aplicații trebuie să se ocupe de date schematizate, unde schema înseamnă:
- Structura: ierarhie, relații, ordine.
- Semantic: vârsta în număr de ani de la naștere.
De fapt, orice date are o schemă, chiar dacă este implicit definită sau susținută de limbajul dumneavoastră de programare. Când vine vorba de structuri complexe de date, ajungem să scriem obiecte de transfer de date (DTO) și cod responsabil pentru IO, adesea în diferite limbi. De îndată ce crește și evoluează, devine rapid un coșmar să întreținem toate aceste piese. Aici este locul în care cadrele de serializare câștigă jocul.
În primul rând, orice cadru de serializare definește o abstractizare pentru definirea schemei de date care nu este legată de un anumit limbaj de programare sau platformă. Această abstractizare este cunoscută ca DSL (limbaj specific domeniului).
Având un astfel de DSL, putem defini schema de date pentru o anumită aplicație. Definiția, la rândul său, poate fi exprimată în mai multe forme, dar adesea cadrele de serializare acceptă o singură formă care este bine potrivită pentru DSL-ul său. Prea complicat? Iată un exemplu binecunoscut: XSD și XML.
XSD definește un DSL, XML este (recomandat) pentru a defini documentele care se potrivesc cu schema XSD. Dar, puteți folosi și „xsd.exe” pentru a genera clase DTO care se potrivesc cu XSD, prin urmare, clasele generate sunt doar o altă formă. Rețineți că puteți genera XML din DTO și invers și acestea vor fi identice din punct de vedere semantic, deoarece semantica este comună: este definită cu XSD. Pentru a rezuma, un cadru de serializare vă oferă un DSL, pe care îl utilizați pentru a defini scheme de date într-un anumit format care este cel mai bine acceptat de cadrul dat.
Schema abstractă de date va fi în cele din urmă materializată într-un set de entități exprimate într-un limbaj de programare. Toate cadrele de serializare oferă instrumente speciale numite generatoare de cod.
Ei generează tot codul de suport pentru limbajele de programare țintă, care este necesar pentru clienții să lucreze cu date schematizate: DTO-uri, proxy etc. Acest lucru este necesar în cele din urmă pentru limbajele puternic tipizate, în timp ce poate fi opțional pentru limbajele tip duck (dinamic) .
Ultima, dar nu în ultimul rând, este persistența datelor pe fir. Datele reale vor fi în cele din urmă serializate în octeți bruti (sau text) și deserializate înapoi.
Toate cadrele de serializare a datelor oferă o altă abstractizare aici numită protocoale. Un protocol definește un set de reguli care definesc modul în care datele structurate ar trebui serializate sau deserializate conform schemei sale. Fiecare protocol este implementat în mod normal pentru toate limbajele de programare și platformele suportate de un anumit cadru de serializare. Cu cât suportă mai multe limbaje/platforme de programare, cu atât va oferi mai multe implementări.
Imaginați-vă că un cadru este dispus să accepte protocolul JSON, apoi trebuie să ofere cititor/scriitor JSON pentru, de exemplu, C#, C++, Windows, Linux etc.
Punând totul împreună: orice cadru modern de serializare a datelor vă oferă următoarele:
- Abstracții: DSL și protocoale.
- Instrumente de generare a codului.
- Implementări de protocol.
Microsoft Bond este un cadru modern de serializare a datelor. Oferă protocoale DSL puternice și flexibile, generatoare de cod pentru C++ și C#, implementări eficiente de protocoale pentru Windows, Linux și Mac OS X.
Timp de câțiva ani, Bond a rămas o tehnologie de uz intern, dar datorită inițiativei Microsoft Open Source, Bond a fost disponibil pe GitHub: Microsoft Bond.
Concurenți în serializarea datelor
Rivalitatea dintre giganții software a dus la apariția unui număr de cadre de serializare:
- Google Inc. - Google Protocol Buffers
- Facebook Inc. - Thrift, care este acum întreținut de Apache
- Apache Foundation Software - Avro
Evident, toate sunt incompatibile, ceea ce este în regulă dacă nu vă faceți API-ul public folosind unul dintre acestea.
Fiecare dintre ele are argumente pro și contra, așa că poți alege dintre ele în funcție de nevoile tale.
De ce Bond?
Răspunsul oficial la această întrebare este aici: „De ce Bond”.
Iată rezumatul rapid:
- Bond acceptă sistemul de tip bogat, inclusiv generice.
- Bond acceptă versiunea schemei și compatibilitatea bidirecțională.
- Bond acceptă manipularea schemei de rulare.
- Bond susține diverse colecții: „vector
, Hartă , lista ”. - Bond acceptă serializarea leneșă de tip sigur: „bonded
” - Bond acceptă protocoale (formate) conectabile cu marshaling și transcodare
O notă importantă este că Bond urmează strategia „pay to play”. Cu cât adăugați/utilizați mai multe funcții, cu atât plătiți mai mult pentru dimensiune și viteză. Acest lucru oferă dezvoltatorilor o mare flexibilitate.
Să fim sinceri și să enumeram și dezavantajele:
- Bond vizează stiva Microsoft care acceptă C++ și C#, dar nu acceptă Java (încă).
- Bond nu acceptă tipul de unire („unul dintre” în protobuf).
Dar performanță?
Când vine vorba de compararea unui cadru cu altul, dezvoltatorii caută adesea comparații de performanță. Dar să ne amintim că aceste cadre constau din DSL, generatoare de cod și protocoale. Dacă luați în considerare doar performanța protocoalelor, atunci veți rata caracteristicile oferite de DSL și codegens. Uneori, a avea un DSL mai bun este mult mai important decât a avea o diferență de câteva procente în viteza de serializare.

În afară de viteză, codificările eficiente din punct de vedere spațiu acceptate de unele protocoale ar putea fi, de asemenea, importante. Vă încurajez să faceți o comparație de performanță/spațiu cu datele specifice domeniului dvs. Acesta este singurul mod de a estima toate beneficiile pe care le-ați putea obține dintr-un anumit cadru.
Acest articol vine cu proiectul demonstrativ care demonstrează utilizarea cadrului Bond citind toate înregistrările din jurnalul de evenimente al aplicației Windows, serializându-le ca obiecte Bond și deserializându-le înapoi.
Pentru a construi și a rula demonstrația, nu trebuie să instalați alt software decât Visual Studio.
Folosind Microsoft Bond
Obținerea Bond
Consultați ghidul oficial despre obținerea Bond pentru platformele dvs.
Pentru proiectele .NET, acest lucru este la fel de simplu ca:
install-package Bond.CSharp
Pachetul include:
- Generator de cod (gbc.exe) în folderul bin
- biblioteci .NET
- Sarcini MSBuild
Fluxul de lucru
Fluxul de lucru include următorii pași:
- Învățați DSL și definiți schema de date prin scrierea fișierelor „.bond”.
- Utilizați generatorul de cod ("gbc.exe") pentru a obține DTO-uri pentru limbajul dvs. de programare.
- Faceți referire la fișierele generate, precum și la bibliotecile de execuție Bond din proiectul dvs.
Luați în considerare utilizarea sarcinilor MSBuild furnizate cu cadrul pentru a automatiza pasul de generare a codului.
Prezentare generală a caracteristicilor DSL
Când începeți să scrieți primul fișier „.bond”, va trebui să-i cunoașteți sintaxa și caracteristicile. Vă rugăm să vizitați pagina de documentație oficială care descrie IDL-ul în detalii. Să analizăm doar caracteristicile de bază:
- Module: schema poate fi împărțită în diferite fișiere, care sunt incluse cu declarația „import”.
- Spațiu de nume: au același sens ca și C++/C#.
- Structuri definite de utilizator: o unitate de definiție a tipului de utilizator.
- Declarația directă este utilă pentru structurile de date recursive.
- Tipuri de bază: „bool, uint8 (prin 64), int8 (prin 64), float, double, string, wstring”.
- Tipuri de containere: „blob, list
, vector , a stabilit , harta<K, T>, nulă ”. - Alias-uri și mapare personalizate, de exemplu, dacă doriți să aveți „DateTime” în C#, dar bifează (“int64”) pe fir.
- Atribute personalizate: utile pentru generarea de cod personalizat.
Plictisit? Iată un exemplu:
namespace MyProject struct MyRecord { 0: string Name = "Noname"; 1: vector<double> Constants; }
unde „0” și „1” sunt numerele ordinale ale câmpului (pot fi orice numere întregi cu orice ritm) și = "Noname"
este valoarea implicită (opțională).
Generarea codului
Cadrul Bond oferă un instrument de generare de cod scris în Haskell. Iată cum se generează cod C# și C++ dintr-o schemă „.bond” în linia de comandă:
gbc c# example.bond gbc c++ example.bond
Protocoale acceptate (formate)
Bond acceptă trei tipuri de protocoale:
- Protocoale etichetate: „CompactBinary” și „FastBinary”
Protocoalele etichetate intercalează metadatele schemei în sarcina utilă. Acest lucru face ca sarcina utilă să se auto-descrie, permițând consumatorilor să o interpreteze chiar și fără a cunoaște schema utilizată de producător.
- Protocoale neetichetate: „SimpleBinary”
Protocoalele neetichetate serializează numai datele și, prin urmare, necesită ca consumatorii să cunoască schema de încărcare utilă printr-un mecanism în afara benzii. Protocoalele neetichetate sunt adesea folosite în scenariile de stocare deoarece permit stocarea unei scheme o singură dată (de exemplu, într-un tabel de sistem dintr-o bază de date), eliminând astfel supraîncărcarea metadatelor din multe înregistrări care utilizează aceeași schemă.
- Protocoale bazate pe DOM: „SimpleJson” și „SimpleXml”
Protocolul bazat pe DOM analizează întreaga sarcină utilă într-un model de obiect de date în memorie, care este apoi interogat în timpul deserializării. De obicei, acest tip de protocol este utilizat pentru a implementa codificări bazate pe text, cum ar fi JSON sau XML.
Pentru fiecare protocol, biblioteca de execuție Bond vă oferă clasele Reader și Writer corespunzătoare, care fac treaba la serializarea propriu-zisă.
Utilizarea protocoalelor este destul de simplă și puțin mai dificilă decât celebrul „JsonConvert.SerializeObject()”:
var record = new MyRecord { Name = "FooBar", Constants = { 3.14, 6.28 } }; var output = new OutputBuffer(); var writer = new CompactBinaryWriter<OutputBuffer>(output); Serialize.To(writer, record); var input = new InputBuffer(output.Data); var reader = new CompactBinaryReader<InputBuffer>(input); record = Deserialize<Example>.From(reader);
Ce urmeaza?
Dacă îți place Bond și dacă ai mult timp liber pentru codare, ia în considerare dezvoltarea unuia dintre aceste articole. Nu voi enumera toate beneficiile pe care le puteți obține în urma contribuției, dar știu că mulți dezvoltatori caută idei la care să contribuie:
- Implementați un port în Java. Înlocuiți Java cu alte limbi principale la alegere.
- Implementați importul/exportul schemei Bond pentru a fi schimbate cu alte DSL-uri (de exemplu, „.proto <=> .bond”).
Orice ați decide să faceți în privința lui Bond, vă recomand să îl contactați mai întâi pe Adam Sapek. El este liderul acestui proiect și vă va ghida cu ceea ce este cel mai solicitat de piață.