Poslední příspěvky

Stran: [1] 2 3 ... 10
1
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od Franta Kučera kdy Dnes v 21:34:43 »
Navíc často ten dict může obsahovat jen omezenou množinu typů, takže třeba neomezeně dlouhé číslo do něj nejde uložit přímo jako číslo, ale jako řetězec a pak se bokem serializátoru do JSONu musí říct, ať to uloží jako číslo, ne jako řetězec (i když to tak je v tom slovníku).
No a? To je správně.

A není jednodušší to číslo nechat třeba jako BigInteger a naučit ten generátor, jak mapovat BigInteger na datové typy daného formátu? K čemu je dobré to převádět na String a pak si někde bokem předávat informaci, že tohle vlastně není String ale číslo?
2
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od Franta Kučera kdy Dnes v 21:30:39 »
Já ti nerozumím. V čem, že je ten problém?

Problém je v tom, že to nemusí být stromová struktura, ale může to být obecný graf a na jeden objekt může vést reference z víc míst. Pokud to řešíš přes reflexi, tak tam tu informaci o tom, že jde o stejný objekt, akorát je na něj odkazováno z víc míst, máš zachovanou. Ale když to přesypeš do mapy map, tak se tam ta informace ztratí (nebo si minimálně přiděláš dost práce s tím, abys ji tam zachoval).
3
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od Franta Kučera kdy Dnes v 21:25:01 »
Ale vysvětli mi, proč bych měl tím dictem něco ztrácet? Nevidím proto jediný důvod...

Tohle už jsem komentoval někde výše. Když už se to tedy bude řešit takhle ručně (osobně bych spíš použil spíš tu reflexi a anotace nebo kód generovaný ze specifikace), tak bych tam nechal normální datové typy toho programovacího jazyka – a jejich mapování na datové typy formátu, ať si řeší ta serializační knihovna (specifika se dají upravit konfigurací, ale nevidím důvod, proč by někdo měl být nucen to ručně programovat).

Proč už nikdy nepoužiju reflexi na serializaci: To takhle jeden kolega v kódu, který jsem přebral použil reflexy nad Enum, což ve výsledku znamenalo, že pro každou hodnotu Enumu do dalo jeden int. Hezké, krásně se to namapovalo do databáze. Pak někdo přidal nový záznam do Enumu. A první odstranil, protože ten se už neměl nikdy použít. A najednou si klienti stěžovali, že se nám mrší data.

To ovšem není chyba reflexe ale logická chyba v návrhu. Neměl to mapovat na čísla ale na textové hodnoty a k tomu tu reflexi klidně mohl použít. Případně to mohl přemapovat na jednoznakové konstanty nebo i na ta čísla, aby to v DB zabíralo míň místa, ale musel by tam mít pevně dané mapování. Taky by pomohla zkušenost třeba s C++, protože to člověka naučí ty enumy neodstraňovat a nové přidávat jen na konec.

Připravit se kvůli tomu o reflexi mi přijde škoda. Jsou např. homoikonické jazyky, které jdou v tomhle mnohem dál. Ta reflexe je tak na půl cesty, ale i tak je to velmi užitečný nástroj (spíš tedy pro tvorbu knihoven a frameworků než aplikací, tam to moc nepatří).

Nedávno jsem tady do nějaké diskuse napsal, že generování XML je někdy lepší si napsat sám, ručně, bez knihoven a hned se seběhli místní trollové, co že si to dovoluji si takovou věc psát sám… Přitom to generování XML je výrazně jednodušší než parsování (byť si nepíšeš vlastní parser asi zpracováváš SAX události nebo pracuješ nad DOMem nebo něco podobného). (jen dodávám, že cílem toho mého generátoru nebylo generování libovolného XML, ale určité podmnožiny, která je pro moje potřeby dostačující – důležité je, aby výstup bylo validní XML)

Ty výhrady k tomu generovanému kódu částečně chápu. Sám jsem s tím bojoval u Swaggeru resp. OpenAPI, kde generátor nebyl dost zralý, některé věci to nepodporovalo vůbec nebo to generovalo nesmysly… to bylo dost peklo. Něco vyřešili autoři generátoru v novějších verzích, něco jsme vyřešili sami vlastními šablonami. Ale i tak si myslím, že je většinou lepší si jednou odladit šablony/generátor než to psát pokaždé ručně. A JAXB je oproti tomu mnohem zralejší a spolehlivější technologie (byť to zemětřesení, které přišlo po Javě 8, s tím nepěkně zamávalo).

Jedna ze zkušeností, co mne v tomhle ovlivnila, byla, když  jsem  kdysi  pozoroval  lidi, kteří seděli asi dva metry od sebe, jeden psal server v Javě, druhý psal klienta v JavaScriptu a neustále řešili, že ten druhý posílá  atribut  s „jiným  názvem“ nebo  „starým  způsobem“…  v každé  verzi  byly  chyby tohoto typu a pořád se na to plýtval čas a vyvolávalo to hádky. Mezi sebou si sdíleli dokument ve  Wordu,  ve kterém  měli příklady, jak se má služba volat… Takže když mi dneska někdo tvrdí, jak nepotřebuje schéma, a že je to prý jednoduché a že stačí napsat pár příkladů a všem to bude jasné… tak se mi otevírá pomyslná kudla v kapse, protože vím, jak to dopadá. Přitom tohle se v oboru řeší od pradávna a obecně  se  to  jmenuje IDL  (interface  description language). Konkrétních implementací je spousta, ale podstatná je ta myšlenka, že máš nějakou strojově  čitelnou  specifikaci,  která definuje ten kontrakt, a ze které obě strany vycházejí.

Ale každopádně, pokud si píšeš parser ručně ale máš tu specifikaci a ne jen pár příkladů, tak je to ještě ten lepší případ.

Dělám to stejně, protože ono se to nakonec vyplatí vždycky mít to napsané ručně. Třeba když při integraci zjistíte, že protistrana posílá formát, který není v souladu se specifikací (třeba se mají posílat prázdné hodnoty jako element s nil, ale oni ten povinný element vůbec nepošlou). A když to reklamujete, dozvíte se, že jim to ale generovaný kód dělá takhle a nic s tím neudělají. Tak jsem to jednoduše vyřešil u sebe a upravil jsem parsování, a ten povinný element nebyl zas až tak povinný.

To se mi taky párkrát stalo, ale buď to šlo řešit domluvou a druhá strana uznala, že to je chyba a opravila to, aby to specifikaci odpovídalo, nebo jsme ustoupili my a upravili si to XSD nebo Swagger u sebe, a tudíž nám generátor vytvořil třídy, na které pasovala i ta původně neplatná data. Tohle se dá i případně automatizovat (tady je fajn, že XSD a WSDL jsou taky XML a dají se prohnat XSLT transformací).
4
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od BoneFlute kdy Dnes v 21:03:54 »
Už se mi několikrát vyplatilo si ten parser psát ručně (vlastně už to ani jinak nedělám - napsal jsem si na to knihovnu se kterou se to dělá snadno). Prvotním důvodem bylo, že XSD generátory generovaly typy, co se těžko používají (tehdy jsme měli Kotlin a používali data classy a XSD generátor uměl jen tradiční Java classy s gettery a settery bez null anotací). Takže bylo vlastně míň práce parsovat XML ručně, navíc jsme díky tomu objevili, že z té služby chodí i data mimo specifikaci.

Já na jednu stranu mám rád používání různých těch automatický generátorů, ale je fakt, že ve výsledku je to kolikrát úplně stejné množství popisného kódu, protože různé výjimky a hacky. Pro mě je to sympatické, že je to alespoň deklarativní. A třeba naopak, nad XSLT jsem zlomil hůl. Je snazší a čitelnější to parsovat a serializovat v Rustu.
5
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od BoneFlute kdy Dnes v 20:59:11 »
Ale vysvětli mi, proč bych měl tím dictem něco ztrácet? Nevidím proto jediný důvod...

Protože ne všechny formáty jsou jako dict. Některé serializační formáty např. nemají názvy polí, nebo mohou vzít kus paměti, kde je struktura (s definovaným layoutem) a nic dalšího s ním nedělat. Nebo dokoknce větší blok paměti, kde je více struktur, které na sebe odkazují (třeba pomocí relativních offsetů).
Já ti nerozumím. V čem, že je ten problém?

Navíc často ten dict může obsahovat jen omezenou množinu typů, takže třeba neomezeně dlouhé číslo do něj nejde uložit přímo jako číslo, ale jako řetězec a pak se bokem serializátoru do JSONu musí říct, ať to uloží jako číslo, ne jako řetězec (i když to tak je v tom slovníku).
No a? To je správně.
6
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od BoneFlute kdy Dnes v 20:52:05 »
Ale vysvětli mi, proč bych měl tím dictem něco ztrácet? Nevidím proto jediný důvod...

Tohle už jsem komentoval někde výše. Když už se to tedy bude řešit takhle ručně (osobně bych spíš použil spíš tu reflexi a anotace nebo kód generovaný ze specifikace), tak bych tam nechal normální datové typy toho programovacího jazyka – a jejich mapování na datové typy formátu, ať si řeší ta serializační knihovna (specifika se dají upravit konfigurací, ale nevidím důvod, proč by někdo měl být nucen to ručně programovat).

Proč už nikdy nepoužiju reflexi na serializaci: To takhle jeden kolega v kódu, který jsem přebral použil reflexy nad Enum, což ve výsledku znamenalo, že pro každou hodnotu Enumu do dalo jeden int. Hezké, krásně se to namapovalo do databáze. Pak někdo přidal nový záznam do Enumu. A první odstranil, protože ten se už neměl nikdy použít. A najednou si klienti stěžovali, že se nám mrší data.

Druhá věc je ta, že pointa není zda ten serializační systém psát ručně, generovat podle wsdl, nebo jakkoliv jinak. Pointa je v tom, že já vytvořím interface, a pak mohu s maximální jistotou de/serializovat předenm neznámý objekty, stačí, když splní kontrakt.

Řeč byla o OOP.

Samozřejmě, že v praxi se hřeší. Protože výkon. Protože neznalost. Protože lennost. Protože cena.

Automatická serializace pomocí reflexe je snadná, rychlá a křehká.

Serializace podle kontraktu je bezpečná, rozložitelná do týmu, flexibilní.

Serializace objektu přímo do cílového stavu je pracná, výkonná, neflexibilní, nevhodná pro knihovní kód.
7
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od Filip Jirsák (forum) kdy Dnes v 20:50:01 »
Už se mi několikrát vyplatilo si ten parser psát ručně (vlastně už to ani jinak nedělám - napsal jsem si na to knihovnu se kterou se to dělá snadno). Prvotním důvodem bylo, že XSD generátory generovaly typy, co se těžko používají (tehdy jsme měli Kotlin a používali data classy a XSD generátor uměl jen tradiční Java classy s gettery a settery bez null anotací). Takže bylo vlastně míň práce parsovat XML ručně, navíc jsme díky tomu objevili, že z té služby chodí i data mimo specifikaci.
Dělám to stejně, protože ono se to nakonec vyplatí vždycky mít to napsané ručně. Třeba když při integraci zjistíte, že protistrana posílá formát, který není v souladu se specifikací (třeba se mají posílat prázdné hodnoty jako element s nil, ale oni ten povinný element vůbec nepošlou). A když to reklamujete, dozvíte se, že jim to ale generovaný kód dělá takhle a nic s tím neudělají. Tak jsem to jednoduše vyřešil u sebe a upravil jsem parsování, a ten povinný element nebyl zas až tak povinný.

A setkávám se s tím snad pokaždé, že někdo přijde s tím, že to přece nebude psát ručně a nechá si to vygenerovat, a pak si mi chodí stěžovat, že v tom vygenerovaném kódu nejde něco vyřešit. I když teda pro JSON většinou používám automatické mapování hodnot, jenom strukturu objektů si dělám vlastní.
8
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od Radek Miček kdy Dnes v 20:10:14 »
Smyslem té serializace je, že chci s někým komunikovat – typicky s nějakým externím systémem nebo třeba s jinou instancí svého programu. Proto si dohodneme nějaké rozhraní, kontrakt, který budou obě strany dodržovat, a který popisuje logickou strukturu předávaných dat případně i protokol jejich předávání. Ten koncept IDL nevznikl jen tak pro nic za nic…

A proto má smysl, aby ty objekty vygenerované z téhle specifikace jí odpovídaly 1:1 – abych mohl ve své aplikaci mohl vytvářet nebo číst libovolné struktury, které jsou dle té specifikace validní. Tady není moc prostor pro kreativitu a nemá smysl si to dělat po svém a jinak.

Už se mi několikrát vyplatilo si ten parser psát ručně (vlastně už to ani jinak nedělám - napsal jsem si na to knihovnu se kterou se to dělá snadno). Prvotním důvodem bylo, že XSD generátory generovaly typy, co se těžko používají (tehdy jsme měli Kotlin a používali data classy a XSD generátor uměl jen tradiční Java classy s gettery a settery bez null anotací). Takže bylo vlastně míň práce parsovat XML ručně, navíc jsme díky tomu objevili, že z té služby chodí i data mimo specifikaci.
9
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od Radek Miček kdy Dnes v 19:52:10 »
Ale vysvětli mi, proč bych měl tím dictem něco ztrácet? Nevidím proto jediný důvod...

Protože ne všechny formáty jsou jako dict. Některé serializační formáty např. nemají názvy polí, nebo mohou vzít kus paměti, kde je struktura (s definovaným layoutem) a nic dalšího s ním nedělat. Nebo dokoknce větší blok paměti, kde je více struktur, které na sebe odkazují (třeba pomocí relativních offsetů).

Navíc často ten dict může obsahovat jen omezenou množinu typů, takže třeba neomezeně dlouhé číslo do něj nejde uložit přímo jako číslo, ale jako řetězec a pak se bokem serializátoru do JSONu musí říct, ať to uloží jako číslo, ne jako řetězec (i když to tak je v tom slovníku).
10
Vývoj / Re:Přechod z Javy na Rust. Ano či ne?
« Poslední příspěvek od Franta Kučera kdy Dnes v 19:34:27 »
Přijdete o zapouzdření, takže si zabetonujete vnitřnosti.
Jak jednou objekt serializujete, tak už takřka nemůžete překopat vnitřní reprezentaci. Nějaká aktualizace pak obvykle něco rozbije.

Ve výsledku pak občas máte vnitřnosti objektů dvakrát. Jednou pro sebe, jednou pro serializátor a přesypáváte je tam a zpět.

Smyslem té serializace je, že chci s někým komunikovat – typicky s nějakým externím systémem nebo třeba s jinou instancí svého programu. Proto si dohodneme nějaké rozhraní, kontrakt, který budou obě strany dodržovat, a který popisuje logickou strukturu předávaných dat případně i protokol jejich předávání. Ten koncept IDL nevznikl jen tak pro nic za nic…

A proto má smysl, aby ty objekty vygenerované z téhle specifikace jí odpovídaly 1:1 – abych mohl ve své aplikaci mohl vytvářet nebo číst libovolné struktury, které jsou dle té specifikace validní. Tady není moc prostor pro kreativitu a nemá smysl si to dělat po svém a jinak. Ty objekty/třídy nemám pro nějaký serializátor, ale pro podporu toho formátu a jeho logického modelu. Slouží to jako most mezi mým programovacím jazykem (abych používal normální třídy, struktury, konstanty, volal metody, funkce…) a tím formátem nebo protokolem. A tady je žádoucí dodržovat správnou úroveň abstrakce a nedovolit těm strukturám specifickým pro daný formát, aby prosakovaly do zbytku programu, který už je obecný. Takže ano, budu tam ty třídy mít dvakrát, nebo třeba jedenáctkrát, pokud budu pracovat s deseti formáty. Ale pokaždé to jsou trochu jiné struktury a data (pokud by tomu tak nebylo, tak by to znamenalo, že ten program je nejspíš vcelku zbytečný a nic moc nedělá). Tzn. mám nějaké jádro programu a v něm používám nějaké entity-třídy – to je můj datový model, který odpovídá mému záměru logice toho programu. A pak tam mám moduly pro napojení na různé externí systémy a v nich se používají třídy specifické pro dané protokoly nebo formáty. V těchto modulech je pak nějaká obchodní logika, která na jedné straně pracuje s mými entitami a na druhé straně se strukturami specifickými pro ten formát nebo protokol.

Pokud by ta aplikace měla nějaké extrémní nároky na výkon nebo požadavek, že se data nemají v paměti kopírovat, tak bych se na nějaké objekty a konstruování jejich stromu úplně vykašlal a z parseru bych emitoval události, které by se průběžně zpracovávaly… případně bych vyrobil ukazatele na části dat v té původní paměti, aby se to nikam nekopírovalo a zpracovalo rovnou na místě.
Stran: [1] 2 3 ... 10