<?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>Thu, 08 Jul 2010 15:38:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Novinky léta 2010 okolo ASP.NET</title>
		<link>http://www.augi.cz/programovani/novinky-leta-2010-okolo-asp-net/</link>
		<comments>http://www.augi.cz/programovani/novinky-leta-2010-okolo-asp-net/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 15:38:46 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=427</guid>
		<description><![CDATA[V posledním měsíci Microsoft uvolnil několik nových technologií, které souvisí s webovým vývojem, ale leckdy mají i větší přesah. Podívejme se zběžně na ně, třeba Vás některá z nich zaujme nebo inspiruje.

IIS Developer Express
Když člověk dosud vyvíjel v ASP.NET, měl prakticky jen dvě možnosti, jak svou aplikaci otestovat &#8211; použít webový server vestavěný ve Visual [...]]]></description>
			<content:encoded><![CDATA[<p>V posledním měsíci Microsoft uvolnil několik nových technologií, které souvisí s webovým vývojem, ale leckdy mají i větší přesah. Podívejme se zběžně na ně, třeba Vás některá z nich zaujme nebo inspiruje.<br />
<span id="more-427"></span></p>
<h2>IIS Developer Express</h2>
<p>Když člověk dosud vyvíjel v ASP.NET, měl prakticky jen dvě možnosti, jak svou aplikaci otestovat &#8211; použít webový server vestavěný ve Visual Studiu (<em>ASP.NET Development Server</em> zvaný také <em>Cassini</em>) nebo použít lokální IIS Web Server. Nevýhodou první možnosti je to, že nemáme k dispozici vše, co v plném IIS, a tak ladíme v jiném prostředí, než kde budeme aplikaci provozovat.<br /> Nevýhodou použití IIS je to, že jeho verze je spjatá s verzí operačního systému vývojářského stroje (takže opět jiné prostředí pro vývoj a pro nasazení).<br />
Proto Microsoft přišel s IIS Developer Express, které spojuje výhody velkého IIS 7.x (obsahuje tedy všechny jeho fičury, včetně SSL nebo URL Rewrite, a to na všech Windows od XP výše včetně) a lehkost Cassini, tj. xcopy distribuce (není třeba nic instalovat/registrovat), nejsou třeba administrátorská práva a použití (včetně integrace do Visual Studia) je jednoduché a intuitivní. Nainstalovat si ho můžete přes <a href="http://www.microsoft.com/web/downloads/platform.aspx">Web Platform Installer</a>.<br />
Podrobnosti v <a href="http://weblogs.asp.net/scottgu/archive/2010/06/28/introducing-iis-express.aspx">článku Scotta Guthrieho</a>.</p>
<h2>SQL Server Compact Edition 4</h2>
<p>Jedná se o novou verzi embedded relační databáze. Její výhodou je žádná instalace, takže i pokud máte k dispozici jen sdílený hosting, není to problém &#8211; stačí do <em>bin</em> adresáře nakopírovat binárky. Další zásadní vlastností je to, že databáze podporuje (dosti velký) subset jazyka <a href="http://technet.microsoft.com/en-us/library/bb510741.aspx">Transact-SQL</a> (používaný ve velkém SQL Serveru) a je možné použít nejen klasický ADO.NET přístup, ale i další oblíbené O/R mappery. Důležité je také to, že tento produkt (stejně jako IIS Developer Express) je zdarma.<br />
Zajímavostí (značně užitečnou) je přítomnost podpory pro stránkování přímo v této verzi T-SQL &#8211; přes příkazy <em>OFFSET</em> a <em>FETCH</em> &#8211; takže není nutné používat <a href="http://technet.microsoft.com/en-us/library/ms189798.aspx">ranking functions</a>. Více detailů najdete <a href="http://blogs.msdn.com/b/sqlservercompact/archive/2010/07/07/introducing-sql-server-compact-4-0-the-next-gen-embedded-database-from-microsoft.aspx">v tomto blogspotu</a>.</p>
<h2>Razor</h2>
<p>Razor je nový templatovací engine, tedy něco jako dosavadní (ne-příliš oblíbený) <a href="http://msdn.microsoft.com/en-us/library/bb126445.aspx">T4</a>. Zjednodušeně řešeno je to třída, do které strčíme data a šablonu a jako výsledek dostaneme string (data přetransformovaná šablonou).<br />
Pro webové vývojáře je zajímavý tím, že bude použit jako alternativa ke stávajícím WebForms stránkám (typicky soubory s příponou <em>aspx</em>), což se vzhledem k méně zašumněné syntaxi hodí; ale není to žádný přelomový krok. Soubory mají příponu <em>cshthml</em> nebo <em>vbhtml</em>, podle jazyka, který používáme uvnitř šablony (C# nebo VB.NET), a říká se jim <em>ASP.NET Web Pages</em>.<br />
Připravuje se také nový view-engine pro ASP.NET MVC, který bude založen právě na Razoru. Btw. prvního preview ASP.NET MVC 3 bychom se měli podle jednoho komentáře na blogu Scotta Guthrieho dočkat již v průběhu tohoto měsíce (červenec 2010).<br />
Poměrně podrobný popis syntaxe najdete kde jinde než <a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx">v článku Scotta Guthrieho</a>.</p>
<h2>WebMatrix</h2>
<p><a href="http://www.microsoft.com/web/webmatrix/">WebMatrix</a> je free vývojové prostředí pro tvorbu jednoduchých webů. Je postavené na ASP.NET Web Pages (jednoduchý framework nad ASP.NET), který využívá výše zmíněného Razoru pro zápis &#8220;dynamického&#8221; kódu v tzv. <a href="http://en.wikipedia.org/wiki/Spaghetti_code">spaghetti stylu</a> (jedna dlouhá nudle). Není to tedy nic pro profi vývojáře, je mířeno spíše na začátečníky a hobby vývojáře. Pokud bude vývojáři WebMatrix těsný, je možné projekt překlopit do verze pro Visual Studio. I zde najde začátečník či hobby vývojář free vývojové prostředí &#8211; <a href="http://www.microsoft.com/express/downloads/#2010-Visual-Web-Developer">Visual Web Developer 2010</a>.<br />
Z prostředí WebMatrixu je možné ovládat také <em>IIS Developer Express</em> a <em>SQL Server Compact Edition</em> (které se instalují spolu s WebMatrixem), takže vývojář má k dispozici kompletní free webový stack pro vývoj.<br />
Úvod do WebMatrixu najdete <a href="http://weblogs.asp.net/scottgu/archive/2010/07/06/introducing-webmatrix.aspx">zde</a>, podrobnější informace např. na webu <a href="http://www.asp.net/webmatrix">asp.net</a>.</p>
<h2>Visual Studio 2010 v češtině</h2>
<p>Nevím jaky Vy, ale já jsem odpůrcem lokalizace vývojových nástrojů. Angličtina prostě k vývojařině patří a alespoň základy by tak měl umět každý, kdo to myslí s programováním vážně. <a href="http://msdn.microsoft.com/cs-cz/ff799046.aspx">Lokalizačaní balíček pro Visual Studio 2010</a> je možné nainstalovat do Visual Studia minimálně verze Professional &#8211; to je dle mého skromného názoru způsobeno tím, že Express edice nepodporují addony. Nicméně pokud má být lokalizace určena především pro edukativní účely, není to myslím problém, protože většina &#8220;IT škol&#8221; je v programu <a href="http://www.microsoft.com/cze/education/licence/msdn_academic_alliance/default.mspx">MSDN AA</a>, příp. studenti mohou využít programu <a href="http://www.dreamspark.cz/">DreamSpark</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/novinky-leta-2010-okolo-asp-net/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Really simple IoC/DI container implementation</title>
		<link>http://www.augi.cz/programovani/really-simple-iocdi-container-implementation/</link>
		<comments>http://www.augi.cz/programovani/really-simple-iocdi-container-implementation/#comments</comments>
		<pubDate>Wed, 19 May 2010 10:39:48 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=426</guid>
		<description><![CDATA[I&#8217;m sure you know (or at least have heard of) Inversion of Control/Dependency Injection principle. It&#8217;s a very handy principle that leads to plugable application design, simplifies unit-testing and so I can recommend its using.
	I wanted to use some really simple IoC/DI container with small footprint. Unity or PicoContainer.NET are propagated as &#8220;lightweight IoC/DI containers&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m sure you know (or at least have heard of) <a href="http://en.wikipedia.org/wiki/Inversion_of_Control">Inversion of Control</a>/<a href="http://en.wikipedia.org/wiki/Dependency_Injection">Dependency Injection</a> principle. It&#8217;s a very handy principle that leads to plugable application design, simplifies unit-testing and so I can recommend its using.<br />
	I wanted to use some really simple IoC/DI container with small footprint. <a href="http://unity.codeplex.com/">Unity</a> or <a href="http://docs.codehaus.org/display/PICO/Home">PicoContainer.NET</a> are propagated as &#8220;<em>lightweight IoC/DI containers</em>&#8221; so I wanted to use one of them. Before I had looked into source code of Unity. And&#8230;what the hell? Lightweight? There are dozens of classes and interfaces! I&#8217;m sure that Unity is really good piece of software but I needed something less sophisticated and more fast. Despite IoC/DI is very strong principle it&#8217;s very simple to implement &#8211; so I decided to write my own really lightweight IoC/DI container. Just because I love programming <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
	<span id="more-426"></span></p>
<p>I can never say that I will not change the used IoC/DI container (e.g. when I would want to use some <em>heavy</em> Unity features or separate file configuration) so I decided that my container will implement the <a href="http://commonservicelocator.codeplex.com/sourcecontrol/network/Show?projectName=CommonServiceLocator&#038;changeSetId=27688#332684">ServiceLocatorImplBase</a> abstract class from <a href="http://commonservicelocator.codeplex.com/">CommonServiceLocator</a> library. So I had to implement two methods &#8211; <em>DoGetInstance</em> and <em>DoGetAllInstances</em>. Implementing of this abstract class ensures that I will use <a href="http://commonservicelocator.codeplex.com/sourcecontrol/network/Show?projectName=CommonServiceLocator&#038;changeSetId=27688#332676">one interface</a> (from <em>CommonServiceLocator</em>) in whole application (except registrations). And so if I want to use some other IoC/DI container then I would change types registration only (because it&#8217;s <em>always</em> container specific). The rest of application wouldn&#8217;t require changes.</p>
<h2>The storage</h2>
<p>What does container do? It maps type to some instance. So let&#8217;s start with this storage:</p>
<pre class="brush: csharp">Dictionary&lt;Type, Func&lt;Type, object>> _Registrations;</pre>
<p>We map <em>Type</em> to delegate. The delegate has one parameter (<em>Type</em>) and returns instance of this type. So we map type to method that obtains type instance. The method can just call parameterless constructor or it can be something more sophisticated. We are not limited when writing this method &#8211; it&#8217;s a regular method.<br />
	The <a href="http://commonservicelocator.codeplex.com/sourcecontrol/network/Show?projectName=CommonServiceLocator&#038;changeSetId=27688#332684">DoGetInstance</a> method has actually two parameters &#8211; <em>Type</em> and <em>string</em> (<em>key</em>). So we have to add one mapping to our storage and one parameter to our delegate:</p>
<pre class="brush: csharp">Dictionary&lt;Type, Dictionary&lt;string, Func&lt;Type, string, object>>> _Registrations;</pre>
<p>Actually, it could be handy to have access to container from <em>creating</em> method so I add one more parameter to the delegate:</p>
<pre class="brush: csharp">Dictionary&lt;Type, Dictionary&lt;string, Func&lt;SimpleContainer, Type, string, object>>> _Registrations;</pre>
<p>And that&#8217;s all! We are now able to store all data we need.</p>
<h2>Methods</h2>
<p>Next, we have to implement <em>DoGetInstance</em> method. It&#8217;s very straightforward:</p>
<pre class="brush: csharp">protected override object DoGetInstance(Type serviceType, string key)
{
	var creators = _Registrations[serviceType]; // map type
	if (creators != null &#038;&#038; creators.Count > 0)
	{
		Func&lt;SimpleContainer, Type, string, object> creator;
		if (string.IsNullOrEmpty(key) || !creators.TryGetValue(key, out creator) || creator == null) // try to map key
		{
			// use empty key as fallback
			creators.TryGetValue(string.Empty, out creator);
		}
		if (creator != null)
		{
			return creator(this, serviceType, key);
		}
	}
	throw new ActivationException(string.Format("Creator for '{0}' for key '{1}' not found.", serviceType, key));
}</pre>
<p>Next, we have to implement some method that will register method for type instance obtaining:</p>
<pre class="brush: csharp">public void Register(Type serviceType, string key, Func&lt;SimpleContainer, Type, string, object> creator)
{
	Dictionary&lt;string, Func&lt;SimpleContainer, Type, string, object>> creators;
	if (!_Registrations.TryGetValue(serviceType, out creators))
	{
		_TypeToCreators.Add(serviceType, creators = new Dictionary&lt;string, Func&lt;SimpleContainer, Type, string, object>>(StringComparer.OrdinalIgnoreCase));
	}
	creators[key ?? string.Empty] = creator;
}</pre>
<p>Very easy, I think. And that&#8217;s all! We now have IoC container that is able to handle most of our requirements. Don&#8217;t you believe me? Let&#8217;s implement some supporting extensions methods that handle common scenarios.<br />
		Before we start I would like to notice that I implemented <em>DoGetAllInstances</em> abstract method in very similar way too. And I added common <em>IDisposable pattern</em> into our container too (check source code download at the end of this article).</p>
<h2>Basic overloads</h2>
<p>I really like strong typed languages and so I like generics. Let&#8217;s implement generic <em>Register</em> method:</p>
<pre class="brush: csharp">public static void Register&lt;T>(this SimpleContainer container, string key, Func&lt;SimpleContainer, Type, string, object> creator)
{
	container.Register(typeof(T), key, creator);
}</pre>
<p>Our container should be able to serve singleton for us:</p>
<pre class="brush: csharp">public static void RegisterInstance&lt;T>(this SimpleContainer container, string key, T instance)
{
	// we store instance reference in scope of lambda function bellow
	container.Register(typeof(T), key, (c, t, k) => instance);
}</pre>
<p>Do you want to dispose singleton at the end of program (more exactly &#8211; when container is disposing) ?</p>
<pre class="brush: csharp">public static void RegisterSingleton&lt;T>(this SimpleContainer container, string key, T instance)
{
	var asIDisposable = instance as IDisposable;
	if (asIDisposable != null)
	{
		container.Disposing += (sender, eventArgs) => asIDisposable.Dispose();
	}
	container.Register(typeof(T), key, (c, t, k) => instance);
}</pre>
<h2>Dependency injection</h2>
<p>Well, we have very handy and lightweight container but it is not IoC/DI container &#8211; we don&#8217;t manage dependency injection at all. If we want to use dependency injection then we can do that by hand:</p>
<pre class="brush: csharp">container.Register&lt;IMyInterface>((c, t, k) => new MyInterfaceImplementation(
	c.GetInstance&lt;ISomeOtherInterface>(),
	c.GetInstance&lt;IDifferentInterface>()));</pre>
<p>Our <em>MyInterfaceImplementation</em> class has constructor with two parameters and we have to resolve these parameters when we are constructing the object. So we just delegate this task recursively to container. Pretty cool!<br />
		But programmers (including me) are too lazy and so we want to simplify this very common task:</p>
<pre class="brush: csharp">public static void Register&lt;T, TImplementation>(this SimpleContainer container, string key)
{
	var ctors = type.GetConstructors();
	if (ctors == null || ctors.Length == 0)
	{
		throw new ActivationException(string.Format("Appropriate constructor not found in type '{0}'.", type));
	}
	var ctor = ctors[0];

	var containerParameter = Expression.Parameter(typeof(SimpleContainer), "container");
	var typeParameter = Expression.Parameter(typeof(Type), "type");
	var keyParameter = Expression.Parameter(typeof(string), "key");

	var creator = Expression.Lambda(typeof(Func&lt;SimpleContainer, Type, string, object>),
		Expression.New(ctor,
			// ctor parameters
			ctor.GetParameters().Select(p => (Expression)Expression.Call(containerParameter, "GetInstance", new[] { p.ParameterType }))),
		containerParameter, typeParameter, keyParameter); // lambda parameters
	return (Func&lt;SimpleContainer, Type, string, object>)creator.Compile();
}</pre>
<p>This may look difficult but it&#8217;s very easy &#8211; we construct lambda expression that invokes constructor and supplies constructor parameters via <em>container.GetInstance</em> method call. Just the same that we did by hand.</p>
<h2>Registration overriding</h2>
<p>We usually use one <em>main</em> container but sometimes we could want to change resolving for some specific types. Then we can use <em>containers hierarchy</em> that handles <em>registration overriding</em>.<br />
		We have to add <em>ParentContainer</em> property (e.g. of type <em>SimpleContainer</em>) to our <em>SimpleContainer</em> class. Then we create two extension methods:</p>
<pre class="brush: csharp">public static SimpleContainer CreatePermanentChildContainer(this SimpleContainer container)
{
	return new SimpleContainer { ParentContainer = container };
}

public static SimpleContainer CreateChildContainer(this SimpleContainer container)
{
	var child = container.CreatePermanentChildContainer();
	container.Disposing += (sender, eventArgs) => child.Dispose();
	return child;
}</pre>
<p>We can use these extension method to implement very handy method:</p>
<pre class="brush: csharp">public static void RegisterWithOverride&lt;T>(this SimpleContainer container, string key, Func&lt;SimpleContainer, Type, string, object> creator, Action&lt;SimpleContainer> overrideContainer)
{
	container.Register&lt;T>(key, (c, t, k) =>
	{
		using (var cc = container.CreatePermanentChildContainer())
		{
			overrideContainer(cc);
			return creator(cc, t, k);
		}
	});
}</pre>
<p>Our new method has one more parameter &#8211; <em>overrideContainer</em> that is aimed for registration overrides.<br />
	And finally, we can use this pretty cool extension method:</p>
<pre class="brush: csharp">// most of classes will use ServiceOne for IMyService
container.Register&lt;IMyService, ServiceOne>();
// but IMyInterface will use ServiceTwo for IMyService
container.RegisterWithOverride&lt;IMyInterface, MyInterfaceImplementation>(cc =>
	{
		cc.Register&lt;IMyService, ServiceTwo>();
	});</pre>
<h2>Summary</h2>
<p>As you can see, implementation of own lightweight IoC/DI can be very easy. It could be probably better to use some good known IoC/DI container in large enterprise application but if your requirements aren&#8217;t very high, you don&#8217;t need registration via external configuration file (so registration in code is sufficient) and you want to have good performance then own lightweight IoC/DI container can be good solution.<br />
	I created project <a href="http://simplecontainer.codeplex.com">SimpleContainer</a> on <a href="http://www.codeplex.com">CodePlex</a> and so you can download source codes <a href="http://simplecontainer.codeplex.com/releases/view/45552">here</a>. You can let me know if you (don&#8217;t) like that and/or use that.<br />
	I implemented extensions method for registering instance for one web-request too. It uses own implementation of <em>IHttpModule</em> so if you want to use this feature then you have to register this module in your <em>web.config</em>.<br />
	<em>Footnote: I discovered that there are some light IoC/DI containers for .NET: <a href="http://funq.codeplex.com/">Funq</a> and <a href="http://munq.codeplex.com/">Munq</a>. But these containers are much more complicated &#8211; remember that <em>SimpleContainer</em> core is just one class and the second class contains set of extension methods only.</em>
	</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/really-simple-iocdi-container-implementation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cassandra očima .NET programátora</title>
		<link>http://www.augi.cz/programovani/cassandra-ocima-net-programatora/</link>
		<comments>http://www.augi.cz/programovani/cassandra-ocima-net-programatora/#comments</comments>
		<pubDate>Mon, 10 May 2010 20:29:22 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=425</guid>
		<description><![CDATA[V poslední době je v módě termín NOSQL (Not Only Sql) a tak se i já o něm zmíním. Není to proto, že bych potřeboval být nutně cool, ale byl jsem nucen se na  NOSQL podívat, protože nabízí efektivní řešení některých specifických úkolů, u kterých klasické relační databáze ztrácí dech. Je trošku zavádějící mluvit [...]]]></description>
			<content:encoded><![CDATA[<p>V poslední době je v módě termín <a href="http://en.wikipedia.org/wiki/NoSQL">NOSQL</a> (<em>Not Only Sql</em>) a tak se i já o něm zmíním. Není to proto, že bych potřeboval být nutně cool, ale byl jsem <em>nucen</em> se na  NOSQL podívat, protože nabízí efektivní řešení některých specifických úkolů, u kterých klasické relační databáze ztrácí dech. Je trošku zavádějící mluvit o NOSQL databázích (přestože to jsou báze dat), proto upřednostňuji termín NOSQL úložiště. NOSQL úložišť existuje <a href="http://en.wikipedia.org/wiki/NoSQL#Taxonomy">mnoho typů</a>, já se ale zaměřím jen na úložiště typu <a href="http://en.wikipedia.org/wiki/BigTable">BigTable</a>, konkrétně na <a href="http://cassandra.apache.org/">Cassandru</a>. Co zde popíšu ale do jisté míry platí i pro <a href="http://en.wikipedia.org/wiki/HBase">HBase</a>.<br />
<span id="more-425"></span></p>
<p>V čem byste implementovali úložiště dat, aby bylo opravdu rychlé? C/C++? Asm? Některá NOSQL úložiště jdou touto cestou (např. <a href="http://www.mongodb.org/">MongoDB</a>), ale Cassandra a HBase jsou implementovány v Javě. Ano, v tom <em>strašné, pomalém a zdroježeroucím molochu</em>, jak by Javu mnozí počastovali. Ale vězte, že na tomto <em>molochu</em> běží celý internet&#8230;tedy, ehm, Facebook <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  Cassandra je totiž zopensourcovatělé jádro Facebooku, ale dnes ji používá i Twitter a další služby.<br />
Implementace v Javě určila i ekosystém okolo těchto úložišť, takže prakticky všechny nástroje a knihovny okolo jsou také implementovány v Javě. A zde vyvstává otázka jak komunikovat s úložištěm z .NETu. Protože celá komunikace probíhá přes síť, není to nic složitého. Mnozí by očekávali nějaký známý protokol jako <a href="http://en.wikipedia.org/wiki/SOAP">SOAP</a> nebo <a href="http://en.wikipedia.org/wiki/OData">OData</a>, ale Cassandra i HBase používají (IMHO mezi .NET komunitou zcela neznámý) Thrift.</p>
<p><a href="http://en.wikipedia.org/wiki/Thrift_(protocol)">Thrift</a> je síťový binární protokol pro <a href="http://en.wikipedia.org/wiki/Remote_procedure_call">RPC</a>, který je ale i přes svou binárnost otevřený k rozšíření (není nutné se vázat na jednu verzi služby). Thrift ale není jen definice protokolu. Thrift dále přináší vlastní <a href="http://en.wikipedia.org/wiki/Interface_description_language">IDL</a> (jazyk pro popis rozhraní služby), který umí dodávané nástroje transformovat do mnoha jazyků (C# nevyjímaje). Takže spolu s Cassandrou si stáhneme Thrift API a z toho si nagenerujeme klientské třídy v C#. Je to tedy stejný postup, jako když z WSDL generujeme třídy pro komunikace přes SOAP.</p>
<p>API Cassandry není moc bohaté a vlastně nám umožňuje jen vybírat hodnoty podle klíčů a hodnoty ukládat. Více v <a href="http://wiki.apache.org/cassandra/API06">dokumentaci</a>.</p>
<h2>Datový model</h2>
<p>Nejvyšší úrovní dělení je tzv. <em>KeySpace</em> (~databáze), který obsahuje <em>ColumnFamilies</em> (~tabulky). Každá <em>ColumnFamily</em> obsahuje řádky, které jsou identifikovány pomocí klíče. Každý řádek může obsahovat libovolný počet sloupců. Každý sloupec (identifikovaný jménem) má přiřazenu hodnotu a timestamp (který dodává aplikace!). Hodnotou sloupce nemusí být jen <em>byte[]</em>, ale opět to může být další <em>Map</em>a &#8211; pak mluvíme o tzv. <em>SuperColumn</em>.<br />
Datový model pro programátory:<br /><em>Map&lt;byte[], Map&lt;byte[], Map&lt;byte[], Tuple&lt;byte[], TimeStamp&gt;&gt;&gt;&gt;</em>.<br />
Neboli:
<ul>
<li>KeySpace name (typicky string) -> ColumnFamilies</li>
<li>ColumnFamily name (typicky string) -> Rows</li>
<li>Row key (byte[]) -> Columns</li>
<li>Column name (string) -> ColumnValue (byte[], timestamp)</li>
</ul>
<p>Často se datový model vysvětluje (a je to tak přesnější) tak, že se obrátí <em>ColumnFamily</em> a řádek, tedy že řádek obsahuje ColumnFamilies.<br />
Důležité je, že v konfiguraci se nastavují pouze KeySpaces a ColumnFamilies. Všechno ostatní je variabilní a může se to měnit &#8211; a to na každé úrovni. To mj. znamená, že každý řádek může mít libovolný počet sloupců a u každého řádku mohou být sloupce úplně jiné.<br />
Data jsou fyzicky setříděná podle klíčů a sloupce také seřazeny podle názvů. Protože se všude pracuje s blobama <em>byte[]</em>, máme možnost definovat, jakým způsobem se má třídit.</br><br />
Velmi pěkný popis datového modelu Cassandry naleznete <a href="http://arin.me/blog/wtf-is-a-supercolumn-cassandra-data-model">v tomto článku</a>.</p>
<p>Jak jsem psal, Cassandří API je poměrně jednoduché a tak Vás možná napadne, že vybírání hodnot jen podle klíčů není dostatečné. A je to možné! Opravdu Vaše aplikace nemusí být vůbec vhodná pro nasazení na NOSQL úložišti. Ale i tak je vybírání podle klíčů poněkud svazující a proto byla ve verzi Cassandry 0.6 přidána <a href="http://wiki.apache.org/cassandra/HadoopSupport">podpora pro Hadoop</a>.</p>
<h2>Hadoop</h2>
<p><a href="http://en.wikipedia.org/wiki/Hadoop">Hadoop</a> je v Javě napsaný open-source framework pro psaní spolehlivých, škálovatelných a distribuovaných výpočtů. Sestává se z několik částí, přičemž nás bude zajímat hlavně <a href="http://hadoop.apache.org/mapreduce/">MapReduce</a>, což je implementace <a href="http://en.wikipedia.org/wiki/MapReduce">MapReduce</a> algoritmu. To je zjednodušeně řečeno algoritmus, který nám umožní položit dotazy, které se dají snadno paralelizovat.<br />
Tento Map/Reduce se pak typicky využívá nad NOSQL úložištěm <a href="http://hadoop.apache.org/hbase/">HBase</a> (další část Hadoopu), které je postavené nad distribuovaným file systémem <a href="http://hadoop.apache.org/hdfs/">HDFS</a> (také součást Hadoopu).</p>
<p>Když chceme zadat nějakou Map/Reduce úlohu, musíme předat do <em>jobtracker</em>u <a href="http://en.wikipedia.org/wiki/JAR_(file_format)">jar</a>, který obsahuje třídy implementující rozhraní <a href="http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/mapreduce/Mapper.html">Mapper</a> a <a href="http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/mapreduce/Reducer.html">Reducer</a>.<br />
Pokud chceme dělat něco jednoduchého a nechce se nám kódit v Javě, můžeme použít <a href="http://hadoop.apache.org/common/docs/r0.15.2/streaming.html#Hadoop+Streaming">Hadoop Streaming</a>, což není nic jiného než konkrétní implementace Mapperu a Reduceru, která volá námi zadaný program a komunikuje s ním přes stdin/stdout. Konkrétně to funguje tak, že do Mapperu, resp. Reduceru, přichází řádky oddělené znakem nového řádku. Na řádku je nejprve klíč následovaný tabulátorem. Zbytek do konce řádku je hodnota.<br />
Na jednoduché věci to určitě stačí, ale pokud chceme absolutní svobodu, pak musíme sáhnout po <a href="http://hadoop.apache.org/common/docs/r0.20.2/api/org/apache/hadoop/mapred/pipes/package-summary.html">Hadoop Pipes</a>. Jeho základem je opět implementace Mapperu a Reduceru, která tentokrát volá tenký wrapper v C++ (přes sockety). S tímto wrapperem je už možné komunikovat z téměř jakéhokoliv jazyka, protože je pro něj dostupné <a href="http://www.swig.org/">SWIG rozhraní</a> (něco jako Thrift, ale funguje to <em>lokálně</em>). Takže díky tomuto můžeme psát Map/Reduce funkce v jakém jazyce chceme.</p>
<p>Psaní Map/Reduce dotazů se nám může ale pěkně zkomplikovat, zvláště když dotazy vyžadují více iterací. Pak můžeme sáhnout po projektu <a href="http://hadoop.apache.org/pig/">Pig</a> (součást Hadoopu), který nám umožní zapsat dotazy v jazyce <a href="http://hadoop.apache.org/pig/docs/r0.6.0/cookbook.html">Pig Latin</a> (ne nepodobný Linqu). Pig Front-end zadaný dotaz naparsuje, zoptimalizuje a vytvoří <a href="http://hadoop.apache.org/pig/javadoc/docs/api/org/apache/pig/impl/logicalLayer/LogicalPlan.html">LogicalPlan</a>, který popisuje, jak by se měl daný skript spustit. O samotné vykonání se pak postará Pig Back-end. Nyní existují dvě implementace Pig Back-endu &#8211; nad lokálním úložištěm (méně zajímavé) a nad Map/Reduce (obsahuje imlementaci Mapperu a Reduceru).<br />
Abychom tedy mohli napsat Map/Reduce dotaz, nemusíme tedy nutně psát kód v Javě, ale místo toho předáme jen string obsahující skript v jazyce Pig Latin.</p>
<p>Podobný účel jako Pig má také projekt <a href="http://wiki.apache.org/hadoop/Hive">Hive</a>, který přináší ještě vyšší stupeň abstrakce a umožňuje dotazovat do <em>libovolného</em> úložiště (pomocí jazyka <em>QL</em>), jehož strukturu jsme schopni popsat (musíme tedy zavést nad úložištěm strukturu). Hivem se ale nebudu teď zabývat, protože ještě není v <em>production quality</em>.</p>
<h2>Shrnutí</h2>
<p>Jak tedy pracovat s Cassandrou z .NET? Pokud si vystačíme s API, které nám nabízí Cassandří Thrift, pak si stačí nagenerovat třídy pro C# a máme vystaráno. Pokud Vám připadá Thriftové rozhraní příliš low-level, jsou k dispozici i <a href="http://wiki.apache.org/cassandra/ClientOptions">nějaké nadstavby</a> (třeba connection pooling je dobrý nápad).</p>
<p>Pokud chceme provádět Map/Reduce operace, je situace složitější, protože v jádru jde vždy o Javu.<br />
Můžeme mít např. jednoduchou web-service, do které budeme posílat <em>jar</em>y s Mapperem a Reducerem. Nebo můžeme mít na serveru předpřipravené <em>jar</em>y a modifikovat soubor s parametry uložený uvnitř nich (je to jen <em>zip</em>).<br />
Další možností je posílat do naší webové služby pouze dotazy v jazyce <em>Pig Latin</em> &#8211; pak už jsme blízko klasické situaci, kdy na SQL server posíláme dotazy v SQL.</p>
<p>Pokud se někdo rozhodne nasadit Cassandru na svůj projekt, měl by se nejprve důkladně obeznámit s jejím datovým modelem a zjistit, jestli bude mít k dispozici věci, které potřebuje a třeba je považuje za samozřejmost (díky SQL světu). Není to všespásný zlatý grál a nehodí se na všechny typy projektů.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/cassandra-ocima-net-programatora/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Architektura Modelu</title>
		<link>http://www.augi.cz/programovani/architektura-modelu/</link>
		<comments>http://www.augi.cz/programovani/architektura-modelu/#comments</comments>
		<pubDate>Sat, 01 May 2010 14:46:07 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=420</guid>
		<description><![CDATA[V moderních aplikacích na platformě .NET se začínají prosazovat nejrůznější návrhové vzory, což jistě přispívá nejen k lepšímu návrhu aplikací, ale i ke snadnější komunikaci mezi vývojáři. Dosud jsem blogoval především o návrhovém vzoru, který se týkal pouze návrhu Prezentace &#8211; Model-View-Controller. Existují ale i jiné prezentační vzory, také Model-View-Presenter a jeho klony se těší [...]]]></description>
			<content:encoded><![CDATA[<p>V moderních aplikacích na platformě .NET se začínají prosazovat nejrůznější návrhové vzory, což jistě přispívá nejen k lepšímu návrhu aplikací, ale i ke snadnější komunikaci mezi vývojáři. Dosud jsem blogoval především o návrhovém vzoru, který se týkal pouze návrhu Prezentace &#8211; <a href="http://en.wikipedia.org/wiki/Model-view-controller">Model-View-Controller</a>. Existují ale i jiné <em>prezentační</em> vzory, také <a href="http://en.wikipedia.org/wiki/Model-view-presenter">Model-View-Presenter</a> a jeho klony se těší velké popularitě (např. v ASP.NET WebForms a WPF/Silverlightu). Tyto návrhové vzory ale neřeší návrh celé aplikace, řeší jen Prezentaci. Zbytek aplikace je nazajímá &#8211; ten schovávají za písmenko <strong>M</strong> &#8211; <strong>Model</strong>. Za Model se tedy v tomto případě považuje vše, co není Prezentace (front-end), tedy back-end. A právě návrhu Modelu (back-endu) bych se chtěl v tomto článku (a následujících) věnovat.</p>
<p>	<span id="more-420"></span></p>
<h2>Třívrstvá architektura</h2>
<p>Po dlouhá léta byla standardem pro dobře navrženou aplikaci (aspoň já jsem to tak vnímal) klasická třívrstvá architektura, kterou má téměř každý vývojář tak nějak zažitou.<br />
	
<div style="text-align: center;"><img src="http://www.augi.cz/wp-content/uploads/architektura-modelu-trivsrtva-klasicka.png" alt="klasická třívrstvá architektura" title="klasická třívrstvá architektura" width="247" height="164" class="aligncenter size-full wp-image-422" /></div>
<p>
	Podívejme se blíže na závislosti, které máme mezi jednotlivými vrstvami. Prezentační vrstva je závislá na business vrstvě. To je legitimní závislost, protože by nám ve většině případů neměl návrh uživatelského rozhraní zásadně ovlivňovat business vrstvu. Proč? Například kvůli možnosti zavedení nové prezentační vrstvy. Závislost tímto směrem a striktní oddělení nám tedy umožňuje snadno vyvinout novou prezentační vrstvu (např. vedle webového rozhraní budeme chtít s naší aplikací komunikovat také přes webové služby).</p>
<p>Druhá šipka nám říká, že business vrstva je závislá na přístupu k datům. I toto má zdánlivě svou logiku&#8230;ale je opravdu způsob uložení dat ta nejdůležitější část naší aplikace? Není srdcem naší aplikace spíše business logika? Často ano! A tím jsme právě vyslovili jednu ze základních myšlenek <a href="http://en.wikipedia.org/wiki/Domain-driven_design">Domain Driven Design</a> (tím se ale zatím zaobírat nebudu). Protože je tedy business logika to nejdůležitější, proč by měla záviset na přístupu k datům, proč by se měla přizpůsobovat? Ať se radši přizpůsobí DAL! Obraťme tedy zmiňovanou závislost.<br />
	
<div style="text-align: center;"><img src="http://www.augi.cz/wp-content/uploads/architektura-modelu-trivsrtva-lepsi.png" alt="lepší třívrstvá architektura" title="lepší třívrstvá architektura" width="245" height="165" class="aligncenter size-full wp-image-423" /></div>
<p>
	Pokud Vás předchozí odstavec nepřesvědčil, že by mohlo být vhodné obrátit závislost mezi BL a DAL, přistupme k situaci praktičtěji.<br />
	DAL neví zhola nic o naší business vrstvě. Je to tedy nějaká víceméně univerzální knihovna pro přístup k datům. Když pracujeme třeba s nějakou relační databází a chceme udělat nějaký krutopřísně rychlý dotaz, občas se nevyhneme tomu, že jsme nuceni napsat třeba nějaký specifický SQL dotaz. A kam ho zapíšeme? No přece do business logiky! Do DAL ho zapsat nemůžeme, protože ten přece o BL nic neví &#8211; DAL je univerzální knihovna, kterou používáme klidně ve více nesouvisejících projektech. Takže abychom dosáhli lepšího výkonu, máme nějaký specifický SQL dotaz v BL &#8211; nesmrdí Vám to? Nechtělo by to přehodnotit návrh (závislosti) ?<br />
	Dalším argumentem pro obrácení závislosti <em>může</em> být to, že ve stávajícícm návrhu nejsme schopni jednoduše vyměnit DAL. Aplikace totiž přistupuje pouze k BL a nemá nad DAL kontrolu (ten je skryt za BL). Jednoduchá výměna DAL se nám může hodit nejen v případě migrace na jiné úložiště, ale také v případě psaní unit testů.</p>
<h2>Jiný pohled</h2>
<p>Pokud člověk ve firmě vyvíjí jedinou aplikaci a nemá tak potřebu sdílet DAL mezi nesouvisejícími aplikacemi, tak už možná tuto závislost obrátil, protože DAL přizpůsobil business layeru a dopsal do něj (do DALu) nějaký ten krutopřísný specifický dotaz. Je dobré si uvědomit, že tímto je zavedena závislost DALu na BL. A pokud nemáme interface DALu oddělený od implementace, tak tu máme <em>krásnou</em> kruhovou závislost &#8211; DAL je přizpůsoben na míru BL a BL používá konkrétní implementaci DALu. Jinými slovy, jeden bez druhého nemůže existovat a z jistého pohledu máme provázánou business vrstvu a konkrétní přístup k datům.</p>
<p>Obraťme tedy závislost mezi BL a DAL (který jsem přejmenoval na Persistence) a koukněme se, co z toho pro nás vyplývá &#8211; především to, že si BL může diktovat, jak má vypadat vrstva <abbr title="nestandardizovaný pojem zavedený pro účely tohoto článku">Persistence</abbr>. V praxi to znamená, že <em>Persistence</em> nyní nemusí být (jako DAL) obecná knihovna pro přístup k datům (ale může z takové knihovny vycházet!), ale je to knihovna, která posluhuje BL a přizpůsobuje se jí. Rozhraní <em>IPersistence</em> tedy může vypadat třeba nějak takto:
<pre class="brush: csharp">public interface IBlogPersistence
{
  IEnumerable&lt;Article> GetArticles();
  void AddArticle(Article article);
  void UpdateArticle(Article article);
  void RemoveArticle(Article article);
  IEnumerable&lt;Comment> GetArticleComments(Article article);
  IEnumerable&lt;Article> GetArticlesWithComments();
}</pre>
<p>Jak vidno, toto není rozhraní univerzální knihovny pro přístup k datům. Nějaká knihovna pro přístup k datům (třeba <a href="http://en.wikipedia.org/wiki/ADO.NET_Entity_Framework">Entity Framework</a>, <a href="http://en.wikipedia.org/wiki/LINQ_to_SQL">Linq2Sql</a>, <a href="http://en.wikipedia.org/wiki/NHibernate">NHibernate</a>, &#8230;) ale může být použita pro implementaci výše uvedených metod. To už je ale implementační detail, který je skryt za rozhraním.<br />
	Je zřejmé, že nyní můžeme ve vrstvě <em>Persistence</em> pěkně tunit třeba svoje SQL dotazy bez toho, aniž bychom si zašpinili BL. BL totiž zná pouze interface vrstvy <em>Persistence</em>.<br />
	Jedním z prvků <a href="http://en.wikipedia.org/wiki/Solid_%28Object_Oriented_Design%29">SOLID</a>ní architektury je <a href="http://en.wikipedia.org/wiki/Open/closed_principle">Open/closed princip</a> (btw. <a href="http://ca.wikipedia.org/wiki/Principi_open/closed">verze v katalánštině</a> <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ), který říká, že rozhraní by mělo být <em>otevřené k rozšíření</em> ale <em>uzavřené ke změnám</em>. Pokud je tedy předpoklad, že se budou požadavky na Persistence měnit a museli bychom tedy měnit interface <em>IPersistence</em> (přidávat metody), může být vhodné použít nějaký přístup, který nám umožní psát další dotazy proti Persistence aniž bychom měnili jeho interface. Toto řeší tzv. <a href="http://rarous.net/weblog/377-domenove-dotazy.aspx">doménové dotazy</a>, což je tedy způsob, jak se dostatečně obecně dotazovat do Persistence (jak mu předat dotaz). Když chceme implementovat doménové dotazy, můžeme vytvořit třeba množinu tříd, které pro nás dostatečně popíšou požadované dotazy. Zde může být dobrým nápadem použít něco již existujícího, třeba Linq. Ano, mířím tím k tomu, že dobrou výchozí implementací Persistence může být <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx">DataContext</a> z Linq2Sql nebo <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx">ObjectContext</a> z Entity Frameworku. Avšak mysleme stále na to, že tyto konkrétní frameworky jsou jen implementační detail, který je skryt kdesi v hloubi implementace IPersistence.<br />
	Jen bych dodal, že Linqem se nikterak neomezujeme jen na relační databáze nebo dokonce jen na Ms Sql &#8211; pomocí Linqu se lze dotazovat do CSV souborů, do leckterých NOSQL databází nebo do čeho chceme &#8211; nikdo nám nebrání nepsat si vlastní Linq provider. Omezujeme se tedy jen na to, že persistentní vrstva si musí umět poradit s Linqem (příp. jeho podmnožinou).</p>
<h2>Implementace závislostí</h2>
<p>Pro lepší pochopení zde přikládám diagram, který znázorňuje celou architekturu aplikace.<br />
	
<div style="text-align: center;"><a href="http://www.augi.cz/wp-content/uploads/architektura-modelu-prvni.png"><img src="http://www.augi.cz/wp-content/uploads/architektura-modelu-prvni-239x300.png" alt="architektura aplikace" title="architektura aplikace" width="239" height="300" class="aligncenter size-medium wp-image-421" /></a></div>
<p>
	Jádrem naší aplikace jsou tedy nějaké business objekty, které se <em>nějak</em> persistují pomocí rozhraní <em>IPersistence</em> &#8211; to je jedna assembly. Důležité je, že o použité implementaci <em>IPersistence</em> nerozhoduje BL (protože ta ani žádnou implementaci nezná), ale konkrétní implementaci musíme do BL <em>nějak</em> dodat (injektovat) při použití z aplikace &#8211; např. přes parametr konstruktoru.<br />
	Dále je třeba rozhraní <em>IPersistence</em> někde implementovat. Můžeme mít třeba dvě implementace (ve dvou různých assembly) &#8211; <em>MsSqlPersistence</em> (pracuje proti MS Sql) a <em>MockPersistence</em> (pro účely unit testů).</p>
<p>Když pak máme nějakou aplikaci (třeba webové GUI), tak si musíme v Controlleru/Presenteru vytvořit instanci BL, tzn. musíme to něj strčit (injektnout) nějakou konkrétní implementaci <em>IPersistence</em> a pak už můžeme s BL vesele pracovat (a BL používá nainjectovanou implementaci IPersistence).<br />
	Slovem <em>injektnout</em> v předchozích větách jsem se snažil naznačit, že může být velmi vhodné mít závislosti vyřešené přes <a href="http://www.augi.cz/programovani/iocdi-v-net/">Dependency Injection</a>. Pak nám stačí při startu webové aplikace nakonfigurovat kontejner tak, aby nám pro rozhraní <em>IPersistence</em> vracel instanci třídy <em>MsSqlPersistence</em> (v unit testech obdobně) &#8211; pak se nám kontejner sám postará o to, že při vytváření instance BL nám do něj přes konstruktor nainjectuje nakonfigurovanou implementaci rozhraní <em>IPersistence</em>.</p>
<h2>Závěr</h2>
<p>Zde prezentovaná architektura aplikace jistě není ideální a nemusí být ani vhodná pro každou aplikaci, ale myslím, že je lepší než klasický třívrstvý návrh. Rozhodně by si zasloužila další vylepšení, ale to by bylo na mnoho dalších článků. Proto tento článek neberte jako dogma a finální řešení, jak se mají dělat aplikace &#8211; berte ho jako návod na možné řešení problémů, se kterými se můžete ve Vaší aplikaci setkat.<br />
	V případných dalších článcích by se rád posunul v návrhu dále, konkrétně trošku směrem k DDD. Úmyslně jsem tu nechtěl hned vybalit DDD, protože se jedná o poměrně rozsáhlou záležitost plnou nových pojmů a myšlenek, které jsem ještě ne zcela vstřebal a přijal za své (co jsem četl, tak 3 roky studia a aplikace DDD na 3 projektech je dobrý základ pro základní pochopení DDD) a proto si netroufám v tomto směru zatím dále edukovat. Cílem článku je pouze ukázat čtenáři jinou cestu a trošku se zamyslet nad dogmatem klasické třívrstvé architektury aplikace (která nemusí být v každé situaci vhodná).</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-modelu/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>IoC/DI v .NET</title>
		<link>http://www.augi.cz/programovani/iocdi-v-net/</link>
		<comments>http://www.augi.cz/programovani/iocdi-v-net/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 10:28:21 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=419</guid>
		<description><![CDATA[V poslední době se hodně mluví a píše o moderních programovacích technikách (TDD, DDD) a o s nimi souvisejících technologiích. Mezi ně patří i poněkud konstrbatá zkratka IoC/DI &#8211; Inversion of Control/Dependency Injection, na kterou se podíváme v tomto článku. Předem podotýkám, že je článek některé skutečnosti zjednodušuje a slouží především jako úvod do problematiky.

Inversion [...]]]></description>
			<content:encoded><![CDATA[<p>V poslední době se hodně mluví a píše o moderních programovacích technikách (<a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a>, <a href="http://en.wikipedia.org/wiki/Domain-driven_design">DDD</a>) a o s nimi souvisejících technologiích. Mezi ně patří i poněkud konstrbatá zkratka IoC/DI &#8211; <a href="http://en.wikipedia.org/wiki/Inversion_of_Control">Inversion of Control</a>/<a href="http://en.wikipedia.org/wiki/Dependency_Injection">Dependency Injection</a>, na kterou se podíváme v tomto článku. Předem podotýkám, že je článek některé skutečnosti zjednodušuje a slouží především jako úvod do problematiky.<br />
<span id="more-419"></span></p>
<h2>Inversion of Control</h2>
<p>Vzpomínám si, že už před lety jsem někde četl, že by se mělo programovat proti interfacům, ne proti konkrétním třídám. <em>Inversion of Control</em> myšlenku programování proti rozhraním mohutně používá a v jistých ohledech dotahuje do konce. V případě IoC de facto nevytváříme aplikaci jako monolit, ale jako sadu komponent, které implementují různá rozhraní. Tyto komponenty s okolním světem opět komunikují opět pouze pomocí rozhraní, bez závislosti na konkrétních implementacích. Komponenta tak řeší opravdu jen svoje <em>problémy</em>, nestará se o okolní komponenty.<br />
Aplikaci pak vdechneme život tím, že určíme, jak propojit komponenty do fungující aplikace.<br />
Rozbití aplikace na komponenty (rozhraní), jejichž konkrétní implementace (třídy) lze jednoduše vyměnit, je velmi užitečná vlastnost. Můžeme díky tomu jednoduše sestavit více podobných aplikací, které se liší např. tím, odkud načítají data (MySql, MsSql, soubor, webová služba, &#8230;). V případě testování je pak snadná výměna komponent aplikace k nezaplacení.</p>
<p>Klíčové je, že pracujeme s rozhraními a téměř nikde by se tak nemělo vyskytovat klíčové slovo <em>new</em>, protože tím bychom se fixovali na nějakou konkrétní implementaci. S IoC tento úkol delegujeme na tzv. IoC kontejner. To je třída, která ví, jak <strong>získat instanci třídy</strong>, která implementuje dané rozhraní. Rozhraní IoC kontejneru může tedy vypadat nějak takto:</p>
<pre class="brush: csharp">public interface IIoCContainer
{
  TService GetInstance&lt;TService>();
}</pre>
<p>Takže místo <em>ICar c = new Car()</em> nyní voláme třeba <em>ICar c = OurContainer.Current.GetInstance&lt;ICar>()</em>.</p>
<p>Různé IoC kontejnery ale mají různá rozhraní a proto by případný přechod na jiný (lepší) IoC kontejner znamenal v lepším případě udělat replace přes celý projekt (např. &#8220;<em>OurContainer.Current.GetInstance</em>&#8221; -&gt; &#8220;<em>BetterContainer.Instance.GetNewInstance</em>&#8220;). To je samozřejmě fuj, ale problém řeší projekt <a href="http://commonservicelocator.codeplex.com/">CommonServiceLocator</a>, který přináší jednotné rozhraní pro nejrozšířenější IoC kontejnery. Ono rozhraní má sice více metod, ale de facto se jedná jen o overloady metody <em>GetInstance</em> z výše uvedeného rozhraní &#8211; <a href="http://commonservicelocator.codeplex.com/sourcecontrol/network/Show?projectName=CommonServiceLocator&#038;changeSetId=27688#332676">podívejte se sami</a>. Btw. <em>CommonServiceLocator</em> se tak jmenuje proto, že se jedná o implementaci návrhového vzoru <a href="http://en.wikipedia.org/wiki/Service_locator_pattern">Service locator</a>, což je takový centrální bod aplikace.</p>
<p>Kontejner je třeba (typicky na začátku programu, při startu webové aplikace apod.) patřičně <strong>nakonfigurovat</strong>, aby věděl, jak získávat implementace požadovaných rozhraní. Každý IoC kontejner má různé možnosti konfigurace a vytvoření jednotného rozhraní pro konfiguraci by znamenalo, že se zbytečně omezíme (protože hledáme průnik). Ale k vytvoření jednotného rozhraní pro konfiguraci kontejneru ani není motivace &#8211; konfigurace je totiž obvykle jen v pár souborech, takže není takový problém ji přepsat.<br />
Syntaxe konfigurace je tedy pro každý IoC kontejner unikátní a bývá uvedena buď v kódu nebo v nějakém konfiguračním souboru. Konfigurace kontejneru v kódu může vypadat např. takto:</p>
<pre class="brush: csharp">myContainer.Register&lt;ICar, Car>();</pre>
<p>Tady říkáme, že pokud někdo bude chtít rozhraní <em>ICar</em>, má se použít třída <em>Car</em>.</p>
<p>V praxi se setkáváme s různými požadavky na životnost objektů &#8211; vždy nechceme, aby nám metoda <em>GetInstance</em> vrátila novou instanci. Např. můžeme chtít, aby ve webové aplikaci objekt žil po celou dobu jednoho požadavku, tedy aby metoda <em>GetInstance</em> vracela v průběhu jednoho požadavku stále tutéž instanci. Nebo můžeme chtít, aby se vracela tatáž instance v průběhu celého programu (tedy singleton). Všechno tohle kvalitní IoC kontejnery umí. Základem je ale schopnost konfigurace a získání instance implementující dané rozhraní.</p>
<h2>Dependency Injection</h2>
<p>IoC kontejner většinou funguje tak, jak jsem popsal &#8211; řekneme mu, jaká třída implementuje jaké rozhraní (což by si btw. mohl zjistit pomocí reflexe sám, ale to může vést na nejednoznačnosti). Většinou ale explicitně neříkáme, jak konkrétně se má daná třída vytvořit &#8211; s tím se musí kontejner nějak vypořádat sám. Pokud by Vás zajímalo, co se může dít uvnitř, mrkněte na <a href="http://www.augi.cz/programovani/vytvareni-instanci-predem-neznamych-trid-v-c/">můj článek</a> o vytváření instancí v době kompilace (v době kompilace IoC kontejneru!) neznámých typů za běhu.<br />
Pokud má třída bezparametrický konstruktor, tak je to úloha poměrně snadná. Ale co když má konstruktor nějaké parametry? Pak přichází ke slovu tzv. <em>constructor injection</em>. Kontejner si zjistí, jaké parametry jakých typů konstruktor má. Konkrétní hodnoty parametrů pak získá tak, že &#8220;zavolá <em>GetInstance&lt;TParameter&gt;</em> sám na sebe&#8221;. Pak již nic nebrání tomu zavolat konstruktor se správnými parametry.<br />
Dále se používá ještě <em>setter injection</em>, kdy se IoC kontejner postará po vytvoření objektu ještě o přiřazení správné hodnoty do property, která má public <em>setter</em> (a samozřejmě i nějaký <em>getter</em>).</p>
<h2>Praxe</h2>
<p>Dejme tomu, že máme auto, které má motor, a chceme nastartovat <em>nějaké</em> auto s <em>nějakým</em> motorem:</p>
<pre class="brush: csharp">public interface IEngine
{
  void Start();
}

public interface ICar
{
}

public class Engine : IEngine
{
  public void Start()
  {
    Console.WriteLine("engine started");
  }
}

public class Car : ICar
{
  public Car(IEngine engine)
  {
     engine.Start();
  }
}

public static class Bootstrapper
{
  public static void Run()
  {
    // vytvoreni kontejneru
    var container = new OurContainer();

    // propojeni naseho IoC kontejneru na Service locator
	// using Microsoft.Practices.ServiceLocation;
    ServiceLocator.SetLocatorProvider(c => container);

    container.Register&lt;ICar, Car>();
    container.Register&lt;IEngine, Engine>();
  }
}

public static class Application
{
  public static void Main()
  {
    Bootstrapper.Run(); // konfigurace

    // kontejner vi, ze ma pouzit tridu Car
    // take vi, ze rozhrani IEngine implementuje trida Engine
	// using Microsoft.Practices.ServiceLocation;
    ICar c = ServiceLocator.Current.GetInstance&lt;ICar>();
  }
}</pre>
<p>Je to velmi jednoduché &#8211; registraci provedeme pomocí metody <em>Register</em>, získání instance pak pomocí metody <em>GetInstance</em>.</p>
<p>V praxi je na výběr z mnoha IoC/DI kontejnerů. Mezi nejznámější patří <a href="http://unity.codeplex.com/">Unity</a> (přímo od Microsoftu), <a href="http://www.castleproject.org/container/index.html">Microkernel a Windsor Container od Castle</a>, <a href="http://www.springframework.net/">Spring.NET</a>, <a href="http://structuremap.github.com/structuremap/index.html">StructureMap</a>, <a href="http://code.google.com/p/autofac/">Autofac</a>, <a href="http://ninject.org/">Ninject</a>, <a href="http://docs.codehaus.org/display/PICO/Home">PicoContainer.NET</a>&#8230;<br />
Ale není nic extrémně složitého vytvořit si vlastní jednoduchý IoC(/DI) kontejner, takže pojďme na to:</p>
<pre class="brush: csharp">public class OurContainer
{
  // mapovani z typu (nejcasteji rozhrani) na metodu, ktera vraci instanci implementujici dane rozhrani
  private readonly Dictionary&lt;Type, Func&lt;OurContainer, object>> _TypeCreators = new Dictionary&lt;Type, Func&lt;OurContainer, object>>();

  // registace typu
  public void Register(Type type, Func&lt;OurContainer, object> creator)
  {
    _TypeCreators[type] = creator;
  }

  // vraceni instance
  public object GetInstance(Type type)
  {
     return _TypeCreators[type](this);
  }

  // genericke varianty predchozich
  public void Register&lt;T>(Func&lt;OurContainer, object> creator)
  {
    Register(typeof(T), creator);
  }

  public T GetInstance&lt;T>()
  {
    return (T)GetInstance(typeof(T));
  }  

}</pre>
<p>Jádrem našeho řešení je to, že pro každý typ (interface) máme přiřazeného delegáta, který umí vytvořit instanci třídy implementující dané rozhraní.<br />
Tento náš kontejner můžeme nakonfigurovat tímto způsobem:</p>
<pre class="brush: csharp">var container = new OurContainer();
container.Register&lt;IEngine>(c => new Engine());
container.Register&lt;ICar>(c => new Car(c.GetInstance&lt;IEngine>()));</pre>
<p>Zajímavý je poslední řádek &#8211; konstruktor třídy <em>Car</em> vyžaduje jeden parametr typu <em>IEngine</em>, takže při volání musíme nějak získat instanci třídy implementující toho rozhraní. A není nic krásnějšího než k této úloze použít &#8220;<em>rekurzivně</em>&#8221; IoC kontejner.</p>
<p>Nyní tedy máme k dispozici IoC kontejner, který sice neumí DI, automatické vytváření instancí (dodáváme delegáta, který se o to postará), ani některé další vymoženosti (např. řízení životnosti objektů), ale přesto může být užitečný (už jen proto, že to není žádný zbytečně přebujelý moloch).<br />
Pojďme dále implementovat automatické vytváření instancí, včetně <em>constructor injection</em>:</p>
<pre class="brush: csharp">public void Register&lt;T, TImplementation>()
{
  // ziskame konstruktory implementujici tridy
  var ctors = typeof(TImplementation).GetConstructors();
  if (ctors == null || ctors.Length == 0)
  {
    throw new InvalidOperationException(string.Format(
	  "Appropriate constructor not found in type '{0}'.",
	  typeof(TImplementation).FullName));
  }
  var ctor = ctors[0]; // vezmeme prvni konstruktor

  // zkonstruujeme lambda expression, ktera vytvori instanci implementacni tridy
  // lambda ma jeden vstupni parametr typu OutContainer
  var containerParameter = Expression.Parameter(typeof(OurContainer), "container");
  var creator = Expression.Lambda(typeof(Func&lt;OurContainer, object>),
    Expression.New(ctor,
      ctor.GetParameters()
	  // pro kazdy parametr konstruktoru vygenerujeme volani GetInstance na kontejneru
	  .Select(p => (Expression)Expression.Call(containerParameter, "GetInstance", new[] { p.ParameterType }))),
      containerParameter);

  // zaregistrujeme zkompilovanou lambdu
  Register&lt;T>((Func&lt;OurContainer, object>)creator.Compile());
}</pre>
<p>Kód funguje tak, že si při registraci sestavíme lambda expression, kterou následně zkompilujeme a použijeme jako delegáta, který umí vytvořit třídu implementující dané rozhraní. Nic složitého.<br />
Konfigurace je nyní o poznáni pěknější:</p>
<pre class="brush: csharp">var container = new OurContainer();
container.Register&lt;IEngine, Engine>();
container.Register&lt;ICar, Car>();</pre>
<p>Tento náš IoC/DI můžeme dále vylepšovat. Např. podpora pro instance žijící během jednoho HTTP požadavku lze jednoduše implementovat pomocí kolekce <a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.current(v=VS.90).aspx">System.Web.HttpContext.Current</a><a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.items(v=VS.90).aspx">.Items</a>.<br />
Dalším logickým krokem by mohlo být upravení našeho kontejneru tak, abychom ho mohli použít pomocí <em>CommonServiceLocator</em>u &#8211; v tomto případě stačí odvodit naši třídu od abstraktní <a href="http://commonservicelocator.codeplex.com/sourcecontrol/network/Show?projectName=CommonServiceLocator&#038;changeSetId=27688#332684">ServiceLocatorImplBase</a> a implementovat dvě metody &#8211; <em>DoGetInstance</em> a <em>DoGetAllInstances</em>. To už ale jistě zvládnete sami <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </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/iocdi-v-net/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>JavaScript očima programátora v2</title>
		<link>http://www.augi.cz/programovani/javascript-ocima-programatora-v2/</link>
		<comments>http://www.augi.cz/programovani/javascript-ocima-programatora-v2/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 20:28:37 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=417</guid>
		<description><![CDATA[Najít na internetu článek nebo dokonce seriál, který by se systematicky zabýval JavaScriptem, není nic jednoduchého &#8211; převažují články, které ukáží, jak deklarovat proměnné, v lepším případě funkce, poví něco o datových typech a tím to většinou končí. Navíc většina článků je mířena na použití JavaScriptu v rámci prohlížeče. Zřejmě i takovýto nedostatek informací vedl [...]]]></description>
			<content:encoded><![CDATA[<p>Najít na internetu článek nebo dokonce seriál, který by se systematicky zabýval JavaScriptem, není nic jednoduchého &#8211; převažují články, které ukáží, jak deklarovat proměnné, v lepším případě funkce, poví něco o datových typech a tím to většinou končí. Navíc většina článků je mířena na použití JavaScriptu v rámci prohlížeče. Zřejmě i takovýto nedostatek informací vedl k tomu, že se z JavaScriptu stal jazyk, jenž je obestřen mnoha mýty, legendami a polopravdami, a mezi skutečnými programátory je značně neoblíben a/nebo nepochopen. Proto jsem se rozhodl sepsat tento článek, který představuje JavaScript z pohledu programátora, který je odkojen klasickými programovacími jazyky jako Pascal, C, C++, C# nebo Java. <strong>Článek představuje JavaScript jako univerzální jazyk, bez jakéhokoliv zaměření na nějakou konkrétní oblast nasazení (např. prohlížeče).</strong> Proč? Dnešní internet je plný rich internet aplikací, jejichž výkonnost je často limitována rychlostí JavaScriptu a proto bylo v posledních letech vynaloženo mnoho úsilí na to, aby JavaScript běhal co nejrychleji. Proto lze očekávat nasazení JavaScriptu i v non-browser úlohách, např. se nabízí použití JavaScriptu na server-side záležitosti &#8211; pak by mohla být celá RIA napsána v jednom jediném jazyce. Např. použití JavaScriptu v <a href="http://en.wikipedia.org/wiki/NoSQL">NoSql</a> databázi <a href="http://en.wikipedia.org/wiki/CouchDB">CouchDB</a> na psaní <a href="http://en.wikipedia.org/wiki/MapReduce">MapReduce</a> funkcí je již realitou.</p>
<p>    <span id="more-417"></span></p>
<h2>Úvod</h2>
<p>Co je JavaScript?<br />
    JavaSript je jedním z dialektů standardizovaného jazyka <a href="http://en.wikipedia.org/wiki/ECMAScript">ECMAScript</a>. Další používané dialekty jsou <a href="http://en.wikipedia.org/wiki/ActionScript">ActionScript</a> (bohatší syntaxe), <a href="http://en.wikipedia.org/wiki/JScript">JScript</a>, <a href="http://en.wikipedia.org/wiki/InScript">InScript</a> nebo <a href="http://en.wikipedia.org/wiki/QtScript">QtScript</a>. Ukázky v tomto článku jsou většinou otestovány v JavaScriptu verze 1.8, konkrétně implementaci <a href="http://en.wikipedia.org/wiki/SpiderMonkey_(JavaScript_engine)">SpiderMonkey</a>, což je vůbec první implementace JavaScriptu a využívá ji např. Firefox (i když dnes v optimalizované verzi TraceMonkey). Ke SpiderMonkey je také vynikají <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide">dokumentace</a>, kterou doporučuji strčit do záložek, pokud to myslíte s JavaScriptem vážně.<br />
	K dalšímu studiu jazyka doporučil přímo <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript specifikaci</a>, která je dostupná taky <a href="http://bclary.com/2004/11/07/">v praktické HTML verzi</a>.<br />
	Článek popisuje i některé techniky, které se nehodí pro použití na webu, protože je ne všechny současné prohlížeče podporují. Před začátkem vývoje konzultujte minimální verze podporovaných prohlížečů s <a href="http://www.robertnyman.com/javascript/">těmito</a> <a href="http://en.wikipedia.org/wiki/ECMAScript#Dialects">pěknými</a> <a href="http://en.wikipedia.org/wiki/ECMAScript#Version_correspondence">tabulkami</a>.</p>
<p>JavaScript je dynamický jazyk. Dynamičnost spočívá v tom, že nic nemá pevný typ (jde o slabě typovaný jazyk), objekty mohou během běhu programu měnit svoje atributy a je zde magická funkce <em>eval</em>, která spustí string.<br />
    JavaScript je funkcionální jazyk. Funkce lze do sebe libovolně vnořovat, přičemž vnější funkce tvoří uzávěr (<a href="http://en.wikipedia.org/wiki/Closure_(computer_science)">closure</a>) vnitřních funkcí.<br />
    JavaScript je objektově orientovaný, avšak beztřídní, jazyk &#8211; nemá třídy, jen objekty. Pro dědění se používají tzv. prototypy (JavaScript podporuje <a href="http://en.wikipedia.org/wiki/Prototype-based_programming">prototypovou dědičnost</a>).<br />
    JavaScript neumožňuje explicitní uvolnění paměti &#8211; o řízení paměti se stará Garbagge Collector.</p>
<p>Datové typy (tak, jak je lze získat pomocí operátoru <a href="http://bclary.com/2004/11/07/#a-11.4.3">typeof</a>):</p>
<ul>
<li><em>number</em> &#8211; číslo celé (<em>117</em>, <em>015</em> (oktalově), <em>0&#215;15</em> (hexa)) i desetinné (<em>3.14</em>, <em>3.14E-15</em>)</li>
<li><em>string</em> &#8211; textový řetězec, <em>&#8220;bla&#8221;</em> nebo <em>&#8216;bla&#8217;</em></li>
<li><em>boolean</em> &#8211; <em>true</em> nebo <em>false</em></li>
<li><em>undefined</em> &#8211; má jedinou hodnotu <em>undefined</em></li>
<li><a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a> &#8211; funkce</li>
<li><em>object</em> &#8211; objekt</li>
</ul>
<p>Kromě funkcí a objektů jsou to všechno primitivní typy, ale umí se <a href="http://en.wikipedia.org/wiki/Boxing_(computer_science)#Boxing">zaboxovat</a>.<br />
    Při porovnání hodnot máme dvě možnosti:</p>
<ul>
<li>Buď můžeme použít klasické <em>!=</em> a <em>==</em>, které v případě neshodnosti typů provede potřebné konverze. Takže např. <em>3 == &#8220;3&#8243;</em> je <em>true</em>.</li>
<li>Druhou možností je použití striktního porovnání <em>!==</em> a <em>===</em>, které neprovádí žádné konverze, takže <em>3 === &#8220;3&#8243;</em> je <em>false</em>.</li>
</ul>
<p>	Identifikátory v JavaScriptu jsou case sensitive (narozdíl třeba od ActionScriptu verze 1.0).
    </p>
<h2>Funkce</h2>
<p>Definice funkce může vypadat nějak takto:</p>
<pre class="brush: js">function secti(a, b) {
    var c = a + b; // lokalni promenna
    a += c;
    return a + b + c;
}</pre>
<p>Jedná se o slabě typovaný dynamický jazyk, takže typy parametrů ani návratové hodnoty se neuváději, vše se vyhodnocuje až za běhu. Pokud např. <em>a</em> a <em>b</em> budou stringy, bude se funkce chovat jinak než kdybychom použili čísla.<br />
    Při volání funkce můžeme zadat libovolný počet parametrů. Pokud nějaký definovaný parametr při volání neuvedeme, bude jeho hodnota <em>undefined</em>. Pokud jich bude více, můžeme se k nim dostat přes pole <a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments">arguments</a>, které obsahuje všechny předané parametry (má položku <em>length</em> a indexuje se klasicky od nuly hranatými závorkami). Všechny parametry se vždy předávají hodnotou, není zde žádná přímá podpora pro předání parametru odkazem.<br />
    Možnost neuvedení parametrů de facto znamená, že všechny parametry jsou volitelné. Když parametrům chceme přiřadit nějakou defaultní hodnotu, dělá se to často takto:</p>
<pre class="brush: js">function secti(a, b) {
    a = a || 0; // pokud je a undefined, null nebo prazdny retezec, priradi se do nej nula
    b = b || 0;
    var c = a + b; // lokalni promenna
    a += c;
    return a + b + c;
}</pre>
<p>Uvnitř funkce můžeme definovat lokální proměnné pomocí klíčového slůvka <em>var</em>, jak bylo ukázáno.</p>
<p>Výše ukázaný způsob zavedení funkce se nazývá <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/function">function declaration</a> (nebo také <em>function statement</em>) a můžeme ho poznat tak, že mezi <em>function</em> a otvírací závorkou je povinné jméno. Tento způsob zavedení funkce vytvoří funkci daného jména a automaticky ji přiřadí do proměnné stejného jména.<br />
	Jiným způsobem zavedení funkce je tzv. <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/function_Operator">function expression</a> (také <em>function operator</em>), který se pozná podle toho, že jméno funkce je v tomto případě nepovinné a zavedení funkce je součástí výrazu. To typicky znamená, že výsledek <em>function expression</em> přiřadíme do nějaké námi definované proměnné.</p>
<pre class="brush: js">var secti = function(a, b) {
    return a + b;
};
</pre>
<p>Nyní vytváříme anonymní funkci, kterou přiřazujeme do proměnné <em>secti</em>. Jméno funkce můžeme uvést i v tomto případě, ale na toto jméno se můžeme odkazovat jen z těla této funkce &#8211; odnikud jinud není vidět (hodí se tak např. pro rekurzi).</p>
<pre class="brush: js">var secti = function secti_blabla(a, b) { // jmeno funkce a promenne se nemusi shodovat
    return a + b; // jen tady je secti_blabla videt
};
</pre>
<p>Zjednodušeně řečeno můžeme říci, že <em>function statement</em> vytvoří funkci a automaticky i proměnnou stejného jména, naproti tomu <em>function expression</em> pouze vytvoří funkci a o uložení do nějaké proměnné se musíme postarat sami.</p>
<p>Každá funkce je zároveň objektem (konkrétně instancí třídy <a href=https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a>) a lze ji zavést (poslední, třetí, způsob) i takto: <em>new Function(&#8221;a&#8221;, &#8220;b&#8221;, &#8220;return a + b;&#8221;)</em><br />
    Poslední parametr je string nesoucí tělo funkce, všechny předchozí parametry jsou názvy parametrů funkce.</p>
<h3>Uzávěry</h3>
<p>Funkce lze do sebe libovolně vnořovat (tj. v těle funkce můžeme definovat další funkci). Důležité je vědět, že uzávěr tvoří vždy celá funkce, ne blok příkazů uzavřený ve složených závorkách, jak je to běžné např. v C#. Tam bychom napsali kód v následujícím smyslu a vše by fungovalo.</p>
<pre class="brush: js">for (var i = 0; i < poleObjektu.length; i++) {
  var item = poleObjektu[i];
  document.getElementById(item.id).onclick = function() {
    alert(item.name);
  }
}</pre>
<p>V JavaScriptu toto ale fungovat nebude, protože uzávěr se tvoří vždy jen na úrovni celé funkce, takže to, že <em>item</em> definujeme uvnitř těla cyklu, nám nepomůže (v C# ano).<br />
Od verze JavaScriptu 1.7 má náš problém snadné řešení - místo klíčového slova <em>var</em> použijeme nové klíčové slovo <a href="https://developer.mozilla.org/en/New_in_JavaScript_1.7#Block_scope_with_let">let</a>, které vytváří uzávěr na nižší úrovni než funkce.<br />
    Pokud jsme odkázáni pracovat s nižší verzí JavaScriptu, nezbývá nám než zajistit vytvoření další úrovně uzávěru - voláním další funkce v těle cyklu:</p>
<pre class="brush: js">function makeAlertFunction(message) {
    return function() { alert(message); } // vracime funkci s uzaverem na funkci makeAlertFunction
}
for (var i = 0; i < poleObjektu.length; i++) {
    var item = poleObjektu[i];
    document.getElementById(item.id).onclick = makeAlertFunction(item.name);
}</pre>
<h2>Objekty</h2>
<p>Objekt je vlastně jen hash table, nese tedy dvojice <em>klíč - hodnota</em>. Hodnotou může být cokoliv, tedy i funkce. Položka se definuje prostým přiřazením: <em>obj.novaPolozka = 5;</em>. Pokud položka neexistuje, dostáváme při jejím čtení hodnotu <em>undefined</em>. K položkám se dá přistupovat dvěma způsoby:</p>
<pre class="brush: js">obj.polozka = 5;
obj["polozka"] = 5;</pre>
<p>Položku objektu lze i zrušit: <em>delete obj.polozka;</em></p>
<p>Nyní bych rád udělal menší vsuvku a zmínil jak vypadá běhové prostředí (kontext, ve kterém náš program běží). Je to děsivě jednoduché - vše je objekt (i primitivní objekty se umí zaboxovat) a vždy se nacházíme v kontextu nějakého objektu (k němuž máme přístup pomocí všudypřítomného readonly <em>this</em>). Pokud jsme na top-level úrovni, ukazuje <em>this</em> na globální objekt (v prohlížečích je to <a href="http://www.w3schools.com/jsref/obj_window.asp">window</a>). Celý program v JavaScriptu je pak vlastně tělo globální funkce.</p>
<p>Zpět k objektům. Jak vytvořit nový objekt?</p>
<ul>
<li>Anonymní objekt snadno - do složených závorek uzavřeme dvojice <em>jmeno : hodnota</em> a oddělíme je čárkami. Hodnota může být cokoliv, klidně další objekt nebo funkce (už víme, že funkce je objekt, konkrétně instance třídy <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a>):
<pre class="brush: js">var car = {
    name : "Honda",
    model : "Civic",
    owner : { name : "Jiri", surname : "Novak" },
    printMe : function() {
        return this.name + ' ' + this.model + ' owned by ' + this.owner.name + ' ' + this.owner.surname;
    }
};</pre>
<p>        Samozřejme můžeme vytvořit i prázdný objekt: <em>var empty = {};</em><br />
        Takovému způsobu zápisu objektu do složených závorek se říká <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Literals#Object_Literals">object literal</a> nebo <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Creating_New_Objects/Using_Object_Initializers">object initializer</a> a zápis je podobný jako v případě <a href="http://en.wikipedia.org/wiki/JSON">Jsonu</a>. Ale rozdíly tam jsou, např. v Jsonu nemůžeme logicky použít funkce, protože slouží pouze k přenosu dat, v Jsonu jsou u stringů povoleny jen dvojité uvozovky atp...<br />
        Pokud voláme funkci objektu (tedy metodu) <em>car.printMe();</em>, je před voláním metody do <em>this</em> přiřazeno <em>car</em>. Proto se metoda chová dle očekávání.</li>
<li>Voláním funkce prefixované klíčovým slovem <em>new</em> - takové funkce je slušné pojmenovat s prvním písmenem velkým a říkat jim <em>konstrukční funkce</em> (<em>constructor functions</em>). Klíčovým slovem <em>new</em> řekneme, že chce vytvořit nový (prázdný) objekt a tento použít jako <em>this</em> uvnitř volání (konstrukční) funkce. Uvnitř funkce máme tedy k dispozici <em>this</em>, což je úplně prázdný objekt. Logickým cílem konstrukční funkce je tento objekt zinicializovat.
<pre class="brush: js">function Car(carName, model) {
    this.name = carName;
    this.model = model;
    this.printMe = function() { // tohle neni nejefektivnejsi, stay tuned
        return this.name + ' ' + this.model;
    };
}</pre>
<p>    Na konstrukční funkce tudíž můžeme pohlížet podobně jako na třídy v jiných jazycích - je to totiž předpis, jak zkonstruovat konkrétní objekt. Pokud budu v dále textu mluvit o třídách, budu mluvit právě o konstrukčních funkcích.</p>
<p>    Pokud zavoláme toto, vytvoří se nám objekt podle očekávání: <em>var c = new Car("Honda", "Civic");</em>. Co když ale na slovíčko <em>new</em> zapomeneme? Pak nedojde k vytvoření nového prázdného objektu a jeho přiřazení do <em>this</em>. Bez <em>new</em> se jedná o úplně normální volání funkce a tudíž uvnitř funkce dojde k přiřazením do aktuálního <em>this</em> objektu. Pokud se nám podaří takovou funkci zavolat bez <em>new</em> z top-level úrovně, nadefinujeme položky <em>name</em> a <em>model</em> a funkci <em>printMe</em> na globálním objektu.</li>
</ul>
<p>Následuje komentovaný příklad, na kterém si ukážeme i něco nového, zajímavého a užitečného, takže nepřeskakovat <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<pre class="brush: js">// vytvorime promennou Car, do ktere priradime funkci se tremi parametry
// velke pismenko na zacatku jmena funkce indikuje, ze se jedna o konstrukcni funkci a tudiz by mela byt volana pomoci new
var Car = function(name, model, manufactured) {
    // nadefinujeme dve polozky v aktualnim this objektu
    this.name = name || 'Honda'; // pokud nebylo jmeno specifikovano, pouzije se 'Honda'
    this.model = model || 'Civic';

    // jsme ve funkci, takze muzeme nadeklarovat lokalni promennou
    // ta bude zcela podle ocekavani viditelna jen z teto funkce a funkci vnorenych
    // <strong>o lokalnich promennych v konstrukcnich funkcich se casto mluvi jako o privatnich polozkach objektu</strong>
    // k takovym polozkam se pristupuje jen pres jejich jmeno, tedy "made", zadne "this.made"!
    var made = manufactured;

    // nadefinujeme polozku, do niz priradime funkci, tedy vytvorime metodu objektu this
    // uvnitr metody muzeme pouzit lokalni promennou made
    this.howOld = function(now) { return now - made; }

    // stejne tak ale vidime i parametry funkce
    // <strong>parametry funkce jsou taktez oznacovany za privatni polozky objektu</strong>
    // a ze jsme pouzili stejne jmeno metody jako predtim? neva, stara se prepise
    this.howOld = function(now) { return now - manufactured; }

    // <strong>dve vyse uvedene metody pristupovaly k privatnim polozkam</strong>
    // <strong>takove metody se nazyvaji privilegovane</strong>

    // lokalni promenna muze byt jakehokoliv typu, tedy klidne funkce
    // takze toto je privatni metoda
    // <strong>k privatnim polozkam pristupujeme primo jejich jmenem</strong>
    // <strong>neprivatni polozky objektu musime prefixovat "this."</strong>
    // polozky jsou vsechno, i funkce, takze volani metody musi byt vzdy necim prefixovano
    // (v pripade tehoz objektu prefixem "this.")
    var printInfo = function () { println(this.name + " from " + made); }

    // vyse uvedene se da zapsat zkracene takto (drobne rozdily v implementaci tam ale jsou)
    function printInfo2() { println(this.name + " from " + made); }

    // je dobrym zvykem u novych trid definovat metodu toString, ktera vraci popis objektu
    // toto je public metoda, neni privatni ani privilegovana
    // vsimneme si, ze do polozky toString neprirazuji nejakou anonymni funkci jako v predchozich ukazkach,
    // ale pojmenovanou funkci - to muze pomoci pri debugu pri prochazeni stacku
    this.toString = function toString () { return this.name };
}

// vytvorime Hondu Civic s neznamym datem vyroby
var hc = new Car();
hc.howOld(); // vrati Nan (takovy ciselny undefined)
hc.toString(); // vrati "Honda"
//hc.printInfo(); // skoncilo by chybou - v konstrukcni funkci nikde nevidim prirazeni do this.printInfo
</pre>
<h2>Vestavěné objekty JavaScriptu</h2>
<p>JavaScript obsahuje pár vestavěných tříd. Jednak to jsou třídy, které zjednodušeně řečeno reprezentují zaboxované hodnotové typy (<a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/Boolean_Object">Boolean</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/Number_Object">Number</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/String_Object">String</a>); o třídě <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/Function_Object">Function</a> už řeč byla; a dále tu máme třídy, které nám usnadní řešení některých specifických úkolů: <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/Date_Object">Date</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/RegExp_Object">RegExp</a> (pro jeho vytvoření je možné použít i speciální literály uzavřené do slešů, např. <em>var re = /ab+c/;</em> je to samé jako <em>var re = new RegExp("ab+c");</em>), <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/Math_Object">Math</a> (obsahuje různé užitečné matematické funkce).</p>
<p>Asi tou nejzajímavější třídou je ale <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/Array_Object">Array</a>, tedy pole, konkrétně "dynamické" pole. Má položku <em>length</em>, která vrací hodnotu nejvyššího indexu v poli + 1. Pokud přiřazujeme do objektu pole položky s celočíselnými klíči, strkají se do pole. Protože je pole ale zároveň objekt, můžeme do něj přiřazovat i položky s nečíselnými klíči, např. <em>pole.bla = "nazdar";</em></p>
<pre class="brush: js">var pole = []; // to same jako new Array();
var inicializovanePole = [ 1, "bla", { name: "ja" }, 8, 5.8 ];
pole[2] = "dva"; // pole.length == 3, pole[0] == undefined, pole[1] == undefined
pole["2"] = "dva"; // stejne jako predchozi
pole.push("dalsi"); // dana hodnota se umisti na konec pole
pole[pole.length] = "dalsi"; // lamerska verze predchoziho
var dalsi = pole.pop(); // vrati posledni prvek pole a prvek z pole vynda
pole.length = 1; // nastaveni velikosti pole
</pre>
<p>JavaScript obsahuje vedle vestavěných tříd také <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions">pár užitečných funkcí</a>. To nejzajímavější je dozajisté <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/eval">eval</a>, která umí spustit JavaScriptový kód uložený ve stringu.</p>
<h2>this</h2>
<p>Klíčové slovíčko <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/this_Operator">this</a> je v JavaScriptu obestřeno mnoha mýty, přitom jeho fungování je docela jednoduché.<br />
    Na začátku programu je nastavené na globální objekt (v případě prohlížeče objekt <a href="http://www.w3schools.com/jsref/obj_window.asp">window</a>) a změnit se dá čtyřmi způsoby:</p>
<ul>
<li>Zavoláním funkce s klíčovým slovem <em>new</em>. Jak už bylo řečeno, v tomto případě dojde k vytvoření nového prázdného objektu a jeho přiřazení do <em>this</em>, tedy něco jako <em>this = {};</em>. Po návratu z (konstrukční) funkce je <em>this</em> vráceno na původní hodnotu.</li>
<li>Volání metody. Viz příklad výše - <em>hc.howOld();</em>. Dojde k nastavení <em>this</em>u na <em>hc</em>, zavolání funkce <em>howOld</em> a obnovení původní hodnoty <em>this</em>u.</li>
<li>Volání metody pomocí <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/call">call</a> objektu <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a>. Metodu můžeme zavolat takto: <em>hc.howOld.call(someOtherObject, par1, par2);</em>. Zde se stane něco podobného jako v předchozím případě, pouze <em>this</em> je nastaveno na námi zadanou hodnotu <em>someOtherObject</em>. Můžeme tedy volat metodu nad objektem, který danou metodu vůbec neobsahuje.</li>
<li>Obdobně jako předchozí případ funguje <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/apply">apply</a>. Rozdíl je pouze v tom, že nyní nepředáváme parametry jednotlivě, ale <em>apply</em> má dva parametry - první parametr je nová hodnota <em>this</em>u, druhý parametr je pole parametrů. Metoda <em>apply</em> se využívá např. tehdy, když chceme z funkce zavolat funkci se stejnými parametry jako má aktuální funkce - pak zavoláme <em>funkce.apply(this, arguments);</em> Jak bylo řečeno, <a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments">arguments</a> obsahuje pole aktuálních parametrů, takže tímto ho pouze přepošleme do jiné funkce.</li>
</ul>
<h2>Prototypy</h2>
<p>Vše je objekt, tedy i funkce je objektem. To je vidět v předcházejícím odstavci - funkce (reprezentovaná objektem třídy <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a>) má metody <em>call</em> a <em>apply</em>. Dále má ještě metodu <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/toString">toString()</a>, která vrací zdrojový kód funkce (pokud je k dispozici). Objekt <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a> má dále položku <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/length">length</a>, která udává počet deklarovaných parametrů, a hlavně má položku <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Object/prototype">prototype</a>. <em>prototype</em> obsahuje položky, které jsou společné pro všechny objekty vytvořené pomocí této (konstrukční) funkce.<br />
    V praxi to funguje takto: napíšeme třeba <em>var spz = hc.spz;</em>. JavaScript se nejprve podívá, zda má objekt <em>hc</em> nějakou položku s názvem <em>spz</em>. Pokud ano, prostě ji vrátí. Pokud ne, podívá se do objektu <em><strong>Car</strong>.prototype</em>, zda ten nemá položku položku <em>spz</em>. Pokud ji ani ten nemá, vrátí se <em>undefined</em>. Do objektu <em><strong>Car</strong>.prototype</em> se dívá proto, že <em>hc</em> bylo vytvořeno pomocí konstrukční funkce <em>Car</em>.<br />
    Důležité je si uvědomit, že <em>prototype</em> je pořád jen jeden, bez ohledu na to, kolik objektů jsme pomocí dané konstrukční funkce vytvořili - všechny používají ten samý <em>prototype</em>. <em>prototype</em> si tedy můžeme představit jako kontejner pro <a href="http://en.wikipedia.org/wiki/Static_method#Static_methods">statické</a> položky třídy.<br />
    Jak je to ale s přiřazením do takové položky? To probíhá jinak, tak bacha na to. Když uděláme <em>hc.spz = 'neco';</em>, tak se JavaScript koukne, jestli existuje v objektu <em>hc</em> položka s názvem <em>spz</em>. Pokud ano, tak je její hodnota přepsána novou hodnotou. Pokud položka není nalezena, je v objektu vytvořena. <strong>Při přiřazování se <em>prototype</em> neuplatní!</strong></p>
<pre class="brush: js">var hc = new Car();
var sf = new Car("Skoda", "Fabia");

// zajistime, aby vsechny objekty vytvorene pomoci Car mely polozku spz
Car.prototype.spz = 'prvni';
println(hc.spz); // 'prvni'
println(sf.spz); // 'prvni'

// pri prirazeni se prototype neuplatnuje
hc.spz = 'druha';
println(Car.prototype.spz); // 'prvni'
println(hc.spz); // 'druha'
println(sf.spz); // 'prvni'

// samozrejme kdyz priradime do prototype...;)
Car.prototype.spz = 'treti';
println(Car.prototype.spz); // 'treti'
println(hc.spz); // 'druha'
println(sf.spz); // 'treti'

// oba objekty byly zkonstruovany stejnou constructor function
println(hc.constructor == sf.constructor); // true
// a byla to constructor function Car
println(hc.constructor == Car); // true

// zmena prototypu bez explicitniho vypsani jmena constructor function
hc.constructor.prototype.spz = 'ctvrta'; // stejne jako Car.prototype.spz = 'ctvrta';
println(Car.prototype.spz); // 'ctvrta'
println(hc.spz); // 'druha'
println(sf.spz); // 'ctvrta'

// vyse uvedene neplati jen na stringy, ale na vse, tedy i na funkce/metody</pre>
<p>Co je vhodné umístit do <em>prototype</em>? Jsou to položky, které se nemění, tzn. především metody. Když totiž umístíme metodu do <em>prototype</em>, tak se už při každém volání konstrukční funkce (tedy vytváření nové instance) nebude metoda znovu vytvářet a přiřazovat do <em>this</em>, ale místo toho bude existovat jen jednou v <em>prototype</em> - tudíž šetříme pamětí (viz poznámka o neefektivnosti v jednom z předchozích příkladů).<br />
    Ale pozor, do <em>prototype</em> můžeme dát jen ty metody, které nejsou privilegované, tedy ty, které si nesahají na nějakou lokální proměnnou nebo parametr konstrukční funkce. Ono to totiž ani nedává moc smysl.</p>
<pre class="brush: js">var Car = function(name) {
    // blbost!
    this.constructor.prototype.testMethod = function() { return name; }
}</pre>
<p>Abychom měli přístup k privátním položkám, musí být přiřazení do <em>prototype</em> umístěno v konstrukční funkci. To ale znamená, že vytvoření oné metody a přiřazení do <em>prototype</em> probíhá při každém vytvoření instance třídy <em>Car</em>, přičemž se do <em>prototype</em> přiřadí funkce, která má uzávěr posledního volání funkce <em>Car</em>! Tedy metoda <em>testMethod</em> by vždy vracela jméno poslední vytvořené instance.<br />
    Stačí zapamatovat si jednoduché pravidlo - nepřiřazovat do <em>prototype</em> v konstrukční funkci, ale až za ní.</p>
<p>Kdyby někdo ale výše popsané chování vyžadoval (což se může stát, člověk nikdy neví), tak bych zde upozornil na jednu věc (vyžaduje ale znalosti z další části článku, takže tuto poznámku zatím klidně přeskočte). Privilegované položky v <em>prototype</em> totiž nejsou enumerabilní, tj. pokud budeme projíždět všechny položky objektu cyklem <em>for-in</em>, nedostaneme se k privilegované metodě. A to může způsobit problémy při implementaci vícenásobné dědičnosti. Abychom se tomuto problému vyhli, nepřiřazujeme v ukázce do <em>Car.prototype</em>, ale do <em>this.constructor.prototype</em>, což bude např. v případě volání konstruktoru z poděděné třídy <em>BestCar</em> znamenat totéž co <em>BestCar.prototype</em>. Použitím konstrukce <em>this.constructor.prototype</em> tedy umožníme přiřazení do <em>prototype</em> aktuálního objektu a vyhneme se nutnosti vyenumerovat tuto položku při kopírování z <em>prototype</em> do <em>prototype</em>.</p>
<p>Kromě metod můžeme do prototypů umístit i konstanty, pokud chceme k těmto konstantám přistupovat přes instance. V opačném případě je vhodnější umístit konstanty přímo do objektu konstrukční funkce, tedy např. <em>Car.MAX_SEATS = 10;</em>. V takovém případě musíme ale počítat s tím, že (pokud nepoužijeme nějaký trik) se k této konstantě nedostaneme přes jméno odvozené třídy, takže např. <em>BestCar.MAX_SEATS</em> bude <em>undefined</em>.</p>
<h3>Prototypy podrobněji</h3>
<p>Výše uvedený popis prototypů v JavaScriptu je trošku zjednodušený, avšak pro běžnou praxi dostatečný. Pro zájemce se mrkneme na prototypy podrobněji.<br />
	Specifikace ECMAScriptu mluví o vnitřní property každého objektu s názvem <a href="http://bclary.com/2004/11/07/#_Prototype_">[[Prototype]]</a>, ke které se nedá nijak dostat (např. SpiderMonkey to ale umožňuje přes <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/proto">__proto__</a>). A právě toto je ta property, přes kterou se skutečně provádí hledání položky objektu! Je užitečné znát tyto skutečnosti:</p>
<ul>
<li>Prototypové fallbackování při hledání properties se neděje přes property <em>prototype</em> (instance ani žádnou takovou property nemá), ale přes nepřístupnou property <em>[[Prototype]]</em> (kterou má každý objekt).</li>
<li>Každá funkce (instance "třídy" <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a>) má property <em>prototype</em>, což je iniciálně prázdný objekt s položkou <em>constructor</em>, která vede zpět na onu funkci. Toto je jediná "standardní" property s názvem <em>constructor</em> v JavaScriptu.</li>
<li><strong>Když vytvoříme instanci objektu podle nějaké konstrukční funkce (klasické <em>new</em>), tak se do <em>[[Prototype]]</em> nové instance zkopíruje property <em>prototype</em> použité konstrukční funkce.</strong> Nová instance nemá žádnou property jménem <em>prototype</em>.</li>
<li><em>[[Prototype]]</em> sice přímo měnit nemůžeme (protože k ní nemáme většinou žádný přístup), ale můžeme využít skutečnosti z předchozího bodu a měnit její položky přes property <em>prototype</em> použité konstrukční funkce, např. přiřazovat do <em>Car.prototype.spz</em>. Pokud to chceme dělat dynamičtěji, může použít konstrukci <em>hc.constructor.prototype</em> (která ale při změně prototypu za běhu nemusí fungovat podle očekávání) nebo nejlépe použít funkci <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/getPrototypeOf">getPrototypeOf</a>, která byla zavedena v ECMAScriptu 3.1 (JavaScriptu 1.8.1).<br />
	  Pokud tyto novější verze použít nemůžeme, ale v budoucnu se to pravděpodobně změní, můžeme použít ne-ideální vlastní implementaci této funkce, jak je popsána mj. <a href="http://ejohn.org/blog/objectgetprototypeof/">v tomto článku</a> (sekce "<em>Cross-Browser Implementation</em>").</li>
<li>Když vytváříme funkci, tak tím vlastně vytváříme instanci třídy <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a>. Z předchozích bodů tedy vyplývá, že třeba <em>Car</em> má jako <em>[[Prototype]]</em> nastavenu hodnotu <em>Function.prototype</em>.</li>
<li>Operátor <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/instanceof_Operator">instanceof</a> vůbec nesahá na property <em>constructor</em>. Místo toho vezme property <em>prototype</em> konstrukční funkce (zadána jako pravý operand). Dále pak vezme <em>[[Prototype]]</em> levého operandu a dokud není <em>null</em>, tak při shodě vrací <em>true</em>, jinak postupuje přes <em>[[Prototype]]</em> dále chainem (kerý končí u prapředka Object, který má <em>[[Prototype]]</em> nastaven na <em>null</em>).</li>
<li>Pokud tedy přiřadíme do property <em>prototype</em> konstrukční funkce <strong>po</strong> vytvoření instance, tak nám <em>instanceof</em> nebude fungovat dle očekávání.</li>
</ul>
<h2>Properties</h2>
<p>Jak jsme si již řekli, položky objektu (properties) lze definovat prostým přiřazením, tedy <em>obj.polozka = hodnota;</em> či <em>obj["polozka"] = hodnota;</em>. V moderních JavaScriptových enginech (implementující tuto vlastnost ECMAScriptu5) je tu ale ještě další možnost -<br />
	property můžeme definovat pomocí speciální funkce <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/defineProperty">defineProperty</a>, kterou si hned ukážeme na příkladu:</p>
<pre class="brush: js">// prvni parametr je objekt, pro ktery property definujeme
// druhy parametr je jmeno property
// treti parametr je tzv. property descriptor, coz je anonymni objekt s predepsanymi properties
Object.defineProperty(Car.property, "someProperty", {
	value: 36, // hodnota
	writable: true, // zda je mozne do property priradit
	enumerable: true, // zda bude property videt pri enumerovani pomoci for cyklu
	configurable: false // zda se da property smazat pomoci delete
});</pre>
<p>Je to tedy velmi podobné, jako kdybychom udělali <em>Car.property.someProperty = 36;</em>, pouze máme větší kontrolu nad vlastnostmi definované property. Takovémuto <em>property descriptoru</em> se říká <em>data descriptor</em>.<br />
	Zajímavější jsou <em>accessor descriptory</em>:</p>
<pre class="brush: js">
Object.defineProperty(Car.property, "someProperty", {
	get: function() { return this.someValue; }, // getter (volitelny)
	set: function(value) { this.someValue = value; }, // setter (volitelny)
	//writable: true, // writable nema u accessor descriptoru smysl
	enumerable: true, // zda bude property videt pri enumerovani pomoci for cyklu
	configurable: false // zda se da property smazat pomoci delete
});</pre>
<p>Buď <em>getter</em> nebo <em>setter</em> lze vynechat a tím docílíme read-only, resp. write-only property.<br />
	Pokud chceme získat <em>property descriptor</em> nějaké existující property, máme k dispozici funkci <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/getOwnPropertyDescriptor">getOwnPropertyDescriptor</a>.</p>
<p>Jak jsem psal, výše popsané je záležitost ECMAScriptu 5 a třeba ve webových prohlížečích je v současnosti možné toto použít pouze na DOM objekty v IE8+. Pokud potřebujeme nějaké takové chování už nyní, můžeme v prohlížečích Safari, Opeře, Firefoxu a Chrome, příp. JS enginech SpiderMonkey a TraceMonkey, použít následující konstrukce:</p>
<pre class="brush: js">// definice na existujicim objektu
Car.prototype.__defineGetter__("someProperty", function() { return this.propValue; } );
Car.prototype.__defineSetter__("someProperty", function(value) { this.propValue = value; } );

// definice v ramci object initializeru
var obj2 = {
    get someProperty() { return this.propValue; },
    set someProperty(value) { this.propValue = value; }
};</pre>
<p>Místo funkce <em>getOwnPropertyDescriptor</em> zde můžeme použít funkce <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/lookupGetter">__lookupGetter__</a> a <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/lookupSetter">__lookupSetter__</a>.<br />
	A když jsme už u těch podtržítkových záležitostí, tak přihodím jednu třešňičku, kterou umožňuje <em>SpiderMonkey</em>. Do <em>obj.<a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/noSuchMethod">__noSuchMethod__</a></em> můžeme přiřadit funkci, která očekává dva parametry. První je jméno funkce a druhý její parametry. Tato přiřazená funkce bude zavolána vždy, když někdo na objektu <em>obj</em> zavolá metodu, která není definována.</p>
<p><a href="http://www.robertnyman.com/javascript/javascript-getters-setters.html">Tato stránka</a> docela pěkně ukazuje, kde si člověk může dovolit použít jaké způsoby vytváření properties.<br />
	K properties s gettery a/nebo settery bych ještě dodal, že jsou to de facto metody, takže pokud přistupují jen k public položkám (tj. přes <em>this</em>), patří do <em>prototype</em>.</p>
<h2>Statements</h2>
<p>Teď si dáme trošku oddech a mrkneme na <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements">statements</a>. Ty jsou téměř stejné jako v C, takže je netřeba moc rozebírat - máme tu <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for">for</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/while">while</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/do...while">do-while</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/break">break</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/continue">continue</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/if...else">if-else</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/switch">switch</a>...<br />
    Za zmínku snad stojí jen <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for...in">for-in</a>. Ten nám totiž umožní iterovat přes všechna jména položek objektu:</p>
<pre class="brush: js">for(var key in someObj) {
    println(key + ': ' + someObj[key]); // klic: hodnota
}</pre>
<p>Pokud chceme iterovat přímo přes hodnoty položek objektu, můžeme přes <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for_each...in">for each-in</a>:</p>
<pre class="brush: js">for each (var v in someObj) {
    println(v);
}</pre>
<h2>Dědičnost</h2>
<p>A to nejlepší nakonec - klasická třídní dědičnost není JavaScriptem přímo podporována, JavaScript umí prototypovou dědičnost (vzpomeňte na fallbackování při hledání properties popsané výše). JavaScript je ale natolik ohebný jazyk, že je možné klasickou třídní dědičnost různými způsoby simulovat. Zde bych rád ukázal některé používané přístupy a přidám i nějaké svoje nápady. Nejprve předvedu řešení, která jsou k vidění na internetu a nejsou správná, a popíšu, v čem je u nich problém - i některá špatná řešení může být důležité znát.<br />
    V následujících příkladech budu předpokládat, že <em>T1</em> je bázová třída a <em>T2</em> je třída odvozená od <em>T1</em>.</p>
<p>Často je k vidění následující konstrukce: <em>T2.prototype = new T1;</em><br />
    Toto velmi jednoduché řešení jakž-takž funguje, ale má řadu nevýhod:</p>
<ul>
<li>Při této deklaraci dojde k vytvoření instance třídy <em>T1</em>, což nemusí být úplně ok (kdyby třeba <em>T1</em> alokovala nějaké zdroje apod.).</li>
<li><em>T2.prototype.constructor</em> bude nelogicky roven <em>T1</em>. Lze řešit přiřazením <em>T2.prototype.constructor = T2;</em></li>
<li><em>T2</em> nezdědí z <em>T1</em> privátní položky, takže volání privilegovaných metod selže.</li>
<li>Při vytváření instance <em>T2</em> se nevolá konstrukční funkce <em>T1</em>.</li>
<li>V této podobě neumožňuje vícenásobnou dědičnost.</li>
</ul>
<p>Výhodou tohoto řešení je jednoduchost zápisu.</p>
<p>Následující řešení je zajímavější (avšak stále ne moc dobré):</p>
<pre class="brush: js">var T2 = function(cpar1, cpar2, cpar3) {
    // vytvorime public polozku s nazvem parentClass, ktera ukazuje na constructor function predka
    // tim dame do T2 metodu, ktera umi zkonstruovat objekt typu T1
    this.parentClass = T1;
    // zde udelame to, pred cim jsem varoval - zavolame constructor function bez "new"
    // protoze se ale jedna o volani metody objektu T2, preda se do ni aktualni this
    // takze tato trida bude zinicializovana jako T1
    this.parentClass(cpar1, cpar2 + cpar3);
    // nyni nasleduji T2 specific zalezitosti jako obvykle
}</pre>
<p>Výhody:</p>
<ul>
<li>Informace o dědění je obsažena přímo v definici třídy.</li>
<li>Můžeme volat konstruktor předka s libovolnými parametry.</li>
<li>Privátní položky <em>T1</em> jsou správně zinicializovány a neperou se s položkami <em>T2</em>, neboť každé žijí v jiné <em>closure</em>.</li>
<li>Nejsme omezeni na jednoho předka - můžeme volat více <em>constructor functions</em>.</li>
</ul>
<p>Nevýhody:</p>
<ul>
<li>Nedědí se <em>prototype</em>.</li>
<li>Zápis dědičnosti jsou dva příkazy.</li>
<li>Zavádí se nová public položka objektu (v ukázce pojmenovaná <em>parentClass</em>).</li>
</ul>
<p>U posledních dvou nevýhod jsem sám vymyslel (heč! <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ) jak se jich zbavit. Jednoduše využijeme jedné z možností, jak protlačit vlastní <em>this</em> do funkce.</p>
<pre class="brush: js">var T2 = function(cpar1, cpar2, cpar3) {
    // zavolame constructor function T1, ale podstrcime mu aktualni this
    T1.call(this, cpar1, cpar2 + cpar3);
    // pokud maji T1 a T2 stejne parametry, lze zapis zkratit nasledovne
    //T1.apply(this, arguments);
    // nyni nasleduji T2 specific zalezitosti jako obvykle
}</pre>
<p>Toto řešení nám krásně pořeší dědění instančních položek, ale stále nám zde zůstává problém s neděděním prototypu. Zde ukážu několik přístupů k dědění prototypu, resp. vytvoření správného prototype chainu - prostě aby se při hledání property v prototypech správně propadávalo do prototypů nadtříd.</p>
<ul>
<li>Zdánlivým cílem je, aby <em>T2.prototype</em> obsahovalo to samé, co <em>T1.prototype</em>, plus něco navíc. Řešení je tudíž naprosto přímočaré:
<pre class="brush: js">T2.prototype = T1.prototype;
// obnoveni konstruktoru
T2.prototype.constructor = T2;
// T2 specific prototype polozky</pre>
<p>        Nevýhodou tohoto přístupu je to, že neumožňuje vícenásobnou dědičnost. Té se ale v praxi já osobně snažím vyhnout, protože to přináší další zlo, na které je třeba pamatovat - možné překrývání jmen položek jednotlivých bázových tříd.<br />
		Další (poměrně zásadní) nevýhodou tohoto řešení je to, že když něco přidáme do <em>T2.prototype</em>, tak se nám to objeví i v <em>T1.prototype</em>.</li>
<li>Pokud chceme přesto umožnit vícenásobnou dědičnost, postupoval bych následovně. Do všech funkcí si přidáme metodu <em>extend</em>, která nám překopíruje všechny (resp. všechny enumerabilní) položky daného prototypu do prototypu aktuálního objektu.
<pre class="brush: js">// metoda na kopirovani z prototypu do prototypu
// pokud nechceme vicenasobnou dedicnost, tak ji nepotrebujeme
Function.prototype.extend = function extend(b) {
    b = b.prototype;
    for (var i in b) {
	    // SpiderMonkey/TraceMonkey specific
        var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
        if (g || s) {
            if (g) this.prototype.__defineGetter__(i, g);
            if (s) this.prototype.__defineSetter__(i, s);
        } else {
            this.prototype[i] = b[i];
        }
    }
};</pre>
<p>        Místo přiřazení do prototypu pak stačí zavolat <em>T2.extend(T1);</em>.<br />
        Nevýhodou tohoto řešení je, že pokud přidáme něco dodatečně do <em>T1.prototype</em>, tak se nám změna neprojeví v <em>T2.prototype</em>. Pokud máme striktně oddělenu "implementaci" a "použití", tak to není problém, ale trošku se tím omezujeme v jinak krásně dynamickém prostředí JavaScriptu.<br />
		Na internetu je občas toto řešení s kopírováním properties použito i na implementaci jednoduché dědičnosti - to je ale zbytečné a je lepší použít některé řešení popsané níže.
		</li>
<li>Abychom využili prototypovou dědičnost pro implementaci třídní dědičnosti naplno, potřebujeme dosáhnout toho, aby při <strong>ne</strong>nalezení property v <em>T2.prototype</em> došlo k hledání v <em>T1.prototype</em> (potřebujeme zřetězit prototypy). Takže cílem je, aby skrytá property <em>[[Prototype]]</em> objektu <em>T2.prototype</em> (tedy "<em>T2.prototype.[[Prototype]]</em>") byla rovna <em>T1.prototype</em>.
<pre class="brush: js">// metoda na zretezeni prototypu
Function.prototype.extend = function extend(child) {
    // pokud mame primy pristup k [[Property]] pres __proto__ (SpiderMonkey/TraceMonkey), je to jednoduche
    if (child.prototype.__proto__) {
        child.prototype.__proto__ = this.prototype;
    } else {
        // vytvorime si pomocnou konstrukcni funkci...
        var F = function() { };
        // ...ktera ma prototype nastaveno na "T1.prototype"
        F.prototype = this.prototype;
        // "T2.prototype.[[Prototype]]" bude odkazovat na F.prototype (=== T1.prototype)
        child.prototype = new F();
        // nastavime spravny constructor
        child.prototype.constructor = child;
    }
};

T1.extend(T2); // pouziti
</pre>
<p>        Když můžeme <em>[[Prototype]]</em> přímo změnit, je implementace jednoduchoučká. Pokud ne, musíme si trošku pomoci.<br />
        Abychom zajistili, že "<em>T2.prototype.[[Prototype]]</em>" bude nastaveno na <em>T1.prototype</em>, musíme <em>T2.prototype</em> vytvořit nějakou funkcí, která má <em>prototype</em> rovno <em>T1.prototype</em>. A není nic jednoduššího, než si takovou pomocnou funkci vyrobit (<em>F</em>).
		</li>
<li>Výše uvedené řešení je nejlepší, jaké v době psaní článku znám. Protože se ale může tato "best-practice" změnit, může být do budoucna výhodné abstrahovat způsob vytváření tříd, resp. hierarchie tříd, jak to ukazuje např. <a href="http://zdrojak.root.cz/clanky/oop-v-javascriptu-iii/">článek Daniela Steigerwalda</a>.
		</li>
</ul>
<h2>Finální komentovaná ukázka dědičnosti</h2>
<pre class="brush: js">var Trida1 = function(cpar1, cpar2) {
    // instancni polozky
    this.field1 = cpar1 + cpar2;
    this.field2 = "hola";
    // privatni polozky
    var pfield1 = cpar2;
    var pfield2 = "hola hej";
    // privatni metoda
    var pmethod1 = function(par1) { println("Trida1.pmethod1 called"); };
    // metoda pristupujici k privatnim polozkam, tedy privilegovana
    this.method1 = function(par1) { println("Trida1.method1 called"); this.method2(); println(pfield1); };
    // property pristupujici k privatnim polozkam (SpiderMonkey/TraceMonkey specific syntax)
    this.__defineGetter__("prop1", function() { return pfield1; } );
    println("Trida1 contructor called");
};

// metoda (a prip. property) pracujici pouze nad public polozkami
Trida1.prototype.method2 = function(par1) { println("Trida1.method2 called"); };
// konstanty dostupne pres instance
Trida1.prototype.CONST1 = 1;
// konstanty dostupne pres jmeno tridy
Trida1.CONST2 = 2;

// podedime tridu
var Trida2 = function(cpar1, cpar2, cpar3) {
    // volame konstruktor predka se dvema parametry
    Trida1.call(this, cpar1, cpar2 + cpar3);
    // instancni polozka
    this.newfield1 = cpar1;
    // privatni polozka stejneho jmena jako privatni polozka v predkovi
    // diky ruznym closures zadny problem
    var pfield1 = cpar2;
    // property, ktera nam zpristupnuje privatni polozky pfield1 teto tridy (SpiderMonkey/TraceMonkey specific syntax)
    this.__defineGetter__("prop2", function() { return pfield1; } );
    println("Trida2 contructor called");
};

Trida1.extend(Trida2); // zretezime prototypy

// tridy nadefinovany, nyni je jdeme pouzivat
var t1  = new Trida1(58, 12);
var t2  = new Trida2(-28, -98, -5);
var t22 = new Trida2(59, 65, 158);
t1.method1();
t2.method1();
// cteni privatnich polozek stejneho jmena
println(t22.prop1);
println(t22.prop2);</pre>
<h2>Singleton</h2>
<p>Jako bonus na závěr bych ukázal dvě možnosti, jak implementovat návrhový vzor singleton, který se často v JavaScriptu označuje jako <a href="http://www.yuiblog.com/blog/2007/06/12/module-pattern/">module pattern</a>.</p>
<pre class="brush: js">// nadeklarujeme funkci, kterou hned zavolame
var Singleton1 = function() {
    // datove polozky musi byt jako lokalni promenne
    // prirazeni do this by znamenalo prirazeni do aktualniho objektu, coz muze byt ledasco
    var val1 = 1;
    var val2 = 2;
    var val3 = 3;

    // z funkce vracime anonymni objekt, ktery tvori verejny interface pro nas singleton
    return {
        prop1 : 2,
        funkce : function(par1, par2) {
            return par1 + par2;
        },
        get value1() { return val1; }, // SpiderMonkey/TraceMonkey specific syntax
    }
}(); // vsimnete si () - funkci ihned volame</pre>
<p>Udělali jsme to, že jsme nadeklarovali funkci, ale nijak jsme ji nepojmenovali ani do ničeho nepřiřadili, ale hned po definici jsme ji zavolali. Funkce vrací anonymní objekt, který tvoří veřejný interface pro náš singleton a pouze přes něj můžeme přistupovat k privátním položkám singletonu. Ty jsou implementovány jako lokální proměnné oné nepojmenované funkce.</p>
<pre class="brush: js">// nadeklarujeme konstrukcni funkci, kterou hned zavolame pomoci new
var Singleton2 = new function() {
    // datove polozky mohou byt privatni i public
    this.val1 = 1;
    var val2 = 2;
    var val3 = 3;

    this.prop1 = 2;
    this.funkce = function(par1, par2) {
        return par1 + par2;
    }
    this.__defineGetter__("value1", function() { return val1; });
};</pre>
<p>Toto řešení funguje tak, že nadeklarujeme konstrukční funkci a hned ji zavoláme pomocí <em>new</em>. Zde je úroveň "zatajení implementace" o něco nižší, neboť pomocí <em>Singleton2.constructor</em> se dostaneme k oné nepojmenované konstrukční funkci.<br />
	Rozdíl mezi těmito dvěma řešeními je spíše kosmetický a není problém vymyslet další způsoby implementace singletonu.</p>
<h2>Shrnutí</h2>
<ul>
<li>JavaScript je dynamický objektově orientovaný skriptovací jazyk s prototypovou dědičností</li>
<li>všechno je objekt, včetně funkcí</li>
<li>objekt je hash mapa (jméno -> hodnota)</li>
<li>objekt můžeme vytvořit dvěma způsoby - zavoláním <em>new Trida</em> nebo pomocí <em>object literalu</em>: <em>{ name: "Ja", age : 27, }</em> (podobné jako Json)</li>
<li>nějaký objekt je vždy aktuální - <em>this</em> (na top-level úrovni je to globální objekt, v prohlížečích <a href="http://www.w3schools.com/jsref/obj_window.asp">window</a>)</li>
<li>aktuální objekt (<em>this</em>) můžeme změnit čtyřmi způsoby - zavoláním funkce na objektu (tedy metody), voláním <em>new Trida</em> a dále pomocí speciálních metod třídy <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Function</a>: <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/call">call</a> a <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/apply">apply</a></li>
<li>Každá funkce má přiřazen <em>prototype</em>, na který vede odkaz (přes "skrytou" property <em>[[Prototype]]</em>) ze všech objektů, které byly vytvořeny touto (konstrukční) funkcí.</li>
<li><em>prototype</em> se používá především na definování metod</li>
<li>co bylo definované jako poslední (stejného jména), to platí</li>
<li>tento článek nepostihuje všechny možnosti JavaScriptu, ty jsou daleko širší</li>
<li>design mého blogu není moc přívětivý na dlouhé výpisy kódů, proto si můžete článek prohlédnout také <a href="http://www.augi.cz/JS%20ocima%20programatora%20v2.html">v plain html</a> nebo stáhnout <a href="http://www.augi.cz/JS%20ocima%20programatora%20v2.pdf">jako PDF</a></li>
</ul>
<p>&copy; <a href="http://www.augi.cz">Michal Augustýn (Augi)</a> 2009 - 2010</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/shBrushJScript.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/javascript-ocima-programatora-v2/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC 3 &#8211; co nás čeká?</title>
		<link>http://www.augi.cz/programovani/asp-net-mvc-3-co-nas-ceka/</link>
		<comments>http://www.augi.cz/programovani/asp-net-mvc-3-co-nas-ceka/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 16:21:56 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=416</guid>
		<description><![CDATA[Sotva Microsoft uvolnil ASP.NET MVC 2, hned se na Codeplexu objevila roadmapa pro ASP.NET MVC, tedy takový nástřel, na co se bude tým dále soustředit. Vezměme si k ruce assembly ASP.NET MVC 2 Futures a podívejme se na to.

ASP.NET MVC Futures
Začněme s Futures. Assembly je ve své poslední verzi poměrně hubená, dost možná proto, že [...]]]></description>
			<content:encoded><![CDATA[<p>Sotva Microsoft uvolnil <a href="http://www.augi.cz/programovani/asp-net-mvc-2/">ASP.NET MVC 2</a>, hned se na Codeplexu objevila <a href="http://aspnet.codeplex.com/wikipage?title=Road%20Map&#038;referringTitle=MVC">roadmapa pro ASP.NET MVC</a>, tedy takový nástřel, na co se bude tým dále soustředit. Vezměme si k ruce assembly <a href="http://aspnet.codeplex.com/releases/view/41742#DownloadId=110348">ASP.NET MVC 2 Futures</a> a podívejme se na to.<br />
<span id="more-416"></span></p>
<h2>ASP.NET MVC Futures</h2>
<p>Začněme s <em>Futures</em>. Assembly je ve své poslední verzi poměrně hubená, dost možná proto, že většina věcí byla přesunuta přímo do core assembly. Tradičně zde nalézáme <strong>MVC Controls</strong>, tedy kontrolky pro ASP.NET WebForms s prefixem <em>mvc:</em>. Idea to je zajímavá, protože aspx šablony jsou s těmito kontrolkami takové více konzistentní, než když máme kód &#8220;rozbitý&#8221; voláním <em>Html helper</em>ů apod. Prostě a jednoduše, <em>aspx</em> by mělo obsahovat ideálně žádný &#8220;imperativní kód&#8221; (ideálně jen &#8220;deklarativní&#8221;) a <em>MVC Controls</em> k tomuto cíli vedou. Zůstává jen otázka, proč se za tak dlouhou dobu kontrolky nedostaly do core assembly a ani se nestaly příliš oblíbenými&#8230;<br />
Další věci, které najdeme ve Futures, jsou povětšinou jen drobnosti, které sice potěší, ale nepřináší nic převratného.</p>
<h2>MVCContrib</h2>
<p>Když už zmiňuji Futures, určitě bych se měl zmínit také o <a href="http://www.codeplex.com/MVCContrib">MVCContrib</a> &#8211; to je komunitní rozšíření pro ASP.NET MVC. Najdeme zde další užitečné maličkosti, ale i jednu poměrně zajímavou věc &#8211; <a href="http://mvccontrib.codeplex.com/wikipage?title=T4MVC&#038;referringTitle=Documentation">T4MVC</a>, která nám umožní generovat odkazy v silně typovém stylu. Ale na můj vkus je použitý způsob zajištění silné typovosti při generování odkazů příliš invazivní a očekávám, že se zapracuje na zvýšení výkonnosti generování odkazů pomocí generik. V současné době je ale <em>T4MVC</em> velmi dobrá (a hlavně výkonná) alternativa.</p>
<h2>ASP.NET MVC 3</h2>
<p>A teď k oné zmiňované <a href="http://aspnet.codeplex.com/wikipage?title=Road%20Map&#038;referringTitle=MVC">roadmapě</a>. Opět zde najdeme nějaké <em>blbinky</em>, jako např. možnost jedním ajaxovým voláním zupdatovat více DIVů na stránce, a lepší podpora klientského programování vůbec &#8211; třeba užší návaznost na jQuery (UI) nebo podpora pro client-side templates, které nám umožní formátovat příchozí json data. Vůbec to vypadá, že propojení server-side a client-side kódu je zajímavý úkol, který by se měl ještě nějak pěkně vyřešit.<br />
Dále se píše o &#8220;dependency injection at all levels&#8221;, tedy možnosti jednoduše a unifikovaným způsobem nahradit/doplnit nějakou funkcionalitu v ASP.NET MVC. S tím trošku souvisí i užší integrace s <a href="http://www.codeplex.com/MEF">MEF</a>.<br />
To nejzajímavější se ale skrývá pod položkou &#8220;<em>View Engine Options</em>&#8220;, kde se píše o experimentech s &#8220;<em>new streamlined view engine syntax</em>&#8221; &#8211; měl jsem možnost ho vidět a vypadá opradu skvěle. Dále se tu píše o snadnější integraci ostatních view-enginů, což také potěší. Osobně budu rád, když se zbavím defaultního aspx view-enginu.</p>
<h2>Shrnutí</h2>
<p>Mně osobně na ASP.NET MVC vadil právě defaultní aspx view-engine, takže jsem rád, že se ledy v této oblasti pohnuly &#8211; ať už to je nový view-engine nebo lepší podpora pro alternativní view-enginy. Také lepší podpora pro client-side programování a lepší extensibilita pomocí IoC kontejnerů a MEF jistě potěší.<br />
Co byste rádi viděli v dalších verzích ASP.NET MVC Vy?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/asp-net-mvc-3-co-nas-ceka/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC 2</title>
		<link>http://www.augi.cz/programovani/asp-net-mvc-2/</link>
		<comments>http://www.augi.cz/programovani/asp-net-mvc-2/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 09:59:59 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=414</guid>
		<description><![CDATA[Microsoft před pár dny uvolnil další verzi ASP.NET MVC, verzi 2. V době psaní článku je dostupná verze pro Visual Studio 2008. Verze pro 2010 jakoby nebude, protože ASP.NET MVC 2 bude dodáváno přímo s Visual Studiem 2010.
Ve verzi 2 není myslím nic, co by každého, kdo trošku sleduje scénu, překvapilo. ASP.NET MVC se totiž [...]]]></description>
			<content:encoded><![CDATA[<p>Microsoft před pár dny uvolnil další verzi ASP.NET MVC, <a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&#038;FamilyID=c9ba1fe1-3ba8-439a-9e21-def90a8615a9">verzi 2</a>. V době psaní článku je dostupná verze pro Visual Studio 2008. Verze pro 2010 jakoby nebude, protože ASP.NET MVC 2 bude dodáváno přímo s Visual Studiem 2010.<br />
Ve verzi 2 není myslím nic, co by každého, kdo trošku sleduje scénu, překvapilo. ASP.NET MVC se totiž vyvíjí pod open source licencí <a href="http://www.opensource.org/licenses/ms-pl.html">Ms-PL</a>, zdrojové kódy jsou dostupné na <a href="http://aspnet.codeplex.com/wikipage?title=MVC&#038;referringTitle=Home">Codeplex</a>u a tým vždy před releasem udělá několik pracovních verzí, díky čemuž má velmi dobrý feedback od komunity a ven jde dobře otestovaná věc.<br />
Protože ale ne každý má čas/náladu/whatever sledovat průběžně novinky v ASP.NET MVC, podíváme se v tomto článku na zoubek novinkám ve verzi 2 (vůči verzi 1).<br />
<span id="more-414"></span><br />
Za dva hlavní motivy nové verze bych označil větší typovou bezpečnost (tedy konec stringovým konstantám) a lepší znovupoužitelnost kódu (<a href="http://en.wikipedia.org/wiki/DRY">DRY</a>).</p>
<h2>(Render)Action</h2>
<p>Pokud jste chtěli v ASP.NET MVC 1 znovupoužít nějaký kód ve view, pravděpodobně jste vytvořili <em>ascx</em> soubor (<em>partial view</em>) a pak ho renderovali pomocí metody <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.renderpartialextensions.renderpartial(VS.100).aspx">Html.RenderPartial</a>. Užitečné, ale není to vhodné, pokud potřebujeme nějakou více autonomní partial view &#8211; typicky, aby partial view sosal nějaká data z Modelu. Jinými slovy, pokud nemůžeme nebo nechceme předávat data z rodičovského view do partial view a partial view si data tedy musí načíst sám.<br />
Protože přistupovat k Modelu přímo z View je prasečina, máme tu k dispozici náhradu &#8211; metody <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.childactionextensions.renderaction(VS.100).aspx">Html.RenderAction</a> a <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.childactionextensions.action(VS.100).aspx">Html.Action</a>. První metoda slouží k tomu, že nám vyrenderuje danou akci. Tzn. specifikujeme <em>controller</em> a <em>action</em> a ASP.NET MVC se postará o to, že se tato akce zavolá a dojde tedy k renderu. Druhá metoda, <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.childactionextensions.action(VS.100).aspx">Html.Action</a>, udělá to samé, ale výsledek volání akční metody nevyrenderuje, vrátí nám ho jako string.<br />
Akční metody, které voláme takto přes <em>Html.(Render)Action</em>, se nazývají <em>child action methods</em> a pokud chceme zajistit, aby určitá akční metoda byla volatelná pouze takto (a ne jako klasická akční metoda), můžeme ji označit atributem <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.childactiononlyattribute(VS.100).aspx">ChildActionOnly</a>.</p>
<h2>Silně typový <em>HtmlHelper</em></h2>
<p>Pokud jsme chtěli v čistém ASP.NET MVC 1 vykreslit třeba inputítko pro nějakou property modelu (resp. view-modelu), museli jsme udělat něco jako <em>Html.TextBox(&#8221;Price&#8221;)</em>, tedy použít stringovou konstantu. Nyní je <a href="http://msdn.microsoft.com/en-us/library/dd492619(VS.100).aspx">HtmlHelper</a> silně typový, genericky zná typ (view)modelu, což nám umožňuje nyní zapsat pěknější <em>Html.TextBoxFor(m =&gt; m.Price)</em>.</p>
<h2>ModelMetadata</h2>
<p>Třída <a href="http://msdn.microsoft.com/en-us/library/dd505255(VS.100).aspx">ViewDataDictionary</a> nyní neobsahuje pouze property <a href="http://msdn.microsoft.com/en-us/library/dd460191(VS.100).aspx">Model</a>, ale také nově <a href="http://msdn.microsoft.com/en-us/library/ee450613(VS.100).aspx">ModelMetadata</a> (stejnojmené třídy), která nese informace o viewmodelu. Tato data se načítají pomocí zvoleného <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.modelmetadataprovider(VS.100).aspx">ModelMetadataProvider</a>u, defaultně je to <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.dataannotationsmodelmetadataprovider(VS.100).aspx">DataAnnotationsModelMetadataProvider</a>, který používá atributy z jmeného prostoru <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx">System.DataAnnotations</a>. Pomocí <a href="http://msdn.microsoft.com/en-us/library/ee450613(VS.100).aspx">ViewModel.ModelMetadata</a> se tedy můžeme dostat k dašlím zajímavým informacím o viewmodelu, což umožnilo vylepšení validací, a to jak server-side, tak client-side (v JavaScriptu). Např. není problém udělat ani <a href="http://bradwilson.typepad.com/blog/2010/01/remote-validation-with-aspnet-mvc-2.html">remote client-side validace</a>.</p>
<h2>Templating</h2>
<p>Asi nejzásadnější věc, které vznikla díky <em>ModelMetadata</em>, je templating. Templating je zjednodušeně řečeno mechanismus, který nám umožní pro každý datový typ specifikovat, jak se bude renderovat pro prohlížení (<em>DisplayTemplate</em>) a pro editaci (<em>EditorTemplate</em>). K tomu slouží především metody <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.displayextensions.displayfor(VS.100).aspx">Html.DisplayFor</a> a <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.editorextensions.editorfor(VS.100).aspx">Html.EditorFor</a>.<br />
Pokud chceme např. vytvořit templates pro třídu <em>Product</em>, stačí vytvořit <em>ascx</em> soubory (de facto klasické partial views) v podadresářích <em>DisplayTemplates</em> a <em>EditorTemplates</em>.<br />
Velice pěkný a podrobný <a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html">seriál o templatingu</a> v ASP.NET MVC 2 napsal Brad Wilson, zájemcům o hlubší poznání doporučuji.</p>
<h2>Ostatní</h2>
<p>V ASP.NET MVC 2 přišlo i několik drobných změn, které mohou zpříjemnit život, např. <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.asynccontroller(VS.100).aspx">asynchronní controller</a>, který může přispět k větší výkonnosti naší aplikace, explicitnější zápis volitelných routovacích parametrů pomocí <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.urlparameter.optional(VS.100).aspx">UrlParameter.Optional</a> (<a href="http://haacked.com/archive/2010/02/12/asp-net-mvc-2-optional-url-parameters.aspx">podrobnější popis</a> od Phila Haacka), nebo explicitní zápis defaultních hodnot parametrů akčních metod pomocí standardního atributu <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx">DefaultValue</a>.</p>
<h2>Bonus: generování odkazů</h2>
<p>Jak jistě víte, odkazy se ve view generují často pomocí <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.linkextensions.actionlink(VS.100).aspx">Html.ActionLink</a>. Defaulně se mu ale předávají stringy, což jak víme, je fůj. Takže v <em>MvcFutures</em> byly k dispozici metody, které umějí generovat odkazy silně typově, pomocí generik a lambda funkcí. Velmi pěkné! Ale strašlivě pomalé <img src='http://www.augi.cz/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /><br />
Právě proto vznikl projekt <a href="http://mvccontrib.codeplex.com/wikipage?title=T4MVC">T4MVC</a> (nyní součást projektu <a href="http://mvccontrib.codeplex.com/">MvcContrib</a>), který využívá <a href="http://msdn.microsoft.com/en-us/library/bb126445.aspx">T4</a> (generování kódu ještě před kompilací) a umožňuje bezpečné generování odkazů. Osobně ale doufám, že se podaří urychlit původní generování pomocí generik a budu jej moct v pohodě používat. Proč? Jednoduše proto, že se mi takový zápis líbí víc <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/asp-net-mvc-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC &#8211; lokalizace url</title>
		<link>http://www.augi.cz/programovani/asp-net-mvc-lokalizace-url/</link>
		<comments>http://www.augi.cz/programovani/asp-net-mvc-lokalizace-url/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 19:02:14 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=412</guid>
		<description><![CDATA[Na dnešním internetu je důležité, aby url měly ten správný tvar, a díky tomu je do jisté míry můžeme považovat za součást prezentační vrstvy. Určitě ale nechceme, aby nějaké stringy z prezentační vrstvy ovlivňovaly to, jak se budou jmenovat naše třídy nebo metody v aplikaci. Ale právě přesně to se v ASP.NET MVC děje &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>Na dnešním internetu je důležité, aby url měly ten správný tvar, a díky tomu je do jisté míry můžeme považovat za součást prezentační vrstvy. Určitě ale nechceme, aby nějaké stringy z prezentační vrstvy ovlivňovaly to, jak se budou jmenovat naše třídy nebo metody v aplikaci. Ale právě přesně to se v ASP.NET MVC děje &#8211; adresa ve tvaru &#8220;<em>/controllerName/actionName</em>&#8221; je typicky mapována na akční metodu s názvem &#8220;<em>actionName</em>&#8221; ve třídě &#8220;<em>controllerName</em>Controller&#8221;. No ale kdo by chtěl mít metodu s názvem &#8220;追加する&#8221;? A co na to lokalizace?<br />
<span id="more-412"></span><br />
Ti zkušenější z vás jistě vědí, že v případě akčních metod se dá toto vyřešit pomocí atributu <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionnameattribute.aspx">ActionName</a>. Pokud nám jde o jednorázové přejmenování, tak je toto řešení v pohodě. Pokud je naším cílem ale nějaké obecnější schéma přejmenování, pak s <em>ActionName</em> nevystačíme. Pokud např. děláme web v češtině a názvy controllerů a akčních metod chceme mít anglicky, tak s <em>ActionName</em> vystačíme.</p>
<p>Předpokládejme teď ale situaci, kdy web má pro více jazyků stejnou strukturu, liší se jen obsah a url. Pak jistě nebudeme chtít mít controllery s názvy Product, Produkt, Producto atd. a podobně pro akční metody. Tedy vnitřek aplikace bude pro všechny jazyky stejný, lišit se budou pouze url (lokalizaci obsahu teď řešit nebudeme). A abychom nemuseli mít uvnitř aplikace code-path pro každý jazyk, bylo by pro nás nejvýhodnější převést problém na předchozí případ, tedy pracovat jen s jedněmi názvy. Naším cílem je tedy jakási normalizace url do standardního tvaru.</p>
<p>Ve webové aplikaci většinou pracujeme s url na dvou místech &#8211; hned na začátku zpracování požadavku (abychom věděli, co vůbec dělat, jaký controller a akční metodu vybrat) a při generování url. Obě tyto věci má pod palcem routing, takže si napíšeme vlastní routovací pravidlo, což je velmi jednoduché. Odvodíme třídu od standardní <a href="http://msdn.microsoft.com/en-us/library/system.web.routing.route.aspx">System.Routing.Route</a> a přetížíme metody <a href="http://msdn.microsoft.com/en-us/library/system.web.routing.route.getroutedata.aspx">GetRouteData</a> (používá se na začátku zpracování požadavku) a <a href="http://msdn.microsoft.com/en-us/library/system.web.routing.route.getvirtualpath.aspx">GetVirtualPath</a> (používá se při generování url), ve kterých zajistíme nahrazení lokalizovaného stringu za normalizovaný, resp. opačně. Jde nám tedy o to, abychom po vstupu url do systému ji znormalizovali, a po výstupu ze systému ji zlokalizovali.<br />
Zde uvedu příklad, který umožní odekorovat controller atributem <em>ControllerName</em> a tím změnit název controlleru pro routing (tedy obdoba již zmiňovaného <em>ActionName</em>).</p>
<pre class="Code"><span style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;">[<span style="color: #2b91af;">AttributeUsage</span>(<span style="color: #2b91af;">AttributeTargets</span>.Class | <span style="color: #2b91af;">AttributeTargets</span>.Interface)]
<p style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">ControllerNameAttribute</span> : <span style="color: #2b91af;">Attribute</span>
<p style="margin: 0px;">{
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> ControllerNameAttribute(<span style="color: blue;">string</span> nameForRouting)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; NameForRouting = nameForRouting;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">string</span> NameForRouting
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">get</span>;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">set</span>;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">}
<p style="margin: 0px;">&nbsp;
<p style="margin: 0px;"><span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">LocalizableRoute</span> : <span style="color: #2b91af;">Route</span>
<p style="margin: 0px;">{
<p style="margin: 0px;">&nbsp;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> LocalizableRoute(<span style="color: blue;">string</span> url, <span style="color: #2b91af;">IRouteHandler</span> routeHandler)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; : <span style="color: blue;">base</span>(url, routeHandler)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: #2b91af;">RouteData</span> GetRouteData(System.Web.<span style="color: #2b91af;">HttpContextBase</span> httpContext)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">var</span> res = <span style="color: blue;">base</span>.GetRouteData(httpContext);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (res == <span style="color: blue;">null</span>)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">return</span> <span style="color: blue;">null</span>;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">object</span> o;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">string</span> s;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (res.Values.TryGetValue(<span style="color: #a31515;">&quot;controller&quot;</span>, <span style="color: blue;">out</span> o) &amp;&amp; (s = o <span style="color: blue;">as</span> <span style="color: blue;">string</span>) != <span style="color: blue;">null</span>)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (RouteToController.TryGetValue(s, <span style="color: blue;">out</span> s))
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; res.Values[<span style="color: #a31515;">&quot;controller&quot;</span>] = s;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">return</span> res;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: #2b91af;">VirtualPathData</span> GetVirtualPath(<span style="color: #2b91af;">RequestContext</span> requestContext, <span style="color: #2b91af;">RouteValueDictionary</span> values)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">object</span> o;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">string</span> s;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (values.TryGetValue(<span style="color: #a31515;">&quot;controller&quot;</span>, <span style="color: blue;">out</span> o) &amp;&amp; (s = o <span style="color: blue;">as</span> <span style="color: blue;">string</span>) != <span style="color: blue;">null</span>)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (ControllerToRoute.TryGetValue(s, <span style="color: blue;">out</span> s))
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; values[<span style="color: #a31515;">&quot;controller&quot;</span>] = s;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">return</span> <span style="color: blue;">base</span>.GetVirtualPath(requestContext, values);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">static</span> <span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">string</span>&gt; RouteToController = <span style="color: blue;">new</span> <span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">string</span>&gt;(<span style="color: #2b91af;">StringComparer</span>.OrdinalIgnoreCase);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">static</span> <span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">string</span>&gt; ControllerToRoute = <span style="color: blue;">new</span> <span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">string</span>&gt;(<span style="color: #2b91af;">StringComparer</span>.OrdinalIgnoreCase);
<p style="margin: 0px;">&nbsp;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">static</span> LocalizableRoute()
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">var</span> ct = <span style="color: blue;">typeof</span>(System.Web.Mvc.<span style="color: #2b91af;">IController</span>);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">var</span> at = <span style="color: blue;">typeof</span>(<span style="color: #2b91af;">ControllerNameAttribute</span>);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> a <span style="color: blue;">in</span> <span style="color: #2b91af;">AppDomain</span>.CurrentDomain.GetAssemblies().Where(aa =&gt; !aa.GlobalAssemblyCache))
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> t <span style="color: blue;">in</span> a.GetTypes().Where(tt =&gt; tt.IsClass &amp;&amp; !tt.IsAbstract &amp;&amp; ct.IsAssignableFrom(tt)))
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">var</span> controllerName = t.Name;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (controllerName.StartsWith(<span style="color: #a31515;">&quot;T4MVC_&quot;</span>))
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">continue</span>;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">var</span> att = t.GetCustomAttributes(at, <span style="color: blue;">true</span>);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (att != <span style="color: blue;">null</span> &amp;&amp; att.Length &gt; 0)
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">var</span> routingName = ((MvcUtils.Attributes.<span style="color: #2b91af;">ControllerNameAttribute</span>)att[0]).NameForRouting;
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (controllerName.EndsWith(<span style="color: #a31515;">&quot;Controller&quot;</span>))
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; controllerName = controllerName.Substring(0, controllerName.Length - <span style="color: #a31515;">&quot;Controller&quot;</span>.Length);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (RouteToController.ContainsKey(routingName))
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">&quot;Controller's routing name '{0}' is ambigious.&quot;</span>, routingName));
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">if</span> (ControllerToRoute.ContainsKey(controllerName))
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue;">throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">&quot;Controller's regular name '{0}' is ambigious.&quot;</span>, routingName));
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RouteToController.Add(routingName, controllerName);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ControllerToRoute.Add(controllerName, routingName);
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; }
<p style="margin: 0px;">}

</span></pre>
<p>Uvedená ukázka je jen takový návod &#8220;jak na to&#8221;. Např. pokud máme url ve tvaru &#8220;<em>langCode/controller/action</em>&#8220;, tak můžeme (de)lokalizaci provádět podle hodnoty <em>langCode</em>, čímž už získáváme ony avizované lokalizované url.</p>
<p>Nyní tedy máme napsanou vlastní třídu routovacích pravidel a už nám zbývá jen vytvořit konkrétní pravidla, typicky v metodě <em>Application_Start</em> v souboru <em>Global.asax.cs</em>. Nemůžeme použít extenzní metodu <em>MapRoute</em>, protože ta používá natvrdo třídu <em>System.Routing.Route</em>, ale i tak se nejedná o nic složitého:</p>
<pre class="Code"><span style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;">routes.Add(<span style="color: #a31515;">&quot;Default&quot;</span>, <span style="color: blue;">new</span> <span style="color: #2b91af;">LocalizableRoute</span>(<span style="color: #a31515;">&quot;{controller}/{action}/{id}&quot;</span>, <span style="color: blue;">new</span> <span style="color: #2b91af;">MvcRouteHandler</span>())
<p style="margin: 0px;">{
<p style="margin: 0px;">&nbsp;&nbsp;&nbsp; Defaults = <span style="color: blue;">new</span> <span style="color: #2b91af;">RouteValueDictionary</span> { { <span style="color: #a31515;">&quot;controller&quot;</span>, <span style="color: #a31515;">&quot;domu&quot;</span> }, { <span style="color: #a31515;">&quot;action&quot;</span>, <span style="color: #a31515;">&quot;Index&quot;</span> }, { <span style="color: #a31515;">&quot;id&quot;</span>, <span style="color: #a31515;">&quot;&quot;</span> }, },
<p style="margin: 0px;">});

</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.augi.cz/programovani/asp-net-mvc-lokalizace-url/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Vytváření instancí předem neznámých tříd v C#</title>
		<link>http://www.augi.cz/programovani/vytvareni-instanci-predem-neznamych-trid-v-c/</link>
		<comments>http://www.augi.cz/programovani/vytvareni-instanci-predem-neznamych-trid-v-c/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 21:15:32 +0000</pubDate>
		<dc:creator>Augi</dc:creator>
				<category><![CDATA[Programování]]></category>

		<guid isPermaLink="false">http://www.augi.cz/?p=409</guid>
		<description><![CDATA[Pokud se snažíte v C# psát aplikace modulárně a genericky, tak můžete narazit na to, co je naznačeno v nadpisu &#8211; vytváření instancí tříd, jejichž typ není v době kompilace znám. Jak na to si ukážeme v tomto článku, včetně porovnání výkonu. Konkrétně se zaměřím na vytváření instancí pomocí bezparametrického konstruktoru a příliš nebudu řešit [...]]]></description>
			<content:encoded><![CDATA[<p>Pokud se snažíte v C# psát aplikace modulárně a genericky, tak můžete narazit na to, co je naznačeno v nadpisu &#8211; vytváření instancí tříd, jejichž typ není v době kompilace znám. Jak na to si ukážeme v tomto článku, včetně porovnání výkonu. Konkrétně se zaměřím na vytváření instancí pomocí bezparametrického konstruktoru a příliš nebudu řešit to, kolik zabere příprava té které metody instanciace &#8211; jde mi o vytváření velkého množství instancí malého počtu tříd.<br />
<span id="more-409"></span><br />
Dejme tomu, že jsou dva způsoby, jak dostat informaci o typu třídy, jejíž instanci chceme vytvořit.</p>
<h2>Generický parametr</h2>
<p>Začněme tím víc typovým způsobem &#8211; máme za úkol vytvořit instanci typu, jenž máme předán jako parametr generiky. Na generické parametry můžeme klást různé požadavky (za klíčovým slovem <em>where</em>) a jedním z nich je existence bezparametrického konstruktoru (<em>new()</em>). Konstrukce instance třídy předané jako generický parametr vypadá takto:</p>
<pre class="Code"><span style="font-family: Monospace;"><span style="color: blue;">class</span><span style="color: black;"> </span><span style="color: #2b91af;">ClassFactory</span><span style="color: black;">&lt;T&gt; </span><span style="color: blue;">where</span><span style="color: black;"> T : </span><span style="color: blue;">new</span><span style="color: black;">()
{
    </span><span style="color: blue;">public</span><span style="color: black;"> </span><span style="color: blue;">static</span><span style="color: black;"> T Create()
    {
        </span><span style="color: blue;">return</span><span style="color: black;"> </span><span style="color: blue;">new</span><span style="color: black;"> T();
    }
}</span> </span></pre>
<p>To je z hlediska designu docela pěkný, silně typový, přístup s kontrolou existence bezparametrického konstruktoru. Podívejme se teď, jaký <a href="http://en.wikipedia.org/wiki/Common_Intermediate_Language">CIL</a> kód nám z této metody vypadl:</p>
<p><img class="aligncenter size-full wp-image-410" title="CIL - new T()" src="http://www.augi.cz/wp-content/uploads/cil_create_instance.png" alt="CIL - new T()" width="340" height="310" /></p>
<p>Jak vidno, volá se statická generická metoda <em>System.Activator.CreateInstance&lt;T&gt;</em>. Tato metoda je úplně normální a můžeme ji tudíž použít na vytvoření instance kdykoliv, když máme k dispozici generický typ. Můžeme ji použít ale i tehdy, když nemáme na generickém parametru specikováno omezení <em>new()</em>, což může vyústit ve výjimku za běhu. Proto doporučuji navrhnout aplikaci tak, abychom se přímémo volání metody <em>CreateInstance&lt;T&gt;</em> vyhnuli (tzn. nějak zajistit omezení generického parametru). Ve stejném duchu se vyjadřuje i <a href="http://msdn.microsoft.com/en-us/library/0hcyx2kd.aspx">dokumentace k této metodě</a>.</p>
<h2>System.Type</h2>
<p>Druhým způsobem, jak se k nám může dostat informace o třídě, jejíž instanci máme vytvořit, je pomocí třídy <em>System.Type</em>. Tuto třídu můžeme získat různými způsoby:</p>
<pre class="Code"><span style="font-family: Monospace;"><span style="color: #2b91af;">Type</span><span style="color: black;"> t1 = </span><span style="color: blue;">typeof</span><span style="color: black;">(</span><span style="color: #2b91af;">TestClass</span><span style="color: black;">); </span><span style="color: green;">// přímo z typu
</span><span style="color: #2b91af;">Type</span><span style="color: black;"> t2 = someObject.GetType(); </span><span style="color: green;">// z kterékoliv instance lze získat aktuální typ
</span><span style="color: #2b91af;">Type</span><span style="color: black;"> t3 = System.Reflection.</span><span style="color: #2b91af;">Assembly</span><span style="color: black;">.GetEntryAssembly().GetType(</span><span style="color: #a31515;">"Test.TestClass"</span><span style="color: black;">); </span><span style="color: green;">// ze stringu!
</span><span style="color: #2b91af;">Type</span><span style="color: black;"> t4 = </span><span style="color: blue;">typeof</span><span style="color: black;">(</span><span style="color: #2b91af;">ClassFactory</span><span style="color: black;">&lt;&gt;).MakeGenericType(t1); </span><span style="color: green;">// získání typu generiky s konkrétním generickým typem</span> </span></pre>
<p>A jak vytvořit instanci takové typu, o němž máme informaci v podobě instance třídy <em>System.Type</em>? Takto <img src='http://www.augi.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre class="Code"><span style="font-family: Monospace;"><span style="color: green;">// jednoduše
</span><span style="color: blue;">var</span><span style="color: black;"> i1 = </span><span style="color: #2b91af;">Activator</span><span style="color: black;">.CreateInstance(t1);
</span><span style="color: green;">// složitěji - získáme konstruktor a zavoláme ho
</span><span style="color: blue;">var</span><span style="color: black;"> i2 = t1.GetConstructor(</span><span style="color: #2b91af;">Type</span><span style="color: black;">.EmptyTypes).Invoke(</span><span style="color: blue;">null</span><span style="color: black;">);</span> </span></pre>
<p>Výhodou těchto dvou řešení je to, že ho můžeme použít i pro konstruktory s parametry. Nevýhodou je ukrutná pomalost. Proto uvedu ještě jedno řešení, které spočívá v tom, že si dynamicky vygenerujeme CIL kód, který vytváří instanci třídy:</p>
<pre class="Code"><span style="font-family: Monospace;"><span style="color: green;">// vytvoříme dynamickou metodu
</span><span style="color: blue;">var</span><span style="color: black;"> dynamicMethod = </span><span style="color: blue;">new</span><span style="color: black;"> </span><span style="color: #2b91af;">DynamicMethod</span><span style="color: black;">(</span><span style="color: #a31515;">"blabla"</span><span style="color: black;">, t1, </span><span style="color: #2b91af;">Type</span><span style="color: black;">.EmptyTypes);
</span><span style="color: blue;">var</span><span style="color: black;"> ilGenerator = dynamicMethod.GetILGenerator();
</span><span style="color: green;">// vygenerujeme do ní kód, který zavolá bezparametrický konstruktor
</span><span style="color: black;">ilGenerator.Emit(</span><span style="color: #2b91af;">OpCodes</span><span style="color: black;">.Newobj, t1.GetConstructor(</span><span style="color: #2b91af;">Type</span><span style="color: black;">.EmptyTypes));
</span><span style="color: green;">// a vrátí jeho výsledek
</span><span style="color: black;">ilGenerator.Emit(</span><span style="color: #2b91af;">OpCodes</span><span style="color: black;">.Ret);
</span><span style="color: green;">// vycucneme si delegáta na dynamickou metodu
</span><span style="color: blue;">var</span><span style="color: black;"> creator = (</span><span style="color: #2b91af;">Func</span><span style="color: black;">&lt;</span><span style="color: blue;">object</span><span style="color: black;">&gt;)dynamicMethod.CreateDelegate(</span><span style="color: blue;">typeof</span><span style="color: black;">(</span><span style="color: #2b91af;">Func</span><span style="color: black;">&lt;</span><span style="color: blue;">object</span><span style="color: black;">&gt;));
</span><span style="color: green;">// a voláme delegáta, který nám vrací instance
</span><span style="color: blue;">var</span><span style="color: black;"> instance = creator();</span> </span></pre>
<p><a href="http://vlko.zilina.net/">vlko</a> mi v komentáři připomněl ještě jednu možnost, jak vytvářet instance (díky!). Je to podobné jako předchozí generování CILu, ale je to trošku abstrahovanější, modernější. Vygenerujeme takovou lambda expression, která bude vracet novou instanci, a tuto lambda expression zkompilujeme na delegáta. Kdybych udělali ale toto, tak dostaneme výjimku za běhu:</p>
<pre class="Code"><span style="font-family: Monospace;"><span style="color: blue;">var</span><span style="color: black;"> lambdaCreator = (</span><span style="color: #2b91af;">Func</span><span style="color: black;">&lt;</span><span style="color: blue;">object</span><span style="color: black;">&gt;)System.Linq.Expressions.</span><span style="color: #2b91af;">Expression</span><span style="color: black;">.Lambda(System.Linq.Expressions.</span><span style="color: #2b91af;">Expression</span><span style="color: black;">.New(</span><span style="color: blue;">typeof</span><span style="color: black;">(</span><span style="color: #2b91af;">TestClass</span><span style="color: black;">))).Compile();</span> </span></pre>
<p>Konkrétně tuto výjimku: <em>Objekt typu System.Func`1[CreateInstanceTest.TestClass] nelze přetypovat na typ System.Func`1[System.Object].</em>. Problém je v tom, že jazyk C# 3.0 nepodporuje kontravarianci generických typů, tudíž nelze přetypovat <em>Func&lt;TestClass&gt;</em> na <em>Func&lt;object&gt;</em>. V C# 4.0 už toto bude bez problémů možné.<br />
Aby vytváření instancí pomocí zkompilované lambda expression fungovalo i v C# 3.0, musíme vygenerovat takovou lambda expression, která bude přímo vracet <em>Func&lt;object&gt;</em> &#8211; tudíž musíme nově vytvořenou instanci ještě v lambda expression přetypovat na <em>object</em>:</p>
<pre class="Code"><span style="font-family: Monospace;"><span style="color: blue;">var</span><span style="color: black;"> lambdaCreator = (</span><span style="color: #2b91af;">Func</span><span style="color: black;">&lt;</span><span style="color: blue;">object</span><span style="color: black;">&gt;)System.Linq.Expressions.</span><span style="color: #2b91af;">Expression</span><span style="color: black;">.Lambda(System.Linq.Expressions.</span><span style="color: #2b91af;">Expression</span><span style="color: black;">.Convert(System.Linq.Expressions.</span><span style="color: #2b91af;">Expression</span><span style="color: black;">.New(</span><span style="color: blue;">typeof</span><span style="color: black;">(</span><span style="color: #2b91af;">TestClass</span><span style="color: black;">)), </span><span style="color: blue;">typeof</span><span style="color: black;">(</span><span style="color: blue;">object</span><span style="color: black;">))).Compile();
</span><span style="color: blue;">var</span><span style="color: black;"> instance = lambdaCreator();</span> </span></pre>
<p>Místo metody <em>Convert</em> můžeme použít také <em>ConvertChecked</em> nebo <em>TypeAs</em>, ale <em>Convert</em> je podle mých jednoduchých měření nejefektivnější.</p>
<h2>Výkon</h2>
<p>Na závěr uvedu jednoduché výkonové srovnání jednotlivých metod, včetně zpomalení oproti běžnému volání <em>new</em>. Měření není nikterak přesné a má sloužit je k orientaci v problematice. Vždy jsem vytvářel 1024 * 1024 instancí jednoduché <em>public</em> třídy:</p>
<table border="0">
<tbody>
<tr>
<th>Způsob</th>
<th>Čas v ms</th>
<th>Zpomalení</th>
</tr>
<tr>
<td><em>new TestClass();</em></td>
<td>20,55</td>
<td>1,0</td>
</tr>
<tr>
<td><em>Activator.CreateInstance<TestClass>();</em></td>
<td>1980</td>
<td>96</td>
</tr>
<tr>
<td><em>ClassFactory<TestClass>.Create();</em></td>
<td>1998</td>
<td>97</td>
</tr>
<tr>
<td><em>Activator.CreateInstance(typeof(TestClass))</em></td>
<td><strong>289</strong></td>
<td><strong>14</strong></td>
</tr>
<tr>
<td><em>ctor.Invoke(null)</em></td>
<td><strong>1641</strong></td>
<td><strong>80</strong></td>
</tr>
<tr>
<td><em>creator()</em></td>
<td>27,64</td>
<td>1,3</td>
</tr>
<tr>
<td><em>lambdaCreator()</em></td>
<td>30,09</td>
<td>1,5</td>
</tr>
</tbody>
</table>
<p>Jak vidno, <em>Activator.CreateInstance&lt;T&gt;()</em> a <em>new T()</em> je stejně rychlé, což jsme si již vysvětlili. Negenerická metoda <em>Activator.CreateInstance()</em> stejně jako přímé volání konstruktoru o dost pomalejší než klasické vytvoření pomocí <em>new</em>. Tomu se přibližuje jen dynamicky vyemitovaný CIL kód, resp. zkompilovaná lambda expression.</p>
<p>Jak jsem psal, toto měření proběhlo pro vytváření <em>public</em> třídy. Pokud ale změníme viditelnost třídy na <em>internal</em>, dostáváme jiná čísla:</p>
<table border="0">
<tbody>
<tr>
<th>Způsob</th>
<th>Čas v ms</th>
<th>Zpomalení</th>
</tr>
<tr>
<td><em>new TestClass();</em></td>
<td>20,49</td>
<td>1,0</td>
</tr>
<tr>
<td><em>Activator.CreateInstance<TestClass>();</em></td>
<td>1965</td>
<td>96</td>
</tr>
<tr>
<td><em>ClassFactory<TestClass>.Create();</em></td>
<td>1966</td>
<td>96</td>
</tr>
<tr>
<td><em>Activator.CreateInstance(typeof(TestClass))</em></td>
<td><strong>4071</strong></td>
<td><strong>199</strong></td>
</tr>
<tr>
<td><em>ctor.Invoke(null)</em></td>
<td><strong>4877</strong></td>
<td><strong>238</strong></td>
</tr>
<tr>
<td><em>creator()</em></td>
<td>26,83</td>
<td>1,3</td>
</tr>
<tr>
<td><em>lambdaCreator()</em></td>
<td>32,09</td>
<td>1,6</td>
</tr>
</tbody>
</table>
<p>Co k tomu říci? Snad jen &#8211; zajímavé <img src='http://www.augi.cz/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
Pro úplnost přikládám <a href="/wp-content/uploads/CreateInstanceTest.cs">testovací kód</a>.</p>
<h2>Závěr</h2>
<p>Pokud máme vytvářet instanci typu, jehož přesný typ není v době kompilace znám, je z hlediska výkonu (nepočítaje start-up) nejvýhodnější využít možnosti generování CIL kódu. Pokud chceme takto použít konstruktor s parametry, je to také možné, ale vytváření dynamické metody již bude složitější.<br />
Upřednostnění metody s generováním CILu platí i pro situaci, kdy máme typ k dispozici ve formě generického parametru s omezením <em>new()</em>. Bude to rychlejší než volání <em>new T()</em>. Omezení na generický typ bych ale určitě nechal, abychom se nepřipravili o kontrolu během kompilace.<br />
No a pokud nechceme toto vůbec řešit, můžeme využít třeba služeb nějakého <a href="http://martinfowler.com/articles/injection.html">IoC/DI</a> kontejneru <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/vytvareni-instanci-predem-neznamych-trid-v-c/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
