<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Augiho web</title>
	<atom:link href="http://www.augi.cz/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.augi.cz</link>
	<description>Osobní stránky jednoho podivného programátora...</description>
	<lastBuildDate>Fri, 27 Apr 2012 20:06:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Atributy jsou zlo</title>
		<link>http://www.augi.cz/programovani/atributy-jsou-zlo/</link>
		<comments>http://www.augi.cz/programovani/atributy-jsou-zlo/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 20:06:37 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=446</guid>
		<description><![CDATA[Atributy v C# (v ostatních jazycích známé např. jako anotace) považuju ve většině případů za zlo, protože porušují SRP &#8211; třída pak dělá více než musí &#8211; navíc si s sebou nese metadata. Na první pohled vypadají atributy jako super věc, ale snadno můžete narazit na situaci, kdy se vám vymstí mít všechno na jedné [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/en-us/library/z0w1kczw.aspx">Atributy v C</a># (v ostatních jazycích známé např. jako <em>anotace</em>) považuju ve většině případů za zlo, protože porušují <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">SRP</a> &#8211; třída pak <em>dělá</em> více než musí &#8211; navíc si s sebou nese metadata. Na první pohled vypadají atributy jako super věc, ale snadno můžete narazit na situaci, kdy se vám vymstí mít všechno na jedné hromadě &#8211; a pak budete litovat, že používáte atributy.<br />
<span id="more-446"></span><br />
Představte si, že např. děláte systém, který máte nasazený u více zákazníků. Defaultně máte na třídě <em>Person</em> omezení pomocí <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.stringlengthattribute.aspx">atributu</a> na maximální délku příjmení na 50 znaků. Teď si ale jeden zákazník vzpomene, že potřebuje maximální délku zvýšit na 100 znaků. Pokud nechceme provést tuto úpravu i u ostatních zákazníků, jsme s atributy v problémech.</p>
<p>Mnohem více se mi líbí uložení metadat někde úplně mimo a vytažení metadat pro danou třídu dynamicky z nějakého metadata-provideru za běhu aplikace. Odkud si metadata onen provider vytáhne je jeho problém &#8211; může si je vytáhnout z databáze, konfiguračních souborů nebo klidně z atributů.</p>
<h3>ASP.NET MVC</h3>
<p>Pokud sledujete vývoj ASP.NET MVC, došlo zde přesně k tomuto posunu od atributů k obecnému metadata-provideru. V prvních verzích ASP.NET MVC se ViewModely odekorovaly pomocí atributů z namespace <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx">DataAnnotations</a> a podle toho se vyrenderovaly UI prvky (omezení na max. délku stringu v JavaScriptu apod.).<br />
V posledních verzích došlo k zobecnění a byla zavedena abstraktní třída <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.modelmetadataprovider(v=vs.98).aspx">ModelMetadataProvider</a>, z které můžete podědit a tahat si metadata odkukoliv je libo. Samozřejmě je standardně dodáván <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.dataannotationsmodelmetadataprovider(v=vs.98).aspx">DataAnnotationsModelMetadataProvider</a> (to je jméno! <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ), který čte metadata z <em>DataAnnotations</em> atributů, čímž je zajištěna zpětná kompatibilita.</p>
<p>Díky tomuto obecnému konceptu můžete např. validační pravidla definovat pěkně silně typově pomocí <a href="https://github.com/JeremySkinner/FluentValidation">FluentValidation</a> a do ASP.NET MVC je přenést pomocí <a href="https://github.com/JeremySkinner/FluentValidation/blob/master/src/FluentValidation.Mvc3/FluentValidationModelMetadataProvider.cs">FluentValidationModelMetadataProvider</a>.</p>
<h3>Jak se tedy postavit k použití atributů?</h3>
<p>Když už máte nějaké třídy, které jsou odekorovány atributy a nemůžete to změnit, napište alespoň kód pracující s těmito třídami tak, aby se atributy nepoužívaly napřímo, ale zprostředkovaně přes nějakého metadata-providera.</p>
<p>Pokud bych dělal na <em>malé</em> neperspektivní aplikaci, asi bych použití atributů překousl. Ale vždy (vždy!) nějak abstrahujte čtení atributů, tj. nevolejte napřímo <a href="http://msdn.microsoft.com/en-us/library/system.attribute.getcustomattributes.aspx">GetCustomAttributes</a>. A právě tato abstrakce je de facto onen metadata-provider.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/atributy-jsou-zlo/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Dependency Injection a Lazy Loading</title>
		<link>http://www.augi.cz/programovani/dependency-injection-a-lazy-loading/</link>
		<comments>http://www.augi.cz/programovani/dependency-injection-a-lazy-loading/#comments</comments>
		<pubDate>Wed, 14 Mar 2012 23:13:01 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=445</guid>
		<description><![CDATA[Pokud vám název článku něco připomíná, nemýlíte se &#8211; nechal jsem se inspirovat článkem Davida Grudla, na nějž bylo mnoho zajímavých reakcí. Ano, i v PHP komunitě se řeší věci jako dependency injection, lazy loading, SOLID nebo čistý kód V tomto článku přináším můj pohled na daný problém a popíšu elegantní způsob řešení v .NETu. [...]]]></description>
			<content:encoded><![CDATA[<p>Pokud vám název článku něco připomíná, nemýlíte se &#8211; nechal jsem se inspirovat <a href="http://phpfashion.com/dependency-injection-versus-lazy-loading">článkem</a> <a href="https://twitter.com/davidgrudl">Davida Grudla</a>, na nějž bylo mnoho <a href="http://phpfashion.com/diskuse-ke-clanku-o-lazy-loadingu">zajímavých</a> <a href="http://www.knesl.com/articles/view/lazy-loading-pomoci-factory-vs-accessor">reakcí</a>. Ano, i v PHP komunitě se řeší věci jako dependency injection, lazy loading, SOLID nebo čistý kód <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
V tomto článku přináším můj pohled na daný problém a popíšu elegantní způsob řešení v .NETu. <em>Nechci polemizovat s Davidem ani porovnávat jeho řešení s mým &#8211; jeho článek berte prosím jen jako inspiraci, které mě vedla k sepsání tohoto článku.</em><br />
<span id="more-445"></span><br />
David ve svém článku řešil situaci (přeloženo do C# a ASP.NET MVC), kdy máme Controller, který zajišťuje zobrazení formuláře a zároveň jeho zpracování:</p>
<pre class="brush: csharp">public class HomeController : Controller
{
  public HomeController(ILoginService loginService)
  {
    LoginService = loginService;
  }

  public ILoginService LoginService { get; private set; }

  public ActionResult ShowLogin()
  {
     return PartialView();
  }

  public ActionResult ProcessLogin(Credentials credentials)
  {
     LoginService.Login(credentials);
     // ...not important
  }
}</pre>
<p>Pokud se bude přihlašovací dialog zobrazovat na každé stránce (jak bývá zvykem), bude se vždy do tohoto <em>HomeController</em>u injectovat nějaká <em>ILoginService</em> &#8211; a pokud má konkrétní použitá implementace závislost třeba na <em>IDbConnection</em> (připojení do databáze), tak to už může být problém, protože si třeba zbytečně vytáhneme z connection poolu připojení do databáze, které nám může na zatíženém webu chybět.</p>
<p>Jak z toho ven? V .NETu máme k dispozici třídu <a href="http://msdn.microsoft.com/en-us/library/dd642331.aspx">Lazy&lt;&gt;</a>, která nám umožní to samé, co popsal David ve svém článku &#8211; ke zpřístupnění/vytvoření <em>živé</em> instance <em>ILoginService</em> dojde až tehdy, když si sáhneme na property <a href="http://msdn.microsoft.com/en-us/library/dd642177.aspx">Value</a>. Implementace bude pak vypadat takto:</p>
<pre class="brush: csharp">public class HomeController : Controller
{
  public HomeController(Lazy&lt;ILoginService&gt; loginService)
  {
    LoginService = loginService;
  }

  public Lazy&lt;ILoginService&gt; LoginService { get; private set; }

  public ActionResult ShowLogin()
  {
     return PartialView();
  }

  public ActionResult ProcessLogin(Credentials credentials)
  {
     LoginService.Value.Login(credentials);
     // ...not important
  }
}</pre>
<p>Problem solved, fuck yeah! Nebo ne? Pozorný čtenář začne větřit <del>problém</del> smradlavý kód. V jednom příkazu (první řádek metody <em>ProcessLogin</em>) se nám totiž objevily dvě tečky, což je dobrá indikace toho, že porušujeme <a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law Of Demeter</a>. Protože je ale <em>Value</em> property BCL objektu, tak bych se z toho hned dogmaticky nehroutil. Ale za bližší prozkoumání tato situace určitě stojí.</p>
<p>Elegantní řešení, kterým se vyhneme použití <em>Lazy</em> a zároveň se zbavíme zbytečného injectování <em>ILoginService</em>, je rozdělit <em>HomeController</em> na dva menší Controllery &#8211; to je nakonec správně i podle SRP. Problem solved. Nebo ne? Nevím jak vy, ale já nechci mít v projektu trilión tříd s jednou metodou, takže přemýšlejme dál. A nebo ne &#8211; začněme úplně od začátku!</p>
<h2>Znovu a lépe</h2>
<p>Proč jsme začali vůbec komplikovat ten původní jednoduchý a přímočarý kód? Protože jedna z akčních metod se volá méně častěji a protože vytvoření <em>ILoginService</em> může být náročné. Proč ale do implementace tahat takovéhle předpoklady? Co je <em>HomeController</em>u do toho? Tomu <strong>musí</strong> být jedno, jak je <em>ILoginService</em> implementovaná a jestli je její vytvoření náročné nebo ne &#8211; <strong>programujeme proti rozhraním</strong>!</p>
<p>Jediný, kdo může/musí vědět o konkrétních použitých třídách, jejich vztazích a způsobech použití, je <a href="http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx">kompoziční root</a>, neboli kontejner. To je místo, kde skládáme z malých kousků výslednou aplikaci.</p>
<p>Takže implementaci <em>HomeController</em>u necháme pěknou a čistou, tak jak je v první ukázce kódu. Problém se zbytečným vytvářením těžké implementace <em>ILoginService</em> (nazvěme ji <em>HeavyLoginService</em>) vyřešíme chytrou konfigurací kontejneru:</p>
<p>Vytvoření <em>HomeController</em>u nakonfigurujeme tak, že se jako parametr konstruktoru předá jen proxy, která implementuje <em>ILoginService</em>. Při prvním přístupu k této proxy dojde k vytvoření <em>HeavyLoginService</em> a veškerá volání bude proxy delegovat na tuto živou instanci. V kompozičním rootu bychom tedy mohli mít toto:</p>
<pre class="brush: csharp">public class LoginServiceProxy : ILoginService
{
  public LoginServiceProxy(Func&lt;ILoginService&gt; accessor)
  {
     Accessor = accessor;
  }

  private Func&lt;ILoginService&gt; Accessor { get; set; }
  private ILoginService Live { get; set; }

  public LoginResult Login(Creadentials credentials)
  {
    if (Live == null)
    {
       Live = Accessor(); // thread safety?
    }
    return Live.Login(credentials);
  }
}</pre>
<p>Předávaná lambda <em>accessor</em> se postará o dodání nějaké živé implementace <em>ILoginService</em>, v našem případě tedy <em>HeavyLoginService</em>.<br />
Jistě uznáte, že psát takovýto kód stále dokolečka dokola pro každý interface (který může mít samozřejmě více metod) je nuda a docela bychom se opakovali. Takže proxy nebudeme psát ručně, ale nějak si je nagenerujeme.</p>
<p>Mohli bychom to dělat třeba pomocí <a href="http://en.wikipedia.org/wiki/Text_Template_Transformation_Toolkit">T4</a> ještě před kompilací, ale já stejně jako <a href="http://blog.renestein.net/Lazy+Loading+Zpo%C5%BEd%C4%9Bneacute+Nahraacutevaacuteniacute+Objekt%C5%AF+Do+Kolekce+I+Ve+Starscaroniacute+Aplikaci+S+Vyu%C5%BEitiacutem+Dynamickeacute+Proxy.aspx">můj velký vzor</a> použiji knihovnu <a href="http://www.castleproject.org/dynamicproxy/index.html">Castle DynamicProxy</a> <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Nejprve si vytvoříme interceptor, což je de facto implementace všech metod naší proxy, tedy všech metod daného interface:</p>
<pre class="brush: csharp">public class LazyLoadInterceptor&lt;T&gt; : IInterceptor
{
  public LazyLoadInterceptor(Func&lt;T&gt; accessor)
  {
    Accessor = accessor;
  }

  private Func&lt;T&gt; Accessor { get; set; }
  private T Live { get; set; }

  public void Intercept(IInvocation invocation)
  {
    // will be called for all methods
    if (Live == null)
    {
        Live = Accessor();
    }
    invocation.ReturnValue = invocation.Method.Invoke(Live, invocation.Arguments);
  }
}</pre>
<p>Je to tedy prakticky to samé, co jsme viděli u ručně psané proxy. Jediný rozdíl je ve způsobu volání <em>živé</em> metody. Toto funguje bezvadně, jen metoda <a href="http://msdn.microsoft.com/en-us/library/a89hcwhh.aspx">Invoke</a> nepatří k nejrychlejším, tudíž se vyplatí zde použít třeba nacachované <a href="http://www.codeproject.com/Articles/14593/A-General-Fast-Method-Invoker">generování IL kódu</a>.</p>
<p>Proxy objekt pak vytvoříme takto (v praxi bychom si to asi zabalili to nějaké pěkné <em>Utils</em> metody):</p>
<pre class="brush: csharp">var pg = new ProxyGenerator(); // cache them!
ILoginService proxy = pg.CreateInterfaceProxyWithoutTarget&lt;ILoginService&gt;(
  new LazyLoadInterceptor&lt;ILoginService&gt;(() => new HeavyLoginService()));</pre>
<p>Takto získanou <em>proxy</em> uspokojíme závislost <em>HomeController</em>u.</p>
<h2>Závěr</h2>
<p><em>HomeController</em> zůstal krásně čistý a lazy loading <em>těžké</em> implementace závislosti je krásně skryt za proxy. U mě dobrý.</p>
<p><script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script><br />
	<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js"></script></p>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"/>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"/>
<p>	<script type="text/javascript">
		if (SyntaxHighlighter) {
			SyntaxHighlighter.all();
		}
	</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/dependency-injection-a-lazy-loading/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Užitečné události</title>
		<link>http://www.augi.cz/programovani/uzitecne-udalosti/</link>
		<comments>http://www.augi.cz/programovani/uzitecne-udalosti/#comments</comments>
		<pubDate>Sun, 12 Feb 2012 14:14:49 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=444</guid>
		<description><![CDATA[Události (events) nemusí být jen záležitostí uživatelského rozhraní, ale mohou najít uplatnění i v ostatních částích aplikace, i když pak jsou události jinak technicky provedené. Vezměte si např. situaci, kdy se uživatel zaregistruje do naší aplikace. Co je třeba udělat? Někam tuto informaci persistovat a odeslat na zadaný e-mail ověřovací kód: public class RegistrationService : [...]]]></description>
			<content:encoded><![CDATA[<p>Události (events) nemusí být jen záležitostí uživatelského rozhraní, ale mohou najít uplatnění i v ostatních částích aplikace, i když pak jsou události jinak technicky provedené.<br />
<span id="more-444"></span><br />
Vezměte si např. situaci, kdy se uživatel zaregistruje do naší aplikace. Co je třeba udělat? Někam tuto informaci persistovat a odeslat na zadaný e-mail ověřovací kód:</p>
<pre class="brush: csharp">public class RegistrationService : IRegistrationService
{
  public void RegisterUser(UserToRegister user)
  {
    Repository.Add(user);
    MailingService.SendConfirmation(user);
  }
}</pre>
<p>Co když budeme chtít na tuto událost reagovat ještě nějak jinak? Třeba budeme chtít zobrazovat seznam posledních deseti registrovaných uživatelů, stranou si štosovat uživatele, co použili jako registrační mail z GMailu atd.</p>
<p>Kdybychom přidali třeba jen další dvě volání nějakých dalších Services, začal by nám kód pěkně smrdět, protože by třída <em>RegistrationService</em> měla mnoho závislostí. Jak z toho ven?</p>
<p>Nadefinujme si tato dvě velmi jednoduchá rozhraní:</p>
<pre class="brush: csharp">public interface IEventPublisher
{
  void Publish(object e);
}

public interface IEventHandler&lt;TEvent&gt;
{
  void Handle(TEvent e);
}</pre>
<p>Rozhraní <em>IEventPublisher</em> bude <strong>používat</strong> třída, která vyvolává nějakou událost. V našem příkladu bude mít třída <em>RegistrationService</em> závislost na tomto rozhraní, která při použití constructor injection vypadá nějak takto:</p>
<pre class="brush: csharp">public RegistrationService(IRepository repository, IEventPublisher eventPublisher)
{
  // save parameters to the properties or fields
  Repository = repository;
  EventPublisher = eventPublisher;
}</pre>
<p>V metodě <em>RegisterUser</em> pak vykonáme jen &#8222;primární&#8220; záležitosti (uložení do databáze) a posléze vyvoláme novou událost pomocí volání <em>EventPublisher.Publish(new UserRegistered(user));</em>. Třída <em>UserRegistered</em> reprezentuje událost a je to obyčejná <a href="http://en.wikipedia.org/wiki/Plain_Old_CLR_Object">POCO</a> třída.</p>
<p>Každý, kdo chce být informován o události <em>UserRegistered</em>, pak musí implementovat druhé definované rozhraní &#8211; <em>IEventHandler&lt;UserRegistered&gt;</em>. Tzn. v metodě <em>Handle</em> pak máme kód, který reaguje na vyvolání události.</p>
<pre class="brush: csharp">public class MailingService : IMailingService, IEventHandler&lt;UserRegistered&gt;
{
  public void Handle(UserRegistered e)
  {
     // send the confirmation e-mail
  }
}</pre>
<p><strong>Tím docílíme pěkného oddělení zdroje události od konzumentů události.</strong></p>
<h2>Implementace</h2>
<p>Samozřejmě musíme nějak zajistit, že po volání <em>Publish</em> dojde k zavolání těch správných event-handlerů. Jednoduchá implementace <em>IEventPublisher</em> založená na kontejneru může vypadat nějak takto:</p>
<pre class="brush: csharp">public class SimpleEventPublisher : IEventPublisher
{
  public void Publish(object e)
  {
    var messageType = e.GetType();
    var eventHandlerType = typeof(IEventHandler&lt;&gt;).MakeGenericType(messageType);
    foreach(var eh in Container.ResolveAll(eventHandlerType)) // we must register all event handlers somewhere
    {
       eh.Handle(e);
    }
  }
}</pre>
<p>Tato implementace je velmi naivní, neefektivní a především nejde zkompilovat, protože iterovaná proměnná nebude odpovídajícího generického typu <em>IEventHandler&lt;&gt;</em>. To je ale jen implementační detail, který jde snadno vyřešit pomocí trošky reflexe&#8230;</p>
<p>Princip všech implementací <em>IEventPublisher</em> bude ale stejný &#8211; odněkud zjistit všechny event-handlery pro daný typ události a pro všechny zavolat metodu <em>Handle</em>. Jednoduché. Ale velmi silné! Jsme totiž schováni za velmi jednoduchým rozhraním a můžeme dělat, co je nám libo.</p>
<p>Např. můžeme každé volání metody <em>Handle</em> obalit <em>try-catch</em>em a tak zajistit, že dojde vždy k zavolání všech event-handlerů.</p>
<p>Nemusíme ani event-handlery volat synchronně &#8211; můžeme si událost uložit do nějaké fronty (<a href="http://en.wikipedia.org/wiki/Message_queue">Message Queue</a>?) a event-handlery volat až později (a zbytečně neblokovat) nebo je třeba zpracovávat na úplně jiném stroji.<br />
Můžeme si event-publisher nakonfigurovat tak, že některé události bude odbavovat synchronně, jiné asynchronně.</p>
<p>Můžeme ale změnit i logiku vyhledávání event-handlerů. Můžeme začít třeba podporovat &#8222;dědičnost událostí&#8220;, takže <em>IEventHandler&lt;object&gt;</em> by reagoval na všechny události.</p>
<p>A v neposlední řadě můžeme celé toto delegovat na nějaký existující messagingový framework.</p>
<p>Prostě fantazii se meze nekladou! <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h2>Použití</h2>
<p>Nemá cenu cpát tento koncept do malých nebo jednoduchých aplikací &#8211; ideální použití událostí je v komplexnějších aplikacích, kde je hodně závislostí mezi různými částmi aplikace.<br />
Je dokonce možné si nakonfigurovat event-publisher tak, aby se některé vybrané události publikovali i mimo naši aplikaci a informovali o změně stavu nějaké návazné aplikace. Pak přichází ke slovu <a href="http://en.wikipedia.org/wiki/Enterprise_service_bus">message bus</a>, což je zjednodušeně řečeno one-way (pub/sub) komunikace mezi aplikacemi.</p>
<p>Zajímavé může být použití konceptu událostí v datové vrstvě. Každý jistě zná triggery z databází &#8211; můžete si zaregistrovat funkci, která se při vložení/změně/smazání dat automagicky zavolá. Když ale používáme úložiště, které triggery nepodporuje, nebo máme více úložišť, která mezi sebou neumí na této úrovni spolupracovat, pak potřebujeme posunout triggery o úroveň výše, tj. do našeho kódu.<br />
Události takového typu asi nebudeme chtít vyvolávat ručně, ale budeme to chtít nějak zautomatizovat. Můžeme si třeba napsat <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">aspekt</a> (~wrapper), který zajistí automatické vyvolávání událostí, když se volají metody <em>Add</em>/<em>Remove</em> na Repozitáři.<br />
V praxi to pak může vypadat třeba tak, že ačkoliv máme data uložena v MySql, tak si můžeme napsat event-handler pro událost <em>ProductRemoved</em>, ve kterém invalidujeme položku v <a href="http://memcached.org/">Memcached</a>.</p>
<p>Perzistence založená čistě na událostech se nazývá <a href="http://martinfowler.com/eaaDev/EventSourcing.html">EventSourcing</a>, ale to osobně považuji za extrém, který najde využití u velmi malého počtu projektů.</p>
<h2>Takže?</h2>
<p>Nadefinovali jsme si dvě rozhraní, která budeme používat v naší aplikaci jako takové. Díky tomu si nazabordelíme projekt referencemi na nějaký specifický framework a můžeme kdykoliv velmi jednoduše změnit implementaci/chování událostí.<br />
Události najdou uplatnění jak v aplikaci jako takové (&#8222;doméně&#8220;), tak na úrovni přístupu k datům. Pokud bychom dotáhli použití událostí do konce, dostali bychom <em>EventSourcing</em>, což je ale dle mého názoru u většiny projektů zbytečné.</p>
<p>Události ale jistě stojí za pozornost minimálně kvůli tomu, že dokáží snížit provázanost jednotlivých částí aplikace.</p>
<p><script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script><br />
	<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js"></script></p>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"/>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"/>
<p>	<script type="text/javascript">
		if (SyntaxHighlighter) {
			SyntaxHighlighter.all();
		}
	</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/uzitecne-udalosti/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Co dělat v roce 2012</title>
		<link>http://www.augi.cz/programovani/co-delat-v-roce-2012/</link>
		<comments>http://www.augi.cz/programovani/co-delat-v-roce-2012/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 14:01:55 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=443</guid>
		<description><![CDATA[Díky Vyvojari.sk jsem narazil na zajímavý článek o jedenácti věcech, které by mě dělat každý vývojář v roce 2012. S tím seznamem se dá celkem souhlasit, ale dovolím si komentář a přidám dalších 5 bodů, které by měl bezpodmínečně každý vývojář dělat (na úkor původních jedenácti věcí). Založit si Twitter účet a třeba jen pasivně [...]]]></description>
			<content:encoded><![CDATA[<p>Díky <a href="http://www.vyvojari.sk//News-11-veci-ktore-by-mal-robit-vyvojar-v-roku-2012-102132.aspx">Vyvojari.sk</a> jsem narazil na zajímavý <a href="http://michaelcrump.net/11-things-every-software-developer-should-be-doing-in-2012">článek o jedenácti věcech, které by mě dělat každý vývojář v roce 2012</a>. S tím seznamem se dá celkem souhlasit, ale dovolím si komentář a přidám dalších 5 bodů, které by měl bezpodmínečně každý vývojář dělat (na úkor původních jedenácti věcí).<br />
<span id="more-443"></span></p>
<p>Založit si Twitter účet a třeba jen pasivně ho sledovat je vhodný doplněk k RSS. Velkou výhodu vidím v tom, že se k člověku (pokud sleduje ty správné lidi) dostanou i věci z blogů, které by si do RSS sám nedal. Přečíst si o tom, jak řešit třeba nějaký specifický problém v Javě může člověka někam posunout&#8230;třeba k tomu, aby si uvědomil, jak je C# super <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Je to trošku podobný případ jako když člověk začal používat jako zdroj informací internet (tedy nějaký uzavřený okruh serverů) místo čtení novin. U novin se člověk dostane i k věcem a názorům, které mu v případě &#8222;soukromého vesmíru&#8220; unikají&#8230;</p>
<p>Dalším zajímavým bodem je &#8222;<em>Carry around a modern phone</em>&#8222;. Z mého pohledu ne kvůli tomu, abyste byli free-cool-in, ale protože denodenním používám člověk lépe pochopí, co běžného uživatele trápí a jaká by naše mobilní aplikace opravdu neměla být.</p>
<p>Jak píše jeden komentující, přidal by dvanáctý bod &#8211; &#8222;<em>Get a hobby.</em>&#8222;. Já bych bodů přidal rovnou pět, aby se člověk z toho všeho programování a spol. nezbláznil a třeba nevyhořel:</p>
<ol>
<li>Najděte si ženskou. Pokud už ženskou/rodinu máte, věnujte se jí/jim. Pokud jste rádi Singleton, tak choďte mezi lidi &#8211; a teď myslím lidi, ne programátory <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  A když už chodíte jen mezi programátory, tak aspoň řešte něco jiného než programování. Vystupte ze své komfortní zóny!</li>
<li>Začněte dělat nějaký sport (ne šachy). Aspoň jednou týdně. Jestli máte odpor ke sportu, pusťte si oblíbenou hudbu do uší a běžte se svižným krokem na hodinku projít. Vaše tělo vám bude vděčné.</li>
<li>Najděte si nějaký (ideálně nepočítačový) koníček, který zaměstná jinou než &#8222;analytickou část mozku&#8220;. Začněte se učit nový cizí jazyk, vytáhněte zaprášený hudební nástroj, začněte kreslit, chodit na keramiku, &#8230;</li>
<li>Přečtěte alespoň dvě beletristické knihy. Ač se české školství vehementně snaží vybudovat v nás odpor k literatuře (aspoň já to tak vnímal), nedejte se.</li>
<li>Dbejte na svou životosprávu. Teď nemyslím, abyste se krmili jen salátama a podobnýma nesmyslama, ale snažte se jíst pravidelně a nenechávejte tělo zbytečně dlouho hladovět. Opět, vaše tělo vám bude vděčné.</li>
</ol>
<p>A na závěr bych si dovolil jedno heslo, které mě oslovilo a možná se v něm někteří také najdete:<br />
&#8222;<em>Dřív jsem obdivoval lidi, kteří pracují 16 hodin denně. Teď obdivuji lidi, kteří nemusí pracovat vůbec.</em>&#8220;</p>
<p>A protože se blíží konec roku, tak bych vám rád poděkoval za přízeň a popřál vše dobré do nového roku &#038; happy coding <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/co-delat-v-roce-2012/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Architektura škálovatelných aplikací</title>
		<link>http://www.augi.cz/programovani/architektura-skalovatelnych-aplikaci/</link>
		<comments>http://www.augi.cz/programovani/architektura-skalovatelnych-aplikaci/#comments</comments>
		<pubDate>Sat, 17 Dec 2011 22:44:02 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=442</guid>
		<description><![CDATA[Je to už nějaký pátek, co se zajímám o vzor CQRS (Command Query Responsibility Segragation), který nachází uplatnění především u dvou typů aplikací, které ale nejsou tak časté &#8211; velmi komplexní aplikace (díky CQRS se lze lépe vypořádat s komplexitou) a velmi velké a/nebo vytížené aplikace (které potřebují škálovat). Ačkoliv se takto může zdát znalost [...]]]></description>
			<content:encoded><![CDATA[<p>Je to už nějaký pátek, co se zajímám o vzor CQRS (Command Query Responsibility Segragation), který nachází uplatnění především u dvou typů aplikací, které ale nejsou tak časté &#8211; velmi komplexní aplikace (díky CQRS se lze lépe vypořádat s komplexitou) a velmi velké a/nebo vytížené aplikace (které potřebují škálovat). Ačkoliv se takto může zdát znalost CQRS pro běžného programátora zbytečná (<em>ne každý je Google</em>), je s CQRS spjato mnoho velmi zajímavých konceptů, které mohou nalézt uplatnění i u běžných aplikací. Proto jsem se rozhodl sepsat z mého hlediska to nejzajímavější, co mě CQRS naučilo.<br />
<span id="more-442"></span><br />
Klasická představa vrstvení aplikace je takováto:</p>
<p><center><img src="http://www.augi.cz/wp-content/uploads/CQRS-01.png" alt="" /></center></p>
<p>V krabičce &#8222;Application&#8220; je skryta doménová logika i přístup k datům &#8211; odprostím se tedy prozatím od toho, jak je jádro aplikace implementované (DDD s ORM, Transaction Scripts, Active Record, &#8230;). Místo toho se zaměřme na to, jak je realizována komunikace mezi Aplikací a GUI &#8211; je to nějaká fasáda &#8211; vrstva rozhraní, které utváří API naší Aplikace, a nedělá tedy nic jiného, než že <em>tupě</em> volá Aplikaci.</p>
<p>Ve webovém GUI se striktně rozlišuje (a kdo to nedělá, je prasátko) mezi requesty, které provádí jen čtení (GET), a requesty jen měnícími stav (POST). Jak ví každý slušný webový vývojář, POST požadavek by neměl nic prezentovat (renderovat html) &#8211; měl by jen &#8222;nějak&#8220; zpracovat požadovaný příkaz a říci prohlížeči, kdo mu poskytne vizuální reprezentaci výsledku (tj. na jakou stránku má udělat redirect). Tento koncept je znám jako vzor <a href="http://zdrojak.root.cz/clanky/post-redirect-get-nejen-v-asp-net-mvc/">Post-Redirect-Get</a> a vzásadě to není nic jiného než krásná implementace <a href="http://martinfowler.com/bliki/CommandQuerySeparation.html">CQS</a> &#8211; <strong>Command Query Separation</strong>, což je koncept, který říká, že &#8222;objekt&#8220; by měl mít jen dva druhy metod:
<ul>
<li>provádí výhradně změnu a nic nevrací (tj. vrací <em>void</em> a nemají výstupní parametry)</li>
<li>nemění stav, jen čtou</li>
</ul>
<p>Převedeno do řeči CQRS, GUI (obecně zbytek světa) komunikuje s Aplikací srkzeva Commands (první typ metody) &#038; Queries (druhý typ metody):</p>
<p><center><img src="http://www.augi.cz/wp-content/uploads/CQRS-02.png" alt="" /></center><br />
Šipky ukazují směr <em>toku informace</em>.</p>
<h2>Commands</h2>
<p>Když chceme po Aplikaci něco vykonat (provést nějakou akci, která změní stav), pošleme směrem k Aplikaci tzv. Command. To je obyčejná třída bez metod, jen krabička na data (DTO), jejíž properties představují parametry příkazu, který chceme provést.</p>
<p>Commandové API Aplikace je triviální &#8211; je to jediný interface, který má jednu metodu: <em>void HandleCommand(ICommand command)</em><br />
V zájmu minimalizace requestů se často přidává druhá metoda <em>HandleCommands</em>, jejíž účel si laskavý čtenář jistě domyslí <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
Toto univerzální rozhraní má jediný úkol (často delegovaný na kontejner) &#8211; předat Command do odpovídajícího Command Handleru, který provede jeho zpracování (ten už komunikuje přímo s Aplikací).</p>
<pre class="brush: csharp">public interface ICommandHandler&lt;TCommand&gt; where TCommand: ICommand
{
  void Handle(TCommand command);
}</pre>
<p>V čem je síla takového řešení? Protože pořád nikde nic nevracíme, nemusíme čekat na &#8222;fyzické&#8220; zpracování příkazu, tzn. GUI zobrazí obligátní hlášku &#8222;Váš požadavek <strong>bude</strong> zpracován.&#8220; a může vesele pokračovat dál.</p>
<h3>Informace o zpracování</h3>
<p>Zde vyvstává otázka, jak informovat uživatele/externí systém, že byl příkaz (ne)úspěšně zpracován (pokud ho to zajímá). Protože Command Handlery nic nevrací, musíme použít jinou komunikační cestu &#8211; v případě uživatele na e-shopu nás nepřekvapí klasické poslání mailu. Jiný způsob (pokud chceme informovat uživatele interaktivněji) je ten, že <em>ICommand</em> obsahuje property <em>Id</em> typu <em>Guid</em>, kterou může GUI nastavit a na základě tohoto identifikátoru požadavek trackovat. Konkrétní způsoby realizace jsou mimo rozsah toho článku, ale pěkným řešením je notifikace webového serveru o zpracování Commandu skrze Message Bus a následně nějaká forma (pseudo)persistentního spojení mezi webovým serverem a prohlížečem (pollování, <a href="http://en.wikipedia.org/wiki/WebSocket">WebSockets</a>, &#8230;).</p>
<h3>Benefity</h3>
<p>Přijde vám posílání Commandů zbytečně složité a nestojí podle vás za to, že máme díky němu možnost zadávat příkazy z GUI asynchronně? Souhlasím! Síla tohoto řešení je totiž v tom, že nám <strong>umožní rozložit zátěž v čase</strong> (tj. rozmělnit špičky v zátěži) a <strong>řešit výpadky aplikace</strong>. Těchto neocenitelných benefitů docílíme tím, že GUI nebude Commandy posílat přímo naší aplikaci, ale bude je jen předávat prostředníkovi (Message Bus, Command Bus, Message Queue), který je bude dále přeposílat naší aplikaci.<br />
Pokud zrovna nebude naše aplikace dostupná, tak uživatel v GUI nedostane chybovou hlášku, ale požadavek (Command) se uloží do fronty, a jakmile aplikace naskočí, prostředník to zmerčí, přepošle Command aplikaci a ta ho zpracuje. Uživatel tak dostane mail s potvrzenou objednávkou maximálně o chvilku později a není obtěžován momentálních chvilkovým výpadkem aplikace.</p>
<p>Onen prostředník (MessageBus) by pro nás měla být (podobně jako databáze) jen infrastrukturní záležitost (100% dostupná) a typicky ji nebudeme implementovat sami, ale použijeme nějaké existují řešení &#8211; v případě vlastní infrastruktury např. <a href="http://en.wikipedia.org/wiki/Microsoft_Message_Queuing">MSMQ</a> nebo <a href="http://en.wikipedia.org/wiki/RabbitMQ">RabbitMQ</a>, v případě cloudu např. Azuří <a href="http://www.windowsazure.com/en-us/home/tour/service-bus/">Service Bus</a> nebo Amazoní <a href="http://aws.amazon.com/sqs/">Simple Queue Service</a>.</p>
<h3>Kompatibilita</h3>
<p>Když se na tento způsob interakce GUI a Aplikace podíváme s odstupem, zjistíme, že to není o tolik složitější než klasický přístup. Místo každé hlavičky metody budeme mít třídu reprezentující Command a tělo metody přesuneme do metody <em>Handle</em> odpovídající Command Handleru (nic nebrání, aby jedna třída implementovala více <em>podobných</em> Command Handlerů).</p>
<pre class="brush: csharp">public OldFashionedFacade: IOldFashionedFacade
{
  public void OrderProduct(Product product, Customer customer)
  {
    // handle using Application
  }
}

public class OrderProductCommand : ICommand
{
  public Product Product { get; set; }
  public Customer Customer { get; set; }
}

public class OrderProductCommandHandler: ICommandHandler&lt;OrderProductCommand&gt;
{
  public void Handle(OrderProductCommand command)
  {
     // handle using Application
  }
}
</pre>
<p>Za povšimnutí stojí to, že parametry staré metody přejdou v properties třídy reprezentující Command. Pokud chceme mít nadále dostupné old-fashioned API (např. si nemůžeme dovolit měnit takto zásadně API), můžeme jednoduše nagenerovat toto API z Commandů. Jednoduše pro každý Command vygenerujeme jednu metodu fasádního interface, properties Commandu překlopíme na parametry této metody a metoda bude vevnitř jen volat univerzální <em>Handle</em>. Ale ani tady se nemusíme zastavit &#8211; můžeme např. nagenerovat i metody se sufixem <em>Sync</em>, které zajistí, že Command bude okamžitě zpracován místo zařazení do fronty v MessageBusu (někdy se to může hodit).</p>
<p>Jak vidno, zadávání požadavků do Aplikace přes Commandy nám přináší neuvěřitelné možnosti a v tomto řešení vidím jediný problém &#8211; je těžké rozhodnout, který kód je součástí Aplikace (a měl by tedy být uvnitř Aplikace) a který kód je jen infrastrukturní (a měl by tedy být v Command Handleru). Rozhodně do Command Handleru patří konverze typů, základní validace a autorizace. Zbytek je na vašem rozhodnutí&#8230;</p>
<h2>Queries</h2>
<p>Dotazovací část fasády Aplikace zůstane zvenku prakticky stejná &#8211; pořád se bude jednat o synchronní volání metod, protože uživatel chce vidět produkty v gridu okamžitě. Navenek to tedy mohou zůstat klidně fasádní služby, které budou volat NĚCO vespod. Pokud jste čekali, že to NĚCO bude Aplikace, musím vás zklamat. Prezentovat uživateli data, která prošla skrze Doménovou vrstvu, to bývá jeden z největších problémů nejen z hlediska výkonu (načtete celou entitu a pak zobrazíte jen příjmení) tak z hlediska čistoty kódu &#8211; pokud jste např. přidali entitě <em>Person</em> readonly property <em>DisplayName</em> jen proto, že ji potřebujete v GUI, tak si rovnou dejte facku <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Takže co bude to, co budou volat metody fasádních služeb (Queries) ? Nejefektivnější je sahat přímo do databáze &#8211; v případě .NET přes ADO.NET, příp. nějaký jednoduchý mapper (např. <a href="http://code.google.com/p/dapper-dot-net/">Dapper</a>). Ať se vám to může při prvním pohledu zdát jakkoliv zvrhlé, po několika měsících musím uznat, že je to dobrá cesta a nevede k masivní duplikaci kódu, jak by to mohlo na první pohled vypadat.</p>
<p><center><img src="http://www.augi.cz/wp-content/uploads/CQRS-03.png" alt="" /></center></p>
<p>Jak vidíme, de facto teď máme nad jednou persistentní vrstvou dvě aplikace &#8211; jedna se stará o zpracování Commandů a druhá o co nejrychlejší prezentaci dat uživateli (via Queries). Queries teď dělají to, že spouští (vysoce optimalizované) dotazy nad databází, které tahají jen ta data, která jsou opravdu potřeba.</p>
<p>Když budeme mít ale jen jednu databázi a aplikace zrovna bude pod velkým write-loadem (hodně Commandů), odnesou to Queries vyšší latencí &#8211; proto může být dobrý nápad rozdělit databázi na dvě:</p>
<p><center><img src="http://www.augi.cz/wp-content/uploads/CQRS-04.png" alt="" /></center></p>
<p>OpDB (<em>Operational Database</em>) je běžná databáze v 3NF+, ke které Aplikace přistupuje běžným způsobem &#8211; např. pomocí full-featured ORM &#8211; v .NET se dá za něj považovat asi jen <a href="http://nhforge.org/Default.aspx">NHibernate</a>, Entity Framework teprve bloumá okolo nádraží <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>K <a href="http://martinfowler.com/bliki/ReportingDatabase.html">ReadDB</a> přistupují Queries co nejpříměji, např. přes nějaký zmiňovaný lightweight-ORM. Účelem této databáze je umožnit servírovat data uživateli co nejrychleji. Nejrychlejší by bylo mít pro uživatele předrenderovanou celou stránku (HTML), jen ji přečíst na jeden request z databáze (přes Query, resp. ReadApp) a přes webový server poslat do prohlížeče. To je poněkud extrémní řešení, proto se spokojme s tím, že budeme schopni na jeden request (a řekněme do desítek ms) získat všechna data potřebná pro zobrazení celé stránky, tedy &#8222;ViewModel&#8220; <em>stránky</em>. ViewModel můžeme v databázi mít uložen jako Json, XML, DTO serializované do BLOBu, jak je libo. Jediná podmínka by měla být, že jsme schopni získat všechna <strong>data na jeden jednoduchý dotaz</strong> (žádný join!).</p>
<p>Správně, ReadDB není nic jiného než <strong>předem napopulovaná cache</strong>, po které nechceme nic jiného než vytáhnout surová data na základě nějakého ID. Proto ReadDB nemusí být vůbec klasická relační databáze &#8211; může to být klidně NoSQL databáze! A naše aplikace pak bude cool! <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Synchronizace</h3>
<p>Je nabíledni, že musíme ReadDB průběžně upravovat podle toho, jak se mění OpDB (~synchronizovat). To se typicky děje (opět) pomocí Message Busu, kdy při úpravě Doménového modelu vyvoláme událost, že došlo k nějaké změně (<em>ProductChanged</em>). Kdokoliv (tedy včetně ReadApp) má pak šanci tuto událost odchytit a poupdatovat podle ní odpovídající předpřipravené ViewModely apod.</p>
<p>Pokud ale nechceme udělat takový velký skok v používaných technologiích, není nic ztraceno. Můžeme uvažovat o dvou databázích jen z konceptuálního hlediska, fyzicky budeme mít jen jednu klasickou relační databázi. Jak už jsem psal, na úplném začátku jsme v situaci, kdy v Queries píšeme dotazy nad OpDB. Abychom dosáhli rozumného výkonu, musíme i v tomto řešení začít duplikovat data &#8211; k tomu slouží v klasických relačních databázích indexy. Takže máme databázi s indexy, klasika.</p>
<p>Prvním krokem k možnému budoucímu přesunu na více fyzických databází je to, že vytvoříme pohledy (Views). Prakticky sice budeme dělat pořád to samé, ale dotazy už budou ve své finální podobě (&#8222;<em>SELECT * FROM ViewModel1 WHERE Id = @Id</em>&#8222;) a nebudeme na ně tak muset v dalších krocích sahat.</p>
<p>Další iterací je to, že pohledy budou materializované. Pokud to náš DB stroj neumí, můžeme si je implementovat sami &#8211; jednoduše vytvoříme místo pohledů tabulky se stejnou strukturou. Pak si vytvoříme triggery nad původními tabulkami a podle zápisů do nich budeme upravovat naše <em>materializované pohledy</em>.<br />
Je zřejmé, že se nám tím zpomalí zápis, ale čtení bude bleskurychlé &#8211; takže konkrétní řešení závisí i na tom, jaký je ve vaší aplikace poměr čtení/zápis (nejčastěji to prý bývá 80 % vs. 20 %).</p>
<p>Pokud budeme chtít ReadDB a OpDB skutečně fyzicky rozdělit (a pokud neumíme zajistit spouštění triggerů přes více DB strojů), musíme synchronizaci přenést o úroveň výše. A tím se dostáváme zpět k výše zmiňované synchronizaci přes události (Events), které můžeme vyvolávat tam, kde to bude pro naši aplikaci nejvhodnější &#8211; v DALu, v Doméně nebo třeba po úspěšném zpracování Commandu&#8230;</p>
<h2>UI</h2>
<p>Jak je vidět z posledního obrázku, naše GUI teď prakticky pracuje nad dvěma aplikacemi &#8211; jedna zajišťuje načítání dat a druhá zpracování dat. Načítání dat zůstává prakticky stejné jako v případě klasické (non-CQRS) aplikace, ale rozdíly ve zpracování dat jsou markantní. Už nejsme schopni garantovat to, že po odeslání objednávky ji zákazník hned uvidí v nějakém seznamu, protože třeba příkaz ještě není zpracován nebo ještě nestačila proběhnout synchronizace ReadDB. A tomu je třeba přizpůsobit koncepci uživatelského rozhraní, příp. si více pohrát s aplikací. V části o Commandech jsem se např. zmiňoval o možnosti trackování stavu Commandu&#8230;</p>
<p>V souvislosti s CQRS se často mluví o tzv. <strong>Task-Based UI</strong>, což je alternativa k běžnému CRUD UI. Není to něco, co je v CQRS povinné, ale považuji to za zajímavý koncept, proto ho chci letmo zmínit.<br />
Klasické CRUD UI se vyznačuje tím, že umožňuje vytvořit <em>entititu</em>, upravit ji a příp. ji smazat. Problém je, že když voláme metodu <em>Change</em>, tak tím vůbec nevyjadřujeme <strong>záměr</strong>, proč tak činíme.<br />
Bylo by mnohem lepší, kdychom měli připravené Commandy, které by vyjadřovaly, že např. měníme adresu zákazníka, protože se stěhuje (a podle nové adresy mu doporučit novou výchozí prodejnu), že měníme příjmení zákazníka, protože se oženil/vdala/registroval(a), že mažeme zákazníka, protože zemřel atd.<br />
A pro tyto specifické tasky pak budeme mít specifické UI &#8211; Task-Based UI.<br />
S problematikou ukládání takových informací do databáze souvisí <a href="http://codebetter.com/gregyoung/2010/02/20/why-use-event-sourcing/">Event-Sourcing</a>, ale o tom třeba někdy jindy&#8230;</p>
<h2>Co z toho?</h2>
<p>CQRS je velmi zajímavý vzor, díky kterému jsem se dozvěděl o spoustě zajímavých konceptů, z nichž některé úspěšně používám v praxi. Ty nejzajímavější koncepty (MessageBus, ReportingDatabase) jsem se pokusil nastínit v tomto článku a věřím, že vás mohou inspirovat k dalšímu studiu CQRS a příp. i vylepšení vašich aplikací.</p>
<p>O CQRS není problém vygooglit spoustu materiálů (a možná se vás už ani Google nebude ptát &#8222;Did you mean CARS?&#8220; <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ) &#8211; doporučuji především materiály od <a href="http://codebetter.com/gregyoung/">Grega Younga</a>, <a href="http://www.udidahan.com/?blog=true">Udiho Dahana</a> a <a href="http://abdullin.com/journal/2010/3/23/dddd-cqrs-and-other-enterprise-development-buzz-words.html">Rinata Abdullina</a>.</p>
<p><script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script><br />
	<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js"></script></p>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"/>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"/>
<p>	<script type="text/javascript">
		if (SyntaxHighlighter) {
			SyntaxHighlighter.all();
		}
	</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/architektura-skalovatelnych-aplikaci/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Jak jinak na widgety v ASP.NET MVC</title>
		<link>http://www.augi.cz/programovani/jak-jinak-na-widgety-v-asp-net-mvc/</link>
		<comments>http://www.augi.cz/programovani/jak-jinak-na-widgety-v-asp-net-mvc/#comments</comments>
		<pubDate>Sat, 10 Dec 2011 14:41:12 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=440</guid>
		<description><![CDATA[V předchozím článku jsem ukázal jednu možnost, jak implementovat v ASP.NET MVC (libovolné verze!) &#8222;sidebar widgety&#8220;. V tomto článku bych rád ukázal další možnosti realizace widgetů, na které nebyl v předchozím článku prostor. Ale ani tento článek není kompletním výčtem všech možností&#8230; SuperModel V předchozím řešení jsme od ViewModelu, který reprezentuje stránku s widgety, požadovali, [...]]]></description>
			<content:encoded><![CDATA[<p>V <a href="http://www.augi.cz/programovani/jak-na-widgety-v-asp-net-mvc/">předchozím článku</a> jsem ukázal jednu možnost, jak implementovat v ASP.NET MVC (libovolné verze!) &#8222;sidebar widgety&#8220;. V tomto článku bych rád ukázal další možnosti realizace widgetů, na které nebyl v předchozím článku prostor. Ale ani tento článek není kompletním výčtem všech možností&#8230;<br />
<span id="more-440"></span></p>
<h2>SuperModel</h2>
<p>V předchozím řešení jsme od ViewModelu, který reprezentuje stránku s widgety, požadovali, aby implementoval rozhraní <em>IViewModelWithWidgets</em>. Pokud ale v našem projektu widgety podporuje drtivá většina stránek, nemusí být toto řešení nejvhodnější. Nechceme totiž v zájmu <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a> opakovat definici property <em>Widgets</em> v každém ViewModelu, takže nakonec stejně skončíme u nějakého bázového ViewModelu (který jako jediný tuto property implementuje) a to se nám už nemusí líbit a můžeme začít šilhat po jiném řešení. Přitom ale nemusíme nutně slevovat z našeho požadavku, aby byla celá stránka reprezentována jedním &#8222;ViewModelem&#8220;.</p>
<p>Data pro celou stránku jsou totiž ve skutečnosti reprezentována třídou <a href="http://msdn.microsoft.com/en-us/library/dd505255(v=VS.98).aspx">ViewDataDictionary</a>, která je v <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.controllerbase.viewdata(v=VS.98).aspx">Controlleru</a> i v <a href="http://msdn.microsoft.com/en-us/library/dd493045(v=VS.98).aspx">šabloně</a> dostupná jako property <em>ViewData</em>. Jak již název napovídá, <em>ViewDataDictionary</em> není (zjednodušeně řečeno) nic jiného než <em>Dictionary</em> ze <em>string</em>u na <em>object</em>, který má ale navíc další properties &#8211; a nejvíce na očích je právě property <a href="http://msdn.microsoft.com/en-us/library/dd460191(v=VS.98).aspx">Model</a>, ve které máme typicky instanci našeho ViewModelu.</p>
<p>Vhodnějším řešením, které nás už nebude nabádat k vytváření super-ViewModelu, je tak ukládání dat pro widgety pod <em>nějakým</em> klíčem přímo do <em>ViewData</em>. Kód v akčním filteru (metoda <em>OnActionExecuted</em>) se nám tak ztenčí na pouhé přímé přiřazení do <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.controllerbase.viewdata(v=VS.98).aspx">ViewData</a>. I kód v šabloně bude jednodušší &#8211; omezí se na zjištění, zda je ve <a href="http://msdn.microsoft.com/en-us/library/dd493045(v=VS.98).aspx">ViewData</a> obsažen požadovaný klíč.</p>
<p>Úplně nám tak odpadne potřeba zavádět nějaká infrastrukturní rozhraní jako v řešení z předchozího článku&#8230;</p>
<h2>Ajaxizace</h2>
<p>Uživatele našeho webu bude asi typicky zajímat především hlavní obsah stránky a nechce být zdržován tím, že bude muset čekat o chvilku déle než se načte nějaký zpropadený widget, který ho třeba v danou chvíli vůbec nezajímá. Jaké máme možnosti, když se vzdáme řešení s použitím Action Filterů?</p>
<p>Od <a href="http://www.augi.cz/programovani/asp-net-mvc-2/">ASP.NET MVC 2</a> máme k dispozici helper metody <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.childactionextensions.action(v=VS.98).aspx">Html.Action</a> a <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.childactionextensions.renderaction(v=VS.98).aspx">Html.RenderAction</a>, pomocí kterých můžeme provést jakýsi Sub-Request. Dojde tedy k zavolání dané akční metody a spuštění vráceného <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionresult(v=VS.98).aspx">ActionResult</a>u (jako v případě běžného requestu). Výsledek můžeme získat buď ve formě stringu (<em>Html.RenderAction</em>) nebo je výsledek vyrenderován přímo na místo, kde voláme <em>Html.Action</em>. Toto je velmi silná zbraň a díky ní můžeme prezentační logiku koncipovat zcela jinak.</p>
<p>Ideální mi přijde situace, kdy máme pro každý widget jednu akční metodu a k ní odpovídající šablonu (~<em>ascx</em>~<em>Partial View</em>). Mohli bychom mít jeden &#8222;velký&#8220; Controller jen pro akční metody widgetů, ale bude lepší mít pro každý widget samostatný Controller &#8211; widgety totiž mohou být interaktivní (tj. potřebovat další akční metody pro dodatečnou funkcionalitu) a pravděpodobně budou mít zcela rozdílné závislosti.</p>
<p>Pokud máme pro widget samostaný Controller a samostatnou šablonu, máme ho krásně separovaný. Úkolem hlavní stránky pak bude pouze zajistit volání <em>Html.[Render]Action</em> pro každý widget.</p>
<p>Separace nám přináší i další výhodu &#8211; volání akční metody je skvělý kandidát na kešování &#8211; můžeme využít standardní atribut <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.outputcacheattribute(v=VS.98).aspx">OutputCache</a>.</p>
<p>Nyní jsme ale stále v situaci, kdy se celá stránka načítá během jednoho requestu &#8211; ajaxizace je ale velmi jednoduchá! Pokud totiž akční metodu neoznačíme atributem <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.childactiononlyattribute(v=VS.98).aspx">ChildActionOnly</a>, můžeme ji volat i samostatně v rámci normálního requestu (samozřejmě musíme zajistit, aby se k ní dalo <em>doroutovat</em>).<br />
V hlavní stránce, která dosud volala <em>Html.[Render]Action</em>, se bude nyní generovat kód, který zajistí, že se widgety dotáhnou pomocí samostatných Ajax requestů (např. s využitím <a href="http://zdrojak.root.cz/clanky/html5-ukladame-si-data-k-elementum/">data atributů</a>).</p>
<p>Pokud chceme minimalizovat počet Ajax requestů, můžeme udělat jednu pomocnou akční metodu, která spustí akční metody požadovaných widgetů &#8211; tím se dostaneme na jeden request pro hlavní stránku a druhý request pro widgety.</p>
<h2>Závěr</h2>
<p>V <a href="http://www.augi.cz/programovani/jak-na-widgety-v-asp-net-mvc/">předchozím článku</a> jsem nastínil způsob implementace widgetů, který byl oblíbený v době první verze ASP.NET MVC. V první části toho článku jsem ukázal jeho vylepšení, které nás nenutí používat bázové třídy pro ViewModely a nejen díky tomu je flexibilnější a méně invazivní.</p>
<p>Za nejlepší řešení v současné době ale považuji variantu s <em>Html.[Render]Action</em>, která přináší mnohem větší míru modularity a jako (příjemný) důsledek snadné kešování a podporu pro asynchronní načítání widgetů v samostatném requestu.</p>
<p>Každý projekt si ale žádá svoje a tyto dva články rozhodně nepopisují všechny možnosti, jak je možné widgety v ASP.NET MVC implementovat. Věřím ale, že články mohou posloužit jako inspirace při implementaci widgetů ve vašem projektu&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/jak-jinak-na-widgety-v-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jak na widgety v ASP.NET MVC</title>
		<link>http://www.augi.cz/programovani/jak-na-widgety-v-asp-net-mvc/</link>
		<comments>http://www.augi.cz/programovani/jak-na-widgety-v-asp-net-mvc/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 22:06:32 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=439</guid>
		<description><![CDATA[Už několikrát jsem dostal otázku, jak udělat v ASP.NET MVC &#8222;widgety&#8220;, tedy &#8222;komponenty&#8220;, které jsou někde na okraji každé stránky. Slyšel jsem názory, že ASP.NET WebForms jsou mnohem více nakloněny komponentovému vývoji (souhlasím) a tak je vývoj takových komponentových udělátek ve WebForms mnohem jednodušší než v MVC &#8211; s tím si ale dovolím nesouhlasit. Aby [...]]]></description>
			<content:encoded><![CDATA[<p>Už několikrát jsem dostal otázku, jak udělat v ASP.NET MVC &#8222;widgety&#8220;, tedy &#8222;komponenty&#8220;, které jsou někde na okraji každé stránky. Slyšel jsem názory, že ASP.NET WebForms jsou mnohem více nakloněny komponentovému vývoji (souhlasím) a tak je vývoj takových komponentových udělátek ve WebForms mnohem jednodušší než v MVC &#8211; s tím si ale dovolím nesouhlasit. Aby byl člověk schopen napsat kvalitní komponentu ve WebForms, tak je nutné tento framework znát velmi zevrubně. A v ASP.NET MVC je to úplně stejné &#8211; pokud znáte MVC dobře, tak dokážete i v MVC pohodlně napsat widgetový systém. Mé řešení vám ukáži v tomto článku.<br />
<span id="more-439"></span></p>
<h2>Data pro widgety</h2>
<p>Moje filozofie je taková, že ve ViewModelu (který se vrací v akční metodě pomocí <em>return View(viewModel);</em>) musí být <strong>všechna</strong> data potřebná pro rendering <strong>celé</strong> stránky &#8211; tedy &#8222;hlavní obsah&#8220; i data widgetů.</p>
<p>Na úrovni Controlleru tak musíme zajistit, že načteme data pro všechny widgety, které budeme zobrazovat. Ano, už v Controlleru musíme vědět, co přesně budeme chtít vykreslovat &#8211; tak to má být &#8211; rozhodně bychom neměli takové rozhodnutí nechávat až do View!</p>
<p>Widgety ale nejsou &#8222;tím hlavním&#8220; co chceme v akční metodě dělat &#8211; to je něco jiného &#8211; např. v případě blogového systému načtení informací o článku (text, autor, &#8230;). Přidávat ručně kód pro načítaní widgetů do každé akční metody samozřejmě nebudeme. Takový úkol lze elegantně řešit pomocí aspektů, které jsou v ASP.NET MVC dostupné formou <a href="http://www.asp.net/mvc/tutorials/understanding-action-filters-cs">Action Filterů</a>. Implementujeme tedy v Action Filteru metodu <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.iactionfilter.onactionexecuted(v=VS.98).aspx">OnActionExecuted</a>, která se volá po provedení akční metody.</p>
<p>Jak ale zařídit, abychom mohli v této metodě uložit data pro widgety do ViewModelu? Jednoduše si vytvoříme rozhraní <em>IViewModelWithWidgets</em>, které musí implementovat každý ViewModel, jenž odpovídá stránce, na níž chceme vykreslovat widgety. Zde záleží, jestli máme widgety pevné nebo např. uživatelsky konfigurované.<br />
V prvním případě můžeme mít dílčí ViewModely pro widgety přímo jako properties rozhraní <em>IViewModelWithWidgets</em>.<br />
V druhém případě (který budu uvažovat dále) bude lepší mít jen jednu property typu <em>IEnumerable&lt;IWidget&gt;</em> nesoucí data pro všechny widgety. Rozhraní <em>IWidget</em> by mělo obsahovat minimálně property <em>string PartialViewName</em> &#8211; můžeme ale přidat třeba informace o pořadí widgetů apod.</p>
<p>Kostra Action Filteru může vypadat takto:</p>
<pre class="brush: csharp">public void OnActionExecuted(ActionExecutedContext filterContext)
{
  if (!(filterContext.Result is ViewResultBase))
  {
     return; // we will not render a View
  }
  var vm = ((ViewResultBase)filterContext.Result).Model as IViewModelWithWidgets;
  if (vm == null)
  {
    return; // we don't want to render widgets
  }
  vm.Widgets = InjectedWidgetProvider.GetWidgetsForCurrentUser();
}</pre>
<p>Atributem můžeme odekorovat jednotlivé metody, celé Controllery, příp. zaregistrovat Action Filter jako <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.globalfilters.filters(v=VS.98).aspx">globální</a> nebo ho servírovat pomocí vlastního <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.ifilterprovider(v=VS.98).aspx">Filter Provideru</a> (pak ho nezapomeňte <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.filterproviders.providers(v=VS.98).aspx">zaregistrovat</a>). Poslední možnost doporučuji zejména tehdy, když potřebujete řídit životnost Action Filteru nebo do něj injectovat nějaké závislosti (např. připojení do databáze na přečtení nakonfigurovaných widgetů pro přihlášeného uživatele).</p>
<h2>Vykreslení</h2>
<p>Při použití ASPX enginu (ne-Razor) vyřešíme vykreslení widgetů elegantně pomocí <a href="http://msdn.microsoft.com/en-us/library/wtxbf3hh.aspx">Master Pages</a> (když si ve Visual Studiu vytvoříte nový <em>ASP.NET MVC 3 Web Application</em>, tak ten Master Pages používá).<br />
To znamená, že máme soubor <em>Site.Master</em>, který obsahuje &#8222;šablonu&#8220;, jak má vypadat celá stránka. V této &#8222;šabloně&#8220; máme díry, jejichž obsah se mění &#8211; takže nějaký <em>ContentPlaceHolder</em> pro hlavní obsah, pro menu, pro nadpis stránky apod.<br />
V konkrétním View (např. <em>Detail.aspx</em>) pak pomocí atributu <em>MasterPageFile</em> určíme, jaká Master Page se použije (často máme v projektu jen jednu &#8211; <em>Site.Master</em>) a naším úkolem je dodat obsah pro <em>ContentPlaceHolder</em>y.</p>
<p>Ale zpět k našim widgetům. Kód v <em>Site.Master</em> bude přímočarý &#8211; zjistíme, zda se mají widgety renderovat, a pokud ano, tak je na nějakém vhodném místě (třeba uvnitř nějakého <em>div</em>u) vykreslíme:</p>
<pre class="brush: csharp">if (Model is IViewModelWithWidgets)
{
  foreach(IWidget widgetViewModel in ((IViewModelWithWidgets)Model).Widgets)
  {
     Html.RenderPartial(widgetViewModel.PartialViewName, widgetViewModel);
  }
}</pre>
<p>Pro každý widget pak budeme mít Partial View (<em>ascx</em>), které bude mít Model odpovídajícího typu (implementující rozhraní <em>IWidget</em>).</p>
<h2>Závěr</h2>
<p>Co jsme tedy museli udělat:</p>
<ul>
<li>Připravit si datový model, tj. zavést si rozhraní <em>IWidget</em> a <em>IViewModelWithWidgets</em>.</li>
<li>ViewModely pro widgety musí implementovat rozhraní <em>IWidget</em>.</li>
<li>ViewModely pro stránky, které obsahují widgety, musí implementovat rozhraní <em>IViewModelWithWidgets</em>.</li>
<li>Zajistit naplnění kolekce <em>Widgets</em> na úrovni Controlleru &#8211; k tomu nám skvěle poslouží Action Filter.</li>
<li>Vytvořit Partial View (<em>ascx</em> soubor) pro každý widget a zajistit jeho vykreslení v <em>Site.Master</em>.</li>
</ul>
<p>Dle mého názoru tedy nic extrémně složitého &#8211; ViewModel a Partial View pro widgety jsou nutné minimum (proto to děláme) a infrastrukturního kódu není tolik &#8211; prakticky jen načtení dat v Action Filteru a vykreslení widgetů v <em>Site.Master</em>.</p>
<p>V praxi můžeme chtít toto řešení dále rozvinout &#8211; např. načítat widgety asynchronně pomocí AJAXu. Ani to ale není nic složitého&#8230;<br />
[<a href="http://www.augi.cz/programovani/jak-jinak-na-widgety-v-asp-net-mvc/">navazující článek</a>]</p>
<p><script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js"></script><br />
	<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js"></script></p>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css"/>
<link type="text/css" rel="stylesheet" href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css"/>
<p>	<script type="text/javascript">
		if (SyntaxHighlighter) {
			SyntaxHighlighter.all();
		}
	</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/jak-na-widgety-v-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Zamyšlení nad NoSQL</title>
		<link>http://www.augi.cz/programovani/zamysleni-nad-nosql/</link>
		<comments>http://www.augi.cz/programovani/zamysleni-nad-nosql/#comments</comments>
		<pubDate>Sat, 29 Oct 2011 17:25:48 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=438</guid>
		<description><![CDATA[NoSQL je buzzword, který je tu s námi téměř už tři roky, přesto je pro mnohé lidi velkou neznámou, případně symbolem vzpoury proti zlým ošklivým přežitým enterprise SQL databázím. Rád bych se s vámi podělil o můj pohled na NoSQL, který je ovlivněn hlavně více než rokem používání Cassandry. Co to je? Především je důležité [...]]]></description>
			<content:encoded><![CDATA[<p>NoSQL je buzzword, který je tu s námi <a href="http://en.wikipedia.org/wiki/NoSQL#History">téměř už tři roky</a>, přesto je pro mnohé lidi velkou neznámou, případně symbolem vzpoury proti <em>zlým ošklivým přežitým enterprise</em> SQL databázím. Rád bych se s vámi podělil o můj pohled na NoSQL, který je ovlivněn hlavně více než rokem používání <a href="http://cassandra.apache.org/">Cassandry</a>.<br />
<span id="more-438"></span></p>
<h2>Co to je?</h2>
<p>Především je důležité zdůraznit, co NoSQL není &#8211; rozhodně to není <em>NO SQL</em>, tedy <em>trendy</em> odmítání relačních databází. Zkratka NoSQL znamená <strong>Not Only SQL</strong>, tedy uvědomění si toho, že relační databáze není jediná možnost řešení persistence, že existují i alternativy, které mohou být v některých případech vhodnější.</p>
<p>U rozsáhlejších aplikací pak můžeme dojít k tomu, že na některá data je vhodná relační databáze, na jiná NoSQL databáze a na další data úplně jiná NoSQL databáze. Tento pragmatický přístup, kdy se mixuje použití více databází v jednom projektu, se často označuje jako <a href="http://codemonkeyism.com/nosql-polyglott-persistence/">polyglot persistence</a>.</p>
<p>NoSQL databáze vznikaly (a vznikají) jako řešení reálných problémů &#8211; není to tedy bláznivý výmysl akademiků odtržených od reality, ale vysoce praktická záležitost. Zrod mnoha NoSQL databází je spjat s projekty, které se musely vypořádat s obrovským množstvím dat &#8211; Facebook (<a href="http://cassandra.apache.org/">Cassandra</a>), Google (<a href="http://en.wikipedia.org/wiki/BigTable">BigTable</a>), Amazon (<a href="http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html">Dynamo</a>), LinkedIN (<a href="http://project-voldemort.com/">Voldemort</a>) atd.</p>
<p>Použití NoSQL databáze může mít ale smysl i tehdy, pokud máme méně dat (které by v pohodě zvádla relační databáze) &#8211; třeba protože nějaká NoSQL databáze nabízí datový model, který je pro naši aplikaci přirozenější.</p>
<p>Ale zpět k úvodní otázce. <strong>NoSQL databáze je software pro perzistenci dat, který je alternativou ke klasickým relačním databázím</strong> (nic objevného). NoSQL databází existuje mnoho a dají se rozdělit z <a href="http://en.wikipedia.org/wiki/NoSQL#Taxonomy">mnoha hledisek</a>. Ve velmi specifických případech může dávat smysl vyvinout i vlastní NoSQL databázi (ale myslete na <a href="http://en.wikipedia.org/wiki/Not_Invented_Here">NIH</a>).</p>
<h2>Kdy použít NoSQL</h2>
<p>Rozhodnutí, zda použít místo ověřené relační databáze neznámou NoSQL databázi, není jednoduché, a hlavně to není rozhodnutí jen technické, ale i ekonomické.</p>
<p>NoSQL databáze např. často nemají takové možnosti dotazování jako relační databáze. Zkuste se třeba zamyslet nad tím, jak by ovlivnilo vaši aplikaci, kdyby jedinou podporovanou DB operací bylo uložení řádku a jeho načtení podle nějakého ID (nepřeháním!). To vede k tomu, že je na vaši aplikaci přenášena odpovědnost (např. generování sekundárních indexů), kterou jste dosud považovali za samozřejmou součást databázového enginu. Použití NoSQL databáze tak často znamená kompletní redesign celé aplikace, takže hodně učení a práce pro aplikační programátory (kteří nepracují zadarmo).</p>
<p>Většina dnešních programátorů vyrůstala ve světě, kde jedinou možností uložení dat byla relační databáze. Umí tak s ní dobře pracovat (v čemž jim pomáhají léty vyladěné tooly), jsou na ni schopni napasovat jakýkoliv model a už při úvodním seznamování s novým projektem jim v hlavě automaticky naskakují tabulky a vazby mezi nimi. Takže stojí za zvážení, zda se opravdu vyplatí investovat čas (~peníze) do učení diametrálně odlišných technologií a zda nemůže být ekonomičtější použít léty ověřené relační databáze namísto nové sexy NoSQL databáze.</p>
<p>Tím nechci říct, že se má absolutně kašlat na vzdělávání a inovaci, ale situace na trhu práce je tristní a ne každý má to štěstí (já ano <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ), že pracuje s bandou nadšených vývojářů, kteří čtou blogy, zajímají se o novinky v oboru a po večerech si zkouší nové technologie. Mnohdy člověk musí pracovat s lidmi, pro které je programování jen způsob obživy, odpracují si svých 8 hodin a tím to pro ně končí. A dělat s takovýmto týmem projekt, který používá NoSQL databázi, může být nákladné.</p>
<p>Náklady spojené s přechodem na NoSQL databázi se ale týkají celého týmu. Také vaši admini si budou muset umět poradit s novým SW v infrastruktuře, naučit se ho spravovat, zálohovat, tunit atp.</p>
<h2>Takže?</h2>
<p>Co jsem chtěl říct tímhle zamyšlením? NoSQL je zajímavá alternativa k zavedeným relačním databázím a rozhodně má své místo na trhu a proto doporučuji se o NoSQL databáze zajímat a nějaké si zkusit osahat. Pokud si proti nějaké NoSQL databázi zkusíte napsat jednoduchou aplikaci, neuvěřitelně vám to rozšíří obzory.</p>
<p>Nepoužívejte ale NoSQL databáze jen protože je to cool, protože by to <em>mohlo</em> být lepší nebo protože je používá konkurence. Řiďte se rozumem, ne emocemi. Dobře si spočítejte, co vám NoSQL přinese a jaké budou náklady. Pokud se už pro NoSQL rozhodnete, tak myslete na to, že se nemusíte úplně vzdávat <em>pohodlné</em> relační databáze &#8211; v projektu nemusíte používat jednu jedinou databázi&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/zamysleni-nad-nosql/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Pojďte pracovat do AVASTu!</title>
		<link>http://www.augi.cz/programovani/pojdte-pracovat-do-avastu/</link>
		<comments>http://www.augi.cz/programovani/pojdte-pracovat-do-avastu/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 18:20:39 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=436</guid>
		<description><![CDATA[AVAST is hiring! Pokud chcete pracovat ve firmě, jejíž produkt má více než 130 miliónů uživatelů, ale máte strach, aby Vás nesešrotoval velký moloch, pak práce v AVASTu může být to pravé. Žádný dress-code, žádný open-space, žádný &#8222;manager&#8220;, který Vám bude stát s bičem za zády a diktovat nesmyslné požadavky nebo Vám vyčítat, že jste [...]]]></description>
			<content:encoded><![CDATA[<p>AVAST is hiring! Pokud chcete pracovat ve firmě, jejíž produkt má více než 130 miliónů uživatelů, ale máte strach, aby Vás nesešrotoval velký moloch, pak práce v AVASTu může být to pravé. Žádný dress-code, žádný open-space, žádný &#8222;manager&#8220;, který Vám bude stát s bičem za zády a diktovat nesmyslné požadavky nebo Vám vyčítat, že jste věnovali hodinu sebevzdělávání (třeba formou čtení Augiho blogu <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ).<br />
Každá mince má ale dvě strany, takže relativní svoboda v práci je vyvážena požadavkem na samostatnost, smysl pro pořádek a schopnost sebemotivace.<br />
<span id="more-436"></span></p>
<p><strong>Tato pozice již není volná, ale máme v AVASTu jiné neméně zajímavé pozice pro .NET programátory, takže se mi v případě zájmu <a href="mailto:augustyn@avast.com">neváhejte ozvat</a>.</strong></p>
<p>A o jakouže práci se to jedná? Spolu se mnou, <a href="https://twitter.com/#!/topascz">Tomášem</a> a částečně <a href="https://twitter.com/#!/alenkacz">AlenKou</a> byste spolupracoval(a) na systému pro podporu chodu naší <a href="https://blog.avast.com/category/viruslab/">virové laboratoře</a>, tzn. softwaru pro zpracování velkého množství <em>vzorků</em> z různých zdrojů, jejich automatické zpracování, přidělování analytikům, podporu pro vytváření nových virových definic (příp. samostatné tooly), reporting apod.</p>
<p>Vaším denním chlebem by tak byl C#, (T-)SQL, HTML+JS, vše podle aktuálních potřeb. Zastáváme totiž názor, že než mít specialistu <strong>jen</strong> na jednu věc (databáze, web), je lepší, aby se vývojář staral o <em>vertikální výsek</em> projektu, tj. aby šel se svou částí kódu od databáze, přes aplikační server až po nasazení a podporu. Přirozeně, každý jsme jiný, každého baví něco jiného (a tak se o to víc zajímá), takže zde funguje výměna zkušeností, společné <em>Utils</em> knihovny atd.</p>
<p>Pozornému čtenáři mého blogu asi netřeba zdůrazňovat, že máme rádi nové technologie (pokud má jejich použití smysl) a rádi děláme věci pořádně. Příkladem budiž použití NoSql databáze <a href="http://www.augi.cz/programovani/cassandra-ocima-net-programatora/">Cassandra</a>, <a href="http://www.augi.cz/programovani/unit-testy-a-globalni-stav/">testování</a> (to opravdu není pravidlem v každé firmě) nebo nově <a href="http://www.augi.cz/programovani/prubezna-integrace/">integrační server</a>.</p>
<p>Co očekáváme od uchazeče?</p>
<ul>
<li>perfektní znalost C# (minimálně verze 3)</li>
<li>perfektní znalost .NET Frameworku (minimálně verze 3.5) &#8211; kromě <em>core</em> především ADO.NET, ASP.NET a WCF</li>
<li>zkušenosti s ASP.NET MVC</li>
<li>dobrou znalost MS SQL (2008)</li>
<li><em>praktickou</em> znalost návrhových vzorů (tj. umět je správně aplikovat v praxi, ne je umět vyjmenovat)</li>
<li>znalost základních algoritmů a jejich složitostí (opět umět využít při rozhodování během řešení úkolu)</li>
<li>zkušenosti s psaním testů</li>
<li>obecný rozhled v SW technologiích, tj. nežít jen v MS bublině, vědět co je heap, stack, COM, serializace, tušit jak může fungovat Garbage Collector, jak funguje TCP, HTTP, vědět proč pařez nemůže býti stromem atd. (prostě základy, co musí každý programátor znát)</li>
<li>zájem o nové technologie, přístupy a postupy</li>
<li>&#8230;ale i základní znalost starého dobrého čistého C (schopnost napsat/upravit jednoduchý program v C)</li>
<li>vystudovaná slušná technická univerzita je dobrým předpokladem, nikoliv nutnou podmínkou (tou je znalost metodik UTFG a RTFM)</li>
</ul>
<p>Technický skill ale není vše, takže očekáváme i rozumné osobnostní rysy, především komunikativnost (je potřeba komunikovat se zbytkem virové laboratoře) a rozumnou míru asertivity (nebát se přijít s vlastním nápadem, vylepšením nebo kritikou). Výše zmiňovaná samostatnost, smysl pro pořádek a nadšení pro práci jsou nutnou podmínkou (co si budeme nalhávat, jsme tu tak trošku perfekcionisti a zlí jazykové by řekli, že i trošku workoholici <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ).</p>
<p>Práce není možná z domova, ani na částečný úvazek, ale pracovní doba je &#8222;flexibilní&#8220;, tj. když ráno potřebujete zajít na úřad, tak se svět nezboří. Sedíme v Praze přímo <a href="http://mapy.cz/#x=14.452372&#038;y=50.045165&#038;z=15&#038;d=addr_11540571_0_1&#038;t=s&#038;q=Bud%C4%9Bjovick%C3%A1%201518%2F13a%2C%20Praha&#038;qp=8.785824_47.373659_22.467885_51.854782_6">na Budějovické</a> (metro C), v krásné nové <a href="http://www.trianon.cz/">budově</a>. Kanceláře máme různě velké, ale rozhodně nebudete sedět v openspace.</p>
<p>A co Vám můžeme nabídnou my (pokud Vám výše uvedené nestačí <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ) ?</p>
<ul>
<li>solidní plat</li>
<li>5 týdnů dovolené</li>
<li>firemní angličtina</li>
<li>90Kč stravenky</li>
<li>nealko pití na pracovišti</li>
<li>příspěvek na důchodové připojištění</li>
<li>nekuřácké pracoviště</li>
</ul>
<p>Pokud Vás nabídka práce zaujala, <a href="mailto:augustyn@avast.com">neváhejte mi napsat</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/pojdte-pracovat-do-avastu/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Průběžná integrace</title>
		<link>http://www.augi.cz/programovani/prubezna-integrace/</link>
		<comments>http://www.augi.cz/programovani/prubezna-integrace/#comments</comments>
		<pubDate>Sun, 05 Jun 2011 13:06:44 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=435</guid>
		<description><![CDATA[Continuous integration je volně řečeno souhrn praktik a nástrojů, při kterých vývojáři integrují (commitují) své změny často (typicky alespoň jednou za den). Každá integrace je automaticky ověřena testy a případně může vést až k automatickému nasazení nové verze aplikace (continuous delivery), v případě neúspěchu k okamžitému reportování problému. Přínosy continuous integration jsou především zrychlení vývoje, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://martinfowler.com/articles/continuousIntegration.html">Continuous integration</a> je volně řečeno souhrn praktik a nástrojů, při kterých vývojáři integrují (commitují) své změny často (typicky alespoň jednou za den). Každá integrace je automaticky ověřena testy a případně může vést až k automatickému nasazení nové verze aplikace (<em>continuous delivery</em>), v případě neúspěchu k okamžitému reportování problému.<br />
Přínosy continuous integration jsou především zrychlení vývoje, rychlejší dodávání nových verzí a snížení chybovosti &#8211; to vše <strong>díky automatizaci co nejvíce úkonů</strong>, které je třeba dělat při vývoji, testování a nasazovaní aplikace.</p>
<p>Všechno by to šlo implementovat pomocí vzájemně provázaných skriptů, ale za šťastnější řešení (i když zavádí <a href="http://en.wikipedia.org/wiki/Single_point_of_failure">SPOF</a>) považuji nasazení nějakého <a href="http://en.wikipedia.org/wiki/Comparison_of_Continuous_Integration_Software">integračního serveru</a> coby hlavního koordinátora všech operací. Integrační server toho pro nás může ale dělat ještě více &#8211; např. provázat buildy a verze aplikace s <a href="http://en.wikipedia.org/wiki/Bug_tracking_system">bug trackerem</a> nebo <a href="http://en.wikipedia.org/wiki/Issue_tracking_system">issue trackerem</a> (<a href="http://www.bugzilla.org/">Bugzillou</a>, <a href="http://www.mantisbt.org/">Mantisem</a>, <a href="http://www.atlassian.com/software/jira/">Jirou</a>, &#8230;). Integrační server se tak může stát místem, na kterém vidíte <em>vše o projektu</em> (a slovo <em>integrační</em> tak dostává další rozměr).</p>
<p>V tomto článku bych vám rád popsal, proč a jak jsem nasazoval integrační server já. Moc jsem toho o průběžné integraci předem nenastudoval, přistoupil jsem k věci celkem pragmaticky &#8211; cílem bylo vyřešit problémy, které mě trápili. A díky <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> jsem byl schopen do týdne rozjet prakticky vše, co jsem plánoval &#8211; tedy build Solution s více než 100 projekty (C# a C), spuštění unit testů, integračních testů, nasazení a spuštění akceptačních testů. Všechno samozřejmě plně automaticky, odpálené commitem do SubVersion.<br />
<span id="more-435"></span></p>
<h2>Proč jsem do toho šel?</h2>
<p>Až donedávna byl projekt, na kterém dělám, prakticky one-man-show. To mj. znamenalo, že všechno jsem měl pod palcem já &#8211; od konzistence (zbuildovatelnosti) zdrojových kódů v repository, přes spuštění a úspěšné projití všech testů až po nasazení (přes <a href="http://weblogs.asp.net/scottgu/archive/2010/07/29/vs-2010-web-deployment.aspx">One-Click Publish</a>). A všechny tyto kroky jsem dělal tehdy, když se mi zachtělo.<br />
Tento stav s sebou nesl mnoho problémů &#8211; nejvíc mě pálilo občasné vypublikování neotestovaného kódu (protože touhle změnou jsem prostě nemohl nic rozbít), omylem vypublikovaná DLLka ve špatném formátu (x86 místo x64) a především zdržení spojené s ručním nasazením aplikace (před publikováním nové verze jsem ručně zálohoval aktuální verzi). O ruční synchronizaci aplikace a databázového schématu ani nemluvím. Poslední kapkou bylo to, že k projektu přišel další člověk a já si uvědomil, co všechno si musí nainstalovat, aby byl schopen projekt vůbec zkompilovat.<br />
Zavedení continuous integration tak bylo lékem na všechny výše uvedené problémy.</p>
<h2>Příprava</h2>
<p><em>Jedna věc předem &#8211; je důležité si uvědomit, že &#8222;csproj&#8220; soubory nejsou nic jiného než build scripty pro MSBuild a proto se nebojte do nich zasahovat ručně &#8211; ne vše jde totiž naklikat přes Visual Studio.</em><br />
Prvním krokem k tomu, abyste mohli projekt zařadit do CI, je to, že projekt musí být po čistém checkoutu z repository zkompilovatelný <em>jedním příkazem</em>. Mým cílem tak bylo, aby fungovalo něco jako &#8222;<em>MSBuild.exe MySolution.sln /T:Build /p:Configuration:Release</em>&#8222;. To nebyl problém na mém vývojářském stroji, kde jsem měl nainstalované Visual Studio a knihovny třetích stran nakopírované na správná místa nebo v <a href="http://en.wikipedia.org/wiki/Global_Assembly_Cache">GAC</a>u. Na <em>čistém</em> build serveru to už ale tak růžové nebylo. Takže na co byste si měli dát pozor?</p>
<h3>Pre a Post-build stepy</h3>
<p>Pokud kopírujete v Pre a Post-build stepech nějaké dependence, které nelze jinak vyjádřit, tak zajistěte, aby v době volání příslušného stepu už existovaly &#8211; tedy zajistěte správné pořadí kompilace.<br />
Já jsem řešil poměrně běžnou věc &#8211; mám nějakou nativní DLL knihovnu, kterou potřebuji zkopírovat do výstupního adresáře .NETího projektu. Takže jsem si pěkně naklikal ve Visual Studiu závislosti mezi projekty a kompilace krásně jela. Ale na build serveru byl problém. Závislost mezi .NETím a nativním projektem se totiž uloží jen do <em>sln</em> souboru (což není narozdíl od <em>csproj</em>e build script!). V MSBuildu 3.5 by to bylo ok, protože tam si MSBuild vše pořádně očuchal a správně určil pořadí. To ale údajně způsobovalo u velkých projektů výkonové problémy (?) a tak byla tato fičura v MSBuildu 4.0 odstraněna a MSBuild kouká jen na závislosti uvedené přímo v projektových souborech. Visual studio vám ale nedovolí přidat do .NETího projektu referenci na ne-.NETí projekt, takže nelze jednoduše naklikat závislost .NETího projektu na ne-.NETtím &#8211; musíme <a href="http://blogs.msdn.com/b/msbuild/archive/2010/12/21/incorrect-solution-build-ordering-when-using-msbuild-exe.aspx">referenci ručně dopsat</a> do <em>csproj</em>e. Jako bonus dostaneme ve Visual Studiu žlutý vykřičníček a warning, ale kompilace pomocí MSBuildu probíhá ve správném pořadí.</p>
<h3>Knihovny třetích stran</h3>
<p>Jak říká Martin Fowler &#8211; &#8222;<em>Everything should be in the repository.</em>&#8222;. Takže mějte ve verzovacím systému binárky knihoven třetích stran a z projektů na ně odkazujte pomocí relativních cest (nebojte se podívat přímo do <em>csproj</em>e). Pozor si dávejte hlavně tehdy, když máte na vývojářském stroji nějakou knihovnu nainstalovanou v GACu &#8211; ve spojení s automatickým přidáváním referencí (jako nabízí třeba ReSharper) vám to může připravit nemilé překvapení (nareferencovat assembly z GACu).</p>
<h3>Generované soubory</h3>
<p>Pokud generujete soubory pomocí T4, tak tyto soubory musí být v repository. Jen je potřeba zajistit jejich přegenerování na vývojářově stroji &#8211; to mám udělané tak, že v pre-build stepu spouštím <a href="http://msdn.microsoft.com/library/bb126245.aspx">TextTransform.exe</a>, ale jen pokud existuje soubor &#8222;<em>%CommonProgramFiles(x86)%\Microsoft shared\TextTemplating\10.0\TextTransform.exe</em>&#8220; (instaluje se až s Visual Studiem). To zajistí, že na vývojářském stroji (tj. s nainstalovaným Visual Studiem) dojde v pre-build stepu k přegenerování T4 souboru.<br />
Pokud se rozhodnete vyřešit T4 soubory tímto způsobem, tak reference na <em>custom</em> assembly nedávejte přímo do <em>tt</em> souboru, ale předávejte je přes parametry příkazové řádky.</p>
<h3>Testy</h3>
<p>Připravte se na to, že pokud máte testy napsané v MSTestu, budete muset na stroj, na kterém chcete testy spouštět, instalovat Visual Studio (pokud nechcete použít nějaký alternativní test runner).<br />
Pokud používáte v testech <a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.deploymentitemattribute.aspx">DeploymentItem</a>, tak možná narazíte na jeho trošku podivné chování při zadávání relativní cesty. Osvědčilo se mi zadávat cestu relativně k umístění <em>sln</em> souboru a při spuštění přes <a href="http://msdn.microsoft.com/en-us/library/ms182486.aspx">MSTest.exe</a> pak nastavit jako <em>runconfig</em> soubor <em>LocalTestRun.testrunconfig</em> (který je ve stejném adresáři jako <em>sln</em> soubor).<br />
Dále myslete na to, že tam, kde budete pouštět integrační testy, budete muset mít pravděpodobně dostupné nějaké testovací verze databází apod.</p>
<h3>Transformace configů</h3>
<p>Před tím, než ze zkompilovaných binárek vytvoříte instalační balíčky, <em>můžete</em> mít potřebu upravit nějaké konfigurační soubory v aplikaci. S .NET 4 přišly <a href="http://msdn.microsoft.com/en-us/library/dd465326.aspx">web.config transformation</a>, které toto velmi zjednoduší. Ve webovém projektu máte klasicky soubor <em>web.config</em> &#8211; v něm byste měli mít nastavení, které odpovídá <em>Debug</em> konfiguraci (protože při debugu se nevím proč transformace neprovádějí). Dále budete mít soubor <em>web.Release.config</em> (Visual Studio 2010 má na jeho přidání podporu), ve kterém budou transformace připravující konfiguraci pro <em>Release</em> konfiguraci. Pokud máte v projektu kromě <em>Debug</em> a <em>Release</em> i další konfiguraci (např. <em>Stage</em>), můžete mít transformace i pro tyto další konfigurace (např. <em>web.Stage.config</em>).</p>
<p>Je možné, že budete chtít transformovat i jiný soubor než <em>web.config</em> (my transformujeme <em>log4net.config</em>). To <a href="http://stackoverflow.com/questions/5557866/how-to-transform-log4net-config-like-web-config/5998230#5998230">samozřejmě</a> <a href="http://stackoverflow.com/questions/4750153/transforming-files-with-msdeploy/5381408#5381408">není</a> <a href="http://geekswithblogs.net/EltonStoneman/archive/2010/08/20/using-msbuild-4.0-web.config-transformation-to-generate-any-config-file.aspx">problém</a>.<br />
Pokud nebudete mít na build serveru Visual Studio, tak si dejte pozor, abyste si vybrali to správné <a href="http://stackoverflow.com/questions/5557866/how-to-transform-log4net-config-like-web-config/5623673#5623673">řešení</a>.</p>
<p>Transformaci konfiguračních souborů můžete ale samozřejmě dělat jakkoliv, třeba pomocí vlastních skriptů &#8211; na tom nevidím nic špatného.</p>
<p>Nejen z hlediska bezpečnosti je velmi zajímavou variantou mít v některých konfiguračních položkách místo hodnot jen placeholdery, které se naplní správnými hodnotami až při nasazení. To je velice flexibilní řešení, protože umožní nasadit jeden distribuční balíček v různých prostředích (typicky různé <em>connection string</em>y).</p>
<h3>Vytvoření instalačních balíčků</h3>
<p>Instalační/Distribuční balíčky se zásadně liší podle typu aplikace &#8211; já se zde zaměřím jen na webové aplikace, konkrétně na vytváření balíčků, které se budou dále nasazovat pomocí nástroje <a href="http://technet.microsoft.com/en-us/library/dd569106(WS.10).aspx">MSDeploy</a> (<em>Web Deployment Tool</em>).<br />
Způsob vytvoření balíčku si můžete nastavit přímo ve Visual Studiu, v <em>Properties</em> dané webové aplikace. Já jsem si oblíbil možnost vytvořit balíček jako soubor <em>zip</em> a vytvořit ho v adresáři &#8222;Deploy/Packages&#8220; (relativně k solution).<br />
Důležité je, že balíčky mohou být parametrizované, což umožní výše zmiňované podstrčení správných hodnot do konfiguračních souborů až při nasazení (automaticky jsou takto parametrizovány právě zmiňované <em>connection string</em>y).</p>
<p>Pokud chcete do balíčku přidat nějaké vlastní soubory (u mě to jsou opět nativní DLL knihovny do adresáře <em>/bin</em>), tak to není problém &#8211; stačí je <a href="http://stackoverflow.com/questions/2747081/how-do-you-include-additional-files-using-vs2010-web-deployment-packages/2748752#2748752">dospecifikovat</a> v <em>csproj</em>i.</p>
<p>Jak ale vytvořit balíček z MSBuildu? Zde je opět více možností. Můžete zavolat MSBuild s targetem <em>Package</em> (&#8222;<em>MSBuild /T:Package</em>&#8222;) nebo můžete nechat vytvořit balíčky ihned během kompilace pomocí property <em>DeployOnBuild</em> (&#8222;/p:DeployOnBuild&#8220;).</p>
<h3>Nasazení</h3>
<p>Nasazení děláme pomocí nástroje <a href="http://technet.microsoft.com/en-us/library/dd569106(WS.10).aspx">MSDeploy</a>, který umožňuje plnohodnotné nasazení, tj. nejen zkopírování souborů, ale i vytvoření a ovládání AppPoolu, nastavení práv, migraci databáze atd. Je třeba <a href="http://www.iis.net/download/WebDeploy">ho</a> mít nainstalovaný jak na stroji, ze kterého nasazujeme, tak na stroji, na který nasazujeme. Typický příkaz pro jednoduché nasazení může vypadat nějak takto:</p>
<pre>"%ProgramFiles%\IIS\Microsoft Web Deploy V2\MSDeploy.exe" -verb:sync
 -source:package=Packages/MyApplication.zip
 -dest:auto,computerName="https://deployTargetComputer:8172/msdeploy.axd
?site=Default Web Site",userName=%username%,password=%pwd%,authtype=basic
 -allowUntrusted</pre>
<p>Parametry balíčku (např. výše zmiňované <em>connection string</em>y) se dají nastavit intuitivně pomocí přepínače <a href="http://technet.microsoft.com/en-us/library/dd569089(WS.10).aspx">-setParam</a>, příp. můžete podstrčit celý soubor s parametry.</p>
<h3>Migrace databáze</h3>
<p>Při nasazení aplikace je třeba ověřit, že okolní infrastruktura odpovídá tomu, na co byla aplikace stavěna. Pokud se zaměříme jen na databáze, tak bychom měli ověřit, že schéma v databázi odpovídá tomu, proti čemu chce aplikace pracovat.</p>
<p>To se typicky dělá tak, že aplikace ví verzi schématu (celé číslo), databáze má v nějaké metatabulce uloženu aktuální verzi schématu, a <em>instalační</em> skript je zodpovědný za to, že se zavolají migrační skripty, které zajistí upgrade (příp. downgrade) databáze podle potřeb aplikace, tj. sjednotí verzi schématu požadovanou aplikací a aktuální v databázi.</p>
<p>Celou tuto infrastrukturu si můžeme napsat sami (není to nic složitého), můžeme využít nějaké migrační knihovny, nebo může využít to, co nabízí <a href="http://msdn.microsoft.com/en-us/library/dd465343.aspx">Visual Studio a MSDeploy</a>.</p>
<h2>Můžeme začít!</h2>
<p>Pokud jsme schopni zkompilovat projekt jednoduše ihned po čistém checkoutu z repository, máme na build serveru nainstalovány všechny potřebné věci (.NET 4, VS2010, MSDeploy, &#8230;), umíme generovat distribuční balíčky a máme připraveny skripty pro jejich nasazení, tak nám nic nebrání nainstalovat nějaký integrační server a jednotlivé části této výrobní linky v něm provázat.</p>
<p>Já jsem se rozhodl použít <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> a rozhodně své volby nelituji. O instalaci jsem se díky našemu <a href="http://twitter.com/#!/lukashasik">QA</a> starat nemusel, ale veškerou konfiguraci jsem pak dělal sám a poměrně rychle jsem se zorientoval. Předností je taktéž cena, která je pro menší a střední projekty nulová.</p>
<p>V každém projektu (já mám jen jeden projekt odpovídající celému solution) můžete mít (v Professional verzi, která je zadarmo, až 20) <em>Build Configurations</em>. Jednu <em>Build Configuration</em> bych označil za jednu výrobní linku, takže můžete mít třeba dvě BC z názvy &#8222;Stage&#8220; a &#8222;Production&#8220;. Když budou tyto dvě BC téměř identické, je možné vyextrahovat šablonu a tyto dvě BC na ní založit. Parametrizaci pak provedete přes <em>Build Parameters</em>.</p>
<p>Každá BC v sobě obsahuje posloupnost <em>Build Step</em>ů. Prvním (implictním) krokem je checkout z repository. Další kroky jsou již plně na nás, ale TeamCity nám zde velmi vychází vstříc &#8211; jsou zde připravené &#8222;<em>build step runnery</em>&#8220; pro spuštění MSBuildu, MSTestu, baťáku, PowerShellu, Antu, FxCopu&#8230;a dokonce přímo Solution (takže staší zadat cestu k solution, které chcete zkompilovat).</p>
<p>Dalším důležitým nastavením jsou triggery, které umožní nastavit, kdy se má BC spustit &#8211; kadý den v zadaný čas nebo po commitnutí do repository jsou samozřejmostí.</p>
<h2>Hotovo</h2>
<p>Týdnu, který jsem věnoval zavedení průběžné integrace, vůbec nelituji. Díky CI jsem zautomatizoval drtivou většinou věcí, které je třeba dělat při vývoji, testování a nasazování aplikace. Rozhodně ale nepovažuji současný stav za finální, protože je ještě spousta věcí, které by šly vylepšit nebo přidat &#8211; např. lepší správa konfiguračních souborů, automatický rollback po neúspěšném nasazení atd.</p>
<p>I současný stav je obrovským přínosem a proto vám doporučím začít s CI. Není potřeba začít hned dělat všechny věci, které zde popisuji &#8211; můžete je zavádět <em>průběžně</em>. Stačí začít třeba tím, že se vytvoří build server, který bude po každém commitu kontrolovat <em>zbuildovatelnost</em> solution &#8211; i to je velmi pěkný první krok.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/prubezna-integrace/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

