Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Service Locator

11.44 - 30. května 2009 | ASP.NET 2.0

Znáte vzor Service Locator? Pravděpodobně jste s ním setkali nespočetněkrát aniž byste o tom věděli.

Service Locator je návrhový vzor, který je součástí techniky dependency injection / inversion of control. Jeho úkolem je dodat hotové instance služeb na vyžádání. Můžeme si ho představit nějak tak:

public interface IServiceLocator {
  TService GetService<TService>();
  IEnumerable<TService> GetServices<TService>();
}

Jeho úkolem je poskytnout službu daného typu nebo všechny služby, které splňují danný kontrakt. K čemu je to dobré? Dobré je to především pro konfigurovatelné a rozšiřitelné aplikace. Řekněme, že budu chtít do svého redakčního systému přidat možnost oznámení na e-mail, když někdo zadá komentář. První řešení bude nejspíš to přímočaré:

public class CommentsController : Controller {
  public ActionResult AddComment(Comment comment) {
    // validace a persistence komentáře

    var notificator = new EmailNotificator();
    notificator.send(new CommentNotification(comment));

    return Json(comment);
  }
}

Proč nepřidat možnost odesílání SMSek? Tak jo:

public class CommentsController : Controller {
  public ActionResult AddComment(Comment comment) {
    // validace a persistence komentáře

    var emailNotificator = new EmailNotificator();
    emailNotificator.send(new CommentNotification(comment));

    var smsNotificator = new SmsNotificator();
    smslNotificator.send(new CommentNotification(comment));

    return Json(comment);
  }
}

Skvěle, teď ještě posílání na Twitter nebo na FriendFeed a akce nám krásně roste… :) Takže se oprostíme od toho, že dopředu víme, kudy všudy se chceme nechat informovat o nových komentářích a využijeme Service Locator:

public class CommentsController : Controller {

  private readonly IServiceLocator _serviceLocator;

  public CommentsController(IServiceLocator serviceLocator) {
    _serviceLocator = serviceLocator;
  }

  public ActionResult AddComment(Comment comment) {
    // validace a persistence komentáře

    var newCommentNotification = new CommentNotification(comment);
    var notificators = _serviceLocator.GetServices<INotificator>();
    notificators.Each(notificator => notificator.send(newCommentNotification));

    return Json(comment);
  }
}

Tím jsme také vyřešili problém vznikající při constructor injection a to rostoucí počet parametrů konstruktoru s rostoucími závislostmi. Protože service locator nám dokáže obstarat potřebné služby, nemusíme je injektovat zvlášť.

Ještě se vrátím k poznámce v úvodu, kde jsem psal, že jste se určitě s tímto vzorem setkali, aniž byste si toho byli vědomi. O co jde? O Singleton! :) Singleton je speciální případ service locatoru, který vrací službu jediného typu s řízeným životním stylem jedináčka.

To je všechno pěkné, ale jak tedy service locator ví, jak ty služby získat a jakej mají životní styl? Pokud používáte IoC kontejner, odpověd je snadná: service locator si udělám jako fasádu nad kontejnerem a tu do něj zaregistrujeme. Pokud žádný IoC kontejner nepoužíváte, tak si honem nějaký sežeňte! :)

Autor: Aleš Roubíček | 4x komentováno | Delicious | FriendFeed | Facebook | Linkuj!

Validace v ASP.NET MVC

13.56 - 2. května 2009 | ASP.NET 2.0

Bezpodmínečnou nutností každé aplikace, která zpracovává data z neznámých zdrojů, je validace vstupních dat. V ASP.NET je poměrně sofistikovaná sada komponent, které přidají k vašim vstupním polím validační podmínky a v případě jejich nesplnění je uživatel informován. Validace probíhá jak na straně klienta (pomocí JavaScriptu), tak i na straně serveru. Jenže tyto komponenty jsou plně závislé na serverovém formuláři a v ASP.NET MVC je tedy nelze použít.

Nyní mírně odbočím. Z předchozího odstavce jste si mohli odnést jednu myšlenku. A to, že validace je součástí UI vrstvy aplikace. Pokud však píšete aplikaci, která obsahu spoustu business pravidel, není to úplně nejšťastnější, když máte validační pravidla v UI a pak ještě někde ve vašem modelu. Jedno ze základních pravidel dobrého návrhu říká DRY (don’t repeat yourself – neopakuj se).

ModelState

ASP.NET MVC tedy nepřináší validátory, ale infrastrukturu, která umožňuje v případě chyby uživatele upozornit. Tato infrastruktura je postavená na stavu modelu (ModelState). Stav modelu má vlastnost IsValid a metodu AddModelError. V HtmlHelperu pak najdete dvě extenze ValidationMessage a ValidationSummary, které vypisují chybové hlášky pro konkrétní pole nebo sumář pro všechny. A to je vše, co nám MVC poskytuje. Další práce už je jen na nás.

Jak pracovat se stavem modelu na nejnižší úrovni ukazuje jeden z tutoriálů: Performing Simple Validation. Možná vám to bude stačit, ale pro mne je to příliš práce navíc a ani trochu mi to nepřijde sexy. :) Jaké máme další možnosti?

Můžeme využít vlastní validační vrstvu naší business logiky a napojit jí na stav modelu, tak, jak to ukazuje následující tutoriál: Validating with a Service Layer. Nebo vyžijeme existujících validačních frameworků. Dnes se podíváme na System.Componen­tModel.DataAn­notations a příště na Caste.Componen­ts.Validators.

DataAnnotations

Anotace dat je novinka z ASP.NET Dynamic Data, která usnadňuje automatické generování ASP.NET validátorů na základě modelu. Tyto anotace se dále rozšiřují a v .net 4.0 by to měla být hodně použitelná věcička, která bude v ASP.NET DD, ASP.NET MVC a dokonce i v .net RIA Services. Každopádně nemusíme čekat na velký release platformy a využít anotací již dnes. Jak to tedy funguje?

Jediné, co musíte udělat, je označit vlastnosti vašeho modelu atributy:

[Required]
public string Name { get; set; }

[RegularExpression("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$ ")]
public string Email { get; set; }

Dalším krokem je zaregistrovat nový model binder ` DataAnnotation­sModelBinder`, který na základě anotací provede validaci modelu a nastaví případně jeho stav na nevalidní. O víc už se starat nemusíme. Kde tento model binder získat a další potřebné informace najdete v článku Brada Wilsona DataAnnotations and ASP.NET MVC.

Protože jsem DataAnnotations použil v jedné aplikaci, tak mám několik zkušeností, o které se můžu podělit. DataAnnotation­sModelBinder má problém s komplexními typy, které mají vlastnosti taktéž komplexních typů. Jedním z možných řešení, je hacknout tento model binder a přidat podmínku na ověření komplexní vlastnosti, nebo používat DTO pouze pro účely formulářů ve view (ano, opět návrat k validaci pouze ve view vrstvě). Anotace podporují vracení chybových hlášek z resource souborů, tak nezapomeňte raději všechny hlášky přepsat, protože ty výchozí nevypadají zrovna nejlépe.

Tak, to bychom měli jeden model binder, který už je hotový. Ale jak si napsat vlastní? To si ukážeme někdy příště na Caste.Componen­ts.Validators­. :)

Autor: Aleš Roubíček | 3x komentováno | Delicious | FriendFeed | Facebook | Linkuj!

Vlastní serverové ovládací prvky v ASP.NET MVC

10.32 - 29. března 2009 | Webdesign

Motto: foreach je fajn na prototypování, ale většinou mu za chvíli dojde dech a svádí k zanášení příliš logiky do kódu šablony. A to je špatně.

Už jsem se zmiňoval o tom, že v ASP.NET MVC lze užívat serverové ovládací prvky, takže je využijeme k zapouzdření složitější zobrazovací logiky.

Motivace

Jednou z hlavních nevýhod, kterou jsem viděl na MVC, byl přístup ke skládání šablon. Jednotlivé kusy šablony jsou rozházeny v MasterPage, ViewPage (aspx) a ViewUserControlech (ascx). V Atlasu jsme razili teorii, že šablona by měla být pokud možno co nejcelistvější, aby se nemuselo nikde nic hledat a kodér rychle udělal potřebné změny. Proto existovala sada serverových ovládacích prvků, které byly plně šablonovatelné.

Když naběhlo CHEllou, nechápali jsme, jak to může někdo používat. Každičká část šablony byla (v té době, jak je to dnes – nevím) byla rozeseta v hierarchii složek (podle dědičnosti). A to je v podstatě hlavní rozdíl mezi ASP.NET a architekturou MVC. Tedy pokud jste omezeni view enginem, který používáte.

Již nějaký pátek pracuji na web 2.0 aplikaci, která je postavená mj. na ASP.NET MVC. Měl jsem tedy možnost vyzkoušet hodně možných postupů: od logiky v šabloně, přes HTML helpery, RenderPartial a RenderAction až po vlastní serverové ovládací prvky. A ty nakonec vítězí na plné čáře! Pojďme se podívat, jak si napsat elegantní serverové ovládací prvky pro ASP.NET MVC.

Evoluce logiky v šabloně

Začínal jsem s nadšením s jednoduchou logikou v kódu, tak jak to vidíte v ukázkách či na prezentacích o ASP.NET MVC. Složitější věci jsem se snažil přesunout do HtmlHelperu pomocí vlastních extenzí. Když jsem pak narazil na helpery, které zanáší do view „lambda hell“, trochu mě zamrazilo. Vyberu jen dva příklady: Philův Code based Repeater for ASP.NET MVC a Jardův Simple MVC controls. Nebojte, podobných programátorských krás najdete povícero. Bohužel, je to nepoužitelné pro kodéra. Navíc jsem zastáncem myšlenky minima kódu v šabloně.

Další věcí, která mě tak trochu děsí, je jakým způsobem se předvádí generování HTML formuláře.

<% using(Html.BeginForm("Send", "Comments")) { %>
  <!-- prvky formuláře -->
<% } %>

Je to krásná ukázka užití vzoru IDisposable, ale do šablony nepatří. Helpery uživát jen jako dobré koření – po špetkách.

<form action='<%= Url.Action("Send", "Comments")) %>' method="post">
  <!-- prvky formuláře -->
</form>

Myslím, že takovýto zápis je mnohem srozumitelnější a přitom dělá to samé. Jako bonus můžete ve vašem HTML editoru využívat scope collapsing. Vhodnější by ještě bylo použít helper Url.RouteUrl, který hledá routy podle klíče a tudíž je o dost výkonnější (pokud máte definováno více rout).

Opusťme teď formulář a pokročme k vypisování dat.

Prvním způsobem, jak vypisovat data, je foreach. Je silně typový, což považuju za obrovskou výhodu, a nepřináší overhead v podobě instanciování tříd a parsování šablon serverových ovládacích prvků.

<ul>
<% foreach (var user in Model.Users) { %>
<li><%= user.Name %></li>
<% } %>
</ul>

Tím však jeho možnosti končí. Pokud potřebujeme např. odlišit každou druhou položku, nebo vypsat něco jiného, pokud nejsou žádná data, musíme kód znepřehledňovat, nebo zvolit jiné řešení. Philův repeater už jsem zmiňoval. Další možností je využít asp:Repeater nebo mvc:Repeater. Ani jeden mi nevyhovuje. První se musí nějak nalít daty a pak s nimi svázat (nutnost codebehind nebo script runat=server), druhý zase pracuje s ViewData slovníkem a evalováním. Takže nezbývá než si napsat vlastní.

Silně typový repeater v ASP.NET MVC

Základem je jednoduchá myšlenka. Použít MvcControl z futures a view model opatřit kontrakty.

public interface IHaveUsers {
  IEnumerable<User> Users { get; }
}

public class UsersListViewData : IHaveUsers {
  public IEnumerable<User> Users { get; set; }
  // další vlastnosti view modelu
}

Zavedli jsme si view model třídu, která se nejspíš bude posílat na pohled Index řadičem UsersController. Možná. Každopádně jsme si zavedli jednoduchou abstrakci a možnost znovupoužití v podobě rozhranní IHaveUsers. Snad můžeme dál.

using Microsoft.Web.Mvc;
using Rarous.Web.UI;

[ParseChildren(true)]
public partial class UsersRepeater : MvcControl, ILayoutTemplateable {

  [DefaultValue(typeof(ITemplate), "")]
  [PersistenceMode(PersistenceMode.InnerProperty)]
  [TemplateContainer(typeof(IGenericContainer<User>))]
  [TemplateInstance(TemplateInstance.Multiple)]
  public ITemplate ItemTemplate { get; set; }

  [DefaultValue(typeof(ITemplate), "")]
  [PersistenceMode(PersistenceMode.InnerProperty)]
  [TemplateContainer(typeof(IGenericContainer<User>))]
  [TemplateInstance(TemplateInstance.Multiple)]
  public ITemplate AlternatingItemTemplate { get; set; }

  [DefaultValue(typeof(ITemplate), "")]
  [PersistenceMode(PersistenceMode.InnerProperty)]
  [TemplateContainer(typeof(INamingContainer))]
  [TemplateInstance(TemplateInstance.Multiple)]
  public ITemplate SeparatorTemplate { get; set; }

  public string LayoutContainerId { get; set; }

  [DefaultValue(typeof(ITemplate), "")]
  [PersistenceMode(PersistenceMode.InnerProperty)]
  [TemplateContainer(typeof(INamingContainer))]
  [TemplateInstance(TemplateInstance.Single)]
  public ITemplate LayoutTemplate { get; set; }
}

Podědili jsme si MvcControl, který mimo jiné zpřístupňuje ViewData, a implementovali nějaké šablony.

public partial class UsersRepeater {
  private class UsersViewDataFetcher {
    public IEnumerable<User> GetUsers(object model) {
      var result = model as IHaveUsers;
      if (result != null) {
        return result.Users;
      }
      return null;
    }
  }
}

Jednoduchý helper pro získávání dat z modelu. Zkouší využít kontraktu IHaveUsers, který jsme si zavedli výše, k získání dat z modelu. Zde je místo pro budoucí rozšíření o další možné zdroje. Pokud nic nenajdeme, vrátíme null.

public partial class UsersRepeater {
  protected override void OnPreRender(EventArgs e) {
    base.OnPreRender(e);

    var fetcher = new UsersViewDataFetcher(ViewData.Model);
    var users = fetcher.GetUsers();
    if (users == null) {
      return; // nebo verenderovat NoDataTemplete
    }

    Controls.Clear();

    Control layoutContainer = TemplatingHelper.CreateLayoutContainer(this, this) ?? this;

    var iterator = new ItemsIterator<User>(users);
    foreach (var user in iterator.Iterate()) {
      if (iterator.IsFirst == false) {
        TemplatingHelper.Instantiate(new EmptyContainer(), SeparatorTemplate, layoutContainer);
      }
      ITemplate template = iterator.IsAlternate ? AlternatingItemTemplate ?? ItemTemplate : ItemTemplate;
      TemplatingHelper.Instantiate(new GenericContainer<User>(user), template, layoutContainer);
    }

    layoutContainer.DataBind();
  }
}

Nakonec přepíšeme metodu OnPreRender, ve které získaná data proměníme pomocí šablon na výstupní kód. Používám zde spoustu věcí, které jsem použil již dříve. Jedinou novinkou je třída ItemsIterator, která zaobaluje logiku, pro zjišťování, zda jde o první prvek, alternativní prvek a počítá aktuální index prvku.

public class ItemsIterator<T> {

  private readonly IEnumerable<T> _items;

  public ItemsIterator(IEnumerable<T> items)
    : this(items, 0) {
  }

  public ItemsIterator(IEnumerable<T> items, int firstIndex) {
    _items = items;
    IsFirst = true;
    IsAlternate = false;
    CurrentIndex = firstIndex;
  }

  public bool IsFirst { get; private set; }
  public bool IsAlternate { get; private set; }
  public int CurrentIndex { get; private set; }

  public IEnumerable<T> Iterate() {
    foreach (var item in _items) {
      yield return item;
      IsFirst = false;
      IsAlternate = !IsAlternate;
      CurrentIndex++;
    }
  }
}

Jednoduchá věcička, která je určená k eliminaci otrocky opakovaného kódu.

Užití takového repeateru je pak jednoduché:

<rarous:UsersRepeater runat="server" LayoutContainerId="UsersPlaceHolder">
  <LayoutTemplate>
    <ul>
      <asp:PlaceHolder ID="UsersPlaceHolder" runat="server"/>
    </ul>
  </LayoutTemplate>
  <ItemTemplate>
    <li><%# Container.DataItem.Name %></li>
  </ItemTmplate>
</rarous:UsersRepeater>

Závěr

Snažil jsem se sdělit svůj názor, že v šablonách by mělo být jen tolik programového kódu, kolik je nezbytně nutné. Zároveň se držet zásady jediné zodpovědnosti tříd a znuvupoužitelnosti s využitím generického pomocníka pro iteraci a kontraktů ve view modelu. Zároveň maximálně využít kód, který jsem už psal v předchozích spotech. Je možné, že jsem nepoužil dostatečně kvalitní názvy tříd nebo metod, připomínky klidně piště i k nim.

Autor: Aleš Roubíček | 10x komentováno | Delicious | FriendFeed | Facebook | Linkuj!

Zdroje o ASP.NET MVC pro začátečníky

18.51 - 11. března 2009 | Webdesign

Možná hledáte nějaký materiál, který vám pomůže začít s ASP.NET MVC. Pojďme se podívat, jaké máte možnosti.

Knihy

Asi nejčastějšími studijními materiály jsou knihy. Protože je ASP.NET MVC ještě hodně mladý framework, který ještě nebyl oficiálně vydán (produkční verze), žádná kniha ještě nevyšla. Ale minimálně na dvou se usilovně již několik měsíců pracuje. Ještě lepší zprávou je, že jejich rozpracované verze jsou už nyní k dispozici!

Za první knihou ASP.NET MVC Framework Unleashed stojí Senior Program Manager ASP.NET MVC a autor jedné z nejprodávanějších knih o ASP.NET  – Stephen Walther. Jednotlivé kapitoly publikuje na svém blogu. Ty budou po jejím dokončení z blogu staženy. Publikovány byly zatím tyto kapitoly:

  1. Chapter 1 – An Introduction to ASP.NET MVC
  2. Chapter 2 – Building a Simple ASP.NET MVC Application
  3. Chapter 3 – Understanding Controllers
  4. Chapter 4 – Understanding Views
  5. Chapter 5 – Understanding Models
  6. Chapter 6 – Understanding HTML Helpers
  7. Chapter 9 – Understanding Routing

Další knihou je Professional ASP.NET MVC 1.0 z rukou pánů Scott Guthrie, Phil Haack, Scott Hanselman a Rob Conery. Pokud nevíte, kdo jsou tito pánové zač, tak byste to měli rychle dohnat. ScottGu je autorem ASP.NET a dnes je vicepresidentem vývojářské divize Microsoftu. Phil je Senior Program Manager ASP.NET MVC, Routingu a integrace dynamických jazyků do ASP.NET. ScottHa byl první, kdo loni na MIXu ASP.NET MVC presentoval a Rob Conery je autorem ukázkové aplikace – a především poučných screencastů z její tvorby – StoreFront, která je postavená na MVC frameworku. Z knihy byla zatím uvolněna první kapitola, která je průvodcem krok za krokem jak začít stavět aplikaci s ASP.NET MVC.

Ukázkové aplikace

Pokud se vám dobře učí čtením zdrojových kódů, není nic lepšího, než si zdrojové kódy ASP.NET MVC stáhnout na CodePlexu. Z nich můžete pochytit ledasco, ale jak s tím dělat aplikace už moc ne. Proto tu jsou ukázkové aplikace. Tou první a asi nejrozsáhlejší je MVC Storefront. Jenže její zdrojáky byly chvíli na CodePlexu, pak je Rob smazal a slibuje, že brzy budou nové – aktuální. Další ukázková aplikace vznikla pro potřeby druhé jmenované knihy a jmenuje se Nerddinner.

Webcasty

Když ještě nejsou k MVC Storefront zdrojáky, tak vězte, že k němu je asi pětadvacet screencastů! Rob zde provádí vývojem e-shopu. Během té doby prozkoumává různá zákoutí webového vývoje, vylepšuje design aplikace, užívá užitečných komponent atd. Rozhodně stojí za zhlédnutí.

Další videa, která vám snad pomohou s MVC frameworkem začít, najdete přímo na stránkách ASP.NET MVC.

Záznamy přednášek

Doporučení hodné jsou záznamy z loňského MIXu a PDC, konkrétně tyto:

  1. Developing ASP.NET Applications Using the Model View Controller Pattern
  2. ASP.NET MVC : A New Framework for Building Web Applications

Na letošním MIX, který bude již příští týden, bude asi 5 přednášek věnovaných ASP.NET MVC a očekává se, že tam bude také uvedena jeho finální verze.

Na loňském WebExpu jsem měli s Borkem přednášku o ASP.NET Futures a o MVC jsem také mluvili. Přednáška se natáčela, a pokud bude záznam zveřejněn, tak tam možná najdete pár zajímavých informací. :)

Blogy

Zatím největším zdrojem a zároveň nejroztříštěnějším jsou blogspoty. Nejvíc informací najdete na blozích již výše zmiňovaných pánů. Do jejich společnosti se rád vloudím i se svojí troškou do mlýna, ale troufnu si tvrdit, že v některých už jde o trošičku pokročilejší témata a pro jejich pochopení byste už něco měli mít načteno a nazkoušeno. :)

No koukám, že se mi tady z toho stává pěkná linkfarma, tak to raději ukončím a doufám, že se máte od čeho odrazit…

Autor: Aleš Roubíček | 9x komentováno | Delicious | FriendFeed | Facebook | Linkuj!

Nedělní WTF: Základy programování v jazyce Boo

17.16 - 8. března 2009 | Jen tak

Při pravidelném proklikávání se službou Devlogy.cz jsem zaznamenal výskyt dalšího dílu seriálu Základy programování v jazyce Boo na serveru programujte.com. Vzpomněl jsem si na první díl seriálu, který jsem četl před časem, a opět se mi naježila srst. Šel jsem se tedy podívat, jak s tím autor vládne dál.

No děs a bída. Jestli se takhle někde programuje a ještě k tomu v Boo, tak to je mi moc líto. Boo vzniklo jako agilní jazyk inspirovaný jednoduchostí Pythonu a silou dotnetu. Sice je silně typový, ale nenutí nás typy explicitně vyjadřovat. V podstatě nás nenutí k žádným zbytečnostem. Jeho filosofii lze ukázat na následujících ukázkách výpisu Hello World na konzolu:

class Program {
  public static void Main() {
    System.Console.Write("Hello Wold");
  }
}

Začal jsem nejjednodušším programem v C#, který vypíše na konzolu Hello World. Teď to samé v Boo:

print 'Hello World'

Ano, to je vše.

Když se vrátím k článkům na programujte.com, je vidět, že autor netuší, která bije, když píše:

„Každý kód v Boo musí začínat jmenými prostory.“

A skutečně ukázku s Hello World okořenil krásně zbytečným importem jmenného prostoru System. Není nad to mást začátečníky spoustou zbytečností, protože pak mají pocit, že se toho naučili hodně. :) Bohužel praxe ukazuje, že méně je mnohdy více a tak se posuneme o kousek dál. Tedy spíš zpátky na začátek, kde autor popisuje instalaci IDE. Už tohle je pěkná blbost, protože k vyzkoušení Boo žádné IDE nepotřebujete. Boo je totiž vybaveno interaktivní konzolou booish, která je podobná těm, které můžete znát z dynamických jazyků Python, Ruby nebo třeba z mona – pro C#. Prostě konzola, kde píšete kód a rovnou se vám pod rukama vykonává. Pro začátečnické pokusy ideální.

Další skvělé expresivní zážitky najdeme v druhém a třetím díle v odstavcích věnovaných proměnným. Autor se zapomněl zmínit, že máme k dispozici celý typový systém dotnetu.

„Typů proměnných je více a my si probereme jen ty základní.“

A už začíná deklarovat jednu proměnnou za druhou.

celeCislo as int  //definice, aktuální hodnota 0
celeCislo = 200  //inicializace proměnné
celeCislo as int = 5

Fakt krásné. Všimněte si prvního komentáře. To je stavební kámen další ukázky:

//příklad cyklu while
import System
i as int
while(i < 5):
   print i
   i++

Za takový kód bych si dobrovolně zakázal oběd, abych dostal trochu krve do mozku. Ukázka je bezesporu funkční, ale obsahuje zbytečný import, spoléhá se na implicitní inicializaci hodnotové proměnné, navíc zanáší šum v podobě zbytečných závorek. Takže jak se tedy Boo píše? Ukázka s proměnnými:

integer = 5
realNumber = 5.0
text = 'some text'

Jednoduše přiřadíme hodnotu a kompilátor už ví jakého je typu – a není to object ani variant. ;)

i = 0

while i < 5:
  print i++

A tady je celá myšlenka ukázky cyklu while. Proč je lepší?

  1. Používat komentáře je krásná věc, ale většinou je lepší psát tak, aby se komentáře používat vůbec nemusely. Většinou stačí slušně pojmenovat proměnné (nejlépe celým jménem). Tam, kde chcete napsat komentář, raději zvažte, zda není lepší vytvořit novou metodu s dostatečně popisným názvem.
  2. Zbytečným importem nic nezkazíme, ale zvýšíme šum. Někdo by dokonce mohl přemýšlet nad tím, proč tam ten import vlastně je.
  3. Používat neinicializované proměnné je už na výprask. Než uvádět explicitně typ, to tam radši napište tu implicitní hodnotu, ten kód je pak mnohem srozumitelnější.
  4. No a závorka. Pokud na ní jste z Cčkových jazyků zvyklí, prosím, ale je to další zbytečné zašumění kódu.
  5. Hodit postfixovou inkrementaci na jeden řádek s printem už je jen taková třešnička na dortu.

Výborná je taky ukázka s for cyklem nebo proměnné typu char

Psát texty pro začátečníky je těžké, proto se o ně ani nepokouším, ale neměl by je psát začátečník. Protože chyby, které se v „mládí“ naučíte a zažijete si je, budete pak opakovat a opakovat, než se z nich poučíte. A to stojí čas a ten jsou peníze…

Poučení z dnešního WTF: „Čím méně kódu napíšete dnes, o to se vám bude lépe spravovat zítra.“ :)

Autor: Aleš Roubíček | 7x komentováno | Delicious | FriendFeed | Facebook | Linkuj!

Implementace tag cloudu

18.53 - 28. února 2009 | Webdesign

Zajímavé je, jak se problematice celkem rozšířené vlastnosti webových aplikací v éře Webu 2.0, kterou tag cloud bezesporu je, věnuje málo prostoru. Protože pracuju na jednom sociálním webu a k implementaci tag cloudu jsem se také dostal, tak se na něj pojďme podívat.

Top-down design

Začneme implementací na výstupu. To je to, co vidí uživatel. Porozhlédněme se nejprve po nějakém vhodném mikroformátu. Na snadě je rel-tag, který slouží k označování odkazů tagu. Když budeme hledat dál, jistě narazíme na hTagCloud. Tento mikroformát je sice ve stádiu návrhu, ale dá se říct, že je použitelný v praxi. Jak vypadá?

hTagCloud

Cloud je vyznačen elementem s třídou hTagCloud. Tento element by měl obsahovat seznam tagů. Seznam můžeme označit třídou, zda jde je seřazen podle abecedy (class="alphabetical") nebo podle popularity (class="popularity"). Popularitu jednotlivých tagů označíme posléze třídou. Základní úroveň popularity vyznačuje třída popular. Oblíbenější tagy mají třídu v-popular. Nejoblíbenější tagy pak třídou vvvv-popular. Můžeme takto tedy odlišit pět úrovní popularity.

Ukázka mikroformátu přímo z wiki autorů:

<div class="hTagCloud">
  <ul class="popularity">
    <li class="vvvv-popular"><a href="/tags/Web+Standards+Group">Web Standards Group</a></li>
    <li class="vvv-popular"><a href="/tags/accessibility">accessibility</a></li>
    <li class="popular"><a href="/tags/beta+tester">beta tester</a></li>
    <li class="vvv-popular"><a href="/tags/css">css</a></li>
    <li class="v-popular"><a href="/tags/ex-coder">ex-coder</a></li>
    <li class="vv-popular"><a href="/tags/usability">usability</a></li>
    <li class="vvvv-popular"><a href="/tags/wsg">wsg</a></li>
  </ul>
</div>

To bychom měli HTML kód, teď ještě nastylovat, aby z toho opravdu cloud byl:

.hTagCloud {text-align:center}
.hTagCloud ul{list-style-type:none;padding:0;margin:0}
.hTagCloud li{display:inline;font:.6875em sans-serif;margin:0;padding:0}
.hTagCloud .v-popular{font-size:1.273em}
.hTagCloud .vv-popular{font-size:1.818em}
.hTagCloud .vvv-popular{font-size:2.545em}
.hTagCloud .vvvv-popular{font-size:3em}

Máme tedy připraveno to, co uvidí uživatelé. Teď ještě potřebujeme logiku, která rozhodne, jak populární tagy vlastně jsou.

Implementace na serveru

Nejprve si vytvoříme třídu reprezentující tag. Ta bude obsahovat text tagu a jeho četnost.

public class Tag {
  public string Text { get; set; }
  public int Count { get; set; }
}

Teď budeme potřebovat vypočítat, jak populární vlastně konkrétní tag je. Tady se dostáváme k poměrně zajímavému problému. Nejprve potřebujeme spočítat váhu tagu v cloudu a tu pak promítnout na pětistupňové škále. Praxí je ověřeno, že hezky cloud vypadá, když se použije logaritmická distribuční funkce. Proto si vytvoříme jednoduchý helper, který nám bude váhu tagu vypočítávat a rovnou nám vrátí CSS třídu vhodnou pro hTagCloud.

using System;
using System.Linq;
using System.Text;

public static class TagCloudExtensions {
  private const int MostPopular = 5;
  private const int MorePopular = 2;
  private const int Popular = 1;

  public static string GetCssClass(this IEnumerable<Tag> tags, Tag tag) {
    int minOccurs = tags.Min(t => t.Count);
    int maxOccurs = tags.Max(t => t.Count);

    int distribution = CountDistribution(tag.Count, minOccurs, maxOccurs);

    return GetCssClass(distribution).ToString();
  }

  private static StringBuilder GetCssClass(int distribution) {
    if (distribution < MorePopular) {
      return new StringBuilder("popular");
    }
    if (distribution == MorePopular) {
      return GetCssClass(--distribution).Insert(0, "v-");
    }
    return GetCssClass(--distribution).Insert(0, "v");
  }

  private static int CountDistribution(int currentOccurences, int minOccurs, int maxOccurs) {
    if (minOccurs < Popular) {
      throw new ArgumentOutOfRangeException("There must be atleast one occurence.");
    }

    double weight = (Math.Log(currentOccurences) - Math.Log(minOccurs))
      / (Math.Log(maxOccurs) - Math.Log(minOccurs));
    int distribution = Popular + (int)Math.Round(weight * (MostPopular - Popular));

    return distribution;
  }
}

Tento helper rozšiřuje kolekci tagů o metodu o metodu, která vrátí CSS třídu pro konkrétní tag. A to je vše. Happy tagging!

Autor: Aleš Roubíček | 10x komentováno | Delicious | FriendFeed | Facebook | Linkuj!

Registrace svc handleru pro IIS7

10.55 - 23. února 2009 | Webové služby

Náš intranet používá pro AJAXy ADO.NET Data Services, což je pěkný REST framework. Tento framework je postavený nad IQueryable (tedy LINQ) a také nad WCF. Nedávno jsme prováděli přeinstalace serverů a tak se stalo, že AJAXové dotazy začaly vracet 404.

Bylo to divné, protože jinde to fungovalo a vždy stačil xcopy deployment. Tak jsem zkusil zadat adresu služby do prohlížeče a zase 404. Proč to nejde? Koukám na mapování handlerů v konfiguraci IIS7 a helemese chybí svc binding. Ale proč? Vždyť je všechno nainstalovaný jak má bejt.

Po chvilce pátrání jsme našel jednoduché řešení. Stačí spustit registraci ručně:

"%systemroot%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe –i"

Pro 64-bitové systémy pak:

"%systemroot%\Microsoft.NET\Framework64\v3.0\Windows Communication Foundation\ServiceModelReg.exe –i"

Dnes mi píše Radek, že přesouval intranet na Domain Controller, aby nebyl na našich vývojových strojích a že mu AJAXy vracej 404. Takže tohle je i tak trochu pro něj.

Autor: Aleš Roubíček | Zatím bez komentáře | Delicious | FriendFeed | Facebook | Linkuj!

Serverové ovládací prvky v ASP.NET MVC

12.32 - 21. února 2009 | Webdesign

Docela často se vyskytující fámou je, že v ASP.NET MVC nelze používat serverové ovládací prvky (Server Controls). Pravda to je jen z části, nelze používat jen ty prvky, které pro svoji funkčnost vyžadují ViewState. Pojďme se podívat na ty, které fungují i v ASP.NET MVC a můžou nám poskytnout nějakou zajímavou funkcionalitu a zpřehlednit tak naše View.

MasterPage a Placeholdery

Snad první komponenty, které použijete, jsou asp:ContentPlaceHolder a asp:Content. Narazíte na ně při definování globální šablony (Master Page) a jednotlivých pohledů (View). Většinou je použijete automaticky a ani si neuvědomíte, že jde o serverové komponenty. A to je dobře. Rozhodně je lepší používat master page než server side include nebo do všech stránek vkládat view user controly se sdílenými částmi šablony.

LoginView a spol.

Další rozhodně doporučitelnou komponentou je asp:LoginView. Ta slouší k rozdílnému zobrazování obsahu pro nepřihlášené/přih­lášené uživatele a také pro jednotlivé uživatelské role. Předpokladem je, že využíváte ASP.NET Membership nebo nějakou vlastní implementaci, která nastavuje do kontextu správné IPrincipal. Pak můžete v kódu použít třeba toto:

<asp:LoginView ID="LoginView1" runat="server">
  <AnonymousTemplate>
    Nepřihlášený | <%= Html.ActionLink("Přihlásit se", "Login", "Account") %>
  </AnonymousTemplate>
  <LoggedInTemplate>
    <asp:LoginName runat="server" />| <%= Html.ActionLink("Odhlásit se", "Logout", "Account") %>
  </LoggedInTemplate>
</asp:LoginView>

Tím docílíte zobrazení odkazu pro přihlášení nepřihlášenému uživateli a odkazu pro odhlášení uživateli přihlášenému. Jak vidíte, je možné používat i asp:LoginName pro výpis jména aktuálně přihlášeného uživatele.

Localize pro lokalizaci

Pokud děláte na webové aplikaci, která má být lokalizovaná do více jazyků, jistě se vám bude hodit asp:Localize, které slouží k snadnému definování míst, která mají být nahrazována texty z resource souboru. Nebudu teď řešit jak rozhodnout jaký jazyk zvolit, můžete ho mít natvrdo nastavený ve web.config souboru pro jednotlivé deployované domény, nebo získat nějaký parametr z routy, nebo nechat zjišťovat jazyk podle uživatelova nastavení prohlížeče. Pokud budete mít zájem o problematiku lokalizace, můžu jí věnovat některý další spot. :)

<asp:Localize runat="server" meta:resourcekey="SomeResource1" />

Lokalizaci pak provedeme v patřičném resx souboru následovně:

<data name="SomeResource1.Text" xml:space="preserve">
  <value>Some text</value>
</data>

SiteMapPath pro drobečkovou navigaci

Další serverovou komponentou, kterou můžete ve svých šablonách pohledů využít je asp:SiteMapPath, které slouží ke generování drobečkové navigace podle struktury definované v souboru Web.sitemap.

<asp:SiteMapPath runat="server">
  <PathSeparatorTemplate> &gt; </PathSeparatorTemplate>
</asp:SiteMapPath>

Xml pro transformaci

Jedním z posledních ze standardně dodávaných serverových komponent, které ještě v MVC fungují je asp:Xml, které slouží ke vkládání XML dat a jejich transformaci pomocí XSLT.

<asp:Xml runat="server" DocumentSource="/content/contact.xml" TransformSource="/content/contact.xslt"/>

ViewType pro silný typ modelu v pohledu

RC verze MVC frameworku přinesla vlastní serverovou komponentu, která určuje silný typ pro vlastnost Model vašeho pohledu. Je to alternativa k dědění z generické ViewPage.

<mvc:ViewType runat="server" TypeName="ViewPage&lt;MyProject.Model.Customer&gt;" />

A dál?

Dál můžete používat komponenty třetích stran, nebo vlastní, které nevyžadují ViewState. Pokud máte jako předka vašich stránek System.Web.Mvc.ViewPage nemáte v šablonách dostupný data binging. I na to je třeba dávat pozor. Do budoucna by mělo dojít k tomu, že helpery, které jsou součástí MVC frameworku, se dočkají i zapouzdření do komponent. Ale k tomu dojde až po vydání verze 1.0. Již dnes však můžete najít jejich předběžnou implementaci v tzv. ASP.NET MVC Futures, které si můžete stáhnout na CodePlexu. Najdete mezi nimi tyto komponenty:

  • ActionLink,
  • DropDownList,
  • TextBox,
  • Password,
  • Label,
  • Hidden a
  • Repeater

Jejich předkem je MvcControl, který zpřístupňuje ViewContext a ViewData. Repeater si třeba zajišťuje DataBinding sám, takže není třeba ho explicitně volat ze stránky. Nevýhoudou však je, že je třeba Evalovat data, protože Repeater není silně typový. Mám takový pocit, že můj generický repeater by měl v MVC fungovat bez problémů. Ještě jsem to nezkoušel, ale nevidím důvod, proč by neměl. Asi provedu revizi a připravím vylepšenou variantu pro MVC.

A to je pro dnešek vše.

Autor: Aleš Roubíček | 4x komentováno | Delicious | FriendFeed | Facebook | Linkuj!

Kanonicky proti duplicitám

07.27 - 13. února 2009 | Webdesign

Jedním z velkých problémů dnešních vyhledávačů je duplicitní obsah. Musejí se poprat s velkým množstvím stránek, které vypadají na první pohled shodně a liší se pouze v URL adrese. Jak mají rozhodnout, kterou z těchto adres vrátit uživateli jako jedinou správnou?

Problém duplicitního obsahu

Duplicitní obsah může vzniknout velice jednoduše, nemusí ani dojít ke zkopírování stránky někým jiným. Prostě stačí mít blbě nastavený server a vracet stejný obsah pro URL s i bez www. na začátku. Další možností je, že se vaše adresy dynamických stránek v čase vyvíjí. Začínal jsem s nepěknými adresami ve tvaru clanek.aspx?id=4, pak jsem časem přešel na SEO URL ve tvaru clanek.aspx/4-nejaky-nadpis, později jsem přidal URL rewriter a mé URL vypadaly takto clanek/4-nejaky-nadpis.aspx. Všechny tyto adresy vedou na stejný obsah, ale protože mají jinou URL, jsou to pro vyhledávacího robota různé stránky.

Jako správný poskytovatel obsahu bych měl zajistit, že všechny verze URL jsou stále funkční, ale měly by směřovat na jedinou platnou. Ale jak?

Řešení

Cest k cíli vede samozřejmě spousta. Pokud máte tu možnost, využijte nějaký URL rewriter. Zvolte si kanonickou formu vašich adres a tu všude používejte. Pokud nechcete používat v adresách prefix www., stačí málo.

Na IIS7 s URL Rewriterem přidejte do vašeho web.config souboru do sekce system.webServer/rewrite/rules následující kód:

<rule name="Remove WWW prefix" >
  <match url="(.*)" ignoreCase="true" />
  <conditions>
    <add input="{HTTP_HOST}" pattern="^www\.domain\.com" />
  </conditions>
  <action type="Redirect" url="http://domain.com/{R:1}" redirectType="Permanent" />
</rule>

Na Apachi stačí do souboru .htaccess přidat následující řádky:

# Remove WWW prefix
RewriteCond %HTTP_HOST ^www\.domain\.com [I]
RewriteRule ^/(.*) http://domain.com/$1 [RP]

Co ale dělat, pokud nemáte na serveru možnost URL rewriting provádět?

Naštěstí existuje alternativa. Vývojáři Google, Yahoo a Live Search se domluvili na zavedení link tagu, který určuje kanonickou URL přímo v dokumentu. Do sekce html/head vašich stránek přidejte následující tag:

<link rel="canonical" href="http://domain.com/kanonicka/adresa-stranky" />

Tím dosáhnete toho, že pokud crawler navštíví vaši stránku přes různé adresy, vždy ji bude považovat za jednu a tu samou s adresou, která je hodnotou atributu href.

Autor: Aleš Roubíček | 10x komentováno | Delicious | FriendFeed | Facebook | Linkuj!

Novinky z karavany

06.00 - 12. února 2009 | Webdesign

Ano, je to tak, jak možná někteří tušíte, chystám se psát o tom, co je nového v Twaregu. A únor není na novinky chudý.

Ale začnu hezky od začátku roku, kdy jsme mezi nás přivítali nového člena Miloše Savaru, který se přidal do týmu reklamního systému codename „Hyas“ a pracuje na veřejném API. Jádro zatím podstupuje zátěžové testy. :) Náš komunitní projekt už podporuje OpenID včetně načítání údajů profilu, přibyla schopnost lokalizace pomocí IP adresy a fulltextové hledání.

Dev platforma se nám rozrostla o nový silný stroj a tak došlo k přeinstalování serverů, změně rolí a jmen. Nově používáme jména hadů. Taky se nám dostalo jednoho bladea. A to už se pomalu dostáváme ke spuštění našich webových stránek Twareg.com. Zatím tam není moc obsahu, ale věřím, že bude postupně přibývat. :) Zatím tam najdete náš kontakt, náš tým a nabídku práce. Sice od příštího týdne získáme další posilu týmu, ale pořád sháníme další schopné lidi.

Krom stránek jsem spustili i vlastní twitter: štěbetání tuarégů.

Na stránkách si také můžete všimnout, že jsme se stali členy BizSparku. Ačkoli jsme se na české pobočce Microsoftu dozvěděli, že tento program pro podporu start-upů není pro Českou Republiku určen, tak v programu jsme a můžeme čerpat jeho výhody. Pokud netušíte, co to je BizSpark, tak vězte, že je to program pro začínající firmy, které se rozhodnou vyvíjet na MS platformě. Program je to tříletý. Během této doby máte předplatné MSDN včetně licencí do produkčního prostředí. A to vše za $100. Po uplynutí třech let, tedy zaplatíte $100 a všechny licence, které jste do té doby získali, vám zůstanou.

Tak nám držte palce, pokud chcete, přijďte se na nás podívat, případně zvažte, jestli u nás nechcete pracovat. :)

Autor: Aleš Roubíček | 2x komentováno | Delicious | FriendFeed | Facebook | Linkuj!