Re: Modulární aplikace
Zdravim, my pouzivame tiez myslienku cislo jedna, teda dotazy vo forme in obmedzeni. Tie in obmedzenia, kym sa nejedna o tisicky idciek su uplne vpohode. Ale mame aj vinimku, mame totiz modul, ktory potrebuje citat udaje z mnohych modulov naraz a ma vselijake svoje obmedzenia. Konkretne tento modul exportuje data do ineho systemu a bol navrhnuty genericky. S pomocou malej konfiguracie sa da rozsirit export, niekedy vsak to nejde, lebo su tam nejake podmienky, takze sa napise sql. Exportuju sa cele siete objektov. Ak by to malo byt modularne, tak kazdy modul by mal exportovat svoje data, svoju siet. No to by chcelo ovela viacej premysleny navrch, kedze exportovane udaje nie su cela DB, ale cielom je exportovat mininum dat a dba sa na performanciu, robia sa teda aj joiny medzi modulmi. Cize kedze tento Export robi iba citanie, tak ma dovolene sahat do lubolnej tabulky. Ale tym ze modul ma vsetky query u seba, vznika aj duplicita niektorych dotazov, no nie je toho vela. Zaver z tohoto prikladu znie, ze moze nastat pripad, ked by sa implentacia stazila resp. aj znizila performancia pri dodrzani modularneho dizajnu, ak by sa dobre nepremyslel dizajn. 2010/9/2 Ing. Jan Novotný > Ahoj, > >my jedeme na modulárním systému asi 2 roky (s tím rozdílem, že nemáme > OSGI, ale jen zřetězené aplikační konexty Springu na stejné classpath - > nicméně už to k zavedení modulárnosti stačí). Řešili jsme stejný problém a > obávám se, že neexistuje ideální řešení. Základní pravidlo spočívá ve > správném "řezu" modulů - každý by měl mít jednoznačnou odpovědnost a funkci. > Moduly by se měly vzájemně doplňovat spíš než ve funkcionalitách překrývat. > Prostě příliš malé moduly nejsou dobré, protože mají potom mnoho závislostí > ven, velké moduly také nejsou dobré, protože se tím zase snižuje jejich > použitelnost. Na správném řezu funkcionalitou prostě záleží hodně. >Pokud by jeden modul sahal do dat jiného modulu přímo a nikoliv přes > jeho API povede toto porušení zapouzdřenosti k: svázanosti (couplingu) > těchto dvou modulů, zhoršení testovatelnosti, problém se samostatným > rozvojem modulů (vždy se na ně bude muset pohlížet jako na nějaký provázaný > celek). >My jsme došli ke dvěma možným technikám v těchto případech (naštěstí > těch případů není zase až tak moc). > > 1) obětování výkonu - tj. každý modul udržuje pouze svá data a pokud z > nějakého důvodu potřebuje vrátit či pracovat s daty jiného modulu, jde přes > jeho API - tím se ale samozřejmě nedá využít JOINů a platíme výkonem. Tyto > mezimodulové "dotazy" se alespoň snažíme optimalizovat na metodách API tím, > že tam máme metody pro hromadné načítání dat - např. List > getDataById(Integer... id), která může všechna potřebná data načít > jednorázově přes WHERE id in (...) > > 2) porušením normální formy db - kromě přímého volání mezi moduly na úrovni > API máme ještě jednu formu komunikace postavenou na "observer patternu", > která vychází ze Springu, tj. moduly v důležitých okamžicích své > funkcionality publikují tzv. eventy do systému, na které pak mohou reagovat > listenery v jiných modulech. Tímto způsobem je možné distribuovat některá > důležitá (i agregovaná) data do zbytku systému. Uvedu příklad - máme tzv. > hodnotící modul, který umožňuje hodnotit libovolný obsah kdekoliv (např. ve > formě hvězdiček na nějaké škále), tento modul samozřejmě o obsahu samotném > nic neví - naopak jiný modul, který spravuje daný obsah (třeba články) chce > při vracení článku vracet aktuální hodnotu průměrného hodnocení. Hodnotící > modul vždy po přepočtení aktuálního hodnotícího čísla po daný obsah vyhodí > událost do systému, na kterou může kterýkoliv jiný modul naslouchat. Modul > starající se o články tuto událost odchytí a k článku si uloží dodatečný > údaj o aktuálním hodnocení (již vypočtený, hotový k zobrazení). Tímto > způsobem je porušena normální forma - jeden údaj je v DB uložen 2x, nicméně > data jsou potom již hezky po ruce (bez výkonnostní penalizace) a nedochází k > narušení zapouzdřenosti modulů - jeden může bez problému fungovat bez > druhého, pokud běží oba - spolupracují. > > Pokud existuje ještě nějaký jiný způsob komunikace rád se jej dozvím. > Jak říkám, ani jedna z výše uvedených praktik není úplně ideální, ale na nic > lepšího jsme za ty roky nepřišli :(. > > Honza > > -- > -- > Ing. Jan Novotný > @@ > http://blog.novoj.net > Myšlenky dne otce Fura > -- > > 2010/9/1 David Mach > > Zdravím všechny! >> >> V naší firmě jsme doposud vyvíjeli klasické aplikace na jedné classpath >> (typu "vidím vše, volám vše, využívám vše", čili občas pěkná prasárna). Nyní >> vyvíjíme novou modulární aplikaci postavenou na OSGi, přičemž naše původní >> vize byla ta, že jednotlivé moduly mezi sebou budou komunikovat výhradně >> prostřednictvím API. To by ale například znamenalo,
Re: Modulární aplikace
Při návrhu modulární architektury je třeba brát na zřetel jiná možná použití dat z konkrétního modulu a umožnit zásuvné či rozšiřující submoduly do střev každého modulu. Jestli se použije vzor Listener, Observer a nebo eLISPové hooky je celkem buřt. Potom není nutné si tolik hrát s API, jenom nechat data uvnitř modulu bezpečně (myšleno odolně proti nekonzistencím dat) a správně (dva klíčové termíny Hrubozrnný a Volná vazba) protékat přes ony pluginy. Není ale potřeba se nějak dramaticky zaobírat bezpečností (myšleno přístupovými právy), neboť každý modul bude mít VŽDY možnost sáhnout si do DB ;-) 2010/9/2 Tomas Studva : > Ale mame aj vinimku, mame totiz modul, ktory potrebuje citat udaje z mnohych > modulov naraz a ma vselijake svoje obmedzenia. Konkretne tento modul > exportuje data do ineho systemu a bol navrhnuty genericky. Toto je typický kámen úrazu návrhu modulárních systémů. Generický modul může přímo záviset na zase jen na generických modulech. Pokud chcete v generickém modulu volat něco z negenerického modulu, musíte použít nějaký metajazyk, kterým se deklarativně (typicky pomocí konfigurace) na něj či do něj dostanete. > S pomocou malej > konfiguracie sa da rozsirit export, niekedy vsak to nejde, lebo su tam > nejake podmienky, takze sa napise sql. Exportuju sa cele siete objektov. > Ak by to malo byt modularne, tak kazdy modul by mal exportovat svoje data, > svoju siet. No to by chcelo ovela viacej premysleny navrch, kedze > exportovane udaje nie su cela DB, ale cielom je exportovat mininum dat a dba > sa na performanciu, robia sa teda aj joiny medzi modulmi. Cize kedze tento > Export robi iba citanie, tak ma dovolene sahat do lubolnej tabulky. Ano, SQL se typicky jako metajazyk pro přístp do negenerických modulů používá a pak zde opravdu není problém. Typické nasazení je právě pro statistiky. Exporty bych se snažil řešil jinak a ideálně via pes Partes až na konec kompletace. Export miliónů záznamů se asi nebude dělat každou minutu a každou minutu se nebude dělat export miliónů záznamů, takže tím pádem JOINy určitě oželím. > Ale tym ze modul ma vsetky query u seba, vznika aj duplicita niektorych > dotazov, no nie je toho vela. V tomto problém nevidím. Implementátor při konfiguraci ví, jaké verze negenerických modulů používá a může tedy separátně nastavit dotazy. > Zaver z tohoto prikladu znie, ze moze nastat pripad, ked by sa implentacia > stazila resp. aj znizila performancia pri dodrzani modularneho dizajnu, ak > by sa dobre nepremyslel dizajn. Tak toto je téměř tautologie ;-) > > 2010/9/2 Ing. Jan Novotný >> >> Ahoj, >> my jedeme na modulárním systému asi 2 roky (s tím rozdílem, že nemáme >> OSGI, ale jen zřetězené aplikační konexty Springu na stejné classpath - >> nicméně už to k zavedení modulárnosti stačí). Řešili jsme stejný problém a >> obávám se, že neexistuje ideální řešení. Základní pravidlo spočívá ve >> správném "řezu" modulů - každý by měl mít jednoznačnou odpovědnost a funkci. >> Moduly by se měly vzájemně doplňovat spíš než ve funkcionalitách překrývat. >> Prostě příliš malé moduly nejsou dobré, protože mají potom mnoho závislostí >> ven, velké moduly také nejsou dobré, protože se tím zase snižuje jejich >> použitelnost. Na správném řezu funkcionalitou prostě záleží hodně. >> Pokud by jeden modul sahal do dat jiného modulu přímo a nikoliv přes >> jeho API povede toto porušení zapouzdřenosti k: svázanosti (couplingu) >> těchto dvou modulů, zhoršení testovatelnosti, problém se samostatným >> rozvojem modulů (vždy se na ně bude muset pohlížet jako na nějaký provázaný >> celek). >> My jsme došli ke dvěma možným technikám v těchto případech (naštěstí >> těch případů není zase až tak moc). >> 1) obětování výkonu - tj. každý modul udržuje pouze svá data a pokud z >> nějakého důvodu potřebuje vrátit či pracovat s daty jiného modulu, jde přes >> jeho API - tím se ale samozřejmě nedá využít JOINů a platíme výkonem. Tyto >> mezimodulové "dotazy" se alespoň snažíme optimalizovat na metodách API tím, >> že tam máme metody pro hromadné načítání dat - např. List >> getDataById(Integer... id), která může všechna potřebná data načít >> jednorázově přes WHERE id in (...) >> 2) porušením normální formy db - kromě přímého volání mezi moduly na >> úrovni API máme ještě jednu formu komunikace postavenou na "observer >> patternu", která vychází ze Springu, tj. moduly v důležitých okamžicích své >> funkcionality publikují tzv. eventy do systému, na které pak mohou reagovat >> listenery v jiných modulech. Tímto způsobem je možné distribuovat některá >> důležitá (i agregovaná) data do zbytku systému. Uvedu příklad - máme tzv. >> hodnotící modul, který umožňuje hodnotit libovolný obsah kdekoliv (např. ve >> formě hvězdiček na nějaké škále), tento modul samozřejmě o obsahu samotném >> nic neví - naopak jiný modul, který spravuje daný obsah (třeba články) chce >> při vracení článku vracet aktuální hodnotu průměrného hodnocení. Hodnotící >> modul vždy po přepočtení aktuálního hodnotícího
Re: Divná chyba v SAX parseru?
Dne 1. září 2010 15:48 Kamil Podlesak napsal(a): > Ono se to nezdá, ale používání stále jediné datové struktury (místo > vytváření nových) ušetří hodně práce garbage collectoru a u opravdu > obrovských xml to bude znát (dokonce by mohlo dojít OutOfMemoryError). Nesouhlasím. U opravdu velkých XML (řádově stovky MB a více) není konstrukce objektové reprezentace XML vůbec žádoucí a tedy pro tento případ je HashMapa na atributy získávaná pomocí PullParseru ideálním řešením. A dobrý Pull Parser používá pool, takže se akorát přesunou Stringy. Doufám, že takto funguje STAX (JSR 173). Nikdy jsem jiný než Systinetí PullParser nepoužíval - od dob Systinetu jsem nedělal s velkými XML. > Kamil Podlešák > > 2010/9/1 Tomáš Procházka : >> Díky za tip. Zajímavé, že to v 99% funguje takto naprosto v pořádku, >> kopírovat všechny atributy do hashmapy pro každý XML element mi příjde jako >> zbytečnost, když už to je vše v instanci Attributes :-( >> >> >> --- Původní zpráva --- >> Odesilatel: Kamil Podlesak >> Předmět: Divná chyba v SAX parseru? >> Datum: 1. září 2010, 11:25:40 (GMT +0200) >> Přílohy: >> msgid:aanlktim1orq7=mcrkbitxqjgseuxprdncpsbrsc4s...@mail.gmail.com >> >> K> Zdravím, >> >> K> Nejedná se o chybu, v dokumentaci (javadoc k metodě startElement, od >> K> verze 1.5 výše) je napsáno: >> >> K> atts - the attributes attached to the element. If there are no >> K> attributes, it shall be an empty Attributes object. The value of this >> K> object after startElement returns is undefined >> >> K> Ta poslední věta je klíčová: data z těch atributů si musíte "vytahat" >> K> do nějaké vlastní struktury. >> >> K> Kamil Podlešák >> >> K> 2010/9/1 Tomáš Procházka : Zdravím. >> Setkal se už někdo s tím, že si standardní SAX parser v JDK 1.6 (konkrétně mám 1.6.0.18) vymýšlí neexistující hodnota atributů v XML? >> Konkrétně mám XML, které obsahuje kromě jiného asi 20 000 takovýchto elementů? ... například >>> key="unsubscribe">http://nekde.cz/neco.html >> V SAX handleru, bez jakéhokoliv knihovny, jen v samotné Javě. >> V handleru pak v metod >> public void startElement() si pak pouze uložím do třídních proměnných atributy tagu a nuluju StringBuffer >> this.value.setLength(0); this.attributes = attributes; >> v endElement() pak ukládám do mapy vždy hodnotu atributu key a obsah celého elementu, tedy: >> someMap.put(attributes.getValue("key"), value.toString()); >> všechno funguje, až na to, že zhruba v 300 případech z těch 20 000 elementů se přečte úplně jiný klíč, přípustné hodnoty jsou jen unsubscribe a link a v těch 300 případech tam je něco jako " <" >> Což je samozřejmě nepřípustné >> >> Zkoušel jsem za >> this.attributes = attributes; >> přidat >> if (attributes.getValue(0) != null && !"link".equals(attributes.getValue(0)) && !"unsubscribe".equals(attributes.getValue(0))) { logger.error(" '" + attributes.getValue(0) + "'"); } >> abych si zalogoval všechny případy kdy k tomu dojde a přestalo to dělat, téměř úplně >> Takové chování VM vůbec nechápu. Kdyby to dělalo jen na jednom stroji, tak řeknu, že je něco rozbité na něm. Jenže na ten problém jsme přišli na Linuxovém serveru a bez problémů jsem ho napodobil i na Windows stroji. navíc import ještě probíhá jen v jednom vlákně. >> >> >> Datum: 9:38:09 1. září 2010 -- - Tomáš Procházka >> >> E-mail: t.procha...@centrum.cz WWW: http://www.atomsoft.cz ICQ: 87147320 - >> >> >> Konec původní zprávy >> >> -- >> - >> Tomáš Procházka >> >> >> E-mail: t.procha...@centrum.cz >> WWW: http://www.atomsoft.cz >> ICQ: 87147320 >> - > -- Oto 'tapik' Buchta, ta...@buchtovi.cz, http://tapikuv.blogspot.com
Re: Modulární aplikace
Mate pravdu, no upozornim este na porovnanie join vs in z pohladu performancie. Potencionalny problem in dotazov moze byt, ak by sa databaza rozhodla prechadzat tabulku sekvencne namiesto pouzitia indexu. Ten index tam urcite je, kedze sa jedna o foreign key. Popravde ale ocakavam, ze na sekvencne citanie sa prejde iba ak rozsah ocakavaneho vysledku bude velky (skoro cela tabulka) a teda performancia bude vychadzat narovnako. Na Vasom mieste by som spravil test na databaze, ktoru budete pouzivat s nejakymi rozumne velkymi tabulkami s nejakym beznym query. Staci to spravit z konzoly, netreba z aplikacie. Tomas Studva Oto Buchta wrote / napísal(a): Při návrhu modulární architektury je třeba brát na zřetel jiná možná použití dat z konkrétního modulu a umožnit zásuvné či rozšiřující submoduly do střev každého modulu. Jestli se použije vzor Listener, Observer a nebo eLISPové hooky je celkem buřt. Potom není nutné si tolik hrát s API, jenom nechat data uvnitř modulu bezpečně (myšleno odolně proti nekonzistencím dat) a správně (dva klíčové termíny Hrubozrnný a Volná vazba) protékat přes ony pluginy. Není ale potřeba se nějak dramaticky zaobírat bezpečností (myšleno přístupovými právy), neboť každý modul bude mít VŽDY možnost sáhnout si do DB ;-) 2010/9/2 Tomas Studva : Ale mame aj vinimku, mame totiz modul, ktory potrebuje citat udaje z mnohych modulov naraz a ma vselijake svoje obmedzenia. Konkretne tento modul exportuje data do ineho systemu a bol navrhnuty genericky. Toto je typický kámen úrazu návrhu modulárních systémů. Generický modul může přímo záviset na zase jen na generických modulech. Pokud chcete v generickém modulu volat něco z negenerického modulu, musíte použít nějaký metajazyk, kterým se deklarativně (typicky pomocí konfigurace) na něj či do něj dostanete. S pomocou malej konfiguracie sa da rozsirit export, niekedy vsak to nejde, lebo su tam nejake podmienky, takze sa napise sql. Exportuju sa cele siete objektov. Ak by to malo byt modularne, tak kazdy modul by mal exportovat svoje data, svoju siet. No to by chcelo ovela viacej premysleny navrch, kedze exportovane udaje nie su cela DB, ale cielom je exportovat mininum dat a dba sa na performanciu, robia sa teda aj joiny medzi modulmi. Cize kedze tento Export robi iba citanie, tak ma dovolene sahat do lubolnej tabulky. Ano, SQL se typicky jako metajazyk pro přístp do negenerických modulů používá a pak zde opravdu není problém. Typické nasazení je právě pro statistiky. Exporty bych se snažil řešil jinak a ideálně via pes Partes až na konec kompletace. Export miliónů záznamů se asi nebude dělat každou minutu a každou minutu se nebude dělat export miliónů záznamů, takže tím pádem JOINy určitě oželím. Ale tym ze modul ma vsetky query u seba, vznika aj duplicita niektorych dotazov, no nie je toho vela. V tomto problém nevidím. Implementátor při konfiguraci ví, jaké verze negenerických modulů používá a může tedy separátně nastavit dotazy. Zaver z tohoto prikladu znie, ze moze nastat pripad, ked by sa implentacia stazila resp. aj znizila performancia pri dodrzani modularneho dizajnu, ak by sa dobre nepremyslel dizajn. Tak toto je téměř tautologie ;-) 2010/9/2 Ing. Jan Novotný Ahoj, my jedeme na modulárním systému asi 2 roky (s tím rozdílem, že nemáme OSGI, ale jen zřetězené aplikační konexty Springu na stejné classpath - nicméně už to k zavedení modulárnosti stačí). Řešili jsme stejný problém a obávám se, že neexistuje ideální řešení. Základní pravidlo spočívá ve správném "řezu" modulů - každý by měl mít jednoznačnou odpovědnost a funkci. Moduly by se měly vzájemně doplňovat spíš než ve funkcionalitách překrývat. Prostě příliš malé moduly nejsou dobré, protože mají potom mnoho závislostí ven, velké moduly také nejsou dobré, protože se tím zase snižuje jejich použitelnost. Na správném řezu funkcionalitou prostě záleží hodně. Pokud by jeden modul sahal do dat jiného modulu přímo a nikoliv přes jeho API povede toto porušení zapouzdřenosti k: svázanosti (couplingu) těchto dvou modulů, zhoršení testovatelnosti, problém se samostatným rozvojem modulů (vždy se na ně bude muset pohlížet jako na nějaký provázaný celek). My jsme došli ke dvěma možným technikám v těchto případech (naštěstí těch případů není zase až tak moc). 1) obětování výkonu - tj. každý modul udržuje pouze svá data a pokud z nějakého důvodu potřebuje vrátit či pracovat s daty jiného modulu, jde přes jeho API - tím se ale samozřejmě nedá využít JOINů a platíme výkonem. Tyto mezimodulové "dotazy" se alespoň snažíme optimalizovat na metodách API tím, že tam máme metody pro hromadné načítání dat - např. List getDataById(Integer... id), která může všechna potřebná data načít jednorázově přes WHERE id in (...) 2) porušením normální formy db - kromě přímého volání mezi moduly na úrovni API máme ještě jednu formu komunikace postavenou na "observer patternu", která vychází ze Springu, tj. moduly v důležitých okamžicích s