Attaching presentation I made for my colleagues regarding Redis - The distributed key:value store. Google docs version.
Sunday, August 18, 2013
Friday, July 5, 2013
Constructor dependency injection over property autowiring
I use dependency injection pattern on all projects where it makes any sense, especially spring is following me all my life. Once I've discovered domain driven design, I've realized that model should be rich, clear, reusable, no meaningless dependencies.
Combining of clear model along with spring annotation can bring few issues except model dependency on spring jar files.
See following example what's going on:
And relevant unit tests.
Once you decided to write reboust component, you can't be absolutely sure that someone will use spring (or other DI framework) to push all dependencies.
Well, you need them check. Those are the reasons why I decided to use dependency injection via constructor. The componets just use fully supplied constructor requiring all mandatory dependencies.
See the code:
Such code brings couple of other advantages which you must not see at a glance:
You can browse the code in GitHub.
Combining of clear model along with spring annotation can bring few issues except model dependency on spring jar files.
See following example what's going on:
And relevant unit tests.
Once you decided to write reboust component, you can't be absolutely sure that someone will use spring (or other DI framework) to push all dependencies.
Well, you need them check. Those are the reasons why I decided to use dependency injection via constructor. The componets just use fully supplied constructor requiring all mandatory dependencies.
See the code:
Advantages
Such code brings couple of other advantages which you must not see at a glance:
- Obviously clearer code as there is just only one place where all dependencies are injected and they are final.
- Simple tests
- No more @components with tons of dependencies. This is key point. Do you remember classes which grew and grew and when you opened them last time in your favorite IDE, they had more than 15 dependecies? Well, this is not possible any more. Who would maintain constructor using 15 parameters?
- No circular dependencies. Spring allows to define bean references which leads into closed circuit. I'm surely not alone who do not like it because it's antipattern which hide some wrong design. Once you use dependency using constructor, you will not be able to write such relation anymore.
You can browse the code in GitHub.
Wednesday, June 12, 2013
Wednesday, April 24, 2013
Čas dát NHibernatu sbohem #2 - performance
V minulém díle jsem jsem rozebíral pár nedostatků NHibernatu, které mají z mého pohledu zásadní vliv k nasazení či nenasazení toho výborného frameworku. V tomhle díle bych rád rozebral performance.
Performance lze různě ladit, jak jsem již před pár lety rozbíral. Je spousta možností, jak věci delat. Cachovani, stateless session atd. Ve chvíli, kdy se dostane člověk na hranu rychlosti databáze, musí se začít zaobírat méně obvyklými věcmi, které se běžně neladí.
Kontrukce entit
Vždy jsme na našel projektu ctili DDD, čili chtěli jsme mít rich entity a ne naked. Tím chci říct, že všechny atributy/fieldy jsou encapsulované get/set metodami. Pokud nechcete zveřejnit privátní fieldy, musíte začít používat reflection, což při velkém měřítku při používání pro většinu mapovaných entit začíná být pro .NET problém. Je to pomalé.Existuje několik frameworků (např. FastReflect), které dokážou cachovat reflection přístup, čistou performance přístupu k privátním fieldům to pak zrychlí v našem případě 20x. Samozřejmě custom reflection framework není snadné do NHibernatu nejak integrovat. Je nutné si vyvinout vlastní komponentu, která bude konstruovat entity a tu tam zaintegrovat.
Konstrukce hierarchií entit
Popsaný problém pomalé reflexe plynule přechází v další issue, které člověk musí řešit. Většinou z persistence netaháte jeden typ class, ale hierachii tříd. To znamená, že se persistentního frameworku dotazuji na jeden objekt, který má však další dependance. Typicky v DDD se jedná o agregát, který je separovaný od ostatních agregátů - nemají mezi sebou přímou relaci - a ten obsahuje kolekce dalších druhů entit a tak dál rekurzivně. V našem případě jeden typ agregátu nabobtnal až na dvacet druhů class.Z logiky věci NHibernate konstruuje celý agregát pomocí mappingu, tzn. map klíčů, entit a typů class. Jinak řečeno, materializované entity bude NHibernate ukládat do session a pro dané klíče a typy je linkovat mezi sebou do výsledného agregátu, až z toho nakonec vypadne pouze root instance. Ve chvíli, kdy těch typů a instancí není málo, snadno narazíme na to, že konstruování takového agregátu je dost pomalé.
Nhibernate je obecný framework, který se snaží za runtime zkonstruovat něco, co vy si můžete napsat sami. Performance programového přístupu versus vašeho zakompilovaného je samozřejmě velká v řádu desítek procent ušetřeného času.
Jediné, co musí programátor udělat, je napsat si vlastní linker a vlastní session, která je schopná absorvovat entity a propojovat je přes identifikátory.
Mapping
Přestože se to nemusí zdát, i samotné mapování může mít dopad na výkon Vaší aplikace. Ačkoliv je NHibernate jeden z nejvíc ohebných frameworků, co jsem poznal, mapping neumí zdaleka všechno. Pokud máte složitejší věci, např. kolekce kolekcí nebo dictinary kolekcí, musíte v mapování přijít s workaroundem, protože tohle standardně mapovat nelze. V našem případě jsem vždycky pro daný záznam vytvořili novou (zbytečnou) entitu, která tohle dokázala obalit a tu také namapovali.Místo přirozeného řešení jsem kvůli jemnému omezení museli vytvořit entitu navíc. Samozřejmě, že takový zásah má vliv na performance, např. vytváření entit s následným garbage-collectingem atd. V serverových aplikacích je občas nutné hledět na každou zbytečnou entitu.
Garbage Collecting
Poslední téma, kterého bych se rád dotknul, je produkce entit a následný garbage collecting. Škálovatelná server-side aplikace by neměla plýtvat zdroji. Pokud to dělá, brzy v rámci optimalizací performance narazí. Tahle metrika je vždy strašně těžko měřitelná, protože každý profiler nebo typ měření dává jiné výsledky.Jedna věc je však jistá. Jakékoliv ORM bude produkovat víc odpadu, protože bude vždy víc obecné - to znamená, že bude produkovat obalovací entity - než Vaše custom persistenční logika, která je prostě na míru. Bude produkovat víc obecný kód - jak jste to již popisoval v předchozí kapitole.
Při nasazení NHibernatu do produkce zvedne vždycky čas v GC.
Rozhřešení
Po několika letech používání NHibernatu jsme dospěli do situace, kdy jsme si pro zrychlení persistentní vrstvy museli přepsat určité komponenty nebo vyměnit NHibernate celý. Začali jsme s tím prvním. Jak jsme skončili uvidíme v další kapitole.Sunday, January 13, 2013
Book: Functional Programming for Java Developers: Tools for Better Concurrency, Abstraction, and Agility
Probably all of us forget functional programming in the name of object oriented one. As concurrency and scalability are two buzzwords mentioned these days in every technical acrticle the functional programming notion seems to growing.
The book Functional Programming for Java Developers: Tools for Better Concurrency, Abstraction, and Agility is brief introduction why and how could developer or architect think about development, especialy in the scope of reusable components.
The couple of chapters at the beggining show how functional programming approach can improve thinking of every programmer. Special attention is put on objects immutability or functional recursion.
Next chapters present the example how to write immutable list and maps, how to write useful methods operating above the list using recursion and how to use these methods for everything what you can want from the structure.
Well, I read the book twice. The impact was immediate since I was writting a component based on tree structure. As soon as you realize the immutability is better than classic locking-aware approach you start asking how to achieve such pleasat property on objects requiring mutability by nature. It requires the change of mind. This book can help you a lot.
The book Functional Programming for Java Developers: Tools for Better Concurrency, Abstraction, and Agility is brief introduction why and how could developer or architect think about development, especialy in the scope of reusable components.
The couple of chapters at the beggining show how functional programming approach can improve thinking of every programmer. Special attention is put on objects immutability or functional recursion.
Next chapters present the example how to write immutable list and maps, how to write useful methods operating above the list using recursion and how to use these methods for everything what you can want from the structure.
Well, I read the book twice. The impact was immediate since I was writting a component based on tree structure. As soon as you realize the immutability is better than classic locking-aware approach you start asking how to achieve such pleasat property on objects requiring mutability by nature. It requires the change of mind. This book can help you a lot.
Sunday, December 23, 2012
Čas dát NHibernatu sbohem #1 - nízká transparentnost
Mám rád frameworky. Použít sílu, inteligenci a práci ostatních, kterou nabízí zdarma, mi přijde jako dobrý nápad, který šetří lidské zdroje a člověka učí. Proto také v našem .NET produktu HP Service Virtualization používáme NHibernate, Spring.NET, NUnit atd.
Ostatně princip ORM je dobrý nápad. Team, starající se o persistenci, rychle nabootuje do problematiky persistence, nevynalézá kolo s různými koncepty jako je optimistic locking, session handling, podporuje relativní přenositelnost mezi databázemi a persistentní úroveň napíšete za zlomek času. V následujicí sérii článků bych rád popsal pár postřehů, proč se skoro po třech letech chceme NHibernatu na našem produktu zbavit. Pořadí problému se nemusí nutně shodovat s jejich závažností :-)
Poslední dobou slýchávám názor, že jsou věci složité jinak by je dělal každý. Tohle tvrzení je skoro v rozporu s dobrými programátorskými mravy :-) Asi před rokem jsem četl knížku Tajemství inovací Steva Jobse. Ač nejsem milovník Apple, kniha ve mě zásadně vylepšila náhled na složitost naprogramovaného kódu. Od té doby se snažím dbát na jednoduchost všeho co dělám.
NHibernate je vysoce konfigurovatelný, umí mnoho věcí nastavit, často velmi umě schovává hodně složitou funkcionalitu za jednoduché koncepty. Přesto to pro složitější aplikace nemusí stačit.
Jeden příklad složitosti za všechny. Hibernate Session. Výborný koncept, který umí pomocí optimistického přístupu cachováním šetřit přístup do DB. Zaručuje dokonce prakticky vyšší izolační level než standardní Read Committed - pokud jednou načtete entitu, dostanete během životnosti session vždy stejnou instanci - samozřejmě s určitými vyjímkami. Což jsou přesně ty složitosti o kterých mluvím.
Problém je, že tento koncept musíte vystavit mimo databázovou vrstvu, např. s použitím Transaction API ve Springu v komponentách, které řeší transakce. Jakmile tohle uděláte, nemáte věci pod kontrolou. Potom pracuje se session, alespoň na pozadí, váš celý tým. Všichni členové pak musí umět správně se session fungovat, vědět kdy co dostanou, kdy mají co updatovat, kdy refreshovat. Handlování práce se session začne prorůstat mimo databázi. Mužete ho sice skrýt za repository, ale už je vidět.
Pokud je počet uživatelů podobného API větší, vždycky se najde pár jedinců, kteří jej používají špatně. Vše se později zvrtne k tomu, že místo šetřeni dotazů do databáze se queruje vždycky.
V kombinaci s magičností sklouzneme zákonitě k tomu, že bychom lépe spali, kdybychom si session komponentu psali sami, vynutili si jasný lifecycle manažovaných entit a měli vše pod kontrolou, protože celý zbytek teamu nerozumí detailně session logice a nemá čas číst stovku stránek NHibernate manuálu.
Proč magičností? Springové transakční API handluje lifecycle session. Rádi bychom během celého processení jednoho callu na náš server měli session jako unit of work. Springové transakční API se bohužel nechová tak, že bychom mimo něj poznali, kdy vytvárí novou session a kdy ji znovupoužívá - což je chování, kterého chceme dosahnout. Tímto přesně zajistíme konzistenčnost během celého zpracování.
Další magičnost? Např. v Second Level Cache není občas jasné proč je držena starší entita než očekáváme a několik dnů strávených debugováním NHibernate knihoven nenese ovoce. Musíte potom obcházet celý koncept, tu a tam session či cache clearovat nebo naopak flushovat, aby se v ní objevilo to správné. Začíná se to pak celé nebezpečně hákovat.
NHibernate je mocný nástroj, ale jako vždycky věci normalizuje. Zjednodušení konceptu má vždy velkou nevýhodu a to skrytí určitých věcí o kterých rozhoduje sám framework za vás. Pokud je ale chcete měnit, musíte si přepsat tu a tam nějakou komponentu. Prostě vám občas nesedí defaultní chování.
Pokud tohle chcete, raděj se HNibernatu vyhněte.
Co bude příště? Performance. Kdy a proč se vyhnout NHibernate, když chcete vysokou performance.
Ostatně princip ORM je dobrý nápad. Team, starající se o persistenci, rychle nabootuje do problematiky persistence, nevynalézá kolo s různými koncepty jako je optimistic locking, session handling, podporuje relativní přenositelnost mezi databázemi a persistentní úroveň napíšete za zlomek času. V následujicí sérii článků bych rád popsal pár postřehů, proč se skoro po třech letech chceme NHibernatu na našem produktu zbavit. Pořadí problému se nemusí nutně shodovat s jejich závažností :-)
Poslední dobou slýchávám názor, že jsou věci složité jinak by je dělal každý. Tohle tvrzení je skoro v rozporu s dobrými programátorskými mravy :-) Asi před rokem jsem četl knížku Tajemství inovací Steva Jobse. Ač nejsem milovník Apple, kniha ve mě zásadně vylepšila náhled na složitost naprogramovaného kódu. Od té doby se snažím dbát na jednoduchost všeho co dělám.
NHibernate je vysoce konfigurovatelný, umí mnoho věcí nastavit, často velmi umě schovává hodně složitou funkcionalitu za jednoduché koncepty. Přesto to pro složitější aplikace nemusí stačit.
Jeden příklad složitosti za všechny. Hibernate Session. Výborný koncept, který umí pomocí optimistického přístupu cachováním šetřit přístup do DB. Zaručuje dokonce prakticky vyšší izolační level než standardní Read Committed - pokud jednou načtete entitu, dostanete během životnosti session vždy stejnou instanci - samozřejmě s určitými vyjímkami. Což jsou přesně ty složitosti o kterých mluvím.
Problém je, že tento koncept musíte vystavit mimo databázovou vrstvu, např. s použitím Transaction API ve Springu v komponentách, které řeší transakce. Jakmile tohle uděláte, nemáte věci pod kontrolou. Potom pracuje se session, alespoň na pozadí, váš celý tým. Všichni členové pak musí umět správně se session fungovat, vědět kdy co dostanou, kdy mají co updatovat, kdy refreshovat. Handlování práce se session začne prorůstat mimo databázi. Mužete ho sice skrýt za repository, ale už je vidět.
Pokud je počet uživatelů podobného API větší, vždycky se najde pár jedinců, kteří jej používají špatně. Vše se později zvrtne k tomu, že místo šetřeni dotazů do databáze se queruje vždycky.
V kombinaci s magičností sklouzneme zákonitě k tomu, že bychom lépe spali, kdybychom si session komponentu psali sami, vynutili si jasný lifecycle manažovaných entit a měli vše pod kontrolou, protože celý zbytek teamu nerozumí detailně session logice a nemá čas číst stovku stránek NHibernate manuálu.
Proč magičností? Springové transakční API handluje lifecycle session. Rádi bychom během celého processení jednoho callu na náš server měli session jako unit of work. Springové transakční API se bohužel nechová tak, že bychom mimo něj poznali, kdy vytvárí novou session a kdy ji znovupoužívá - což je chování, kterého chceme dosahnout. Tímto přesně zajistíme konzistenčnost během celého zpracování.
Další magičnost? Např. v Second Level Cache není občas jasné proč je držena starší entita než očekáváme a několik dnů strávených debugováním NHibernate knihoven nenese ovoce. Musíte potom obcházet celý koncept, tu a tam session či cache clearovat nebo naopak flushovat, aby se v ní objevilo to správné. Začíná se to pak celé nebezpečně hákovat.
NHibernate je mocný nástroj, ale jako vždycky věci normalizuje. Zjednodušení konceptu má vždy velkou nevýhodu a to skrytí určitých věcí o kterých rozhoduje sám framework za vás. Pokud je ale chcete měnit, musíte si přepsat tu a tam nějakou komponentu. Prostě vám občas nesedí defaultní chování.
Pokud tohle chcete, raděj se HNibernatu vyhněte.
Co bude příště? Performance. Kdy a proč se vyhnout NHibernate, když chcete vysokou performance.
Sunday, October 2, 2011
Book: The Art of Unit Testing: With Examples in .Net
I finished the reading of The Art of Unit Testing: With Examples in .Net book before a week. The book was categorized as an agile book so you can forget as the book is something like the bible of unit testing. It just summarizes the agile and pragmatic point of view to unit testing more then programmer's manual how to write correctly unit tests.
First chapters define unit testing basis, point to differences between unit and integration testing. The problem is that such text doesn't highlight those differences enough and the reader couldn't understand why the isolation is so much necessary. It's followed by the expression of stubs and mocks and the list of mock frameworks.
The rest of the content is sort of novel about importance of unit testing, the purpose of testing in the company. The most valuable chapter is almost last one which describes how to implement unit testing as a new feature in your company. Such text is applicable for any new technology you want to use in your business.
As I've already said, this book is sort of novel about unit testing, one text which can help you to form your point of view why and how to unit testing, that's all. There is lack of facts important to understand how and why to use isolation frameworks, what can happen when you would write w/o that - which happen in my company anyway :-) - how you would "unit test" any class etc.
Just read the book to complete your glance of unit testing but not suitable for unit testing novices.
First chapters define unit testing basis, point to differences between unit and integration testing. The problem is that such text doesn't highlight those differences enough and the reader couldn't understand why the isolation is so much necessary. It's followed by the expression of stubs and mocks and the list of mock frameworks.
The rest of the content is sort of novel about importance of unit testing, the purpose of testing in the company. The most valuable chapter is almost last one which describes how to implement unit testing as a new feature in your company. Such text is applicable for any new technology you want to use in your business.
As I've already said, this book is sort of novel about unit testing, one text which can help you to form your point of view why and how to unit testing, that's all. There is lack of facts important to understand how and why to use isolation frameworks, what can happen when you would write w/o that - which happen in my company anyway :-) - how you would "unit test" any class etc.
Just read the book to complete your glance of unit testing but not suitable for unit testing novices.
Subscribe to:
Posts (Atom)

