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

Tři přikázání TDD

14.29 - 25. prosince 2011 | Moje práce

Volně přeloženo z knihy The Clean Coder

  1. Nenapíšeš řádky produkčního kódu, aniž bys měl padající test.
  2. Nenapíšeš řádky testovacího kódu, pokud již nejsou aktuální řádky schopné projít (nezkompilovatelný kód také neprojde).
  3. Nenapíšeš řádky produkčního kódu, které nejsou nezbytně nutné, aby prošel aktuálně padající test.

Strava pro vaše oči, uši a mozek

09.26 - 25. prosince 2011 | Moje práce

Už je tomu nějakej ten pátek, co jsem Marianovi slíbil, že napíšu článek s videama, o kterých si myslím, že jsou velmi dobrá na procvičování funkcionálního programování a abstraktního myšlení vůbec. Tak tady jsou:

MinLINQ

První z nich ukazuje implementaci LINQ operátorů pomocí funkcionální kompozice tří základních operátorů Ana, Bind a Cata:

Rx pod kapotou

Další se zabývá velice zajímavými koncepty asynchroního a konkurenčního přístupu v reaktivních extenzích:

Design programovacích jazyků

Poněkud starší video o tom, jak se vaří programovací jazyky, s lidmi, kteří je opravdu navrhují. Erik Meijer je jedním z mistrů Haskellu a mimo jiné i mozkem za LINQ a Rx ve světě dotnetu. Gilad Bracha je toho času součástí týmu tvořícího Dart. A Mads je v teamu tvořící C#. Takže samí zajímaví lidé se zajímavými pohledy na jazyky.

Fukcionální programování

Další video s Erikem „you know“ Meijerem. :) Také staršího data, ale to na kvalitě neubírá, představuje koncepty funkcionálního programování v dotnetu.

A komu to přijde málo a má chuť (a čas) se do funkcionálního programování opravdu obout, tak doporučuju celou 13 dílnou serii Erikových lekcí. Často jsou ukázky v Haskellu, ale tady jde o koncepty a nakonec není od věci podívat se i na jiný programovací jazyk, že.

K čemu vlastně TDD?

13.09 - 18. prosince 2011 | Moje práce

Na proběhnuvším CodeRetreatu jsme se a pány Kolmanem a Augustýnem balivi o tom k čemu vlastně je TDD, jaký má přínos?

Michal argumentoval tím, že dělá testable design a testy píše potom a že je s tím cajk, že nevidí důvod, proč dělat TDD. S Danem jsme nahazovali okřídleané pravdy o výhodách TDD, které Michal zašlapal. A tak jsme nenašli správnou argumentaci. A já o tom musel přemýšlet. Přece tam musí být nějakej zásadní rozdíl!

A on je. Ta největší devíza TDD je iterativní přístup k vývoji. Pakliže se držíte nějaké agilní metodiky a jednou za iteraci máte funkční produkt, který může jít potenciálně do produkce. S TDD jste v takovém stavu takřka každou chvíli (po dokončení kolečka Red-Green-Refactor). Kdykoli za vámi někdo přijde, že chce vidět jak na tom jste, tak nemusíte říkat „těd to nejde, zrovna mám něco rozdělanýho a nefunguje to.“ S TDD vám aplikace funguje takřka pořád. Sice nemá všechny požadované vlastnosti, ale je funkční.

Trénujete na Code Retreat?

09.19 - 26. listopadu 2011 | Moje práce

Již za týden se koná akce, do které jsem tak trochu namočený, Global Day of Code Retreat. My se snažíme připravit jedno místečko v Praze.

Ačkoli má akce za cíl vás vytrénovat v lepší vývojáře, je dobré abyste na něj přišli trochu připravení. :) Určitě si přečtěte pravidla problému, který se bude celý den znova a znova implementovat. Ale nezůstaňte pouze u čtení, zamyslete se nad tím, jak danou úlohu naimplementovat. Nebojte se a jděte ještě dál a vážně tu vaši ideu i zhmotněte!

Dalším krokem jak se na akci připravit, je zacvičit si nějakou tu katu v kódování. Zkuste třeba oblíbenou bowling game nebo string calculator. Procvičíte si tak TDD i nástroje, které budete používat.

O vymýšlení kola

13.48 - 15. listopadu 2011 | Moje práce

V pátek jsem si utvítl, že „Psát virtuální distribuovanej file systém je challenge.“ a hned jsem dostal reakce, že jsem další v řadě a že znova vymýšlím kolo a další parafráze mých výroků.

Jak to tedy je? :)

Challenge pro vás

Ukažte mi implementaci VirtualPathProvideru, který má správně vyřešené cachování a škáluje přes více než jeden webový front-end.

Když se vám to povede, veřejně mě můžete prohlásit za hlupáka, který neumí hledat a znovu vynalézá kolo. Když se vám to nepovede, můžete se mě snažit uplatit, abych vám prozradil pikantní podrobnosti.

Produktivita s CoffeeScriptem?

09.10 - 13. listopadu 2011 | Webdesign

CoffeeScript může zvýšit produktivitu pouze v případě že JavaScript píšete v primitivním editoru typu Notepad. Kdo to s produktivitou v JavaScriptu myslí vážně, investuje pár tisícovek do pořádného IDE s podporou doplňování kódu, type hintingu, refactoringu a integrovaného test runneru.

Kvalitní nástroje jsou něco, co CoffeeScript ještě dlouho mít nebude. A kvalitní nástroje jsou to, co opravdu zvyšuje vaši produktivitu, ne obskurní syntaxe.

ActionInterceptor pro ASP.NET MVC

10.19 - 23. října 2011 | ASP.NET 2.0

V pátek jsem na twitteru publikoval ActionInterceptor a záhy jsem dostal reakci od Dana Kolmana, „proč ne ActionFilterAttribute?“ Sice jsem to na twitteru shrnul, ale klidně si to shrnu ještě jednou a obšírněji. Dělá mi to totiž dobře.

Action Filtry

Action filtry jsou – už od první verze ASP.NET MVC – způsobem, jak rozšiřovat akce o znovupoužitelné aspekty. Můžete tak zabalit často používané koncepty a jednoduše je aplikovat tam, kde je to třeba. Jenže action filtry mají několik zásadních omezení:

  1. Nepřijde mi úplně košer, aby atributy byly nositeli jednotky práce. Jejich úkolem je poskytovat metadata, nikoli funkcionalitu.
  2. Do verze 3 tu nebyla možnost injektovat závislosti, ve 3. verzi přibyl service lokátor (IDependencyResolver), který má k dokonalosti velmi daleko.
  3. Pokud chci přidat aspekt, musím zasahovat do rozšiřovaného kódu.

Všechny tři body jsou pro mne velmi zásadní chyby v návrhu a použitelnosti. Jak je vyřešit?

Action interceptor

Ve svých aplikacích spokojeně používám IoC kontejner Castle.Windsor, který umožňuje snadno vkládat aspekty. Děje se tak pomocí dynamicky vytvářených proxy nad dekorovanými objekty. Jak se má aspekt chovat a kde aplikovat můžeme snadno popsat v objektu, který implementuje rozhraní IInterceptor.

Ze základního popisu to nemusí být zcela zřejmé, ale aspekty můžete aplikovat pouze na virtuální metody. Proto když chcete přidávat aspekt do vašich kontrolerů musíte sáhnout k tomu, že všechny akce budou virtual (což je IMO nesmysl) nebo prostě využijete již existující extension pointy, které MVC framework nabízí. Kupodivu jsou to známé metody, které se objevují i v Action filterech. Implementace Action interceptoru bude tedy vypadat následovně:

using System;
using System.Linq;
using System.Web.Mvc;
using Castle.DynamicProxy;

public abstract class ActionInterceptor : IInterceptor, IActionFilter, IResultFilter {

 public void Intercept(IInvocation invocation) {
    switch (invocation.Method.Name) {
      case "OnActionExecuting":
        Intercept(invocation, OnActionExecuting);
        break;
      case "OnActionExecuted":
        Intercept(invocation, OnActionExecuted);
        break;
      case "OnResultExecuting":
        Intercept(invocation, OnResultExecuting);
        break;
      case "OnResultExecuted":
        Intercept(invocation, OnResultExecuted);
        break;
    }
    invocation.Proceed();
  }

  void Intercept<TContext>(IInvocation invocation, Action<TContext> action) {
    action(invocation.Arguments.First() as TContext);
  }

  public virtual void OnActionExecuting(ActionExecutingContext filterContext) {

  }

  public virtual void OnActionExecuted(ActionExecutedContext filterContext) {

  }

  public virtual void OnResultExecuting(ResultExecutingContext filterContext) {

  }

  public virtual void OnResultExecuted(ResultExecutedContext filterContext) {

  }
}

Užití je pak už pouhé podědění a přepsání patřičné metody podobně jako u Action filtrů.

Aplikace aspektu

Takovýto aspekt můžeme aplikovat několika způsoby. Nejpřímější cestou, bez nutnosti modifikovat cíl aspektu, je konfigurace kontejneru:

Component.
  For<LoggingInterceptor>().
  Lifestyle.Transient,

Component.
  For<HomeController>().
  Lifestyle.Transient.
  Interceptors<LoggingInterceptor>()

A jedem. :)

Další možností je aplikovat interceptor podobně jako action filtr – pomocí atributu:

[Authorization]
public class HomeController : System.Web.Mvc.Controller {

}

public class AuthorizationAttribute : Castle.Core.InterceptorAttribute {
  public AuthorizationAttribute()
    : base(typeof(AuthorizationInterceptor)) {
  }
}

Každý ze způsobů užití má své přednosti. Konfiguraci kontejneru používám tehdy, když potřebuji přidat dočasné nebo velice obecné aspekty. Naopak, pokud potřebuji explicitně vyjádřit nějaký koncept (autorizaci, invalidaci cache apod.), který má být při čtení controlleru zřejmý, použiji atributy.

Repository je anti-pattern

10.04 - 10. září 2011 | ASP.NET 2.0

Žádný vzor není špatný. Vezměme si chudáčka Singletona. Skvělý vzor pro udržení jediné instance v požadovaném scope. Jenže pak se dočtete, že Singleton je neslučitelný s Dependency Inversion Principle. Opravdu? Jak to, že používám DIP i Singletonty už léta? On je problem někde jinde. U lidí co nepřemýšlí. :) Fakt.

Mějme třídu, kde se na pěti místech v jejím kódu vyskytuje HttpContext.Current. Opravdu je to problem Singletonu? Ale kdepak, je to problem v užití, potažmo neschopností dělat čistý design. Přitom stačí nadefinovat členskou proměnnou typu HttpContext (lépe HttpContextBase) a tu si nechat naservírovat pomocí konstruktoru.

Volání HttpContext.Current bude v aplikaci pouze na jednom místě – v Composition rootu aplikace (popř. V konfiguraci IoC kontejneru.) Zbytkem aplikace nám bude protékat právě tato instance.

Doufám, že jsem na těchto pár řádcích dokázal, že Singleton není anti-pattern. Že anti-pattern jsou programátoři.

Říkám repository, myslím Data Mapper

A pomalu se dostáváme k jádru našeho problému. Vzory jsou tu od toho, aby sjednotili slovník, aby každý hned věděl o čem se bavíme. Jenže v případě Repository to došlo tak daleko, že lidé říkají Repository, ale 99 % myslí Data Mapper.

Repository nám schovává datový zdroj za rozhraní kolekce a umožňuje nad ním spouštět doménové dotazy. Světe div se, v dotnetu už něco takového máme. Ano, je to IEnumerable a LINQ!

V praxi se však setkáme s repository, která přímo skládá SQL dotazy, menežuje život entit a má tlusté rozhraní jako prase. Proč? Protože opět selhaly schopnosti návrhu. Zde konkrétně Single Responsibility Principle a Interface Segregation Principle.

Tlustá rozhraní

Tlustá rozhraní u “Repository” vznikají z potřeby zapouzdřit často používané dotazy do znovupoužitelné jednotky. Bohužel i v 21. století je jednotkou znovupoužitelnosti procedura. A tak s každým novým dotazem přidáme na rozhraní “Repository” další a další metodu. To nám spokojeně roste a roste. A opět porušujeme Interface Segregation Principle, Single Responsibility Principle a navíc i Open Closed Principle – a vytváříme krásnou kuličku sraček.

Třída, která toto rozhraní implementuje mívá nezřídka tisíc řádků a dá se v nít “snadno orientovat” pomocí stromečků. Jenže, jak praví Uncle Bob:

“V každé velké metodě se schovávají malé třídy!”

Ale málem bych zapomněl na Liskov Substitution Principle. Určitě jste všichni někdy narazili na potřebu cachovat. :)

Dekorováním za čistší kód!

A tak, když dospějeme k závěru, že tenhle dotaz se provádí dost často a přitom se data takřka nemění, budeme cachovat. První věc, co nás napadne, je nasrat tu cache přímo do repository. Tak to bude transparentí a nikde to nemusím měnit. Au. Lepším řešením je udělat třídu se stejným rozhraním, která v konstruktoru přijímá to samé rozhraní a potřebné metody odekoruje cachováním. Zbylé volá přímo na dekorovaném objektu.

Netvrdím, že jde o dokonalý návrh, ale jde rozhodně o mnohem čistší řešení. A to vše díky dodržování principů SOLIDní architektury. Opakuju se tu o tom už léta, ale asi je to stale potřeba. ;)

Refaktoring

09.31 - 23. července 2011 | Moje práce

Poslední dobou se mi velmi často stává, že narážím na hlášky typu “od devíti refaktoruju a furt to nemá konce,” “refaktoring mi zabere asi tři dny, udělej mi na to task do backlogu” nebo „refaktoroval jsem to a nějak to přestalo fungovat.“ Tohle všechno jsou lži, ať už plynoucí z neznalosti, co to je refaktoring nebo trendy nadužívání tohoto slova v nepatřičných situacích.

Co je to refaktoring?

Refaktoring je pojem, který je definován poměrně přesně. Je to krátká atomická operace nad kódem, která nemění jeho funkci, pouze strukturu. Z definice jasně vyplývá, že věty z úvodu jsou lži.

Refaktoring patří k základní hygieně čistého kódu. Měli byste ho používat neustále. Není to věc, kterou byste měli zahrnovat do plánů jako něco extra, podobně jako testy, jsou jejich nedílnou součástí. A sluší se je zahrnout do časových odhadů jednotlivých úkolů. Ne však jako samostatné úkoly!

Říkám refaktoring, myslím redesign

Refaktoring se stal trendy pojmem. Manažeři mu nerozumí a programátoři se sním furt ohánějí. „Proč ti to trvalo tak dlouho?“ „Ještě jsem musel udělat refaktoring tohodle a tamtoho.“ Jenže jak jsme si řekli v definici, refaktoring je krátká operace! Velmi krátká, pokud máte dobré nástroje, netrvá více než pár stisků kláves. Řádově trvá jednotky sekund.

Refaktoring má navíc tu vlastnost, že i když děláte velkou sérii – provádíte redesign – můžete kdykoli přestat a aplikace stále funguje. Ano, je to tak. Opět to vyplívá jasně z definice. Pokud ne, děláte jenom redesign.

Redesign

„Musíme to přepsat.“ Ta slova nemají manažeři rádi. Znamená to spoustu promarněných (z jejich pohledu – my přece víme, že se to musí udělat a že se to vrátí) hodin/dní (někdy i měsíců a let) práce. A tak se místo redesignování začalo „refaktrovat.“ Přestaňme si lhát. I když třeba během redesignu použijeme nějaký ten refaktoring, pořád je to redesign. Redesignovat můžeme přinejmenším dvěma způsoby:

  1. Hurá redesign, kdy se původní kód zahodí a napíše se to znova a občas se něco z toho původního copy&pastene. Tohle se často dnes nazývá refactoring. A většinou z toho vypadne podobná sračka, jako byla před tím, jen bude mít jiný tvar.
  2. Můžeme postupně refaktorovat a časem se dostat k lepšímu designu. Ale nezapomínejte, vždycky tenhle proces můžete přerušit a aplikace funguje. Stačí, že změny jsou good enough. Váš kód nikdy nebude dokonalý.