sobota 21. ledna 2012

Škůdci vašeho týmového projektu

Proč se nám vlastně projekt nedaří?
Co děláme špatně?
Proč jsme tak neefektivní a pomalí?
Proč narážíme na stále stejné problémy a chyby?

Každý tým občas takové otázky řeší. Tento příspěvek upozorňuje na záležitosti, které obecně projektům škodí. Sám jsem se s každém problémem v praxi setkal a jeho případné vyřešení vždy situaci v projektu vylepšilo. Možná máte zkušenost s dalšími neduhy, které zde neuvádím. Budu rád, když je připíšete do komentáře.

Mezi typické škůdce patří:

  • Nejasné požadavky, vize a cíle projektu
  • Neschopný vedoucí týmu, resp. projektový manažer
  • Špatný výběr členů týmu
  • Nejasnost týmových rolí
  • Nedostatečná motivace
  • Nefungující zajišťování kvality
  • Absence plánování a vyhodnocování
  • Absence popisu interních procesů
  • Špatná podpora týmové práce
  • Problémová komunikace
  • Nevyhodnocování zákaznické zpětné vazby
  • Chybně zvolené technologie
  • Nedostatečná interní projektová dokumentace
  • Alkohol

Nejasné požadavky, vize a cíle projektu

Váš projekt může být úspěšný pouze v případě, že si dokážete jasně zadefinovat požadavky, které má výsledný produkt splňovat. Sběr a vyhodnocování požadavků je prvotní fází vývojového cyklu softwarových systémů. Její důležitost je mnohdy podceňována. Může se totiž stát, že se až při předávání produktu zákazníkovi zjistí, že se obě strany nepochopily a že se musí velká část systému přepracovat. Dostavuje se oboustranná frustrace, posouvání termínů a navyšování nákladů.

V dnešní době používání agilních metodik je tendence zkracovat délku iteračních cyklů a uvolňovat častěji produkční verze s novou funkcionalitou. Můžete být operativnější, pokud však dokážete zajistit dostatečnou kvalitu Vašeho produktu. Časté vydávání verzí systému musí být odůvodněno dodáváním nové funkcionality. Pokud posíláte nové verze pouze kvůli neustálému opravování chyb, nebude vám skřípot zubů Vašich zákazníků znít v uších moc libozvučně.

Vize určují dlouhodobější charakteristiku směřování vašeho produktu. Stanovit reálné a efektivní vize je těžší než určit krátkodobé požadavky. Nelze spoléhat na horoskopy a proto se budoucnost předpovídá poměrně komplikovaně :) I na počátku úspěšnému projektu může dojít dech, pokud se sám sebou uspokojí a přestane investovat do vývoje, výzkumu a vzdělávání zaměstnanců. Pokud pracujete na krátkodobých projektech, vizemi se trápit nemusíte.

Neschopný vedoucí týmu, resp. projektový manažer

Vedoucí týmu je nejdůležitější týmová role. Měl by být pouze jeden a musí být schopen vzít na sebe zodpovědnost za výsledky celého týmu. Vedoucí týmu musí mít přirozený respekt a důvěru podřízených. Měl by být dostatečně vybaven měkkými dovednostmi (soft-skills) a jeho charakter musí být pro ostatní inspirující. Musí být dobrým koučem, psychologem i (v dobrém slova smyslu) manipulátorem (zdravím tímto Steva Jobse).

Vedení rozsáhlejšího projektu lze těžko dělat pouze na dálku. Osobní kontakt nebyl ani v dnešní době stále překonán. Pozitivní i negativní emoce při řešení problémů si nikdy tak neužijete jako v reálu. Vzhledem k tomu, že virtuální konference startrekovského typu se zatím příliš neprosadily, musí být vedoucí týmu fyzicky přítomen ostatním členům.

Vedoucí týmu je zodpovědný za další záležitosti, které jsou jednotlivě propírány v dalším textu.

Špatný výběr členů týmu

Pokud byste měli poskládat váš vlastní projektový tým, koho byste vybrali a podle jakých kritérií? Udělali byste "elitářský" tým z Vašich nejzkušenějších senior pracovníků, kteří jsou však všichni výrazně ambiciózní? Nebo byste vybrali tým juniorů, kteří nejsou zatíženi jinými projekty a mají zatím hlavy čisté a otevřené? Zřejmě zvolíte zlatou střední cestu a namícháte zkušenost stáří s dravostí mládí. Měli byste si však uvědomit, že skupina lidí ještě není tým. Lidé musí být ochotni a schopni spolupracovat, vzájemně si pomáhat, komunikovat a sdílet znalosti. Pokud jste malá firma, máte to jednodušší, zřejmě na projekt nasadíte většinu zaměstnanců.

Pokud se časem ukáže sestavení vašeho týmu jako neefektivní, je třeba co nejdříve jednat. Řešením je přerozdělení kompetencí, posílení nebo u zásadnějších problémů i vyřazení z týmu. Pokud některý člen nerespektuje dohodnutá pravidla a tým tak zpomaluje a oslabuje, ukažte mu dveře. Na druhou stranu je pravda, že výkonnost členů týmu je výrazně ovlivněna jejich řízením ze strany vedoucího. Vedoucí týmu musí svého podřízeného znát a působit na něj správným způsobem. Pak se mohou dostavit výsledky. Bohužel i z vlastní praxe si pamatuji kolegy, kteří ve firmě dojeli na to, že jejich nadřízení s nimi nedokázali pracovat, nedostali potřebnou zodpovědnost a jejich počínání bylo ve výsledku hodnoceno jako neúspěšné.

Nejasnost týmových rolí

Občas narážíme na situace, kdy není úplně zřejmá hierarchie týmu. Kdo je mně přímým nadřízeným v rámci tohoto projektu? Koho mohu úkolovat? Na začátku každého projektu by měl být určen tým a popsány jednotlivé týmové role se soupisem kompetencí a povinností. Pokud tomu tak není, vzniká mnoho neurčitých projektových oblastí, o které se nikdo nestará. Otázky typu Tohle jsem měl dělat já?! nebo Kdo má tohle na starosti?! jsou pak důsledky špatné organizace týmových rolí.

Podle týmových rolí lze strukturovat komunikaci, nastavení přístupových práv nebo organizovat porady. Pokud má člen jasně dané kompetence, může se na svou oblast soustředit a podnikat příslušné pracovní kroky. Pokud kompetence nejsou určeny, stává se, že se pracovní činnosti více členů překrývají a duplikují. A: Jejda, ty jsi udělal přesně to samé co já. Proč ses mě nezeptal? B: Ale to jsem měl přeci dělat já. A: A sakra, máš pravdu!. V horším případě se stane to, že daný úkol nikdo neudělá, protože dotyčný nepochopil, že je to v jeho kompetencích.

Nedostatečná motivace

Finanční motivace jako prvotní motivační faktor je samozřejmě zásadně důležitá. Takže zaplaťte své lidi tak, aby pro ně bylo zajímavé na projektu pracovat.

Ale po nějakém čase práce na projektu se začnou projevovat záležitosti související s nefinanční motivací. Kladete si otázky typu Baví mě taková práce?, Má pro mě nějakou perspektivu?, Získám zkušenosti od zkušenějších členů týmu? Čím jste zkušenější, tím méně vás baví "šablonové" projekty a hledáte nové inspirace a výzvy. Pokud projekt nepatří k nejzajímavějším, musí pomoci vedoucí projektu a dokázat lidi namotivovat a na práci natěšit.

Nezapomeňte, že mnohdy je dostatečnou motivací i vyjádření důvěry k samostatnosti řešení a pochvala za úspěšné dokončení.

Nefungující zajišťování kvality

Na projekty jsou kladeny standardní i specifické kvalitativní požadavky. I přestože nepracujete na kritických projektech pro bankovní nebo armádní sektor, měli byste si zadefinovat pravidla a požadavky související s kvalitou. Mezi kvalitativní nefunkční požadavky na systém patří požadavky na rychlost, uživatelskou přívětivost, robustnost, škálovatelnost a další. I přestože váš systém splňuje dohodnutou funkcionalitu (funkční požadavky), může se stát, že je pomalý, uživatelsky nepřívětivý a ve výsledku špatný.

Mezi zásadní hodnotící kritérium kvality patří stabilita a chybovost systému. Předcházet chybám se dá mnoha mechanismy ve všech fázích vývoje systému. Můžete testovat požadavky na systém, analytické výstupy, návrh systému a samozřejmě implementační část. Je nezbytné zadefinovat testovací ekosystém projektu a hlavně jej dodržovat. Snažte se co nejvíce testů automatizovat (jednotkové, integrační, zátěžové). Zbývající musí "proklikat" tester (předávací). Tester je v některých firmách bohužel stále hodně podceňovaná pozice. Ve velkých firmách je běžné, že tato pozice je seniorská a dostávají se na ni kvalitní zaměstnanci s delší praxí ve vývoji. Dobrý tester se dokáže soustředit i na záležitosti, které by se objevily až v produkčním prostředí. A pokud se chyba dostane až tam, znamená zdaleka největší náklady na její odstranění.

U dlouhodobějších projektů je ještě více důležitá vnitřní (z venku neviditelná) kvalita kódu. Jedná se o dodržování kódovacích standardů definovaných vývojovým jazykem a interními metodikami. Měli byste aplikovat některou ze statických analýz kódu, sledovat důležité metriky a vyhodnocovat kondici celého systému. Měli byste včas odhalit členy vývojového týmu, kteří nedodržují pravidla a sjednat nápravu. Pouze kvalitní kód je v čase dobře udržovatelný a robustní. Systém by neměl být křehký, nepružný a imobilní, viz. článek na tomto webu.

Absence plánování a vyhodnocování

Z dobře naplánovaného projektu lze snadno vyčíst co a kdy se má stihnout. Aktuální stav projektu je potřeba neustále porovnávat s plánem a ten případně přizpůsobovat. Obecně je lepší, když je součástí jízdního řádu projektu detailnější krátkodobá část. Všichni potřebujeme pevné body a milníky, které nám usnadní ukotvení naší práce v čase. Důležitá je také priorita úkolů a požadavků. Někdy se stává, že se příliš úsilí a času věnuje nízkoprioritním záležitostem na úkor těch opravdu podstatných. V počátečních iteracích nemusíte stihnout všechno, ale dodejte zákazníkovi to podstatné a nepodstatné drobnosti řešte později.

Používejte nástroje, které Vám zjednoduší plánování. Určete, které části projektu lze řešit paralelně a rozdělte úkoly. V průběhu řešení sledujte rychlost jednotlivých podtýmů a ty kterým dochází dech stimulujte a řešte důvody pomalosti.

Absence popisu interních procesů

Máte ve firmě popsány procesy typu "zachycení a odstranění chyby", "nový požadavek zákazníka", "otestování úpravy", apod.? Postupujete jednotně nebo si každý hledá svoji optimální cestičku? Pokud jste schopni dodržovat jednotný postup, můžete mnoho částí zautomatizovat, zvýšit efektivitu nějakým nástrojem nebo optimalizovat.

Špatná podpora týmové práce

V dnešní době existuje spousta programových produktů, které podporují práci týmu. Základem je společné úložiště pro projektové dokumenty (požadavky, analýzy, návrhy) a zdrojové kódy. Potřebujete rozdělovat práci na menší části do pracovních položek, které mají vlastní životní cyklus. Součástí týmového prostředí je sestavovací server, který připravuje produkční, testovací a integrační verze Vašeho produktu. Vedoucím pracovníkům přijdou vhod reportovací služby. Nepoužívání těchto nástrojů znamená výrazné snížení efektivity práce a některé projekty bez nich nelze vůbec realizovat.

Problémová komunikace

Dobrá komunikace v týmu je zásadní pro úspěšnou realizaci projektu. Pokud komunikace nefunguje, dochází k mnohdy zbytečným problémům. Říká se, že byste měli spolupracovat pouze s lidmi, které byste si neváhali pozvat k sobě domů. Tato ideální situace však vždy nenastává. Musíte spolupracovat s lidmi, kteří nejsou podle vašeho gusta. V takovém případě je nutné zachovat profesionalitu a pokusit se zbavit případných osobních averzí. Jde přeci o úspěch celého týmu, ne pouze o Vaši osobní záležitost.

Měli byste dokázat určit, jaká forma komunikace je v jednotlivých případech užitečná. Někdy je vhodná offline emailová komunikace, někdy je zase vhodnější zvednout zadek nebo sluchátko a vyřešit problém online ústně. Začínají se také více prosazovat podnikové (projektové) sociální sítě, které nabízejí facebookovský formát komunikace. Nezbytné zůstávají porady různého typu (řešitelské, projektové, krizové, ...).

Nevyhodnocování zákaznické zpětné vazby

Již před vlastním nasazením produktu do provozního režimu je vhodné začít zjišťovat zpětnou zákaznickou vazbu. Můžete použít prototypování a získat zákazníkovy dojmy a připomínky k aktuálnímu stavu projektu. Další indicie použitelnosti získáte ve vlastním provozu. Pokud má být Váš produkt úspěšný, musíte brát zákaznické připomínky opravdu vážně. Nelze samozřejmě reagovat na každou připomínku, ale měli byste s vašimi zkušenostmi vystihnout to podstatné.

Vhodnou metodou je pozorování uživatele při používání systému v reálném provozu. Sedněte si vedle něho a sledujte jeho "míru zmatení" v jednotlivých situacích. Poznáte, která část ovládání systému mu způsobuje největší problémy. V jednoduchosti je síla a krása. Pokud váš systém bude uživatelsky jednoduchý a intuitivní, bude oblíbený a brzy si najde své příznivce. Úspěch vaší práce se nakonec bude měřit podle uživatelské spokojenosti.

Chybně zvolené technologie

Dnešní doba není pro vývojáře úplně jednoduchá. Existuje mnoho vývojových platforem a mnoho cílových prostředí, do kterých budete programový systém nasazovat. Může se stát, že zvolíte technologii, která nebude pro určitou skupinu uživatelů dostupná. Webové aplikace zřejmě budou zobrazitelné na většině zařízení, uživatelský komfort však nebude tak vysoký. Pokud budete chtít poskytnout uživatelům bohatší uživatelské prostředí, musíte vytvořit port na příslušnou cílovou platformu.

Důležitá je také volba programovacích jazyků. Pokud zvolíte jazyk, který členové týmu nemají zažitý, musíte počítat s vyššími náklady na zaškolení a s vyšší chybovostí. Pokud zvolíte technologii, která dožívá a nemá perspektivu, zaděláváte si na problémy s pozdějším rozvojem systému.

Nedostatečná interní projektová dokumentace

Je efektní, když někdo udělá svoji práci v kratším čase, než bylo očekáváno. Pokud je však daní za rychlost to, že nevypracoval potřebnou projektovou a řešitelskou dokumentaci, problémy se jistě brzy dostaví. Řešitel odejde z firmy nebo nemůže pracovat. Je potřeba ve fungujícím systému něco změnit nebo přidat. Bez dokumentace je každý zásah nebezpečný, pracný a stresující. Nakonec se stejně musí vykoumat, jak věci fungují a dokumentace postupně dopracovat.

A kde sdílet dokumentaci? Nabízí se využití projektových portálů, wiki nebo jiných nástrojů. Dokumenty by měly být snadno dostupné a verzovatelné.

Alkohol

Někteří umělci jsou známí tím, že v alkoholovém opojení vytváří svá nejlepší díla. Nepodlehněte iluzi, že i Vám pomůže nějaké to promile k lepšímu výsledku. Vývoj software je vysoce intelektuální činnost, která rozhodně není alkoholem stimulována. Unavený a nesoustředný programátor dělá chyby, ovíněný je neřízenou střelou.

Pokud máte v týmu někoho, kdo nedokáže oddělit práci a alkohol, je potřeba jeho přístup řešit. Nebanalizujte tento problém, v našich zeměpisných šířkách je poměrně častý.

neděle 15. ledna 2012

Fluent interface - nakouknutí za oponu

Proč fluent?

Fluent interface se dá volně do češtiny přeložit jako plynně nebo také ladně používané rozhraní. Jedná se o techniku budování API rozhraní s důrazem na popisnost a snadnost použití. Konzumenti fluent rozhraní ocení příjemný a intuitivní způsob zápisu bez zbytečného opakování stejných sekvencí. Fluent přístup k budování API je typický pro problematiku DSL (doménově specifické jazyky). Tento příspěvek by měl pomoci pochopit základní techniky budování fluent API.

Srovnejme dva způsoby zápisu použití rozhraní pro nastavení fiktivní hry. Nejprve klasické "no fluent" provedení (optimalizací zápisu by mohlo být použití objektových inicializátorů):

Hra hra = new Hra();
 
NastaveniPravidel nastaveniPravidel = new NastaveniPravidel();
nastaveniPravidel.PridatPravidlo("Pravidlo1");
nastaveniPravidel.PridatPravidlo("Pravidlo2");
 
hra.NastaveniPravidel = nastaveniPravidel;
 
NastaveniHracu nastaveniHracu = new NastaveniHracu();
 
NastaveniHrace hrac1 = new NastaveniHrace();
hrac1.Jmeno = "Franta";
hrac1.Vek = 50;
 
nastaveniHracu.PridatHrace(hrac1);
 
NastaveniHrace hrac2 = new NastaveniHrace();
hrac2.Jmeno = "Bloncka";
hrac2.Vek = 18;
hrac2.ZacinaHru = true;
 
nastaveniHracu.PridatHrace(hrac2);
 
NastaveniHrace hrac3 = new NastaveniHrace();
hrac3.Jmeno = "ChuckNorris";
hrac3.JePocitac = true;
 
nastaveniHracu.PridatHrace(hrac3);
 
hra.NastaveniHracu = nastaveniHracu;
 
hra.HaziSeKostkou = true;
hra.Obtiznost = 5;

Ekvivalent s využitím fluent zápisu:

IHra hra = new Hra().
    NastavitPravidla(
        x =>
        {
            x.PridatPravidlo("Pravidlo1");
            x.PridatPravidlo("Pravidlo2");
        }).
    NastavitHrace(
        x =>
        {
            x.PridatHrace("Franta").NastavitVek(50);
            x.PridatHrace("Bloncka").NastavitVek(18).ZacinaHru();
            x.PridatHrace("ChuckNorris").JePocitac();
        }).
    NastavitObtiznost(5).
    HaziSeKostkou();

Posuďte sami, který zápis se Vám víc líbí. Vytváření kódu je v dnešní době také o jeho čitelnosti a znovupoužitelnosti. Fluent technika přispívá právě k dosažení tohoto požadavku. Důkazem je popularita frameworků, které vsadily na fluent rozhraní - StructureMap, Rhino Mock, Fluent NHibernate a další.

Principy fluent rozhraní

Fluent rozhraní má následující charakteristiky:

  • Návratovou hodnotou metod jsou rozhraní, které umožňují řetězení metod.
  • Ukončovací kontext jedné metody je ekvivalentní počátečnímu kontextu metody následující.
  • Posloupnost volání metod může být ukončena metodou, která vrací typ void.
  • Rozhraní je tvořeno výhradně metodami, nastavování vlastností je potlačeno.
  • S výhodou se používají statické třídy a statické metody.
  • Používají se generické typy.
  • Pro nastavování hodnot typu boolean se používají bezparametrické metody, které zapnou nebo vypnou příznak.

Při konstrukci fluent rozhraní se (mimojiné) používají dvě techniky, které stojí za bližší vysvětlení - method chaining a nested closure.

Method chaining - řetězení metod

Poměrně známá technika, která umožní v jednom příkazu zřetězit volání více metod. Finta je v tom, že každá metoda vrací referenci na rozhraní. V takovém případě pak nezáleží na pořadí volání jednotlivých metod. Podívejme se na implementaci rozhraní INastaveniHrace.

public interface INastaveniHrace
{
    INastaveniHrace ZacinaHru();
    INastaveniHrace JePocitac();
    INastaveniHrace NastavitVek(short vek);
}

Ukázka použití z příkladu výše:

x.PridatHrace("Franta").NastavitVek(50);
x.PridatHrace("Bloncka").NastavitVek(18).ZacinaHru();
x.PridatHrace("ChuckNorris").JePocitac();

Nested closure - zapouzdření metody

Technika, která umožní vkládat složitější vnořené konstrukce jako argument volání metody. Ve výše uvedeném příkladě je část týkající se nastavení pravidel a volání metody NastavitPravidla() řešená přes nested closure:

NastavitPravidla(
    x =>
    {
        x.PridatPravidlo("Pravidlo1");
        x.PridatPravidlo("Pravidlo2");
    })

Implementace nested closure využívá delegát Action<T>, za který je v místě volání dosažen příslušný lambda výraz. Deklarace metody NastavitPravidla() v rozhraní IHry s použitím delegátu Action:

IHra NastavitPravidla(Action<INastaveniPravidel> akce);

Implementace metody pak může vypadat takto:

public IHra NastavitPravidla(Action<INastaveniPravidel> akce)
{
    akce(nastaveniPravidel);
    return this;
}

Ukázková implementace fluent rozhraní IHra

using System;
using System.Collections.Generic;
 
namespace Priklad.FluentInterface
{
    public interface IHra
    {
        IHra NastavitPravidla(Action<INastaveniPravidel> akce);
        IHra NastavitHrace(Action<INastaveniHracu> akce);
        IHra NastavitObtiznost(int obtiznost);
        IHra HaziSeKostkou();
    }
 
    public interface INastaveniPravidel
    {
        void PridatPravidlo(string nazev);
    }
 
    public interface INastaveniHracu
    {
        INastaveniHrace PridatHrace(string jmeno);
    }
 
    public interface INastaveniHrace
    {
        INastaveniHrace ZacinaHru();
        INastaveniHrace JePocitac();
        INastaveniHrace NastavitVek(short vek);
    }
 
    public class NastaveniPravidel : INastaveniPravidel
    {
        IList<string> pravidla = new List<string>();
 
        public void PridatPravidlo(string nazev)
        {
            pravidla.Add(nazev);
        }
    }
 
    public class NastaveniHrace : INastaveniHrace
    {
        internal bool jePocitac = false;
        internal string jmeno;
        internal short vek;
        internal bool zacinaHru = false;
        
        public INastaveniHrace ZacinaHru()
        {
            zacinaHru = true;
            return this;
        }
 
        public INastaveniHrace JePocitac()
        {
            jePocitac = true;
            return this;
        }
 
        public INastaveniHrace NastavitVek(short vek)
        {
            this.vek = vek;
            return this;
        }
    }
 
    public class NastaveniHracu : INastaveniHracu
    {
        IList<NastaveniHrace> hraci = new List<NastaveniHrace>();
 
        public INastaveniHrace PridatHrace(string jmeno)
        {
            NastaveniHrace hrac = new NastaveniHrace();
            hrac.jmeno = jmeno;
 
            hraci.Add(hrac);
 
            return hrac;
        }
    }
 
    public class Hra : IHra
    {
        private bool haziSeKostkou = false;
        private NastaveniHracu nastaveniHracu = new NastaveniHracu();
        private NastaveniPravidel nastaveniPravidel = new NastaveniPravidel();
        private int obtiznost;
 
        public IHra NastavitPravidla(Action<INastaveniPravidel> akce)
        {
            akce(nastaveniPravidel);
            return this;
        }
 
        public IHra NastavitHrace(Action<INastaveniHracu> akce)
        {
            akce(nastaveniHracu);
            return this;
        }
 
        public IHra NastavitObtiznost(int obtiznost)
        {
            this.obtiznost = obtiznost;
            return this;
        }
 
        public IHra HaziSeKostkou()
        {
            this.haziSeKostkou = true;
            return this;
        }
    }
}

Statické typy a generika

Výhody fluent rozhraní vyniknou v kombinaci se statickými typy a statickými metodami. Např. při použití mockovacího frameworku Rhino Mocks můžete jednoduchým zápisem nastavit očekávané chování getteru KodMeny mockovaného rozhraní IDoklad:

IDoklad doklad = mockRepository.StrictMock<IDoklad>();
Expect.Call(doklad.KodMeny).Return("EUR").Repeat.Any();

Třída Expect i metoda Call<T>() jsou statické. Vlastnost KodMeny vrátí hodnotu "EUR" a může být dotazována libovolněkrát (Repeat.Any()).

Všimněte si, že metoda Call() je generická. Generický typ použitý při jejím volání je určujícím generickým typem pro metodu Return(). V našem případě je doklad.KodMeny typu string.

Slabé stránky fluent interface

Konstrukce zapsané pomocí zřetězení metod a lambda výrazů se problematicky debugují. Problémem je nemožnost umístění bodu přerušení do podvýrazu. Lambda výrazy nelze používat při ladění ve funkci Watch.

Rozhraní napsané jako fluent často porušují pravidlo jedné zodpovědnosti a nutí k vytváření velkého "božského" objektového typu s mnoha zodpovědnostmi. Je to dané podstatou zřetězení metod, kdy každá metoda musí vracet odkaz na stejné rozhraní.

Dalo by se diskutovat, zda-li definice fluent rozhraní neporušuje Deméterův zákon o přístupu do vnitřních objektů. Pokud Vás tato diskuze zajímá, můžete si ji přečíst na stackoverflow.com.

čtvrtek 22. prosince 2011

Desatero uživatele Twitteru

Twitter je tu už více než pět let. Je na čase, aby někdo stanovil pravidla pro chování uživatelů :-)

  1. Nebudeš využívat jiné sociální sítě. Drž se Twitteru a budeš svobodný. Odprosti se od užívání Facebooku a Google+, které Tě svádí z cesty a narušují Tvé schopnosti stručného vyjadřování.

  2. Nebudeš posílat dotazy na nové tweety nadarmo. Nesmíš mě neustálým ručním dotazováním donucovat, abych Ti vracel nové tweety každých několik vteřin. Dost nám to zatěžuje systém. Nechej to na Tvém klientovi, který má interval občerstvování určitě nastavený rozumně.

  3. Budeš zachovávat každý den několik minut odpočinku. Během této doby se na Twitter ani nepodíváš. Naužírej se strachem, že zmeškáš nějaký zajímavý tweet, můžeš se kdykoliv podívat do historie.

  4. Budeš ctít zakladatele Twitteru i jeho mateřskou firmu Ordeo Inc. Budeš sledovat uživatele @Jack, @Biz, @Noah, @Crystal, @Jeremy, @Adam, @TonyStubblebine, @Ev, @Dom, @Rabble, @RayReadyRay, @Florian, @TimRoberts a @Blaine, protože právě oni byli na počátku vzniku našeho Twitteru.

  5. Nebudeš provádět Unfollow. Nebudeš přestávat sledovat uživatele, jenom proto, že je to Tvůj konkurent a protože nechceš, aby Tě předstihl v počtu followerů.

  6. Nesmilníš a nevložíš příspěvek do jiné mikroblogovací služby. Nemáš zapotřebí, aby ses karikaturami nezralých a příživnických mikroblogovacích služeb připravil o radost ze skutečného Twitteru. Drž se ho a naučíš se psát zajímavě a trefně a ocení Tě mnoho followerů.

  7. Neukradneš obsah cizího tweetu. Nesnaž se zalíbit tím, že zajímavý tweet označíš za svůj. Používej raději Retweet. Co získáš na oblíbenosti a počtu followerů, to ztratíš na klidné mysli.

  8. Nebudeš vystupovat pod falešnou identitou. Nesnaž se být zajímavý tím, že budeš vystupovat za známou osobnost. Twitter Tě odhalí a zablokuje Tvůj účet. Snižuješ důvěryhodnost celé sítě a sám sebe.

  9. Nebudeš žádostivě dychtit po followerech toho, kdo Tě sleduje. Nevnucuj se a nevyžaduj laciné retweety, jenom aby jsi získal rychlé followery. Svým chováním můžeš způsobit rozvrat a Unfollow dotyčného. Buď trpělivý a followeři si cestu k Tobě určitě najdou.

  10. Nebudeš závistivě projíždět seznamy followerů top uživatelů a chamtivě vyhlížet své nové followery. Neužírej se tím, že máš málo followerů. Někomu to jde líp a stačí mu pouze jeho jméno. Někdo to má těžší. Drž se své vize a kvalitním obsahem si své followery určitě získáš.

středa 21. prosince 2011

Vlastní úlohy pro MSBuild

Automatizujte. Váš čas je drahý. Nedělejte ručně činnosti, které za Vás mohou udělat stroje během několika okamžiků a s minimální chybovostí.

Součástí Visual Studia je buildovací systém MSBuild. MSBuild pracuje ve Visual Studiu na pozadí při kompilaci projektů do spustitelného kódu. MSBuild je také využíván při týmovém vývoji na speciálních buildovacích serverech. Ať už provádíte build produkční verze aplikace, build testovací verze, build kontinuální integrace nebo úplně jinou automatizovanou úlohu, může se stát, že vyvstane specifická potřeba, kterou standardní úlohy MSBuildu nezvládnou. Pak se přiblíží okamžik, kdy budete potřebovat napsat úlohu vlastní. Určitě se toho nebojte. Odměnou Vám bude zrychlení práce a uznání ostatních členů vývojového týmu ;-)

Vytvoření knihovny s úlohou

Vytvoříme projekt typu Class Library. V našem příkladu založíme projekt Firma.Nastroje.Build.Ulohy.

Do projektu přidáme reference na frameworkové assembly Microsoft.Build.Framework a Microsoft.Build.Utilities.v4.0 (pro .NET FW 4.0).

Založíme třídu úlohy. Třída musí implementovat rozhraní Microsoft.Build.Utilities.ITask. Je vhodné podědit abstraktní třídu Microsoft.Build.Utilities.Task. Překryjeme metodu Execute(), která je vyvolána MSBuildem během provádění. Provádění úlohy je konfigurovatelné přes nastavení veřejných vlastností třídy. Nezapomeňte projekt zkompilovat ;-)

using System;
 
namespace Firma.Nastroje.Build.Ulohy
{
    /// <summary>
    /// Implementace mojí úlohy sestavení.
    /// </summary>
    public class MojeUloha : Microsoft.Build.Utilities.Task
    {
        /// <summary>
        /// Povinný parametr úlohy.
        /// </summary>
        [Microsoft.Build.Framework.Required]
        public string PovinnyParametrUlohy { get; set; }
 
        /// <summary>
        /// Nepovinný parametr úlohy.
        /// </summary>
        public string NepovinnyParametrUlohy { get; set; }
 
        /// <summary>
        /// Provádění úlohy.
        /// </summary>
        /// <returns>true, pokud je provádění úspěšné.</returns>
        public override bool Execute()
        {
            throw new NotImplementedException();
        }
    }
}

Nasazení knihovny na buildovací počítač

Všechny rozšiřující knihovny, které by měl znát MSBuild, umístěte na buildovacím počítači do adresáře definovaného v proměnné $(MSBuildExtensionsPath). Obvykle se jedná o "c:\Program Files (x86)\MSBuild". Doporučuji knihovnu zařadit ještě do podadresáře podle firmy nebo projektu. Ukázková knihovna bude mít v našem příkladě absolutní cestu "c:\Program Files (x86)\MSBuild\Firma\Firma.Nastroje.Build.Ulohy.dll".

Použití v buildovacím projektu

Nejprve musíme zadeklarovat naši úlohu na začátku řídícího projektového souboru (.proj, .csproj) ...

<UsingTask 
   TaskName="MojeUloha" 
   AssemblyFile="$(MSBuildExtensionsPath)\Firma\Firma.Nastroje.Build.Ulohy.dll"/>

... a poté zadefinovat konkrétní použití buildovací úlohy:

<MojeUloha
   PovinnyParametr="HodnotaPovinnehoParametru"
   NepovinnyParametr="HodnotaNepovinnehoParametru"
   />

Poznámky

  • Pro účely ladění třídy Vaší úlohy si vytvořte jednotkové testy, viz. TDD.
  • Framework Vaší knihovny musí být na buildovacím počítači podporován. Úlohy v jednom buildovacím projektu mohou být napsány pro různé frameworky.
  • Úlohy mohou poskytovat i návratové argumenty.
  • Argumenty úloh mohou být kolekce hodnot, např. kolekce názvů souborů.
  • Alternativou k vlastním úlohám pro MSBuild je vytvoření spustitelné exe aplikace, které předáte potřebné parametry přes příkazovou řádku.

sobota 3. prosince 2011

Pravidla pro pojmenování objektů v C# - část 2

  1. Úvod, jazyk, názvy tříd
  2. Názvy vlastností (properties), polí (fields) a proměnných (variables)
  3. Názvy metod a argumentů
  4. Další pravidla, názvy balíčků, testovací třídy

V předchozím díle jsme se podívali na několik základních pravidel pro názvosloví tříd. Neméně důležité je logicky a významově pojmenovat její vlastnosti, pole a proměnné uvnitř metod.

Názvy vlastností, polí a proměnných

Chtělo by se říci, že názvy veřejných vlastností jsou důležitější než názvy neveřejných vlastností, polí a proměnných. Není to však úplně pravda. Veřejné rozhraní třídy je samozřejmě důležité pro klienty třídy. Správný název urychlí pochopení a ušetří přepínání mezi kódem a dokumentací. Neveřejné názvy jsou však významné pro znovupoužitelnost, čistotu kódu, pochopení významu a efektivní navigaci v kódu.

Na co bychom si tedy měli dát pozor?

  1. Pro názvy vlastností (properties) se používá PascalCase, např. RodneCislo.

  2. Pro názvy polí (fields) se používá camelCase, např. rodneCislo.

  3. Pro názvy konstantních polí se používá PascalCase, např.

    private const int PocetMesicu = 12;

  4. Pro názvy proměnných (variables) se používá camelCase, např. polozky.

  5. Pokud vlastnost a pole (a proměnná) odpovídají stejnému logickému významu, měli by si jejich názvy odpovídat. Např.

    private string rodneCislo;
    
    public string RodneCislo
    {
        get
        {
            return rodneCislo;
        }
    
        private set
        {
            rodneCislo = value;
        }
    }
    

  6. Pokud je vlastnost autoimplementovatelná, tzn. getter je jednoduché vrácení hodnoty pole a setter je jednoduché nastavení hodnoty pole, je vhodné použít zkrácený a přehlednější zápis:

    public string RodneCislo { get; private set; }
    
    Výhodou tohoto zápisu je mimo jiné i jednodušší refaktorizace názvu. Nemusíte refaktorovat zvlášť název vlastnosti a pole.

  7. Pravidla uváděná dále jsou společná pro názvy vlastností, polí i proměnných.

  8. Vyhněte se opakování názvu třídy v názvech jejích vlastností. Např. třída Objednavka by neměla mít vlastnost PopisObjednavky nebo ObjednavkaId. Použijte "holý" název Popis a Id.

  9. V případě odkazu na Id jiné třídy ("primární klíč"), bude název odkazované třídy předcházet názvu vlastnosti Id:

    public class Osoba
    {
        public int Id { get; set; }
    }
    
    public class Uzivatel
    {
        public int OsobaId { get; set; }
    
        public String Jmeno { get; set; }
    }
    
    V tomto případě by bylo zřejmě vhodnější, aby třída Uzivatel nabízela přístup k objektu typu Osoba
    public Osoba Osoba
    

  10. Použijte název třídy v názvech vlastností jiných tříd, které na ni odkazují nebo vlastnost odpovídá vlastnosti odkazované třídy. Všimněte si vlastnosti Kod u třídy Mena a vlastnosti KodMeny u třídy Objednavka. Obě mají v systému stejný význam.

    public class Mena 
    {
        public string Kod { get; set; }
        public string Nazev { get; set; }
    }
    
    public class Objednavka 
    {
        public string KodMeny { get; set; }
        public decimal Castka { get; set; }
    }
    

  11. Pokud je to vhodné, použijte upřesňující významovou příponu. Např. CastkaVMeneDokladu, DobaTrvaniVMilisekundach, DenVTydnu.

  12. Pro booleovské vlastnosti použijte vhodnou předponu, např. JePlatna, MaNarokNaOdmenu.

  13. U zkratek ponechejte pouze první písmeno velké, např. Html, Id, Ico, KategorieDph.

  14. Nepoužívejte v názvech datové typy. Místo PolozkaObjednavkyList použijte PolozkyObjednavky, místo VystaveniDate použijte DatumVystaveni.

  15. Pokud používáte víceslovné názvy, měly by být přiměřeně dlouhé a srozumitelné. Snažte se vyjádřit stručně. Pokud je to však nezbytné, nestyďte se použít delší název.

  16. Stejně jako u názvů tříd je vhodné používat názvy z domény problému. Vycházet byste měli z doménového slovníku, který navrhne doménový analytik.

  17. Vyhněte se používání různých synonym pro logicky stejnou vlastnost různých tříd.

Používáte pravidlo, které zde není uvedeno? Máte připomínku k některému doporučení? Neváhejte vložit komentář.