neděle 26. listopadu 2017

Potřebují firmy mobilní aplikace?

V poslední době se častěji setkávám s tím, že se zvyšuje poptávka po psaní nativních mobilních aplikací. Tato potřeba je často inicializována společnostmi, které potřebují své pole působnosti rozšiřovat na mobilní platformě.

Na tom by asi nebylo nic neobvyklého, kdyby ovšem ona potřeba nebyla často způsobena neznalostí současného stavu a toho, co je a není dnes možné.

Před tím, než se dostaneme k technickému řešení, pojďme se podívat na současný stav. Stav z pohledu obyčejného uživatele...

Když si vzpomenu na dobu před 20 lety, tak si s úsměvem vzpomínam na to, jak jsem každý program, který jsem ve svém počítači měl, zkoumal do morku kostí. Důvod proč tomu tak bylo, byl jednoduchý. Neexistovalo příliš mnoho alternativ. Potřebovali jste správce souborů? Byl zde Norton Commander. Chtěli jste si zahrát střílečku? Pustili jste si Doom.

Ta doba byla jednodušší a složitější zároveň. Složitá byla z toho důvodu, že neexistoval internet (alespoň pro běžné uživatele) a jakékoli informace se často předávaly ústní formou.

Jednodušší byla ve výběru. Je psychologicky dokázáno, že čím víc variant máme, tím je menší pravděpodobnost, že si nakonec vybereme. Důvodem je to, že onen výběr na nás v konečném důsledku působí tak složitě, že onu volbu raději odložíme "na později".

Pokud tuto dobu srovnáme s tou dnešní, tak zjistíme, že uživatelé se chovají úplně jinak, než kdysi. Jsme zahlceni aplikacemi. Jsme zahlceni volbami. Chcete aplikaci na poznámky? Pusťte si Google Play a stáhněte si aplikaci na poznámky. Ale teď kterou, že? Kolik jich dnes máme? Deset? Dvacet? Možná tisíc. Volba se stala tím nejsložitějším, co řešíme. Dnes a denně.

A teď si představte, že do této džungle chcete vstoupit jako firma, která nabízí mobilní verzi vaší webové aplikace. Ať už jste společnost, která nabízí prodej šroubků, oken, či firma, která poskytuje různé služby.

Drtivá většina firem se ihned pustí do mobilního vývoje. Ať už pomocí svých zaměstnanců, nebo pomocí subdodavatele. Výsledkem je často aplikace, která stála milióny a její dopad je žalostný. Z povinnosti si jí stáhli zaměstnanci a pak pár kamarádů kolem.

Problém výběru je spojen i s překážkami, které musíme podstoupit. Abyste použili aplikaci na poznámky, jste nuceni pustit Google Play, aplikaci dohledat a poté nainstalovat. A to už někdy bývá tak složitá varianta, že jí uživatelé nepodstoupí.

Pokud se podíváme na chování uživatelů, tak zjistíme, že každý z nás je schopen ovládat a používat pouze omezený počet aplikací. Ať už se jedná o poznámky či vyhledání MHD spojů. Do toho se míchá další překážka.

Většina firem si totiž myslí, že na to, aby nějak upoutala pozornost, musí být unikátní. V případě loga a základních barev daného "brandu" je vše v pořádku. Ale v případě vizualizace a chování samotné aplikace tomu tak již není.

Pokud se opět vrátíme ke statistikám, tak zjistíme, že uživatelé často vyhledávají takový druh aplikací, které jsou podobné těm předešlým. Je fajn, že společnost pro nás připravila svůj unikátní UI frontend, ale nám se nechce učit jejich způsob ovládání.

Díky všem těm profesionálům, jako jsou UX designéři, máme na konci aplikaci, která je často unikátní. Unikátní ale natolik, že jí nakonec umí ovládat jen tester a programátor. Důvodem není to, že by tito lidé špatně odvedli svou práci, ale to, že po určité době trpí profesní slepotou.

Výsledkem našeho snažení je, že máme webovou aplikaci, mobilní aplikaci a tisíce hodin, které ještě před námi stojí, abychom svou práci dokončili.

A zde bych se zastavil....

Skutečně firmy potřebují nativní mobilní aplikace a unikátní vzhled?

Odpověď je samozřejmě, že NE.

Pokud jste si přečetli předchozí odstavce, mohli jste sami najít základní problémy, které se s tím spojují.

Rozdělme si je do dvou částí:

Nativní aplikace:
  • Nativní aplikace jsou drahé na vývoj
  • Nativní aplikaci je často nutné psát duplicitně (Android, iOS)
  • Nativní aplikace se složitě aktualizuje
  • Nativní aplikace se složitě testuje
  • Nativní aplikaci musí uživatel najít a nainstalovat
Uživatelské rozhraní:
  • Pokud je příliš unikátní, uživatelé mu nerozumí a nebudou se ho chtít učit
  • Musí se dobře adaptovat na daném zařízení (responsivní design)
  • Je náročné ho napsat tak, aby bylo co nejvíce identické na mobilu a webu
S těmito problémy se setkává velká většina firem. Ať už existence mobilní a webové verze slouží ke snížení požadavků na helpdesk, či řeší zvýšení prodejů jednotlivých produktů a nebo se snaží poskytnout novou službu. Vždy řeší, jak nejlépe najít kontakt se zákazníkem a ten si udržet. I když nejsem marketingový specialista, tak jsem specialista v IT s dlouholetou praxí tvorby frontendových aplikací.

A jakožto IT specialista Vám můžu garantovat, že pokud vytvoříte unikátní mobilní aplikaci, tak to budete mít velice těžké, i když budete poskytovat sebelepší produkt. Důvodem bude jen a pouze lenost nás uživatelů, protože se nebudeme chtít učit, jak se Vaše aplikace ovládá. Netoužíme po tom si jí instalovat z Google Play a nechat si zabírat dalších X desítek megabajtů (sakra, už takhle máme málo místa). A už vůbec netoužíme po tom, abychom si jí aktualizovali každý týden.

Jak z toho ven?

Odpovědí je Progressive Web Application a Material Design.

PWA aneb Progressive Web Application

PWA je termín, který před pár lety použil Google. Toto označení je použito pro webové aplikace, které používají modernější webové technologie.

Ve výsledku nejde o nic převratného z pohledu technologie. Jde pouze o to, že Google na Android zařízeních je schopen identifikovat takovouto aplikaci.

Abyste si to představili v praxi, tak je to tak, že v prohlížeči narazíte na webovou stránku, která je identifikována jako PWA. Webový prohlížeč Vám poté nabídne možnost tuto aplikaci přidat na plochu. Poté, co toto potvrdíte, máte možnost onu webovou aplikaci používat tak, že se tváří jako nativní.

Součástí této specifikace je něco, čemu se říká "service workers", který Vám umožňuje, aby Vaše aplikace šla používat i v offline režimu.

A v tom je asi největší rozdíl oproti klasické webové stránce. Onen offline režim je totiž naprosto potřebná vlastnost k tomu, aby takováto aplikace šla reálně používat.

Zeptejte se svým programátorů, zda vědí co je PWA a zda skutečně musíte dnes psát nativní aplikace. Často se totiž objevuje argument typu: potřebujeme geolokaci, potřebujeme notifikace. Všechno a mohem více již PWA aplikace totiž umí.

Otázkou není, zda je již na PWA čas. Otázkou spíše je, kdy touto cestou půjdete vy. Tedy tam, kde to technicky dává smysl.

Material Design

Pokud jsme mluvili o unikatním brandu jako hlavním požadavku marketingových specialistů, tak je dobré se zeptat, co to vlastně znamená. Pokud by totiž, do tohoto brandu, někdo, kromě loga a barev, míchal i věci jako jsou například formulářové prvky, menu, apod, tak vězte, že je to špatně.

Na toto si stačí udělat jeden lehký příklad. Spustťe si na Androidu Google Play. Umíte ho ovládat? Pustťe si na Androidu Gmail. Umíte ho ovládat? Pustťe si ....

Finále totiž je, že dnes máme možnost napsat aplikaci tak, aby použila stejné chování, stejné prvky a tím docílit toho, že naší aplikaci budou uživatelé schopni ovládat, aniž bychom museli provádět složité adaptace a školení.

Google to totiž udělal za nás. Dal nám Material Design a tím pádem i způsob, jak uživatelsky navrhnout naší aplikaci.

Unikátní cesta je cesta do neznáma... A pokud nejste Facebook, tak věřte, že cesta do pekla.

Material Design vychází z jednoduché myšlenky, která říká, že musíme klást větší důraz na dotyková zařízení. Současně s tím ale mít možnost použít toto rozvržení i ve webové aplikaci. Jinými slovy. Díky PWA máte aplikaci pouze jednu. Jednou je použita na webu a jednou v mobilu.

Abyste pochopili, proč je třeba formulářový prvek zbytečné navrhovat, podívejte se na výchozí chování v Material Design. Textové pole má svůj popisek, ve chvíli, kdy kliknete do tohoto pole, se popisek posune nahoru a vy stále vidíte, jaké pole vyplňujete. I když drobnost, tak si uvědomte, že šetřit místo je důležitý aspekt, každé správné mobilní aplikace.

Závěr

I když jsme často nuceni použít nesmyslné požadavky byznysu, někdy je dobré se zpět zeptat svých IT specialistů na to, zda se nevymýšlí kolo. Zda skutečně potřebujeme nativní mobilní aplikace a zda skutečně musíme navrhovat unikátní design, abychom se odlišili od zbytku světa.

Já mám v tomto ohledu jasno. Budu za PWA a Material Design bojovat všude, kde to jen půjde. A to ne z důvodu toho, že by v tom byl jen technický pohled, ale také z důvodu toho, že je to cesta, která může společnostem skutečně pomoci...

čtvrtek 2. listopadu 2017

Jak zvýšit výkon React aplikací?


V době, kdy jsem objevil svět javascript knihoven a frameworků (React či Angular), jsem si říkal: "Sakra, to sice vypadá skvěle, ale musí to být příšerně pomalé, ne?"

Pravdou je, že ano i ne. Vše závisí na tom, jak k dané knihovně přistupujete a jak dobře znáte samotné principy, na kterých je daná knihovna postavena. V případě Reactu je samotný princip až stupidně jednoduchý, který z něj ovšem dělá onu krásu. Tady, stejně jako v životě, platí, že ty nejjednodušší varianty jsou ty nejsprávnější.

Pochopit princip, jak funguje React je vcelku jednoduchý. Je to silně komponentově orientovaná knihovna, která využívá principu one-way binding a immutable stavu. Co to ve výsledku znamená, je to, že na porovnání změny stavu Vám stačí dát mezi dva objekty tři rovnítka (===). Ano, to je vlastně celé. Tedy skoro... :)

Tento článek je určen pro všechny, kteří už prošli první zkouškou a tou je napsání "Hello World" v Reactu. Postupně si rozebereme jednotlivé části, které nám mohou ušetřit problémy s výkonem v React aplikacích.

1. Render metoda musí být rychlá

React se točí kolem jedné jediné věci a tou je render. Render fáze se Vám zavolá vždy, když dojde ke změně stavu. Ať už je to na úrovni props či state. Druhou variantou, kdy dochází k volání render fáze je v době, kdy je samotný předek znovu renderován.

Pokud si tyhle věci spojím, tak se dostanu k tomu, že render metoda se volá častěji, než se na první pohled zdá.

A zde je první poučka: "V render fázi nikdy nevykonávejte náročné operace."

A jak zjistit, kolikrát mi daná komponenta volá render? Na to stačí jednoduchý trik. Prostě a jednoduše si do metody dejte "console.log" a podívejte se sami. Šílené, že? :)

2. Nezapomínat na unikátní klíče u listů

Pokud v Reactu vytváříte tabulku či seznam, tak jste si jiště všimli, že když v dané komponentě, která je v iteraci, nemáte definován atribut key, tak Vám React bude hlásit warning. Ten warning neignorujte. Jde totiž o to, že díky tomu, že dané komponenty jsou ve virtuálním DOMu na stejné úrovni, pomáhá to Reactu s indexací. Výsledek je, že pakliže ony klíče nebudete definovat, nebo nebudou unikátní, tak výkon Vaší aplikace bude klesat.

Příklad s atributem key:
import * as React from 'react';

interface Props {
    readonly users: Array<{ id: string; firstName: string; lastName: string; }>;
}

const UsersTable: React.SFC<Props> = ({users}) => (
    <table>
        {users.map(({id, firstName, lastName}) => (
            <tr key={id}>
                <td>{firstName}</td>
                <td>{lastName}</td>
            </tr>
        ))}
    </table>
);

Tady je vidět, jak správně pracovat s iterovanými prvky v JSX.

3. Snažte se o ploché struktury

Na začátku jsme mluvili o tom, že render metoda se volá vždy, když je renderován rodič. Z toho nám vychází jedno důležité pravidlo a tím je, že bychom se měli snažit více o plochou strukturu. Ve výsledku to znamená, že čím máme hlubší struktury našich komponent, tím se zvyšuje riziko vykonnostních problémů.

Vím, že je to někdy těžké, ale netvořte v React aplikacích vlastní šílené univerzum. Atomizace jednotlivých částí je naprosto v pořádku. Nicméně, atomizace prvků neznamená větší hloubku.

4. Callbacky v render bez bind

Dalším pravidlem je nepoužívat bind(this) v callback funkcích v render.

Pojďme si udělat příklad:
import * as React from 'react';

interface Props {
    readonly onClick: (id: number) => void;
}

class Component extends React.Component<Props> {

    handleOnClick() {
        this.props.onClick(1);
    }

    render() {
        return (
            <button onClick={this.handleOnClick.bind(this)}>Klikni</button>
        );
    }

}

Tento kód trpí jedním neduhem. Tím je samotný bind. Pokud jsme si řekli, metoda render je volána často, tak tento kód nám způsobuje, že je stále dokola vytvářena nová funkce.

Pojďmě se podívat na správný přepis:
import * as React from 'react';

interface Props {
    readonly onClick: (id: number) => void;
}

class Component extends React.Component<Props> {

    handleOnClick = () => {
        this.props.onClick(1);
    };

    render() {
        return (
            <button onClick={this.handleOnClick}>Klikni</button>
        );
    }

}

V podstatě jsme funkci handleOnClick přepsali do arrow funkce, což nám umožňuje to, že samotné this, je this třídy a tím pádem ho nemusíme expresivně definovat přes bind(this).

5. Nevytvářejte zbytečně nové objekty

Pokud jsme se bavili o tom, že React funguje na základě třech rovnítek, které nám říkají, zda se jedná o stejný či jiný objekt, tak ve stejném duchu musíme přemýšlet i my.

Pojďme si udělat jednu ukázku a říci, co je na ní špatně:
import * as React from 'react';
import {Detail, Menu, Page} from './components';

class Container extends React.Component {

    getUser() {
        return {firstName: 'Ales', lastName: 'Dostal'};
    }

    render() {
        return (
            <Page user={this.getUser()}>
                <Menu/>
                <Detail/>
            </Page>
        );
    }

}

Na tomhle kódu je špatně jedna věc a tou je samotný fakt, že s každým voláním render metody se stále dokola vytváří objekt user.

Přepis by vypadal následovně:
import * as React from 'react';
import {Detail, Menu, Page} from './components';

const user = {firstName: 'Ales', lastName: 'Dostal'};

class Container extends React.Component {

    render() {
        return (
            <Page user={user}>
                <Menu/>
                <Detail/>
            </Page>
        );
    }

}

Tomuto způsobu se říká "memorizování", kdy pokud víme a máme objekt jasně definovaný, tak ho nechceme stále vytvářet dokola. Z podobným principem se můžeme setkat i jinde (viz níže).

6. S Reduxem používejte reselect

V případě, že používáte Redux, často se setkáváte s tím, že na jedné straně máte nějak uložená data v Redux store a jinak je potřebujete prezentovat do komponenty. První co se nabízí, že v metodě mapStateToProps budete své props různě přepočítávat. Je velká pravděpodobnost, že tímto způsobem budete s každou změnou v Redux store vytvářet i nové objekty ostatních atributů.

Jelikož by ukázka vydala na samotný článek, odkážu rovnou na knihovnu, kterou doporučuji použít: Reselect.

Tato knihovna vychází z principu memorizování dat, čímž pádem snižuje opakovanou tvorbu objektů v props a snižuje tím i nutnost volat častěji render fázi.

7. Občas použijte shouldComponentUpdate

Jsou situace, kdy se dostanete do fáze, že Vaše render fáze je drahá. To znamená, že již víte, že nelze moc najít způsoby, jak jí ještě více optimalizovat a snižovat náročnost aplikace.

Já jsem se s tímto setkal třeba u grafů Highcharts, které v React aplikacích občas používám.

V té chvíli se nabízí další možnost, jak zlepšit výkon React aplikace a tím je využití metody shouldComponentUpdate. Tato metoda má ve výchozím stavu nastaveno "return true", čímž říká, že render se volá tak, jak jsme si popsali. Pokud danou metodu přepíšete, máte možnost určit, za jakých podmínek se bude render metoda volat.

Pojďme si udělat malý příklad:

import * as React from 'react';
import {Options} from 'highcharts';
import * as ReactHighcharts from 'react-highcharts';

interface Props {
    readonly config: Options;
}

export class Highcharts extends React.Component<Props> {

    shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<{}>, nextContext: any): boolean {
        return (nextProps.config !== this.props.config);
    }

    render() {
        return (
            <ReactHighcharts config={this.props.config}/>
        );
    }
}

Jak si můžete všimnout, tak jsem v dané ukázce použil kontrolu třech rovnítek, kde říkám, že pokud se props skutečně změnilo, spusť render. V opačném případě nikoli.

Pokud píšete React aplikaci, ale stále máte výkonnostní problémy, tento způsob je jeden z nejefektivnějších, jak zařídit, aby Vaše aplikace byla opět svižná.

Bohužel to sebou přináší i jedno riziko. Jak jste si jistě všimli, v nadpisu jsem použil slovo "občas" a to zcela záměrně. Jde totiž o to, že někoho by to mohlo vézt k tomu, že vlastně ve všech komponentách bude přepisovat shouldComponentUpdate. Jenže je tam jedno velké ALE. Tím ale je samotný fakt, že byste s každou změnou props a vůbec modelu museli neustále sofistikovaně upravovat implentaci této metody a věřte, že byste se dostali do fáze, kdy by Vaše aplikace nereagovala, tak jak si představujete. A jediným důvodem by byl lidský faktor.

Tím chci říct, že je naprosto korektní, že se u některých komponent volá render velice často. Pokud jsou dané komponenty optimalizovány a v render metodě nepočítáte model vesmíru, tak to nevadí :)

Další variantou jsou PureComponents, o kterých se můžete dočíst v manuálu.

8. Pomáhejte si dalšími nástroji

První věcí, kterou do svých projektů vždy přidávám je tslint a tslint-react. Jedná se o nástroj, který provádí statickou analýzu kódu, který píšete. Výhodou tslintu je i v tom, že má některá pravidla, která jsou nastavena za učelem upozorňování na možné výkonnostní problémy.

Pokud zůstaneme u ladění výkonu, tak další věcí, kterou občas používám je console.log. Ano, nestydím se za to. Naopak. Občas se chci rychle podívat, jak často se mi některá z metod renderuje a je to naprosto korektní způsob. A nemusíte se bát, tslint Vám vynadá za to, že ve svém kódu máte console.log. Proto ho používám pouze pro ladící účely.

K ladění výkonu je vhodný i Chrome DevTools - Performance. Díky tomu můžete provést sofistikovanou analýzu toho, jak se vaše komponenty chovají a kde vzniká potencionální výkonnostní problém. Více se můžete dozvědet z manuálu.

Závěr

Vypsat všechny známé tipy na zvýšení výkonu React aplikací, by bylo trochu mlácení prázdné slámy. Tento článek berte tak, že je dobré se hlavně zamýšlet nad tím, jak Vaše knihovna funguje a podle toho k ní také přistupovat. Pokud bychom k Reactu přistoupili naprosto nekriticky, tak bychom jednoduše mohli skončit s aplikací, která bude uživatelsky nepoužitelná.

Stále mějte na mysli to, že i když React má virtuál DOM, který nám částečně pomáhá se samotným výkonem, tak nás to úplně neochraňuje od toho, abychom neměli výkonnostní problémy.

Pokud Vás napadá další zajímavý tip na zvýšení výkonu, budu rád, když zanecháte komentář.

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ž...