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.