středa 31. května 2017

Proč právě Typescript?

Pokud to někdo s vývojem v javascriptu myslí vážně, měl by hledat způsob, jak nejlépe napsat udržitelný kód.

Díky vlastnostem, které přinesly ES5 a ES6, máme již k dispozici jazyk, který se netváří tak nepřátelsky.

Nicméně, stále existuje jedna věc, kterou javascript nenabízí a která je u většího projektu dost zásadní. Tou vlastností je typovost.

Proč bychom měli chtít typy v javascriptu?


Odpověď je vcelku jednoduchá. Z důvodu udržitelnosti kódu.

Představte si situaci, že máte projekt, kde chcete provést refactoring či změnu v modelu aplikace. V případě, že váš projekt nemá typy, budete se muset spolehnout pouze na špičkově napsané testy, které vám prozradí, zda jste v kódu něco nerozbili :)

Pojďme si udělat malou ukázku.

Máme entitu uživatele, kterou zobrazujeme v tabulce. Zjednodušený kód by vypadal asi následovně:

const users = [
    {id: 1, firstName:  'Ales', lastName: 'Dostal', roles: ['admin']},
    {id: 2, firstName:  'Petr', lastName: 'Novotny', roles: ['operator']},
];

Nyní toto pole zobrazíme v tabulce:

users.map((row) => (
    <tr>
        <td>{row.firstName} {row.lastName}</td>
        <td>{row.roles.join(', ')}</td>
    </tr>
));

Tady je svět asi v pořádku, ale co nastane, když budete potřebovat provést změnu, která spočívá v tom, že atribut roles budete muset zahodit a říci, že uživatel může obsahovat pouze jednu roli? Atribut roles se přejmenuje na role a přijímat bude pouze jeden řetězec, ale nikoli pole.

const users = [
    {id: 1, firstName:  'Ales', lastName: 'Dostal', role: 'admin'},
    {id: 2, firstName:  'Petr', lastName: 'Novotny', role: 'operator'},
];

Co zbytek vašeho kódu?
Jen velice těžko budete dohledávat, zda objekt user obsahuje ty správné atributy, se kterými pracujete v metodě map, pro vypsání řádku tabulky. Javascript se bude tvářit, že je vše v pořádku a problém zjistíte až za běhu. A to skutečně nechce přeci nikdo.

Pojdmě náš kód obohatit o typovost pomocí Typescriptu. První věcí, kterou musíme udělat je, že si vytvoříme definici typu User.

interface User {
    readonly id: number;
    readonly firstName: string;
    readonly lastName: string;
    readonly roles: string[];
}

Nyní řekneme, že proměná users je typu pole User.

const users: User[] = [
    {id: 1, firstName: 'Ales', lastName: 'Dostal', roles: ['admin']},
    {id: 2, firstName: 'Petr', lastName: 'Novotny', roles: ['operator']},
];

A nyní, když budeme chtít změnit model, změníme definici.

interface User {
    readonly id: number;
    readonly firstName: string;
    readonly lastName: string;
    readonly role: string;
}

V té chvíli nám bude kompilátor Typescriptu vracet chybové hlášení, které nás upozorní, že máme špatně inicializovanou proměnou users a současně, že v metodě map předpokládáme, že existuje atribut roles, které je pole.

Teď si vemte tuto malou ukázku a vynásobte jí třeba 100x krát. Opravdu chcete ještě stavět projekt bez typů?

Co je tedy ten Typescript?


Typescript je jazyk, který byl představen v roce 2012 Microsoftem. V podstatě vychází z jednoduché myšlenky, která říká: "Pište klasicky v javascriptu, jen k němu přidejte typy".
I když Typescript má i další vlastnosti, které javascript nenabízí, tak jeho hlavní přínos je právě v oné přidané typovosti.

V praxi to vypadá tak, že píšete soubor, který si označíte jako typescript soubor (většinou pomocí přípony *.ts) a poté tento soubor zkompilujete kompilátorem Typescriptu. Výsledkem je javascriptový soubor, který je v dané ES specifikaci. O tom, do jaké specifikace chcete soubor kompilovat je na vás.

Více se o typescriptu můžete dozvědět z oficiálního webu.

Typescript není Java


Často se setkávám s tím, že lidé k Typescriptu přistupují jako k Jave. I když zde najdete spoustu společných vlastností, je dobré mít stále na paměti, že Typescript funguje jinak.
Jedním z hlavních rozdílů je to, že Typescript své typy porovnává na úrovni struktury.

Uveďme si příklad:

interface Cat {
    name: string;
}

interface Dog {
    name: string;
}

const cat: Cat = {name: 'Mourek'};
const dog: Dog = cat;

Proč tomu tak je?

Jde o to, že Typescript sice má typy, ale představte si, že jsou to stejně jen jakési flagy, které Vám mají pomáhat při psaní kódu. Poté, co se daný soubor zkompiluje do javascriptu, tak typy jsou odstraněny a pracuje se pouze s JSONem.

Další věcí je, že chyby, které Vám kompilátor Typescriptu bude hlásit můžete často ignorovat. Výsledný kód bude funkční, dokud…

Příkladem je také třeba klíčové slovo readonly, kterým pokud označíte atributy daného typu, tak tím říkáte, že je nelze přímo přepsat. Nicméně, pokud to v kódu ignorujete, tak výsledkem bude validní javascript, protože ten žádné klíčové slovo readonly nezná.
Proto budťe obezřetní, při psaní v Typescriptu. Pořád je třeba mít na paměti, že je to javascript, který si jen typuji.

Další možnosti, jak typovat javascript


Kromě Typescriptu zde existuje ještě jedna varianta, která ve své podstatě dělá to samé (i když jiným způsobem). Tou variantou je FlowType či označováno jen jako Flow. 

Flow je statická typová kontrola, kterou vytvořili lidé z facebooku. Na rozdíl od Typescriptu, je Flow méně invazivní a jedná se v podstatě pouze o "type check", kdežto v případě Typescriptu to je kompletní kompilace.

A proč tedy Typescript a ne Flow?


Tuto otázku jsem si pokládal dost často. Přeci jen, vždy máme touhy pokukovat po alternativách a hledat, zda někdo nemá ten "trávníček o něco zelenější". Já osobně jsem do Typescriptu šel ze dvou hlavních důvodů.

1. Typescript je tady déle a používá ho více knihoven
Tím, že byl první, tak z toho dodnes těží. Týká se to zejména knihoven, které když stáhnete z NPM, často se setkáte s problémem, že daná knihovna nemá definované typy. A pokud ano, je větší pravděpodobnost, že typy budou pro Typescript, nikoli pro Flow.

2. Angular 2
Ač jsem zastánce Reactu a Angular vnímám spíše jako ukázkovou cestu, kterou nejít, dá se zde mluvit o tom, že Typescript je nejvíce zpopularizován právě Angularem 2, který tento jazyk zvolil jako výchozí. Microsoft vytvoří jazyk a Google framework, který ho evangelizuje. Ironie, že? :)

Závěr


Už jste začali používat typy v javascriptu? :)

úterý 30. května 2017

Javascript - map / reduce / filter

V době, kdy jsem se poprvé setkal s javascriptem, nic nenaznačovalo tomu, že by se jednou z tohoto jazyka stalo to, co prožíváme nyní.
Psát o tom, že je to jazyk, který se vrací jako bumerang a v současné době zažívá své znovuzrození, je stejně zbytečné, jako to, že je to jazyk, který má asi nejsvětlejší budoucnost ze všech.

Díky bohu, že jsme se postupně dostali přes různé slepé uličky či uzavřeli jQuery, které splnilo svou historickou povinnost a odešlo do věčných lovišť. Již dávno jsou pryč časy, kdy většina vývojářů k javascriptu přistupovalo způsobem: google -> stackoverflow -> copy & paste.

Díky nové specifikaci (ES5 a ES6), jsme schopni k tomuto jazyku již přistupovat mnohem přímočařeji.

Dnešní ukázka se bude týkat práce s polem. V ukázce je použit typescript.

1. Představte si, že máte uživatele, který má následující vlastnosti:

interface User {
    readonly id: number;
    readonly firstName: string;
    readonly lastName: string;
    readonly roles: string[];
    readonly countOfClicks: number;
}

2. Nyní si vytvoříme pole uživatelů

const users: User[] = [
    {id: 1, firstName: 'Ales', lastName: 'Dostal', roles: ['admin', 'operator', 'manager'], countOfClicks: 32},
    {id: 2, firstName: 'Petr', lastName: 'Vomacka', roles: ['operator', 'manager'], countOfClicks: 43},
    {id: 3, firstName: 'Martin', lastName: 'Novak', roles: ['manager'], countOfClicks: 0},
    {id: 4, firstName: 'Petr', lastName: 'Novotny', roles: ['operator'], countOfClicks: 13},
    {id: 5, firstName: 'Jan', lastName: 'Novak', roles: ['manager', 'superuser'], countOfClicks: 31},
    {id: 6, firstName: 'Petr', lastName: 'Sulek', roles: ['manager', 'superuser'], countOfClicks: 18},
];

Úkol 1: Celkový počet kliků


Prvním zadáním je celkový počet kliků, všech uživatelů.
Pokud bychom nepoužívali ES5 a arrow functions, tak by zápis vypadal následovně:

let countAll = 0;
for (let i = 0; i < users.length; i++) {
    countAll += users[i].countOfClicks;
}
console.log('countAll: ', countAll);

V případě využití ES5 a arrow functions, lze dané zadání přepsat následovně:

const countAll = users.reduce((result, user) => (result + user.countOfClicks), 0);
console.log('countAll: ', countAll);

Výsledek:
countAll: 137

Docela rozdíl, že? Pojdmě se podívat na další možnosti, které již budou využívat pouze ES5 a arrow functions. Nechceme přeci psát zastaralým stylem :)

Úkol 2: Průměrný počet kliků


Dalším úkolem je, znát půmerný počet všech kliků, přes všechny uživatele. Pokud bychom nevycházeli s předchozího výsledku, který bychom jen vydělili celkovým počtem uživatelů, je možné i tento úkol zapsat pomocí funkce reduce:

const average = users.reduce((result, user, index, array) => {
    result += user.countOfClicks;
    if (index === array.length - 1) {
        return result / array.length;
    }
    return result;
}, 0);
console.log('average: ', average);

Výsledek:
average: 22.833333333333332

Úkol 3: Najdi všechny uživatele s jménem Petr


Výsledkem tohoto úkolu by mělo být pole uživatelů, kteří splňují podmínku, že jméno uživatele je Petr.

const petrUsers = users.filter((f) => f.firstName === 'Petr');
console.log('petrUsers: ', petrUsers);

Výsledek:
petrUsers:  [ { id: 2,
    firstName: 'Petr',
    lastName: 'Vomacka',
    roles: [ 'operator', 'manager' ],
    countOfClicks: 43 },
  { id: 4,
    firstName: 'Petr',
    lastName: 'Novotny',
    roles: [ 'operator' ],
    countOfClicks: 13 },
  { id: 6,
    firstName: 'Petr',
    lastName: 'Sulek',
    roles: [ 'manager', 'superuser' ],
    countOfClicks: 18 } ]

Úkol 4: Pole ID uživatelů


Vysledkem úkolu je pole ID uživatelů

const ids = users.map((user) => (user.id));
console.log('ids: ', ids);

Výsledek:
ids: [ 1, 2, 3, 4, 5, 6 ]

Úkol 5: Unikátní pole rolí


Výsledkem bude pole rolí, kde se žádná z rolí nebude opakovat:

const roles = users.reduce((result, user) => {
    result.push(...user.roles.filter((f) => result.indexOf(f) === -1));
    return result;
}, []);
console.log('roles: ', roles);

Výsledek:
roles: ['admin', 'operator', 'manager', 'superuser']

Úkol 6: Pole jmen a počet výskytů


Výsledkem bude pole jmen a počet výskytů v poli uživatelů.


const uniqueFirstNameCount = users.reduce((result, user) => {
    result[user.firstName] = (result[user.firstName] || 0) + 1;
    return result;
}, []);
console.log('uniqueFirstNameCount: ', uniqueFirstNameCount);

Výsledek:
uniqueFirstNameCount: [Ales: 1, Petr: 3, Martin: 1, Jan: 1]

Závěr


Znalost využívání funkcí jako je map, reduce, filter, find či sort je jedna z klíčových věcí, kterou by programátor měl znát.
Díky tomu, že javascript je jazyk, který lze dnes využívat i na serveru, tak díky znalosti funkcí pro pole je možné tuto znalost aplikovat, například pro mongodb.
Pokud by někdo našel optimálnější způsob zápisu, daných úkolů, nechť se o ně podělí v komentáři.

středa 10. května 2017

Jak by se firmy neměly chovat k programátorům? Druhé pokračování...

Vzhledem k tomu, že jsem se zavázal k pokračování článku "Jak by se firmy neměly chovat k programátorům?" Tak tady je.

Příklad 5: Open space je skvělý

Ne, open space je největší zlo, které nikdy nemělo vzniknout. Existují tři důvody, proč ho většina firem používá.

První a jediný pravdivý důvod je to, že je to ekonomicky výhodnější, postavit jednu velkou kancelář, kam posadím 30 lidí. Přeci jen, málokterá firma má peníze na rozhazování.

Druhým důvodem je to, že šéf může lépe kontrolovat, co jeho zaměstnanci dělají a zda jsou vlastně na svém místě. K tomuto se snad dá odpovědět pouze tak, že ano, sice je vidět, zda jste v práci a máte otevřen ten správný program, který má na Vašem monitoru svítit, ale už to nic neříká o tom, zda skutečně pracujete a zda pracujete produktivně.
V jedné firmě jsem zažil skutečné peklo. Nejenom, že jsem byl kontrolován snad i na počet kliků myší, ale navíc jsem „získal“ to nejhorší místo z celé té velké stodoly. To znamená, že za den kolem mě prošlo tak tisíc lidí a to mi způsobovalo to, že jsem se skutečně nebyl schopen soustředit na svou práci. Navíc jsem se občas chtěl podívat i na soukromé věci. Ale otevřít si facebook? Sakra, působil bych jako flákač…

Třetím důvodem je to, že lidé v open space mezi sebou více komunikují. Mám pro Vás smutnou zprávu. Nekomunikují. Lidé si vytváří sociální vazby úplně jinak, než jak by si přáli jejich šéfové. Zažil jsem mnohokrát situaci, kdy lidé, kteří seděli v open space, cca 2 metry od sebe, tak si raději napsali po chatu, protože vůči sobě seděli zády a bylo příliš složité se otočit a mluvit. Navíc by to rušilo ostatní.

Open space je proti lidské přirozenosti. Lidským instinktem je totiž to, že si každý z nás chce vytvořit své „útočiště“. Tedy vlastní pracovní prostor, který nebude nikým narušován. Lidé si chtějí dát na svůj stůl svůj hrníček, fotku rodiny, samolepku svého týmu, apod. Je to pro nás přirozené. Snažíme si vytvořit prostor, který nám bude příjemný a nebude pro nás tak stresující. Bohatě stačí to, že po nás šéf chce výsledky a vyhrožuje snížením mzdy J

Spoustu let jsem pracoval v oddělené kanceláři, kde seděli další tři lidé. Bylo to to nejefektivnější období mého života, které jsem zažil.

Příklad 6: Šéf je jako Steve Jobs

Psát o tom, kdo byl Steve Jobs je asi zbytečné. Vizionář, který…. bla bla bla. Osobně nemám nic proti Jobsovi, sám používám Apple produkty.

Co je ovšem naprosto špatně? Představte si situaci, že pracujete ve firmě, kde dojde na nejhorší. Šéf dostal od manželky k Vánocům novou knihu s názvem: „Buď jako Steve Jobs“. Po vánočních svátcích, naplněn novými poznatky se pokusí je ihned využít. Já jsem šéf, já tomu rozumím nejlépe a já jsem vizionář. A tak začne poučovat ostatní a řídit věci, kterým nerozumí.

Programátor se v té chvíli dostane do svízelné situace. Jak mám šéfovi vysvětlit, že jeho nápad je úplná kravina? Jeho vize je sice dokonalý produkt, ale díky svým neznalostem jen způsobí zničení toho, co do té doby bylo dobře.

Opět něco z praxe. Měl jsem šéfa, který mi dával najevo, že všemu rozumí lépe než já a že ví, jak by věci měly být. Ale já jeho vizi nesdílel. A v tomto případě platí jedno pravidlo: „Boj se svým šéfem nikdy nevyhrajete“. Firmu jsem proto opustil a šel si dál svou cestou… 

Příklad 7: Manažeři rozumí svému byznysu lépe než programátoři

Většina firem má striktně rozděleny své role. Programátor tvoří software a manažer určuje, jak bude software vypadat a co má umět. On přeci mnohem lépe ví, co uživatelé chtějí a co je dneska „cool“.

Možná se zdá, že tady je vše v pořádku. Bohužel tomu tak není.

Zkusím trochu odbočit. Víte, co mají společného firmy jako: Google, Facebook či Microsoft? Ano, správně! Jsou to IT firmy. Ale také společnosti, které byly založeny programátory. Ať už lepšími či horšími, ale byli to programátoři.

Co z toho vyplývá?

Otázka pro manažery. Kdy naposledy jste se ptali svých programátorů na byznys? Co by udělali jinak a nemyslím tím technicky.

Otázka pro programátory. Kdy naposledy se Vás šéfové ptali na byznys? Co byste udělali jinak a nemyslím tím technicky.

Mnoho firem by se možná divilo, s čím by jejich programátoři přišli. Pokud banda manažerů, bez špetky technických znalostí, navrhuje, co by měl software umět a jak by měl vypadat, je to vždy špatně.

A zase trochu praxe. V jedné firmě jsem zažil to, že jsem dostával přesné zadání, které jsem měl implementovat. Tady je svět asi v pořádku, až na to, že to často byly nesmysly, které bych svým uživatelům skutečně nechtěl nabízet. Funkčnosti stály dost peněz a do dnes jsem přesvědčen, že to nemohlo být výhodné ani pro jednu stranu.


Pokračování příště….

React aplikace od začátku do konce

V poslední době jsme byli nuceni napsat více React aplikací, které vždy vychází ze stejného základu. Díky tomu jsem si uvědomil, že i když...