pátek 16. června 2017

React a Typescript

V poslední době se mě několik lidí ptalo, jestli píši v čistém javascriptu, nebo používám něco jiného. Odpověď je jednoduchá: "Mým hlavním jazykem je Typescript". Důvody proč právě Typescript, jsem zmiňoval v jednom z předešlých článků.

Dnes bych se chtěl zaměřit na to, jak vlastně využít Typescript s Reactem. Dnešní článek bude více zaměřen na jednotlivé ukázky, než na teoretickou část.

Kde začít?


V první řadě je nutné říci, že díky tomu, že React je Facebook technologie, primárně své ukázky uvádí buď v čistém javascriptu, nebo pomocí Flow. Důvod, proč právě Flow je zřejmý, je to technologie, která je také od Facebooku.

V té chvíli nastává problém, kde přesně zjistit, jak používat Typescript. Nezbývá tedy nic jiného, než že projdete několik blogů a ukázek na githubu.

Abych vám ušetřil čas, který byste museli trávit při hledání "správného řešení", zkusím projít jednotlivé části, na kterých ukážu, jak Typescript v Reactu použít. V případě ukázky v čistém javascriptu, bude použita ES6 specifikace.

Pojďme tedy na to....

Functional Stateless Components


První, na co se zaměřím jsou stateless komponenty. Jinými slovy, jsou to komponenty, které jsou v podstatě funkcí a neobsahují ani state, ani možnost využítí lifecycle. Jediné, co máte k dispozici jsou props.

React Stateless componenty byly představeny ve verzi 0.14 a veřte, že by vaše aplikace měla být složena z 95%, právě těmito komponentami.

Javascript - Stateless component
import React from 'react';

const HelloWorld = ({name}) => (
    <div>{`My name is ${name}`}</div>
);

export default HelloWorld;

Typescript - Stateless component
import * as React from 'react';

interface Props {
    readonly name: string;
}

export const HelloWorld: React.SFC<Props> = ({name}) => (
    <div>{`My name is ${name}`}</div>
);

První, čeho si můžete všimnout je import. Tato drobná změna není až tak důležitá. Stačí se podívat, jakým způsobem se importuje v Typescriptu a bude vám to jasné.

Druhou věcí je interface. To už je zajímavější část. Důvod, proč definujeme interface jakožto datový typ pro props, je ten, abychom měli danou komponentu "typově pod kontrolou". V rámci definice tohoto typu si můžete všimnout i klíčového slova "readonly". Osobně toto klíčové slovo vnímám jako jednu z ohromných výhod Typescriptu a umožňuje mi nastavovat, že daný atribut je immutable. A pokud víte, jak pracuje props v React komponentách, tak je to přesně vlastnost, kterou chcete využít. Dá se říci, že téměř všechny atributy v typech označuji tímto klíčovým slovem. Immutable stav je přesně to, co v Reactu chceme mít.

Další věcí je export. Sice máte možnost i Typescriptu použít export default, ale nedělejte to. Důvod proč, je vcelku jednoduchý. V případě, že použiji export default, tak v souboru, kam importuji tuto komponentu nemám pod kontrolou její název. Poté se dost zesložiťuje nejen refactoring kódu, ale také i případné dohledávání jednotlivých vazeb. Zjednodušeně řečeno, export default není zrovna dobrá volba.

Typescript - import with default
import NazevKteryJsemSiVymyslel from './HelloWorld';

Typescript - import without default
import {HelloWorld} from './HelloWorld';

Poslední věcí je definování typu pro React Stateless komponentu. K tomuto účelu existuje právě zmíněný deklarovaný typ SFC. Jde o zkratku "StatelessComponent", která je v React typové definici také. Osobně spíše využívám zkratku SFC, která mi šetří místo, které mohu využít pro výčet atributů z props přes destructuring assignment.

Stateful components


Druhou variantou jsou stateful komponenty. Tyto komponenty je vhodné využívat v případě kontejnerů, tedy komponent, které jsou napojeny na Redux. Dalším případem, kdy má stateful komponenta využití, je, pokud potřebujeme state či lifecycle.

Javascript - Stateful component
import React from 'react';

class HelloWorld extends React.Component {

    render() {
        return (
            <div>Hello world!</div>
        );
    }
}

export default HelloWorld;

Typescript - Stateful component
import * as React from 'react';

interface Props {

}

export class HelloWorld extends React.Component<Props, void> {

    render() {
        return (
            <div>Hello world!</div>
        );
    }
}

V tomto jednoduchém případě se příliš věcí nemění. Kromě již zmíněného importu je možné si všimnout, že díky Typescriptu mohu využít generiku, kde prvním parametrem jsou props a druhým state. V případě, že state nepoužíváte (což v případě Reduxu je požadovaný stav), je možné state nastavit na void.

Pojďme se podívat trochu dál....

Redux


Pokud ve své aplikaci používáte Redux, musíte splnit několik kroků, abyste Redux mohli používat. Nechci se zde zabývat tím, jak nastavit Redux, ale jak v rámci Reduxu používat Typescript.

První věc, kterou byste měli udělat, je vytvoření typové definice vašeho state. S největší pravděpodobností budete svojí aplikaci rozdělovat do menších celků, které na konci spojíte pomocí combineReducers.

Nejdříve si tedy navrhneme Redux state, který bude reprezentován následujícími typy. Pro zjednodušení je vše napsáno v jedné části, nicméně je dobré, aby kazdý interface byl ve vlastním souboru.

Typescript - Redux state
export interface UsersState {
    readonly list: User[];
    readonly isFetching: boolean;
    readonly lastFetched: Date;
}

export interface TenantsState {
    readonly list: Tenant[];
    readonly isFetching: boolean;
    readonly lastFetched: Date;
}

export interface State {
    readonly users: UsersState;
    readonly tenants: UsersState;
}

Další věcí jsou redux akce, které budeme chtít z komponent volat, aby modifikovaly redux pomocí reducerů. Definice akcí by mohla vypadat následovně:

Typescript - Redux actions
import {Dispatch} from 'redux';
import {State} from './State';
import {fetch} from 'tva-preferovana-knihovna';

const PREFIX = 'USERS_';

export const UsersActions = {
    FETCHING: `${PREFIX}FETCHING`,
    FETCHED: `${PREFIX}FETCHED`,
    fetchUsers() {
        return (dispatch: Dispatch<State>, getState: () => State) => {
            dispatch({type: UsersActions.FETCHING});
            fetch('Zde bude GraphQL dotaz - REST je mrtvy :)').then((result) => {
                dispatch({type: UsersActions.FETCHED, payload: result});
            }).catch((err) => {
                // Zpracovani chyby, klidne pres dalsi Redux akci
            });
        };
    },
};

Nyní mám vytvořenu akci fetchUsers(), která nejdříve odešle do reduceru akci, že se data nahrávají a poté v Promise callbacku provede druhou akci, která má již i payload, kde jsou stažena daná data.

Další část skládanky jsou samozřejmě reducery. V ukázce používám knihovnu redux-actions, kterou považuji za vhodnou, pokud se chcete vyhnout psaní pomocí switch-case.

Typescript - Reducers
import {handleActions} from 'redux-actions';
import {UsersState as State} from './UsersState';
import {UsersActions as Actions} from './UserActions';

const initialState = {
    list: [],
    isFetching: false,
    lastFetched: null,
} as State;

export const UsersReducer = handleActions<State, any>({

    [Actions.FETCHING]: (state: State): State => {
        return {...state, isFetching: true};
    },

    [Actions.FETCHED]: (state: State, action: Action<User[]>): State => {
        return {...state, isFetching: false, list: action.payload, lastFetched: new Date()};
    },

}, initialState);

Redux máme hotový. Teď už zbývá pouze daný Redux napojit na container.

React Containers


Jak už jsme si řekli, kontejnery jsou v podstatě React Stateful komponenty, které jsou napojené na Redux. Pojdmě si takový kontejner zkusit napsat a využít typovosti, kterou nám nabízí Typescript.

Typescript - React container
import * as React from 'react';
import {bindActionCreators, Dispatch} from 'redux';
import {connect} from 'react-redux';
import {State} from './State';
import {User} from './User';
import {Button} from './Button';
import {UsersList} from './UsersList';

interface OwnProps {
}

interface ConnectedState {
    readonly list: User[];
}

interface ConnectedDispatch {
    readonly fetchUsers: () => void;
}

const mapStateToProps = (state: State): ConnectedState => ({
    list: state.users.list,
});

const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => {
    return bindActionCreators({
        fetchUsers: UsersActions.fetchUsers,
    }, dispatch);
};

class Container extends React.Component<ConnectedState & ConnectedDispatch & OwnProps, void> {

    componentWillMount(): void {
        const {fetchUsers} = this.props;
        fetchUsers();
    }

    handleOnClickRow = (user: User) => {
        console.log('Kliknul jsem na radek: ', user);
    };

    render() {
        const {list, fetchUsers} = this.props;
        return (
            <div>
                <Button onClick={fetchUsers}>Refresh</Button>
                <UsersList data={list} onClickRow={this.handleOnClickRow}/>
            </div>
        );
    }
}

export const UsersContainer = connect<ConnectedState, ConnectedDispatch, OwnProps>(mapStateToProps, mapDispatchToProps)(Container);

Uf, vypadá to šíleně, že? Ale pojďme si to rozebrat a vysvětlit, že to má svůj důvod :)

Co se týče importů, tak tam se nic zajímavého neděje, importujeme to, co v daném kontejneru budeme potřebovat.

Poté vytvoříme tři typy pro props.

První je OwnProps, který říká, že pokud bychom komponentu někdě importovali, je možné přes tento interface doplnit vlastní props. Například v případě, že je kontejner stránkou, na kterou se odkazujete přes React Router 4, bude interface vypadat následovně:

Typescript - Own props with React Router 4
import {RouteComponentProps} from 'react-router';

interface OwnProps extends RouteComponentProps<void> {
}

ConnectedState je typ, který definuje, co jsme z Reduxu vlastně získali. Tento interface je přímo spojen s funkcí mapStateToProps.

ConnectedDispatch je typ, který definuje Redux dispatch akce, které budeme v komponentě volat. Tento typ je přímo spojen s mapDispatchToProps.

V mapDispatchToProps si můžete všimnout funkce bindActionCreators, která přijímá dva parametry. Prvním je objekt obsahující dispatch funkce a v druhém je instance dispatch, která je nutná pro vykonání akce. Návratovou hodnotou je objekt obsahující jednotlivé akce, které jsou volány přes dispatch.

Samotná komponenta není až tak zajímavá. Zjednodušeně říká, že ve chvíli, kdy bude poprvé použita, automaticky načte data. Tyto data získáme z Reduxu do props a předáme je komponentě UsersList, která reprezentuje tabulku uživatelů.

Na konci si můžete všimnout, jakým způsobem se provede mapování na Redux. Metoda connect přijímá dva callbacky, což jsou mapStateToProps a mapDispatchToProps a vrací funkci, jejímž parametrem je naše komponenta, kterou chceme napojit.

V tomto případě tedy neexportujeme třídu, reprezentující naší komponentu, ale výsledek metody connect, který obsahuje naší komponentu, obohacenou o napojení na Redux. Zde také můžete vidět, proč existují tři typy pro props. Metoda connect přijímá tři generické typy, které jsme si definovaly na začátku.

Závěr


O Reactu s Typescriptem by se dalo napsat mnoho věcí. Nicméně, velikost článku by poté byl spíše kompletní příručka, což není cílem. Proto nezbývá, než toto téma rozdělit na víc částí. Příště zkusím vysvětlit, proč třeba nepoužívat funkce.bind(this) a jak se tomu vyhnout.

pondělí 12. června 2017

Co mi vadí na React Relay?

Facebook, jakožto technologická firma, je v současné době na vrcholu. Nejenom proto, že dal světu takové věci jako je React či GraphQL, ale také pro to, že jsou to knihovny, které sám Facebook používá. Díky tomu dostanete věc, která je odladěná pro danou činnost a nemusíte se bát, že jí Facebook přestane podporovat. To je asi jeden z největších rozdílů, kterým se vyznačuje Facebook oproti Googlu. Google se v minulosti dost často ukázal jako vrah svých nenarozených dětí. Každý, kdo se kdy setkal s technologiemi jako je Dart, Angular 1 či třeba GWT by mi jistě dal za pravdu.

Nicméně, bylo by příliš krátozraké, kdyby se člověk automaticky adaptoval na to, co Facebook vypustí. Jednou z věcí, přes kterou jsem se nebyl schopen dostat, je Relay.

Dnešní článek bude opačný. Místo, abych se snažil evangelizovat danou technologii, zkusím vysvětlit, proč není Relay zrovna ideální knihovna.

Začněme hezky od začátku.

Co je Relay?


V případě, že začnete používat React a současně GraphQL, dostanete se do fáze, kdy zjistíte, že přesně pro tento "stack" je určen Relay. Zjednodušeně se dá říct, že Relay je abstraktní vrstva nad vašimi React komponentami, která zajišťuje komunikaci s GraphQL serverem a vaší view vrstvou. Odstíní vás od takových věcí jako je samotný "fetch" na server API či nastavování storage, do kterého se budou načtená data ukládat. Dále za Vás bude řešit error handling a vaše komponenty se stanou prezentační vrstvou pro grafové objekty z API. Umí zařídit optimistické mutace, kdy sami říkáte, že server změnu udělá a vy klienta obelstíte tím, že se budete tvářit, jako kdyby k tomu již došlo.

Relay za vás zařídí většinu nudných věcí. To je skvělé. Až na to, že....

Abych byl schopen popsat, co přesně mi vadí, zkusím Relay rozdělit na dvě části, kterých se to týká. Těmi částmi je GraphQL server a React klient.

GraphQL Server


V případě, že se adaptujete na Relay, dostanete studenou sprchu hned na začátku. Zjistíte totiž, že si nemůžete své GraphQL API psát tak, jak se Vám zlíbí. Relay vám bude hodně věcí předepisovat. První z věcí, kterou musíte doplnit je to, že celé query musí být obaleno jedním hlavním query, který v podstatě říká, že se dotazuji na data přihlášeného uživatele. V tom by až takový problém nebyl. Obalíme query jedním root query a je hotovo. Bohužel tomu tak není.

Další věcí, kterou musíte splnit je identifikátor jednotlivých GraphQL objektů. Jinými slovy to znamená, že identifikátor, nebo chcete-li ID musí být unikátní v globálním stavu.

Co to vlastně znamená? 


Představte si situaci, že máte objekt uživatele, který je reprezentován z databáze. V databázi má vlastní ID. Abychom zařídili globální unikátnost, používá se k tomu následující způsob: "K ID uživatele přičtu název GraphQL objektu a vytvořím unikátní hash." V případě zpětného volání dojde k tomu, že GraphQL nejdříve "rozparsuje" daný identifikátor, abychom z něj dostali ID uživatele. Toto celé se děje z prostého důvodu. Relay má na klientovi vlastní storage, ve kterém jsou jednotlivé záznamy uloženy právě s tímto globálním identifikátorem. V případě, že někde dojde ke změne, tak jí propíše všude, kde je daný identifikátor roven.

Opět uvedu příklad.
Mám tabulku online uživatelů, kde je jméno a příjmení. V jiném panelu edituji uživatele, u kterého změním jméno. V případě, že se jedná o záznam, který je použit i v oné tabulce, provede přepis i tam. Tím Relay částečně zajišťuje aktuálnost dat.

Další věcí, kterou musíte splnit jsou kolekce dat. V případě, že používáte pole záznamů (což jistě používáte), musíte tuto kolekci implementovat tak, jak vám předepisuje Relay. Jedná se zejména o stránkování mezi daty.

Poslední věcí, kterou musíte na serveru splnit jsou mutace. Respektive argumenty mutace. Nelze si je napsat jen tak, jak se mi zlíbí. Musí být obaleny přes vlastní GraphQL objekt "input".

Dobrá zpráva je, že pro všechny potřebné změny, pokytuje Relay vlastní knihovny, které v GraphQL objektech buď implementujete, nebo své objekty touto knihovnou obalujete.

Výsledkem je, že vaše GraphQL API bude připravené pro Relay, ale za jakou cenu? Nejen to, že musíte splnit dané podmínky, pro správné fungovaní Relay, ale také nemáte moc možnost z tohoto "uhnout" vlastním směrem.

Relay v tomto případě prohrává 1:0. Je příliš invazivní a příliš me svazuje.

GraphQL Client alias Relay


Nyní se přesuneme směrem ke klientovi.

Po tom, co s potem ve tváři, splníte všechna předepsaná kritéria na straně serveru, tak musíte počítat s tím, že klient na tom není o moc lépe.
Za prvé je nutné celou vaší React aplikaci obalit Relay komponentou, která je obsahuje vlastní store a zařizuje to, aby vám správně fungovalo "injectování" GraphQL dotazů do komponent.
Výsledek je poté následující. Napíšete vlastní komponentu a obalíte jí pomocí Relay, kam zapíšete GraphQL dotaz. Relay poté zařídí, že vaše komponenta dostane výsledná data pomocí "props".

Díky tomu Relay v podstatě nahrazuje nejznámější implemenaci Fluxu a tím je Redux. Pokud byste se totiž rozhodli, že budete chtít používat Relay a k tomu Redux, musím vás zklamat. Tyto dvě technologie jdou částečně proti sobě. Máte Relay a ten vám přeci stačí.

V tom vidím největší nevýhodu na straně klienta. Nejen, že mě nutí používat Relay a zahodit Redux, ale je navíc opět dost invazivní a dost mě uzamyká někde, kde nechci být. Chci mít volnost v tom, jakým způsobem si budu vlastní komponenty navrhovat. Chci si je rozdělit na kontejnery a komponenty. V případě Relay toto neexistuje. Komponenta je totiž často zároveň kontejnerem.

Pro mě Relay na klientu prohrává opět 1:0.

Co s tím?


Pokud se rozhodnete, stejně jako já, že Relay není tou technologií, kterou byste chtěli použít, nabízí se co s tím. Vedle knihovny Relay existuje ještě jedna knihovna a tou je Apollo.

Apollo má výhodu zejména v tom, že je méně invazivní. Nejenom, že vám nabízí, abyste vedle Apolla používali i Redux, ale je i inkrementálně adaptivní. Tedy máte možnost Apollo začít používat i na existujícím projektu, aniž byste museli provést větší refactoring.

Druhou variantou je vlastní řešení.

Vlastní řešení spočívá v jednoduché myšlence. Mám Redux a akce, které ručně vykonávájí načtení dat ze serveru, stejně jako v případě třeba REST API. Prostě si dotazy píšete mimo komponenty a řídíte si sami, co do Reduxu a jak uložíte.

Touto cestou jsem se vydal i já.

Nejenom, že jsem dostatečně flexibilní, ale také jde o to, že samotné dotazy na server jsou velice jednoduché.

Výsledný kód vypadá třeba následovně:

const fetchEdit = (id: string) => {
    return (dispatch: Dispatch<Store>, getState: () => Store) => {
        dispatch({type: LabelActions.FETCHING_LABEL_EDIT});
        const query = `
            query ($id: ID!) {
                label(id: $id) {
                    id
                    name
                    typeId: type {
                        value:id
                        label:key
                    }
                }
            }`;
        client(dispatch, getState)(query, {id}).then((result) => {
            dispatch({type: LabelActions.FETCHED_LABEL_EDIT, payload: result.data.label});
        }).catch((err) => {
            dispatch({type: LabelActions.ERROR_FETCHED_LABEL_EDIT});
            dispatch(MessageActions.setErrorServer(Lang.CONNECTION_ERROR_LABELS_EDIT, err));
        });
    };
};

Metoda načítá data pro editaci:
  1. Nejprve si do reduxu uložím informaci o tom, že dochází k načítání
  2. Poté, co se načtou data, uložím je do reduxu a oznámím, že jsou načtena
  3. V připadě chyby si sám opět zařídím, abych to oznámil do reduxu

Závěr


I přes to, že se dají nalézt výhody, proč se na Relay adaptovat, tak existuje i spoustu důvodů, proč ne. Jedním z hlavních důvodu je to, že pokud se pokusíte použít Relay, bude technologie víc cílem, než cestou. Doufejme, že nová verze, na které se pracuje, bude méně invazivní a umožní i inkrementální adaptaci. Zatím si nechávám Relay v šuplíku a zůstávám u Reduxu s vlastním řešením, které mi vyhovuje víc.

pondělí 5. června 2017

Jak jsem technologicky postavil startup

Tento příběh pojednává o technologiích, nástrojích a vůbec o všem, co jsem potřeboval k tomu, abych byl schopen, postavit startup na zelené louce.

Každý správný příběh začíná stejně: "Jednou jsem...."

Kapitola první: Nápad


Jednou jsem se setkal s člověkem, který měl nápad na produkt, který se v průmyslu zatím nevyskytuje. I přes prvotní skepsi, kdy jsem si říkal: "Tohle už přeci dávno v průmyslu existuje, ne?", jsem došel ke zjištění, že nikoli.

Tím jsem se dostal ke svému prvnímu poučení. Průmysl je technologicky dost zabržděný. Osobně se domnívám, že těch důvodů, proč tomu tak je, je několik. Za prvé je to fakt, že většina lidí, kteří se pohybují v tomto odvětví jsou často konzervativní a za správné považují pouze léty osvědčené věci. Druhým důvodem je to, že jakákoli změna znamená riziko. Ať už z pohledu finanční ztráty tak i z pohledu stability výroby. No a třetím a nejzásadnějším důvodem je to, že ač zde máme spousty technologických vymožeností, narážíme na to, že je obrovský nedostatek lidí. Tedy nejsou programátoři a další specialisté, kteří by dané vymoženosti transformovali do reálné praxe.
Budoucnost nám jistě nabídne spousty nových a zajímavých produktů a jediné, co nás bude brzdit je pracovní síla, která by dané produkty oživila.

Ale zpět k nápadu.

Pochopil jsem, že tohle by mohlo být ono. Zajímavý produkt, postavený na jednoduchém principu. I když zde budete očekávat, že Vám blíže popíši onen nápad, musím Vás zklamat. Neudělám to. Důvodem ani není to, že bych to chtěl tajit, ale spíše to, že tento příběh není zrovna dobrou platformou, kde bych chtěl zabíhat do těchto detailů. Jen zmíním to, proč jsem se rozhodl, opustit projekt, na kterém jsem v té době pracoval a šel do neznáma, které sebou přináší velké riziko neúspěchu.

Tím důvodem byla pouze jediná věc: "Jednoduchý nápad". Co to znamená? Pokud máte nápad na startup, tak platí jedno pravidlo. Měli byste být schopni jednou větou, nebo ještě lépe, pár slovy popsat, o co vlastně jde. Pokud to nelze, máte bud špatný nápad, nebo jste stále nebyli schopni svůj nápad uchopit tak, jak byste měli.

A nyní už více zůstanu u technologií a nástrojů.

Onen nápad znamenal následující:

  1. Napsat android aplikaci
  2. Napsat server aplikaci
  3. Napsat webovou aplikaci
  4. Současně s tím myslet na to, že aplikace musí být multitenantní a v cloudu.


Kapitola druhá: Nástroje


Ještě před tím, než jsem se pustil do prvních proof of conceptů, jsem si navrhnul nástroje, které budou pro takový projekt stěžejní.

Prvním nástrojem, který jsem věděl, že bude bezpodmínečně nutný je repozitář kódu.
Ať už projekt bude v Jave, PHP či Perlu, vždy potřebujete někde uchovávat svůj kód. Samozřejmě, že volba byla jasná: Git. Proč volit něco jiného, když Git už znám a vím, že splní všechny moje požadavky.
Po prozkoumání dostupných možností, jsem nakonec zvolil BitBucket. Jednak z důvodu toho, že i zdarma umí privátní repozitáře a jednak i pro to, že v rámci ekosystému se mi hodilo to, že od stejné firmy máme i další nástroje.

Druhou nutnou věcí byl tracking systém.
Ať už pro bugy, tak i pro samotný vývoj. Nechcete přeci tyto věci udržovat v excelu, mailu či si psát vlastní systém. Zde byla volba velice jednoduchá. Asi nikoho nepřekvapí, že volba padla na Jiru.
Jira splňuje opět všechno, co potřebuji. Mohu ji provozovat v cloudu, aniž bych musel hloupě instalovat systém na vlastním železe a současně s tím pokrývá velkou část důležitých aspektů. Jednak je to zmíněný tracking pro bugy, ale také možnost Jiru využít pro plánování, ať už pro SCRUM či vlastní upravenou metodiku.
Třešničkou na závěr je samozřejmě propojení BitBucketu s Jirou a tím k jednotlivým ticketům přiřazovat commity z GITu.

Třetím nástrojem byla znalostní databáze, nebo chcete-li wiki. 
Jelikož jsem od Atlassianu využíval BitBucket a Jiru, tak volba byla opět jasná. Confluence. Proč používat něco jiného? Confluence znám a navíc vím, že mi třeba umožní zobrazení dat i z Jiry. Stejně jako u předešlých nástrojů, je opět možné Confluence využívat jako službu v Cloudu a proto není stále nutné mít vlastní servery.

Čtvrtým nástrojem byl komunikační kanál. 
Jestli někdo očekává něco ve stylu: "Máme přeci mail, tak pořídíme vlastní mail server či gmail pro firmy, musím ho zklamat." Mail je jeden z nejhorších možných komunikačních kanálů a využití tohoto nástroje jsem se rozhodl minimalizovat na jeho nutnou potřebu.
Jako komunikační kanál jsem zvolil Slack. Znáte Slack? Ne? O hodně přicházíte. Nechci zde rozepisovat, co všechno Slack umí, ale vyjmenuji pouze to, k čemu ho používámě my.
Tak za prvé je to samotná komunikace mezi uživateli. Chcete Frantovi napsat o nových poznatcích? OK. Napiš mu přes chat. Chceš, aby to viděl i Pepa? Pozvi ho do konference a založte si vlastní místnost. Chceš někde projednávat pouze technické věci? Založ místnost a pozvi lidi, kterých se to týká. Sdílej ukázky kódu, apod. Slack toho nabízí skutečně hodně.
Dalším důvodem, proč Slack, je jeho možnost integrace s ostatními systémy. Nejprve jsem integroval Slack s Jirou. Skvělé, mám možnost si přes Slack prohlížet Jira tickety. Nic složitého.
Další integrací byl samotný BitBucket. Chci notifikace o tom, co se děje v GITu? Není problém, přihlásím se o notifikace a vídím, že Franta provedl commit do GITu, kterým rozbil celý build.
Slack stále nemusím instalovat a mohu ho využívat jako službu v Cloudu.
Stále nepotřebuji vlastní server. Díky bohu.

Pátým a posledním nástrojem je testing tool.
Nejsme neomylní a mít nástroj na zápis testovacích scénářů a současně s tím, mít možnost vyhodnocování jednotlivých exekucí testů, je tedy nutné.
Testovacích nástrojů existuje nepřeberné množství.
Nejdříve jsem se vydal slepou uličkou a tou byly ruzné pluginy do Jiry. Bohužel jsem se dostával do stavu, že plugin byl buď nefunkční a nebo byl dost neefektivní. Nakonec jsme skončili u TestTrail. Jednoduchý nástroj na tvorbu testovacích scénářů a současně s tím i exekuci. Samozřejmostí je opět integrace na Jiru, kde Bug do Jiry vytvoříte přímo v TestTrail. Integrace je obousměrná. Tedy na samotném Jira ticketu máte možnost vidět exekuci z TestTrailu. Ideální. Co víc si přát.

Tím bychom měli samotné nástroje. Pojdmě dál...

Kapitola třetí: Google Cloud


Jelikož jsem na začátku zmínil, že samotná aplikace je multitenantní a v Cloudu, tak potřebujete sami nějaký Cloud, kde byste provozovali svojí aplikaci. Stavět si vlastní servery je stejné, jako se střílet do vlastní nohy. A to přeci nikdo nechce.
Variant, které připadají v úvahu je několik. Ať už zvolíte řešení od Amazonu AWS, Microsoftu Azure nebo Googlu, vždy uděláte dobře. Nakonec jsem zvolil Google Cloud. Důvod proč, není postaven tolik na rozumu, jako emocích. Jednak je to z důvodu toho, že mám firmu Google raději než třeba zmíněný Microsoft a jednak i pro to, že víc důvěřuji firmě, která má svůj hlavní byznys postaven na internetu a Cloudu.
Až později jsem zjistil, že Google do samotného Cloudu investuje nemalé peníze a rozvoj je téměř raketový. Jakožto roční uživatel, mohu sám potvrdit, že se opravdu snaží postupně nabízet a vypiplávat jednotlivé možnosti samotného Cloudu. To je skvělé.
Jednou z věcí, kterou na Google Cloudu skutečně miluji, je připojení na server pomocí SSH ve webu. Ano, ve webu. Není nic jednodušího, než kliknout na daný virtuální server, dát "SSH Connect" a v té chvíli se Vám otevře okno s konzolí samotného serveru. Už není nutné žádné otravné předávání SSH klíčů či jiného zabezpečení pro přístup k serveru.

Kapitola čtvrtá: Programovací jazyk a architektura


Možná by se hodilo tyto dvě věci od sebe odlišit, ale osobně si myslím, že daný jazyk dost ovlivňuje samotnou architekturu. Proto psát o těchto věcech rozděleně, nedává smysl.

Jakožto javista jsem měl volbu jasnou. Backend bude na Tomcatu se Springem, JPA a nějakou relační databází. Webové API bude REST. Frontend udělám Angularem či Reactem a mobilní aplikaci hezky v Jave přes Android Studio.

Tak jsem se pustil do práce. Napsal jsem backend přes Spring Boot a Spring Data REST. Databázi jsem zvolil MySQL s tím, že bude možné jí změnit v případě "požadavků". Přeci jen mám JPA, ne? :)
Současně s tím jsem napsal Android aplikaci, která dělala to, co jsem potřeboval. Fungovala na principu, na kterém jsme se na začátku domluvili.

Poté přišel na řadu web.

Teď bych mohl napsat o tom, jak jsem zvolil Angular či React a napsal SPA webovou aplikaci. Jenže zde něco končí a něco nového začíná....

Měl jsem zkušenosti s Angularem 2, ve kterém jsem si napsal aplikaci, která mi pomáhala, jako team leaderovi, vyhodnocovat skutečnost. I když byl Angular 2 v alfa verzi, tak mi to nevadilo. Nešlo o kritickou aplikaci.

Jenže shodou okolností jsem se v té době dostal k přenášce dvou mladých kluků, kteří, ač angularisti, začali hrozně shazovat Angular a velebit React. V té době jsem React znal spíše teoreticky. Veděl jsem, že má virtuální DOM a že bla bla bla...
Jenže oni mě tak moc nahlodali, že jsem se rozhodl, že do toho proniknu více a frontend tím Reactem přeci jen napíšu.

V té době u mě došlo k tomu, že jsem se zamiloval. Ne, slečna to nebyla, tu už jsem měl :) Ale došlo k tomu, že jsem jednak našel krásu v Reactu, ale hlavne ve funkcionálním a deklarativním programování. Na to jsem z Javy nebyl příliš zvyklý. Přeci jen, i když již existovala Java 8 (lambda funkce), tak většinou nemáte moc možností se s ní setkat.

A tak jsem začal přemýšlet, zda bych javascript nemohl využít i jinde. A ono to šlo! Najednou jsem zjistil, že existuje něco, co se jmenuje React Native a že vlastně i mobilní aplikaci mohu napsat stejnou technologií. A jelikož jsem od přírody liný člověk, tak jsem si řekl, že se přeci nebudu učit více věcí najednou, když mi stači jedna s drobnou obměnou.

A tak došlo k tomu, že jsem zavřel Android Studio, smazal projekt v Jave a přepsal ho do React Native. A vše fungovalo. I to zatracené Bluetooth LE mi v Reactu šlapalo.

Poté přišel na řadu backend. Web a mobil mám v javascriptu/typescriptu a backend v Jave. A v té době mi z nějakého neznámého důvodu začala Java vadit. Sakra, psal jsem v tom jazyku více jak 9 let a měl jsem ten jazyk skutečně rád. Jednoduchý, staticky typový a navíc na server aplikace ideální volba. Jenže v té době jsem objevil další Facebook technologii. GraphQL....

Psát o tom, co je GraphQL není předmětem tohoto příbehu. Jen v rychlosti řeknu, že Vám umožňuje napsat webové API tak, jak byste v RESTu či SOAPu nikdy nebyli schopni. Deklarativně a s možností si psát vlastní dotazy do API, kterým budete říkat, co vlastně chcete vrátit.

Tak došlo na první fázi. GraphQL v Jave. Po zjištění, že pro GraphQL existuje knihovna i do Javy, jsem zajásal. Ale jen do doby, než jsem pochopil, že to je asi jako kdybyste traktor pomalovali jako závodní auto. Zjednodušeně řečeno, díky samotnému deklarativnímu zápisu GraphQL to bylo dost neefektivní.

A jelikož jsem se rozhodl, že GraphQL se už nevzdám, tak jsem musel, se slzou v oku, celý java backend zahodit a přepsat ho pomocí Node.JS/Express. Výsledkem bylo, že jsem měl asi desetinový kód, který toho ve výsledku uměl víc, než v samotné Jave.

Timto jsem se rozloučil s Java světem a stal se už pouze nezávislým pozorovatelem. Jazyka, na kterém jsem sám vyrostl a který jsem považoval za nejlepší variantu na backend.

Výsledkem bylo, že jsem získal "full stack", který používal stejný jazyk na všech úrovních. Díky zaplacenému NPM serveru jsem si začal tvořit vlastní privátní balíčky, které poté sdílel mezi mobilem, webem a serverem.

Ideální kombinace. Funkcionální programování je zábava a navíc je o tolik efektivnější.

V té době se ze mě stal evangelista javascriptových technologií a současně s tím i fanatik, který vyznává pouze jednu pravdu :)

Kapitola pátá: Deployment


Co by to bylo za systém, kdyby neuměl automaticky nasazovat aplikaci na server?

První věcí, kterou jsem k tomuto účelu začal využívat je Jenkins. Jenkins je nástroj pro continuous integration. Uložíte projekt do GITu a on provede nějakou událost. Ať už je to spuštění buildu, testu či samotný deploy aplikace.

Jenkins má spoustu výhod a spoustu nevýhod.
Jednou z velkých nevýhod, alespoň pro naše učely, je to, že na svou robusnost nepřináší tolik výhod. Tím myslím to, že sice přes něj mohu provádět všechny potřebné úkony, ale musím si ho nainstalovat na vlastní server (samozřejmě v Google Cloudu), ale za cenu toho, že musím nakonfigurovat mraky věcí.

Po zralé úvaze jsem Jenkins server smazal a přešel na BitBucket Pipelines.
Co jsou to vlastně Pipelines? Je to takový jednoduchý Jenkins, který na základě změny v GITu, může vykonat událost. Tou událostí může být opět cokoli. Kromě toho, že díky BitBucketu, máme Pipelines zadarmo, tak je i možné Pipelines integrovat se Slackem, takže opět win/win.
A jelikož se vracíme k původní myšlence, že naše aplikace má být v Cloudu a multitenantní, tak samotný deploy aplikací musíme nějak rozumně řídit. A k tomuto účelu nám stejně nemůže sloužit ani Jenkins, ani Pipelines, ale něco jiného.

Třetí a nejlepší variantou je vlastní aplikace, hlídající deployment, servery či stav v GITu. Nechci přesně rozepisovat, jak to funguje, ale vychází z jednoduché myšlenky, která říká: "Chci mít možnost, na jednoduchý klik tlačítka nasadit verzi X/Y na server A a přitom kontrolovat, že server A je v té či oné verzi a je na to připraven."

Kapitola šestá: Shrnutí


Rozepisovat o všech technologiích a knihovnách, které používáme, by bylo příliš vyčerpávající a asi i nudné. Jednou z věcí je třeba error tracking systém přes Sentry.io, který nám hlídá stav aplikací. Ale o tom někdy příště v samostatném článku.

Výsledkem mého snažení bylo několik věcí, které teď v bodech shrnu:

  1. Unifikované prostředí pro vývoj
  2. Jednoduchá správa
  3. Rychlá adaptace vývojářů, testerů
  4. Využití moderních technologií, které jsou přínosné
  5. Připravit firmu na větší počet zaměstnanců v IT
  6. Schopnost řídit systém jak technologicky tak projektově
  7. Minimalizovat náklady na vývoj
Závěrem jedno doporučení. 

Zda chcete vědět, jak správně navrhovat aplikace či celé technologické firmy, musíte mít hlavně zkušenosti s tím, jak to nedělat. 

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ě….

Když programátor založí a řídí firmu

Jako malý jsem chtěl být popelářem. Ani ne tak proto, že bych měl nějaký zvláštní vztah k odpadkům, ale hrozně se mi líbilo, jak...