<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Simon says... architecture!</title>
	
	<link>http://simon-says-architecture.com</link>
	<description>Szymon Pobiega about software engineering and architecture</description>
	<lastBuildDate>Mon, 02 Aug 2010 21:18:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<meta xmlns="http://www.w3.org/1999/xhtml" name="robots" content="noindex,follow" />
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/szymonpobiega" /><feedburner:info uri="szymonpobiega" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>NoSQL Summer</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/t_mznPlQEBs/</link>
		<comments>http://simon-says-architecture.com/2010/08/02/nosql-summer/#comments</comments>
		<pubDate>Mon, 02 Aug 2010 21:18:19 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Notki po polsku]]></category>
		<category><![CDATA[nosql]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=706</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/>Niedawno miałem przyjemność uczestniczyć w pierwszym spotkaniu Krakowskim spotkaniu inicjatywy NoSQL Summer. Zainteresowała mnie, przede wszystkim, forma spotkań &#8212; dyskusje dotyczące przeczytanych &#8220;lektur obowiązkowych&#8221;. Skojarzyło mi się bardziej z dyskusyjnym klubem filmowym, niż typową technologiczną juzergrupą. Postanowiłem się więc wybrać. Nie żałowałem.
Organizacji krakowskich spotkań podjął się Adam Pohorecki. Dzięki temu organizacyjnie wszystko było zapięte na [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/><p>Niedawno miałem przyjemność uczestniczyć w pierwszym spotkaniu Krakowskim spotkaniu inicjatywy <a href="http://nosqlsummer.org/">NoSQL Summer</a>. Zainteresowała mnie, przede wszystkim, forma spotkań &#8212; dyskusje dotyczące przeczytanych &#8220;lektur obowiązkowych&#8221;. Skojarzyło mi się bardziej z dyskusyjnym klubem filmowym, niż typową technologiczną juzergrupą. Postanowiłem się więc wybrać. Nie żałowałem.</p>
<p>Organizacji krakowskich spotkań podjął się <a href="http://adam.pohorecki.pl/">Adam Pohorecki</a>. Dzięki temu organizacyjnie wszystko było zapięte na ostatni guzik. Miłym dodatkiem było piwo sponsorowane przez <a href="http://lunarlogicpolska.com/">Lunar Logic</a>.</p>
<p>Spotkanie przybrało ostatecznie formę wymiany doświadczeń dotyczących różnych baz nierelacyjnych. Oto garść zebranych przeze mnie naprędce wniosków:</p>
<p>Mamy do czynienia z prawdziwym wysypem baz nierelacyjnych. Chyba każdy szanujący się programista za punkt honoru ma napisanie swojej (zupełnie jak niegdyś z kontenerami Dependency Injection).</p>
<ul>
<li>Poszczególne bazy nierelacyjne różnią się podejściem do replikacji/klastrowania.</li>
<li>Najbardziej znany w Krakowie jest <a href="http://couchdb.apache.org/">CouchDB</a>.</li>
<li>Temat NoSQL jest raczej obcy środowsiku .NET. Smutne.</li>
<li>Częstym problemem z bazami nierelacyjnymi jest duży apetyt na przestrzeń dyskową.</li>
<li>Bazy nierelacyjne są już od dawna wykorzystywane produkcyjnie, nawet w Krakowie.</li>
<li>Transakcje obejmujące modyfikacje kilku dokumentów to ZŁO.</li>
<li>API baz nierelacyjnych jest bardziej zbliżone do sposobu działania ich mechanizmów składowania danych</li>
<li>Bazy nierelacyjne wymagają większej świadomości i wiedzy od dewelopera, ale w zamian oferują większe możliwości wpływania na zachowanie mechanizmu składowania danych (np. rozwiązywanie konfliktów.</li>
</ul>
<p>Kolejne spotkanie z cyklu NoSQL Summer<strong> już w najbliższą środę</strong> w siedzibie Lunar Logic (Krasińskiego 17/5). Temat: map/reduce. Więcej informacji można uzyskać za pośrednictwem<a href="http://groups.google.com/group/nosql-summer-krakow"> grupy google Kraków NoSQL Summer</a>. W imieniu organizatorów, zapraszam.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=t_mznPlQEBs:LMWIypOiNaU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=t_mznPlQEBs:LMWIypOiNaU:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/t_mznPlQEBs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/08/02/nosql-summer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/08/02/nosql-summer/</feedburner:origLink></item>
		<item>
		<title>Domain Driven Design, czyli programowanie przez modelowanie</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/GfpO3mgtAhg/</link>
		<comments>http://simon-says-architecture.com/2010/06/28/programowanie-przez-modelowanie/#comments</comments>
		<pubDate>Mon, 28 Jun 2010 03:51:48 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Notki po polsku]]></category>
		<category><![CDATA[DDD]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=692</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/>Podczas 58. spotkania Krakowskiej Grupy Developerów .NET miałem przyjemność poprowadzić prezentację pt. &#8220;Domain Driven Design, czyli programowanie przez modelowanie&#8221;. Ponieważ zakładam, że nie wszyscy jesteście z Krakowa i uczestniczyliście w spotkaniu, pozwolę sobie opisać o czym mówiłem. Prezentację możecie obejrzeć lub ściągnąć (format pptx) stąd (via SlideShare), a przykłady w kodzie stąd.
Rozwiązywanie problemów
Na początku chciałbym [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/><p>Podczas <a href="http://ms-groups.pl/kgd.net/58_spotkanie/default.aspx">58. spotkania</a> Krakowskiej Grupy Developerów .NET miałem przyjemność poprowadzić prezentację pt. &#8220;Domain Driven Design, czyli programowanie przez modelowanie&#8221;. Ponieważ zakładam, że nie wszyscy jesteście z Krakowa i uczestniczyliście w spotkaniu, pozwolę sobie opisać o czym mówiłem. Prezentację możecie obejrzeć lub ściągnąć (format pptx) <a href="http://www.slideshare.net/SzymonPobiega/domain-driven-design-czyli-progamowanie-przez-modelowanie">stąd</a> (via SlideShare), a przykłady w kodzie <a href="http://simon-says-architecture.com/wp-content/uploads/2010/06/DomainModelPatterns.zip">stąd</a>.</p>
<h3>Rozwiązywanie problemów</h3>
<p>Na początku chciałbym skontrastować &#8220;klasyczne&#8221; podejście do rozwiązywania problemów z podejściem wykorzystującym model. Można to zilustrować następująco:</p>
<table class="nostyle">
<tbody>
<tr>
<td>
<p><div id="attachment_693" class="wp-caption aligncenter" style="width: 278px"><a href="http://simon-says-architecture.com/wp-content/uploads/2010/06/problem-solving-without-model.png"><img class="size-full wp-image-693  " title="problem solving without model" src="http://simon-says-architecture.com/wp-content/uploads/2010/06/problem-solving-without-model.png" alt="" width="268" height="191" /></a><p class="wp-caption-text">Podejście klasyczne</p></div></td>
<td>
<p><div id="attachment_695" class="wp-caption aligncenter" style="width: 348px"><a href="http://simon-says-architecture.com/wp-content/uploads/2010/06/problem-solving-with-model.png"><img class="size-full wp-image-695    " title="problem solving with model" src="http://simon-says-architecture.com/wp-content/uploads/2010/06/problem-solving-with-model.png" alt="" width="338" height="173" /></a><p class="wp-caption-text">Podejście z wykorzystaniem modelu</p></div></td>
</tr>
</tbody>
</table>
<p>W wersji klasycznej programista implementuje bezpośrednio wymagania, tak jak zostały one spisane przez analityka (zwykle w formie 10/100/miliona linii &#8220;The system shall&#8230;&#8221;). Dobrze, jeśli w ten proces wpleciona jest pętla sprzężenia zwrotnego, która sprawia, że implementacja pierwszych wymagań ma wpływ na dalszy przebieg procesu analizy.</p>
<p>W podejściu &#8220;Domain-Driven&#8221; tak naprawdę nie istnieją role analityka i programisty. <strong>Istnieje tylko jedna rola &#8212; modelarz</strong>. Modelarz zajmuje się budową modelu rzeczywistości użytecznego w rozwiązaniu konkretnego problemu. Współpracuje on bardzo blisko z ekspertami dziedzinowymi, przetwarzając posiadaną przez nich wiedzę na spójny, niesprzeczny, a co najważniejsze, wykonywalny, model. Dopiero na bazie tego modelu tworzone jest ostateczne rozwiązanie. Możemy odnaleźć dwie pętle sprzężenia zwrotnego: pierwsza dotyczy samego modelu (im więcej modelarz stworzył, tym lepiej rozumie problem), a druga modelu w kontekście aplikacji (im więcej wiemy, co ma robić aplikacja, tym lepiej wiemy, które aspekty należy dokładniej modelować).</p>
<h3>Cechy modelu</h3>
<p>Skoro już wiemy, do czego przydaje się model, warto się zastanowić jakie cechy powinien posiadać dobry model. Oto moja osobista lista w kategorii &#8220;model powinien być&#8221;:</p>
<h4>Użyteczny</h4>
<p>Nie ma sensu budowa idealnego modelu rzeczywistości, ponieważ byłby on tak samo skomplikowany jak ta rzeczywistość. Z punktu widzenia złożoności obliczeniowej jest to niewykonalne. Znane powiedzenie mówi, że <strong>wszystkie modele są błędne, ale niektóre są użyteczne</strong>. Model, który budujemy na potrzeby naszego systemu powinien odzwierciedlać tylko ten fragment rzeczywistości, w ramach którego działa ten system i tylko pod kątem czynności bezpośrednio związanych z jego funkcjonowaniem.</p>
<h4>Hermetyczny</h4>
<p>Model jest kodyfikacją pewnych reguł rządzących modelowanym wycinkiem rzeczywistości. Reguły te nie powinny wyciekać z modelu, co oznacza, że jego klienci (użytkownicy) nie powinni musieć o nich wiedzieć. Przykładem może być reguła, że w modelu programu HR pracownik może mieć w danym momencie co najwyżej jednego pracodawcę. To model, a nie klient, powinien zadbać o to, aby przy zmianie pracy pracownik został odłączony od poprzedniego pracodawcy.</p>
<h4>Podatny na modyfikacje</h4>
<p>Jest to sprzeczne z zasadą Open-Closed Principle (<em>open for extensions, closed for modifications</em>), jednak w przypadku modeli sprawdza się bardzo dobrze. Aby model był nadążał za szybko zmieniającą się rzeczywistością, sam także musi się zmieniać. Nie chcemy przecież, aby skostniały model aplikacji był dla organizacji jej używającej hamulcem rozwoju, prawda?</p>
<h4>Zrozumiały</h4>
<p>O sukcesie modelu i całego projektu decyduje, czy wszyscy jego interesariusze rozumieją przestrzeń problemu. Model powinien stanowić podstawę porozumienia i bazę dla wszędobylskiego języka (<em>ubiquitous language</em>) służącego do komunikacji między wykonawcami systemu (ludźmi technicznymi), a ekspertami dziedzinowymi. W dzisiejszych czasach języki programowania takie, jak C#, są na tyle elastyczne, że pisanie kodu (modelu) tak, aby był zrozumiały dla nieprogramistów nie stanowi już większego problemu.</p>
<h4>Wydajnie implementowalny</h4>
<p>Mimo, iż model nie powinien być zależny od jakiejkolwiek konkretnej technologii, powinien jednak być (w jakiejś technologii) wydajnie implementowalny. Nie chcemy być zależni od NHibernate czy innego ORM-a, jednak akceptowanie faktu, że model będzie przechowywany trwale w <strong>jakiejś </strong>relacyjnej bazie danych za pośrednictwem <strong>jakiegoś</strong> ORM-a pozwala zoptymalizować wiele kwestii. Nie ma sensu udawać niezależności od wszystkich aspektów technologii.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=GfpO3mgtAhg:kCePlgQM260:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=GfpO3mgtAhg:kCePlgQM260:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/GfpO3mgtAhg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/06/28/programowanie-przez-modelowanie/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/06/28/programowanie-przez-modelowanie/</feedburner:origLink></item>
		<item>
		<title>Jak zwątpiłem w transakcje</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/D6064ngLylw/</link>
		<comments>http://simon-says-architecture.com/2010/06/17/jak-zwatpilem-w-transakcje/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 03:49:57 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Notki po polsku]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[NServiceBus]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=684</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/>Transakcje to fajna sprawa. Polubiłem je od pierwszego użycia. Zostałem oczarowany przez ich magiczną właściwość &#8212; zwalniają z myślenia o spójności danych. Cool, przecież nie lubię myśleć. Jeszcze bardziej byłem oczarowany, gdy odkryłem transakcje rozproszone. To dopiero jazda. Mogę coś &#8220;zapdejtować&#8221; na tej bazie, na tej drugiej bazie i jeszcze wrzucić komunikat do kolejki MSMQ [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/><p>Transakcje to fajna sprawa. Polubiłem je od pierwszego użycia. Zostałem oczarowany przez ich magiczną właściwość &#8212; zwalniają z myślenia o spójności danych. Cool, przecież nie lubię myśleć. Jeszcze bardziej byłem oczarowany, gdy odkryłem transakcje rozproszone. To dopiero jazda. Mogę coś &#8220;zapdejtować&#8221; na tej bazie, na tej drugiej bazie i jeszcze wrzucić komunikat do kolejki MSMQ i wszystko wykona się transakcyjnie &#8212; w całości lub wcale.</p>
<p>Od dłuższego czasu zaczynam jednak wątpić w transakcje, szczególnie te rozproszone. Zbyt często ja sam lub ktoś ze znajomych wpada przez nie w pułapkę bez wyjścia. Zamiast używać najodpowiedniejszej technologii, musimy wtedy wziąć taką, która współdziała z naszym sposobem zarządzania transakcjami.</p>
<p>Najczęstszym problemem, na który natrafiałem jest odbieranie i wysyłanie komunikatów do kolejek z jednoczesnym zapisem danych w bazie. Pierwsza rzecz, która przychodzi w takim wypadku do głowy, to transakcja, która obejmuje zarówno infrastrukturę kolejkową, jak i RDBMS. Pierwsza nie oznacza, niestety, najlepsza.</p>
<h3>Nieodpowiednia technologia</h3>
<p>Wymaganie transakcyjności w komunikacji z RDBMS i kolejkami pchnęło mnie kilka lat temu do wykorzystania SQL Server Service Broker jako kolejki komunikatów. Unikalną cechą Service Broker&#8217;a jest fakt, że żyjąc wewnątrz silnika bazodanowego, jest w naturalny sposób zintegrowany z mechanizmami transakcyjnymi SQL Server. Nie ma potrzeby stosowania (wolnych) transakcji rozproszonych, aby wysłać komunikat i zrobić przysłowiowy &#8220;apdejt&#8221;.</p>
<p>Niestety poza tą jedną zaletą, Service Broker ma bardzo wiele wad, z których największą jest brak dobrego gotowego API w C#, o modelu usługowym (np. WCF) nie wspominając. Jest bardzo trudny w użyciu i utrzymywaniu. Definitywnie był to zły wybór technologiczny, podyktowany jedynie chęcią zastosowania mechanizmu transakcji.</p>
<h3>Niezgodność API</h3>
<p>W każdym nietrywialnym systemie wykorzystuje się wiele zewnętrznych bibliotek. Bardzo rzadko pochodzą one od jednego dostawcy. Zdecydowanie częściej jest to mieszanka rozwiązań open source oraz COTS. Problem pojawia się, gdy dwie z bibliotek mają współpracować w ramach jednej transakcji. Weźmy jako przykład NHibernate i NServiceBus. Ten pierwszy posiada własną abstrakcję reprezentującą transakcje, podczas gdy pod spodem korzysta z transakcji ADO.NET. Ten drugi wykorzystuje transakcje System.Transactions do dostępu do MSMQ.</p>
<p>W przypadku użycia obu technologii w jednej transakcji, pojawia się problem, jak sprawić, aby każda z bibliotek mogła wykorzystywać swoje API odwołując się do tej samej fizycznej transakcji. W wypadku wspomnianej pary, jedynym rozwiązaniem jest pozwolić NHibernate używać zewnętrznych transakcji System.Transactions. Jest to jednak zamiana jednego problemu na inny. Do niedawna bowiem pojawiał się w NServiceBus <a href="http://davybrion.com/blog/2010/05/avoiding-leaking-connections-with-nhibernate-and-transactionscope/">wyciek pamięci</a>, ponieważ zachowanie NHibernate w wypadku współpracy z System.Transactions jest bardzo słabo udokumentowane i łatwo o błąd wynikający z niezrozumienia.</p>
<h3>Błedne implementacje transakcyjności</h3>
<p>Jonathan Oliver opisał swoje testy kompatybilności różnych silników bazodanowych z transakcjami rozproszonymi na swoim <a href="http://jonathan-oliver.blogspot.com/2010/04/nservicebus-distributed-transaction.html">blogu</a>. Wnioski nie są optymistyczne: jedynie sterowniki do SQL Server i Oracle w pełni i bez problemów je obsługują.</p>
<p>Z drugiej strony nie dziwie się, że mniej płatne lub darmowe rozwiązania nie wspierają rozproszonych transakcji. Zdecydowana większość systemów radzi sobie bez nich, więc zysk (w sensie pieniędzy z licencji lub satysfakcji użytkowników) z implementacji wsparcia dla nich byłby znikomy.</p>
<h3>Proste rozwiązanie</h3>
<p>Rozwiązanie jest oczywiście proste. Wymaga jednak nieco innego podejścia do projektowania komunikacji. Wystarczy zadbać o to, aby każdy komunikat był</p>
<ul>
<li>albo <em>idempotentny</em> (wielokrotne przetworzenie takiego komunikatu daje taki sam efekt, jak przetworzenie jednokrotne),</li>
<li>albo jednoznacznie identyfikowalny (unikalne ID).</li>
</ul>
<p>Drugi przypadek można sprowadzić do pierwszego dodając rejestr przetworzonych komunikatów zawierający ich unikalne ID i przed obsłużeniem komunikatu sprawdzać, czy aby nie został przetworzony wcześniej.</p>
<p>Po spełnieniu któregoś z powyższych warunków zyskujemy możliwość rozłącznego zarządzania transakcją związaną z obieraniem komunikatu (MSMQ, ServiceBroker) oraz transakcją bazodanową.<strong> Ta pierwsza powinna być zatwierdzana dopiero po zatwierdzeniu tej drugiej</strong>. Powoduje to, że mamy pewność, iż każdy komunikat zostanie przetworzony <strong>co najmniej raz</strong>. Z drugiej strony <em>idempotentność</em> gwarantuje nam, że skutki wielokrotnego przetworzenia będą takie, jak jednokrotnego. Ostatecznie więc uzyskujemy semantykę <strong>dokładnie raz</strong> &#8212; taką samą jak przy zastosowaniu transakcji rozproszonych.</p>
<h3>Praktyka</h3>
<p>Dokładnie taki mechanizm zastosowałem w swoim ostatnim systemie. Pozwolił mi on na użycie klienta Service Broker (użycie tej kolejki było narzucone z góry) w połączeniu z NHibernate <strong>bez konieczności integracji obu technologii</strong>. Ponieważ transakcje były rozdzielone, klient kolejek nie musiał wiedzieć nic o dostępie do danych i <em>vice versa</em>. Prawdopodobnie zaoszczędziło mi to kilka dni pracy przy implementacji, testach i poprawianiu bugów w warstwie integracyjnej. Nauczyłem się także, że <strong>najlepszą strategią integracji technologii jest unikanie integracji technologii, kiedy to tylko możliwe</strong>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=D6064ngLylw:E3BwapEx2Tg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=D6064ngLylw:E3BwapEx2Tg:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/D6064ngLylw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/06/17/jak-zwatpilem-w-transakcje/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/06/17/jak-zwatpilem-w-transakcje/</feedburner:origLink></item>
		<item>
		<title>Fractal structures</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/toQF2pq-8d4/</link>
		<comments>http://simon-says-architecture.com/2010/06/14/fractal-structures/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 04:55:30 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Posts in English]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[MVVM]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=676</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/gb.png" width="17" height="17" alt="" title="Posts in English" /><br/>For the last few days I was mainly pair-programming (pair-refactoring to be honest) some Silverlight UI code. I must confess I really rarely write UI code these days. Actually, I don&#8217;t remember the last time I&#8217;ve written a ASP.NET control from scratch. I did write some UI for DDDSample.Net but it was not production code [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/gb.png" width="17" height="17" alt="" title="Posts in English" /><br/><p>For the last few days I was mainly pair-programming (pair-refactoring to be honest) some Silverlight UI code. I must confess I really rarely write UI code these days. Actually, I don&#8217;t remember the last time I&#8217;ve written a ASP.NET control from scratch. I did write some UI for <a href="dddsamplenet.codeplex.com/">DDDSample.Net</a> but it was not production code after all.</p>
<h3>MVVM</h3>
<p>When I bumped into this Model-View-View Model (MVVM) stuff, I was a little confused. Then came the moment of enlightenment. I realized I saw all of this in totally different context &#8211; in loosely coupled system architecture. Look at this:</p>
<p style="text-align: center;"><a href="http://simon-says-architecture.com/wp-content/uploads/2010/06/UI-vs-System-design.png"><img class="aligncenter size-full wp-image-678" title="UI vs System design" src="http://simon-says-architecture.com/wp-content/uploads/2010/06/UI-vs-System-design.png" alt="" width="503" height="300" /></a></p>
<p>The blue elements on the right is MVVM stuff. It contains of three classic MVVM components and an additional one &#8212; an Event Aggregator. It is used for communication between MVVM triads. Application is organized in such a way, that multiple MVVM triads form vertical slices of functionality. These slices are loosely coupled so that they can be changed independently. Actually, when you value loose coupling much, you should avoid any code sharing between slices.</p>
<p>The orange elements are the building blocks of DDD-based distributed application. It receives commands via Services, then it processes them in a Domain Model which is backed by a Data Store. Finally, state changes are communicated to the outside world via a Message Bus.</p>
<h3>How do slices communicate?</h3>
<p>They use events and (rarely) messages. The name I chose for the diagram, the Event Aggregator, is a little bit misleading, because ViewModels should be able to both publish an event (broadcast to all interested receivers) and send direct message to a concrete receiver. The only shared thing between slices is the definition of messages (sounds like SOA, isn&#8217;t it?).</p>
<h3>Again, how does it relate to system architecture?</h3>
<p>I think the picture says it all. View is an analog of Service interface. View Model is an analog of Domain Model. In fact, one can say that<strong> View Model is the Domain Model</strong> in the context of user interface as it models the domain of particular UI case. The model is the place where all the information lives, a Data Store if you prefer. Finally, the Event Aggregator (with mentioned earlier unicast capabilities) is an analog of a Message Bus (such as NServiceBus).</p>
<h3>How does it work?</h3>
<p>Let&#8217;s look at the example. There are two slices, A and B. For the purpose of the example, let A be master view (a data grid and search) and B &#8212; a details view.</p>
<p style="text-align: center;"><a href="http://simon-says-architecture.com/wp-content/uploads/2010/06/UI-slices.png"><img class="aligncenter size-full wp-image-677" title="UI slices" src="http://simon-says-architecture.com/wp-content/uploads/2010/06/UI-slices.png" alt="" width="441" height="355" /></a></p>
<p>User selects the row on a grid. In response to that View A to generate a command and passes it (by means of data binding) to the View Model A. The View Model validates command, processes it (updates all required properties) and, as a result, it publishes an event &#8220;SelectionChanged&#8221;.</p>
<p>The Event Aggregator receives the event and searches for its subscribes. It finds View Model B so it forwards the event to it. During processing of event, View Model B requests all the data it needs from the Model B and updates its own properties using retrieved values. View B is automatically updates as it is data-bound to its View Model.</p>
<h3>Summary</h3>
<p>As you can see, <strong>good architected applications tend to have fractal structure</strong>. Similar forms can be discovered on various levels of detail. I value such architectures very high. The coherence makes them simple and elegant.</p>
<p>One more thing in case you didn&#8217;t noticed. There is a trend recently to focus architecture discussion not on what&#8217;s horizontal, but on what&#8217;s vertical. As we are (hopefully and at last) moving away from waterfallish processes, we start building applications slice by slice, not layer by layer. These slices do have to have some architecture but not as much <em>design up front. </em>The layers are much less important. I don&#8217;t even care if all the slices have the same layers &#8212; it can be impractical. What I want to have is the conscious process of choosing the layers of each slice so it can be implemented in the simplest possible way.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=toQF2pq-8d4:FgZbTICNnwg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=toQF2pq-8d4:FgZbTICNnwg:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/toQF2pq-8d4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/06/14/fractal-structures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/06/14/fractal-structures/</feedburner:origLink></item>
		<item>
		<title>Tunel SOAP w SOAP i WCF</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/EC7FC9bjTdU/</link>
		<comments>http://simon-says-architecture.com/2010/06/10/tunel-soap-w-soap-i-wcf/#comments</comments>
		<pubDate>Thu, 10 Jun 2010 04:09:37 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Notki po polsku]]></category>
		<category><![CDATA[WCF]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=672</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/>Podczas wstępnego projektowania systemu, nad którym teraz pracuje, natknęliśmy się na dosyć interesujący problem. Polega on na tym, iż docelowe środowisko wdrożeniowe nie pozwala na komunikację między serwerem WWW, a serwerem aplikacyjnym. Komunikacja odwrotna jest możliwa. Sytuację tę przedstawia poniższy diagram.

Te raczej mocne obostrzenia podyktowane są (podobno) polityką bezpieczeństwa. Niestety są one zabójcze dla naszego [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/><p>Podczas wstępnego projektowania systemu, nad którym teraz pracuje, natknęliśmy się na dosyć interesujący problem. Polega on na tym, iż docelowe środowisko wdrożeniowe nie pozwala na komunikację między serwerem WWW, a serwerem aplikacyjnym. Komunikacja odwrotna jest możliwa. Sytuację tę przedstawia poniższy diagram.</p>
<p style="text-align: center;"><a href="http://simon-says-architecture.com/wp-content/uploads/2010/06/no_connection_to_app_server.png"><img class="aligncenter size-full wp-image-673" title="no_connection_to_app_server" src="http://simon-says-architecture.com/wp-content/uploads/2010/06/no_connection_to_app_server.png" alt="" width="478" height="144" /></a></p>
<p>Te raczej mocne obostrzenia podyktowane są (podobno) polityką bezpieczeństwa. Niestety są one zabójcze dla naszego systemu, ponieważ ma on służyć do monitorowania i zarządzania procesami uruchomionymi na serwerze aplikacyjnym. Jak więc monitorować i sterować czymś, z czym nie można się połączyć?</p>
<h3>Tunel</h3>
<p>Odpowiedzią jest tunel SOAP w SOAP wykorzystujący fakt, że komunikacja odwrotna (serwer aplikacyjny wysyła requesty do serwera WWW) jest, jak najbardziej, możliwa. Jak działa taki tunel? Tunel składa się z dwóch końców. Koniec kliencki umiejscowiony jest na maszynie WWW i przyjmuje żądania, które następnie są kolejkowane w pamięci. Serwerowy koniec tunelu jest aplikacją uruchomioną na serwerze aplikacyjnym, która okresowo (raz na kilka sekund) odpytuje (wywołując operację Fetch) koniec kliencki, czy są jakieś zakolejkowane żądania. Jeśli tak, pierwsze żądanie z kolejki jest zwracane w odpowiedzi na wywołanie Fetch. Przesłane żądanie jest następnie forwardowane do odpowiedniego procesu serwerowego. Prześledźmy to na przykładzie.</p>
<h3>Tunel w działaniu</h3>
<ol>
<li>Serwer WWW wysyła żądanie. Adresatem (nagłówek &#8220;To&#8221; w SOAP) jest serwer aplikacyjny, jednak żądanie jest fizycznie (na poziomie TCP) wysyłane na adres klienckiego końca tunelu.</li>
<li>Generowany jest unikalny identyfikator żądania. Żądanie, wzbogacone o dodatkowy nagłówek zawierający wygenerowany identyfikator, jest kolejkowane w oczekiwaniu na wywołanie Fetch.</li>
<li>Serwerowy koniec tunelu wywołuje operację Fetch celem pobrania pierwszego oczekującego żądania. Operacja ta zdefiniowana jest w ten sposób, że request jest pusty, a w odpowiedzi przesyłany jest dowolny komunikat SOAP.</li>
<li>W odpowiedzi na Fetch żądanie (przesyłane jako odpowiedź) trafia do serwerowego końca tunelu.</li>
<li>Serwerowy koniec tunelu forwarduje je (bez jakiejkolwiek ingerencji bądź analizy) do nasłuchującego lokalnie procesu serwera.</li>
<li>Proces serwera zwraca odpowiedź do serwerowego końca tunelu.</li>
<li>Odpowiedź jest forwardowana do końca klienckiego poprzez wywołanie operacji Reply, która pozwala na przesłanie dowolnego komunikatu SOAP (w odpowiedzi na Reply przesyłany jest pusty komunikat). Przed wysłanie do komunikatu dodawany jest nagłówek zawierający identyfikator, który zawierało żądanie.</li>
<li>Kliencki koniec tunelu, na podstawie przekazanego identyfikator kojarzy przesłaną za pomocą Reply odpowiedź z oczekującym żądaniem, a następnie odpowiada klientowi przesyłając mu komunikat otrzymany od serwerowego końca tunelu.</li>
</ol>
<h3>Szczegóły implementacyjne</h3>
<p>Jest kilka kwestii, o których trzeba pamiętać budując rozwiązanie tego typu. Pierwszą z nich jest konieczność użycia WS-Addressing (czyli <em>de facto</em> WSHttpBinding lub pochodnego). W przeciwnym wypadku informacje o adresacie nie będą przeźroczyście transportowane od klienta do serwera. Nie stanowi to problemu w przypadku prostych zastosowań (<em>no security</em>), jednak uniemożliwia np. stworzenie pewnej sesji (<em>reliable session</em>).</p>
<p>Kolejną kwestią techniczną jest konieczność każdorazowego kopiowania komunikatów WCF przed ich forwardowaniem. Specyfika WCF jest taka, że obiekt Message reprezentujący otrzymany komunikat SOAP może być odczytany co najwyżej raz. Jeśli potrzebujemy więcej razy &#8212; musimy utworzyć kopię.</p>
<p>Ustawienie właściwości Action i ReplyAction w atrybucie OperationContract na &#8220;*&#8221; powoduje, że serwis będzie operował na dowolnych komunikatach SOAP. Jest tylko jedna pułapka. Tylko jedna operacja w kontrakcie może mieć ustawione &#8220;*&#8221;, ponieważ inaczej nie byłoby wiadomo do której operacji skierować komunikat.</p>
<h3>Wyjaśnienie</h3>
<p>Nie zachęcam was, broń Boże, to stosowania takich zabawek dla samej idei. Jest to bardzo szczególne rozwiązanie bardzo szczególnego problemu, który zapewne nie występuje zbyt często (oby). Jest to właściwie obejście procedur bezpieczeństwa i, jako takie, powinno być stosowane z rozwagą. W końcu ktoś te procedury w jakimś celu ustalał, prawda?</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=EC7FC9bjTdU:_KRcXOt3A1k:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=EC7FC9bjTdU:_KRcXOt3A1k:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/EC7FC9bjTdU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/06/10/tunel-soap-w-soap-i-wcf/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/06/10/tunel-soap-w-soap-i-wcf/</feedburner:origLink></item>
		<item>
		<title>Why do I find Event Sourcing interesting?</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/_zzSQbdkNSY/</link>
		<comments>http://simon-says-architecture.com/2010/06/07/why-do-i-find-event-sourcing-interesting/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 03:52:57 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Posts in English]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[event sourcing]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=664</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/gb.png" width="17" height="17" alt="" title="Posts in English" /><br/>What makes Event Sourcing so interesting? I it is not the free, proven, audit trial, nor the possibility of reincarnating object in any particular state it had in the history. It is also not the great performance of add-only event store. It is testability.
Why Event Sourcing makes things testable? By splitting up logic responsible for [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/gb.png" width="17" height="17" alt="" title="Posts in English" /><br/><p>What makes Event Sourcing so interesting? I it is not the free, proven, audit trial, nor the possibility of reincarnating object in any particular state it had in the history. It is also not the great performance of add-only event store. It is testability.</p>
<p>Why Event Sourcing makes things testable? By splitting up logic responsible for two distinct things: <strong>calculating new state</strong> of the object and <strong>applying this state change</strong>. Normally, these two operations are mixed in one business logic method like this:</p>
<pre class="brush: csharp;">
public class Customer
{
    public void PlaceOrder(Product product, int quantity)
    {
        CheckProductAvailability();
        CheckCustomerCreditLimit();
        CheckSomethingElse();
        decimal price = CalculateTotalPrice(product, quantity);
        Order o = new Order(product, quantity, price);
        _orders.Add(o);
    }
    //...
}
</pre>
<p>If you read this carefully, you will see that first 4 lines contain the business logic of state change calculation. The last 2 lines, on the other hand, contain no logic at all. Now, what&#8217;s the problem with this code&#8217;s testability?</p>
<p>The problem becomes visible, when I want to test how PlaceOrder behaves when adding fifth order. I have to call PlaceOrder four times to prepare state of the object. <strong>That is wrong, because my test code invokes a lot of logic during preparation phase</strong>. This means that a lot of things can go wrong and nobody likes tests which fail before the actual test code gets executed.</p>
<p>Let&#8217;s see if PlaceOrder can be corrected using SOLID principles. Does it have exactly one reason to change? It seems like it does. When order placement logic changes, the method changes, right? Let&#8217;s dig deeper. What about the last two lines? Do they change when the rest of method changes? Well, I don&#8217;t think so. Looks like they indeed do represent a different concern. So let&#8217;s refactor them to a separate method.</p>
<pre class="brush: csharp;">
public class Customer
{
    public void PlaceOrder(Product product, int quantity)
    {
        CheckProductAvailability();
        CheckCustomerCreditLimit();
        CheckSomethingElse();
        decimal price = CalculateTotalPrice(product, quantity);
        ApplyPlaceOrder(product, quantity, price);
    }
    private void ApplyPlaceOrder(Product product, int quantity, decimal price)
    {
        Order o = new Order(product, quantity, price);
        _orders.Add(o);
    }
    //...
}
</pre>
<p>Now it looks better. At least from the <em>have one reason to change</em> principle. But I don&#8217;t see this improved testability at all. That is because <strong>although we split the responsibilities to separate methods, we left the methods tightly coupled</strong> to one another. Lets see what we can do about this.</p>
<pre class="brush: csharp;">
public class Customer
{
    public void PlaceOrder(Product product, int quantity)
    {
        CheckProductAvailability();
        CheckCustomerCreditLimit();
        CheckSomethingElse();
        decimal price = CalculateTotalPrice(product, quantity);
        Apply(new OrderPlacedEvent(product, quantity, price));
    }
    private void OnOrderPlaced(OrderPlacedEvent @event)
    {
        Order o = new Order(@event.Product, @event.Quantity, @event.Price);
        _orders.Add(o);
    }
    //...
}
</pre>
<p>We introduced a concept of event as a way of encapsulating the state change we are about to apply. Now we can represent state changes by a series of events. The other thing we did was adding the Apply method. What is it? <strong>The Apply method is the API of Event Sourcing</strong>. It is a way of communicating <em>hey, I, the aggregate root, want to apply the state change represented by this event!</em> Apply invokes a method to apply state change. It can do this in a variety of ways: based on convention (like On&#8230; convention in this sample), an attribute or any other. The bottom line is, Apply applies the state change and <strong>it can be called externally</strong>, for example during tested state preparation.</p>
<pre class="brush: csharp;">
[TestFixture]
public class CustomerTests
{
    [Test]
    public void When_placing_fifth_order()
    {
        Product product = new Product();
        //Arrange
        Customer c = new Customer();
        c.Apply(new OrderPlacedEvent(product, 1, 10));
        c.Apply(new OrderPlacedEvent(product, 1, 10));
        c.Apply(new OrderPlacedEvent(product, 1, 10));
        c.Apply(new OrderPlacedEvent(product, 1, 10));

        //Act
        c.PlaceOrder(product, 1);

        //Assert...
    }
}
</pre>
<p>You can see that we invoke no business logic during <em>arrange </em>phase. We only apply <strong>predefined</strong>, known to be right, state changes. The chance something bad will happen during this phase is minimal, as we certainly tested the OnOrderPlaced method in a different test, didn&#8217;t we?</p>
<p>This is what I call well tested code. PlaceOrder method is always tested in isolation, no matter if it is first or fifth order. One cannot overestimate the benefits of a testable codebase. If you happen to play (or work) with Domain-Driven Design, Event Sourcing can be beneficial for you. I see it as the missing piece of puzzle &#8212; <strong>the model is finally fully testable</strong>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=_zzSQbdkNSY:kt6z9Y-y8KQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=_zzSQbdkNSY:kt6z9Y-y8KQ:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/_zzSQbdkNSY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/06/07/why-do-i-find-event-sourcing-interesting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/06/07/why-do-i-find-event-sourcing-interesting/</feedburner:origLink></item>
		<item>
		<title>Ncqrs ciąg dalszy</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/Ls8ESCH2W4c/</link>
		<comments>http://simon-says-architecture.com/2010/06/04/ncqrs-ciag-dalszy/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 03:36:59 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Notki po polsku]]></category>
		<category><![CDATA[ncqrs]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=660</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/>W poprzedniej notce powiedziałem wiele dobrego na temat Ncqrs. Aby być fair, tym razem chciałbym się skupić na kilku mankamentach, które udało mi się zauważyć podczas zabawy z tym frameworkiem.
Ncqrs nie jest jeszcze gotowy do wdrożenia produkcyjnego out-of-the-box. Nie ma co udawać. Biblioteka potrzebuje jeszcze trochę czasu, aby dojrzeć. Z drugiej strony, jeśli komuś zależałoby na [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/><p>W poprzedniej notce powiedziałem wiele dobrego na temat Ncqrs. Aby być fair, tym razem chciałbym się skupić na kilku mankamentach, które udało mi się zauważyć podczas zabawy z tym frameworkiem.</p>
<p><strong>Ncqrs nie jest jeszcze gotowy do wdrożenia produkcyjnego</strong> <em>out-of-the-box</em>. Nie ma co udawać. Biblioteka potrzebuje jeszcze trochę czasu, aby dojrzeć. Z drugiej strony, jeśli komuś zależałoby na jej funkcjonalności i bardzo chciał jej użyć, zawsze może zostać commiterem i poprawić te i owe braki. Na obecnym etapie, do pracy z Ncqrs jest wymagana bardzo dobra znajomość jej wewnętrznych mechanizmów, co czyni ją niepraktyczną w standardowych zespołach deweloperskich (poza R&amp;D).</p>
<p>Serce Ncqrs, czyli definicja<em> korzenia agregatu</em>, jest zbudowane w oparciu o dziedziczenie &#8212; klasy aplikacji dziedziczą z frameworkowych klas bazowych. To dobre na początek, jednak wcześniej czy później przychodzi czas, kiedy trzeba przejść na model POCO. Jest on nie tylko bardziej przyjazny dla dewelopera aplikacji, ale także dla twórcy rozszerzeń.</p>
<p>W Ncqrs w tym momencie brakuje możliwości definiowania encji zawieranych w agregacie (poza korzeniem oczywiście). Z mojego doświadczenia wynika, że takie encje to raczej rzadkość, jednak się zdarzają. Problem w tym, że kiedy się już zdarzają, to są <strong>bardzo </strong>potrzebne.</p>
<p>Nie pisałem tego wszystkiego ot tak sobie. Jeśli jesteś pasjonatem oprogramowania, masz trochę wolnego czasu i chciałbyś pobawić się z naprawdę ciekawymi problemami, Ncqrs czeka na Ciebie! Pracy jest dużo, a te trzy problemy, które wymieniłem w tym poście, to tylko wierzchołek góry lodowej.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=Ls8ESCH2W4c:L8Z5FwC-VmM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=Ls8ESCH2W4c:L8Z5FwC-VmM:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/Ls8ESCH2W4c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/06/04/ncqrs-ciag-dalszy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/06/04/ncqrs-ciag-dalszy/</feedburner:origLink></item>
		<item>
		<title>Ncqrs</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/Vga8l89_IGY/</link>
		<comments>http://simon-says-architecture.com/2010/05/30/ncqrs/#comments</comments>
		<pubDate>Sun, 30 May 2010 14:33:24 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Notki po polsku]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[event sourcing]]></category>
		<category><![CDATA[ncqrs]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=654</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/>W ciągu ostatnich dwóch tygodni moją uwagę przykuł na dobre nowy framework open source &#8212; Ncqrs (witryna CodePlex Ncqrs znajduje się tutaj). Jak sugeruje nazwa, Ncqrs służy do budowy systemów w oparciu o wzorzec architektoniczny Command-Query Responsibility Separation (CQRS). To, czego nazwa nie mówi, to fakt, że Ncqrs narzuca pewną specyficzną implementację wspomnianego wzorca, a [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/><p>W ciągu ostatnich dwóch tygodni moją uwagę przykuł na dobre nowy framework open source &#8212; <a href="http://ncqrs.org/">Ncqrs</a> (witryna CodePlex Ncqrs znajduje się <a href="http://ncqrs.codeplex.com/">tutaj</a>). Jak sugeruje nazwa, Ncqrs służy do budowy systemów w oparciu o wzorzec architektoniczny Command-<em>Query Responsibility Separation</em> (CQRS). To, czego nazwa nie mówi, to fakt, że Ncqrs narzuca pewną specyficzną implementację wspomnianego wzorca, a mianowicie tę opartą o technikę <em>Event Sourcing</em>. Na podstawie <a href="http://codebetter.com/blogs/gregyoung/archive/2010/02/16/cqrs-task-based-uis-event-sourcing-agh.aspx">posta Grega Younga</a> można by się czepiać, że nazwa Ncqrs nie jest zbyt trafna, ale odłóżmy kwestie nomenklatury na bok. Czym jest Ncqrs i jak to się stało, że mnie tak zafascynował?</p>
<h3>Zasada działania</h3>
<p>Ncqrs jest całościowym rozwiązaniem służącym do budowy systemów opartych o silny model domeny, którego stan jest przechowywany za pomocą strumienia zdarzeń. Poniższy diagram prezentuje workflow dla pojedynczego przypadku użycia w Ncqrs.</p>
<p><a href="http://simon-says-architecture.com/wp-content/uploads/2010/05/Ncqrs-workflow.png"><img class="size-full wp-image-655 alignnone" title="Ncqrs workflow" src="http://simon-says-architecture.com/wp-content/uploads/2010/05/Ncqrs-workflow.png" alt="" width="584" height="240" /></a></p>
<h3>Komendy</h3>
<p>Punktem wejścia do Ncqrs są komendy. Są to obiekty, który reprezentują żądania wykonania pewnej operacji na modelu domeny. Komendy są mapowane na operacje za pomocą rozbudowanego rozszerzalnego mechanizmu. Najprostsza implementacja mappera opiera się na dwóch atrybutach, które określają, czy dana komenda ma wykonywać metodę istniejącego obiektu (w nomenklaturze Ncqrs &#8212; <em>korzenia agregatu</em>), czy też tworzyć nowy obiekt. Properties komendy są mapowane (na podstawie nazwy) do parametrów wybranej metody lub konstruktora. Ostatecznie, (jeśli to konieczne) z magazynu danych podnoszony jest odpowiedni obiekt i wykonywana jest odpowiednia metoda (lub konstruktor).</p>
<h3>Operacje biznesowe</h3>
<p>Operacje i konstruktory obiektów są w Ncqrs wywoływane tylko za pośrednictwem komend. <strong>Ich jedynym zadaniem jest wykonanie logiki biznesowej</strong>. Nie mogą one bezpośrednio modyfikować stanu obiektu. Zamiast tego, dozwolonym mechanizm modyfikacji stanu jest zgłaszanie zdarzeń. Operacje biznesowe mogą także komunikować się ze światem zewnętrznym.</p>
<h3>Stosowanie zdarzeń</h3>
<p>Jak już wspomniałem na wstępie, zdarzenia są sposobem przechowywania stanu obiektów w Ncqrs. Operacja biznesowa może zgłosić jedno lub więcej zdarzeń. Dla każdego z nich framework wyszukuje odpowiedniej metody je przetwarzającej. Mechanizm ten jest oczywiście rozszerzalny, a <em>out-of-the-box</em> Ncqrs zapewnia dwa sposoby wiązania zdarzenia z metodą obiektu biznesowego przeznaczoną do jego obsługi: za pomocą konwencji oraz za pomocą atrybutów. Ncqrs wywołuje znalezioną metodę przekazując jej zgłoszone zdarzenie.</p>
<h3>Przetwarzanie zdarzeń</h3>
<p>Metoda przetwarzająca zdarzenie modyfikuje stan obiektu na podstawie danych przekazanych zdarzeniu. Tylko tyle i aż tyle. <strong>Metoda ta nie powinna zawierać żadnej logiki biznesowej</strong> (warunkowej), ani mieć jakichkolwiek skutków ubocznych (komunikacja z innymi systemami itp.).</p>
<p>Zapewne chcielibyście zapytać po co tyle komplikacji? Dlaczego operacja biznesowa nie może zmodyfikować stanu? Odpowiedź jest prosta. Ponieważ stan obiektów jest reprezentowany jako strumień zdarzeń przez nie wygenerowany, aby odtworzyć obiekt niezbędne jest stworzenie jego pustej instancji, a następnie przetworzenie (w kolejności!) wszystkich zapisanych zdarzeń &#8212; oczywiście za pomocą odpowiednich metod przetwarzających. Metody te są więc nie tylko stosowane do modyfikacji stanu podczas przetwarzania, ale także do odtwarzania tego stanu podczas podnoszenia obiektu z trwałego magazynu.</p>
<p>Dzięki takiemu podejściu systemy Event Sourcing (jak Ncqrs) <strong>zapewniają, za darmo, ślad audytowy</strong>, który ma gwarancję poprawności, ponieważ jest on wykorzystywany do budowy obiektów podczas normalnego działania systemu.</p>
<h3>Publikowanie i denormalizacja zdarzeń</h3>
<p>Jeśli wszystko do tej pory przebiegło prawidłowo, wszystkie zgłoszone zdarzenia są publikowane. Oczywiście, także w tym wypadku Ncqrs pozwala wymienić mechanizm publikacji zdarzeń. Domyślny wykorzystuje komunikację wewnątrz procesu, ale dostępny jest także taki, który wykorzystuje <strong>NServiceBus</strong>.</p>
<p>Publikowanie zdarzeń ma dwa cele. Po pierwsze, pozwala powiadomić zainteresowane systemy zewnętrzne o zmianach stanu naszego systemu. Polega to na eskalowaniu &#8220;lokalnych&#8221; (dotyczących naszego systemu) zdarzeń do statusu zdarzeń &#8220;globalnych&#8221; (mających znaczenia dla całego środowiska systemów). Stąd już tylko jeden krok do pełnej <strong>Event Driven Architecture</strong> (EDA).</p>
<p>Drugim celem publikowania zdarzeń jest tzw. denormalizacja, czyli aktualizacja podsystemu obsługi zapytań. Jaki podsystem? O co chodzi? Dokładny opis zagadnienia CQRS znajduej się <a href="http://simon-says-architecture.com/2010/02/19/cqrs-w-praktyce/">tutaj</a>. W tym miejscu wspomnę tylko, że systemy CQRS wykorzystują zwykle dwa osobne magazyny danych dla przetwarzania komend oraz do realizacji zapytań. Do synchronizacji tego drugiego magazynu danych wykorzystywane są właśnie denormalizatory zdarzeń. Proces denormalizacji polega na wykonaniu w bazie danych dla zapytań modyfikacji, które wynikają z opublikowanego zdarzenia. Skąd taka nazwa? Otóż zdarzenia stanowią znormalizowaną (pozbawioną redundancji) postać danych. W magazynie dla zapytań zaś, te same dane mogą mieć wiele reprezentacji, ponieważ nadrzędnym celem jest optymalizacja czasu realizacji zapytań.</p>
<h3>Dlaczego to może działać?</h3>
<p>Jest kilka powodów, które sprawiają, że (pozornie) szalona idea reprezentacji stanu obiektów jako ciągu zdarzeń może działać w praktyce. Oto kilka z nich:</p>
<ul>
<li>zapewnia darmowy, gwarantowany, ślad audytowy</li>
<li>możliwość wykonywania tzw. snapshot&#8217;ów (czyli pełnych zrzutów zserializowanego obiektu biznesowego) co N zdarzeń. Dzięki temu odtwarzanie obiektu wymaga jedynie przetworzenia zdarzeń, które nastąpiły po ostatnim snapthot&#8217;cie</li>
<li>w klasycznym DDD (z użyciem O/RM) podczas podnoszenia obiektu z bazy danych tak naprawdę pobierane jest <strong>wiele wierszy danych</strong> (np. za pomocą podzapytań i złączeń). W przypadku Event Sourcingu pobieranych jest <strong>kilka wierszy przechowujących zdarzenia</strong>. Oba podejścia mają więc podobną złożoność na poziomie bazy danych.</li>
</ul>
<p>Zapraszam Was do zabawy z Ncqrs. Postaram się odpowiedzieć na wszystkie Wasze pytania.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=Vga8l89_IGY:F0iExiMBvJs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=Vga8l89_IGY:F0iExiMBvJs:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/Vga8l89_IGY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/05/30/ncqrs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/05/30/ncqrs/</feedburner:origLink></item>
		<item>
		<title>Windows Communication Foundation 4.0</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/cQTBoQJywf4/</link>
		<comments>http://simon-says-architecture.com/2010/05/28/windows-communication-foundation-4-0/#comments</comments>
		<pubDate>Fri, 28 May 2010 05:10:38 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Notki po polsku]]></category>
		<category><![CDATA[WCF]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=649</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/>Druga część mojej sobotniej prezentacji dotyczyła nowości w Windows Communication Foundation. Aby zmieścić się w założonych piętnastu minutach, spośród wielu ciekawostek o których można poczytać np. u Nicholasa Allena, wybrałem dwie:

RoutingService
WS-Discovery

Dlaczego akurat te dwie? Otóż dlatego, że udało mi się wymyślić jeden wspólny temat, pod szyldem którego mógłbym je prezentować &#8212; usługę Event Brokera. Jeśli [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/><p>Druga część mojej sobotniej prezentacji dotyczyła nowości w Windows Communication Foundation. Aby zmieścić się w założonych piętnastu minutach, spośród wielu ciekawostek o których można poczytać np. <a href="http://blogs.msdn.com/b/drnick/archive/2009/08/14/what-s-new-in-wcf-4-alternative-list.aspx">u Nicholasa Allena</a>, wybrałem dwie:</p>
<ul>
<li>RoutingService</li>
<li>WS-Discovery</li>
</ul>
<p>Dlaczego akurat te dwie? Otóż dlatego, że udało mi się wymyślić jeden wspólny temat, pod szyldem którego mógłbym je prezentować &#8212; usługę Event Brokera. Jeśli ktoś nie kojarzy tego wzorca, Event Broker to pośrednik, który forwarduje informacje o zdarzeniach pochodzące od nadawcy (źródła) do dowolnej liczby odbiorców. Celem tego wzorca jest <strong>zmniejszenie powiązania miedzy nadawcą i odbiorcami</strong>.</p>
<h3>Projekt</h3>
<p>Poniższa prezentacja (6 slajdów) pokazuje sposób działania Event Brokera. Pozostaje jedynie mapowanie poszczególnych funkcji na dostępne technologie. Dzięki nowemu WCF, wszystko czego potrzebujemy znajduje się już na naszym komputerze.</p>
<div id="__ss_4336544" style="width: 425px;"><object id="__sse4336544" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=wcf4bezanimacji-100527235212-phpapp02&amp;stripped_title=wcf-4-4336544" /><param name="name" value="__sse4336544" /><param name="allowfullscreen" value="true" /><embed id="__sse4336544" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=wcf4bezanimacji-100527235212-phpapp02&amp;stripped_title=wcf-4-4336544" name="__sse4336544" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<div style="padding: 5px 0 12px;">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/SzymonPobiega">SzymonPobiega</a>.</div>
</div>
<p>Funkcjonalność rejestracji subskrybentów (otrzymujących komunikaty) w Event Brokerze zapewnia nam obsługa WS-Discovery. Filtrowanie i routowanie przychodzących komunikatów do zainteresowanych odbiorców to funkcje nowego, wbudowanego w WCF, RoutingService&#8217;u. Wszystko, co musimy zrobić własnoręcznie to <strong>sprzęgnąć te dwie technologie</strong> tak, aby reakcja na ogłoszenia WS-Discovery powodowała odpowiednią modyfikację tablicy routingu.</p>
<h3>Routing</h3>
<p>RoutingService to gotowa do użycia usługa dostarczana wraz z nowym WCF.  Jej użycie wymaga trzech prostych kroków: stworzenia nowego hosta, skonfigurowania rodzaju routingu oraz podpięcia odpowiedniego zachowania. W kodzie wygląda to tak:</p>
<pre class="brush: csharp;">
var routerServiceHost = new ServiceHost(typeof (RoutingService));
routerServiceHost.AddServiceEndpoint(typeof (ISimplexDatagramRouter), new BasicHttpBinding(), RouterAddress);
routerServiceHost.Description.Behaviors.Add(new RoutingBehavior(subscriptionManager.RoutingConfiguration));
</pre>
<p><span style="font-weight: normal;">Konfiguracja rodzaju routingu polega na utworzeniu endpoint&#8217;u odpowiedniego typu. Ja wykorzytsałem ISimplexDatagramRouter ponieważ potrzebuje przekazywać pakiety w jednym kierunku. Możliwy jest jednak także routing komunikacji request-response (z tym, że raczej już bez multicast&#8217;u).</span></p>
<p><span style="font-weight: normal;">Do konstruktora RoutingBehavior przekazujemy obiekt RoutingConfiguration, który m.in. zawiera tablicę routingu. </span><span style="font-weight: normal;"><strong>Tablica ta może być modyfikowana z zewnątrz w dowolnym momencie</strong></span><span style="font-weight: normal;">, a dokonane zmiany zostaną uwzględnione podczas routowania następnego komunikatu. Kod modyfikujący tablicę wygląda np. tak:</span></p>
<pre class="brush: csharp;">
var contract = ContractDescription.GetContract(typeof (ISimplexDatagramRouter));
var subscriber = new ServiceEndpoint(contract, new BasicHttpBinding(), address);
RoutingConfiguration.FilterTable.Add(new ActionMessageFilter(actions), new List&lt;ServiceEndpoint&gt; {subscriber});
</pre>
<h3>WS-Discovery</h3>
<p>Mój Event Broker wykorzystuje protokół WS-Discovery poprzez nasłuchiwanie na ogłoszenia (announcements) o pojawieniu się lub zniknięciu usług. Aby dla danej usługi WCF włączyć wysyłanie tych ogłoszeń, wystarczy zmodyfikować jej konfiguracje według poniższego wzorca:</p>
<pre class="brush: xml;">
&lt;services&gt;
  &lt;service behaviorConfiguration=&quot;discoveryBehavior&quot;
            name=&quot;Subscriber.SayHelloService&quot;&gt;
    &lt;endpoint name=&quot;udpDiscoveryEpt&quot; kind=&quot;udpDiscoveryEndpoint&quot; /&gt;
  &lt;/service&gt;
&lt;/services&gt;
&lt;behaviors&gt;
  &lt;serviceBehaviors&gt;
    &lt;behavior name=&quot;discoveryBehavior&quot;&gt;
      &lt;serviceMetadata/&gt;
      &lt;serviceDiscovery&gt;
        &lt;announcementEndpoints&gt;
          &lt;endpoint kind=&quot;udpAnnouncementEndpoint&quot; /&gt;
        &lt;/announcementEndpoints&gt;
      &lt;/serviceDiscovery&gt;
    &lt;/behavior&gt;
  &lt;/serviceBehaviors&gt;
&lt;/behaviors&gt;
</pre>
<p>Konieczne jest dodanie nowego endpointu oraz dodanie do usługi odpowiedniego zachowania. W kodzie nie są potrzebne żadne zmiany. Modyfikacja ta sprawi, że subskrybenci będą wysyłać ogłoszenie w momencie przejścia w tryb on-line. Kolejnym krokiem jest dodanie do Event Brokera kodu, który będzie nasłuchiwał na te ogłoszenia i, zgodnie z ich treścią, modyfikował tablicę routingu. Funkcjonalność tą realizuje poniższy fragment:</p>
<pre class="brush: csharp;">
var subscriptionListener = new SubscriptionListener(subscriptionManager);
var announcementService = new AnnouncementService();

announcementService.OnlineAnnouncementReceived += (s, a) =&gt; subscriptionListener.Subscribe(a);
announcementService.OfflineAnnouncementReceived += (s, a) =&gt; subscriptionListener.Unsubscribe(a);

var announcementServiceHost = new ServiceHost(announcementService);
announcementServiceHost.AddServiceEndpoint(new UdpAnnouncementEndpoint());
</pre>
<p>Jak widać, usługa WS-Discovery oferuje dwa eventy, pod które możemy podpiąć się z własnym kodem. Jest to bardzo wygodny sposób pracy.</p>
<h3>Podsumowanie</h3>
<p>Zapraszam do ściągnięcia całego przykładu <a href="http://code.msdn.microsoft.com/wcfeventbroker">z galerii MSDN</a>. Mam nadzieję, że powyższy post pozwoli Wam łatwiej zrozumieć kod. Specjalnie nie omawiałem klasy obsługującej parsowanie WSDL-a, która jest niezbędna w ostatecznym rozwiązaniu, jednak nie jest ważna z punktu widzenia funkcjonalności Event Brokera. WCF 4 &#8212; polecam każdemu!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=cQTBoQJywf4:-6xgNc5tXrc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=cQTBoQJywf4:-6xgNc5tXrc:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/cQTBoQJywf4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/05/28/windows-communication-foundation-4-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/05/28/windows-communication-foundation-4-0/</feedburner:origLink></item>
		<item>
		<title>Entity Framework 4 a NHibernate</title>
		<link>http://feedproxy.google.com/~r/szymonpobiega/~3/2LQu7Lo4K-8/</link>
		<comments>http://simon-says-architecture.com/2010/05/25/entity-framework-4-a-nhibernate/#comments</comments>
		<pubDate>Tue, 25 May 2010 03:34:17 +0000</pubDate>
		<dc:creator>Szymon Pobiega</dc:creator>
				<category><![CDATA[Notki po polsku]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[entity framework]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[vscl]]></category>

		<guid isPermaLink="false">http://simon-says-architecture.com/?p=645</guid>
		<description><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/>W minioną sobotę miałem przyjemność uczestniczyć w krakowskiej edycji Visual Studio Community Launch. Co prawda, jako jeden z organizatorów, nie jestem najlepszą osobą do obiektywnej oceny tego wydarzenia, ale moim zdaniem było super.
Podczas VSCL miałem okazję sprawdzić się także w roli prelegenta, prowadząc dwie piętnastominutowe mikroprezentacje dotyczące Entity Framework 4 oraz Windows Communication Foundation 4. [...]]]></description>
			<content:encoded><![CDATA[<img src="http://simon-says-architecture.com//wp-content/uploads/pl.png" width="17" height="17" alt="" title="Notki po polsku" /><br/><p>W minioną sobotę miałem przyjemność uczestniczyć w krakowskiej edycji <strong>Visual Studio Community Launch</strong>. Co prawda, jako jeden z organizatorów, nie jestem najlepszą osobą do obiektywnej oceny tego wydarzenia, ale moim zdaniem było super.</p>
<p>Podczas VSCL miałem okazję sprawdzić się także w roli prelegenta, prowadząc dwie piętnastominutowe mikroprezentacje dotyczące Entity Framework 4 oraz Windows Communication Foundation 4. Przykłady kodu dla obu prezentacji umieściłem na <strong>MSDN Code Gallery</strong> odpowiednio <a href="http://code.msdn.microsoft.com/efnhsharedmodel">tutaj</a> i <a href="http://code.msdn.microsoft.com/wcfeventbroker">tutaj</a>. Zapewne duża część z Was nie była na konferencji, dlatego postanowiłem owe przykłady omówić tutaj, na blogu. Dziś – EF4.</p>
<p>W obu przypadkach starałem się wpleść prezentację nowych funkcji danej technologii w jakąś większą historię. Dla Entity Framework tą większą historią jest możliwość współdzielenia (części) modelu z aplikacją napisaną w NHibernate.</p>
<h3>Design</h3>
<p>Solution wygląda tak:</p>
<p><a href="http://simon-says-architecture.com/wp-content/uploads/2010/05/SharedModel.png"><img class="aligncenter size-full wp-image-646" title="SharedModel" src="http://simon-says-architecture.com/wp-content/uploads/2010/05/SharedModel.png" alt="" width="242" height="256" /></a></p>
<p>Znajdują się w nim dwie aplikacje: obsługa zamówień (Orders) oraz bank (Accounts). Obie aplikacje składają się z prostego programu demonstrującego działanie, modelu domeny (Model) oraz obsługi persystencji (DataAccess). Współdzielony fragment to Parties – projekt niezależny od technologii persystencji (bez referencji do NHibernate lub EF) zawierający implementację podmiotów (osób fizycznych i organizacji).</p>
<h3>POCO</h3>
<p>Jednym z celów nowej wersji Entity Framework było wsparcie dla budowy modeli POCO (Plain Old CLR Object). Dlaczego jest to takie ważne? Ponieważ właśnie obsługa POCO pozwala wykorzystywać w EF klasy, które nie były napisane konkretnie z myślą o nim oraz, patrząc z drugiej strony, pozwala wykorzystać klasy napisane specjalnie dla EF w innych kontekstach. POCO daje nam komfort braku zależności od frameworku ORM na poziomie modelu domeny – coś, czego nie sposób przecenić. Dla przykładu, klasa Party reprezentująca podmiot wygląda tak:</p>
<pre class="brush: csharp;">
public class Party
{
   public virtual int Id { get; protected set; }
   public virtual Address Address { get; protected set; }

   protected Party(Address address)
   {
      Address = address;
   }

   protected Party()
   {
   }
}
</pre>
<h3>Lazy Loading</h3>
<p>Leniwe ładowanie (lazy loading) jest kolejnym wielkim nieobecnym z pierwszej wersji EF, który doczekał się implementacji w wersji drugiej (czwartej). Jest ono jednak domyślnie wyłączone. Aby je włączyć, należy dodać do konstruktora kontekstu następującą linię:</p>
<pre class="brush: csharp; light: true;">
ContextOptions.LazyLoadingEnabled = true;
</pre>
<p>Wszystko jednak ma swoją cenę. Ceną, którą płacimy za obsługę leniwego ładowania w EF jest konieczność „wirtualizacji” wszystkich property klas modelu. Jest to niezbędne, ponieważ EF w trakcie działania systemu generuje dynamicznie klasę dziedziczącą po naszej. Nie jest to jednak wielki problem, ponieważ NHibernate ma analogiczne wymaganie. Możemy więc spokojnie przywyknąć do myśli, że standardem dla ORM jest konieczność deklarowania wirtualnych property.</p>
<h3>Value Objects</h3>
<p>Value Objects są nazywane w EF „Complex Type”. Ot, taka fanaberia ludzi z Microsoft. Complex Type w EF może być modyfikowalny. Ja osobiście jednak odradzałbym to ze wszystkich. Niemodyfikowalność Value Object jest bardzo ważną cechą, m.in. ułatwiającą testowanie.</p>
<p>Ponieważ dla Complex Type EF nie prowadzi change tracking’u (sprawdzenie, czy należy zaktualizować bazę wykonywane jest za pomocą porównania wartości aktualnych i pobranych), nie ma sensu wirtualizacja properties CT. Znowu, jest to zgodne z tym, jak ja pracuje z NHibernate. Moje Value Objects muszą być jak najbardziej niezależne kontekstu bazodanowego. Jedyne na co się mogę (i niestety muszę) zgodzić to pusty konstruktor z widocznością protected. Zarówno EF, jaki NHibernate go wymagają. Efektem tego zestawu wymagań jest klasa Address będąca Value Objectem reprezentującym adres podmiotu:</p>
<pre class="brush: csharp;">
public class Address
{
   public string Street { get; private set; }
   public string BuildingNumber { get; private set; }
   public string City { get; private set; }
   public string Country { get; private set; }

   protected Address()
   {
   }

   public Address(string street, string buildingNumber, string city, string country)
   {
      Street = street;
      BuildingNumber = buildingNumber;
      City = city;
      Country = country;
   }
}
</pre>
<h3>Enkapsulacja</h3>
<p>Enkapsulacja to zawsze dobra rzecz. Nie inaczej jest w wypadku modelu domeny. Upublicznianie getterów (a broń Boże setterów) właściwości jest prostą drogą do degradacji naszego modelu do roli prostych struktur danych. A przecież nie o to nam wszystkim chodzi. Z tego powodu bardzo się zmartwiłem po przeczytaniu <a href="http://msdn.microsoft.com/en-us/library/dd468057(v=VS.100).aspx">na MSDN</a> opisu wymagań dla POCO w EF. Wynika z niego (chyba, że ja źle rozumiem), że aby leniwe ładowanie działało, wszystkie właściwości klasy muszą być „public virtual”.</p>
<p>Na szczęście przeglądając sieć natknąłem się na wzmiankę, iż wystarczy „protected virtual”. Postanowiłem sprawdzić. Jakaż była moja radość, gdy okazało się, że wszystko działa. W kontekście enkapsulacji EF4 ma analogiczne wymagania, co NHibernate. Yupi:-)</p>
<p>Klasa Account jest świetnym przykładem enkapsulacji dla kolekcji: lista operacji związanych z kontem nie może być modyfikowana bezpośrednio, ale jedynie poprzez wywołania Credit lub Debit:</p>
<pre class="brush: csharp;">
public class Account
{
   //...
   public decimal Balance { get; protected set; }
   protected virtual IList&lt;Operation&gt; Operations { get; set; }

   //...
   public virtual void Debit(decimal amount, string title)
   {
      if (Balance - amount &lt; 0)
      {
         throw new InvalidOperationException();
      }
      var op = new Operation(-amount, title);
      Operations.Add(op);
      Balance -= amount;
   }

   public virtual void Credit(decimal amount, string title)
   {
      var op = new Operation(amount, title);
      Operations.Add(op);
      Balance += amount;
   }
}
</pre>
<h3>Podsumowanie</h3>
<p>Druga edycja Entity Framework jest o niebo lepsza od poprzedniej. Właściwie mogę powiedzieć z czystym sumieniem, że jest nawet używalna w kontekście Domain-Driven Design. Cieszy mnie to niezmiernie, bo lubię mieć wybór. Pluralizm to dobra rzecz. Czy rozważam przesiadkę z NHibernate na EF? Na pewno nie w tej wersji. Przewaga NH w przypadku bardziej skomplikowanych kwestii jest jeszcze zbyt duża. Z drugiej strony nie potrzebuję (i nie będę potrzebował) wszystkich tych kwestii związanych z obsługą architektur n-tier, w które Microsoft pakuje tyle pary.</p>
<p>Jeśli jednak EF będzie się rozwijać w tak szybkim tempie, jest wysoce prawdopodobne, że wersja 6.0 będzie stanowić groźną konkurencje dla NHibernate także w kontekście DDD.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=2LQu7Lo4K-8:Pkfn2d1H7YA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/szymonpobiega?a=2LQu7Lo4K-8:Pkfn2d1H7YA:0VBWazUhMmc"><img src="http://feeds.feedburner.com/~ff/szymonpobiega?d=0VBWazUhMmc" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/szymonpobiega/~4/2LQu7Lo4K-8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simon-says-architecture.com/2010/05/25/entity-framework-4-a-nhibernate/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://simon-says-architecture.com/2010/05/25/entity-framework-4-a-nhibernate/</feedburner:origLink></item>
	</channel>
</rss>
