IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Základné best practices pre návrh softvéru

V minulej lekcii, Najčastejšie chyby programátorov - Rozdelenie aplikácie do tried , sme si ukázali dobré praktiky SRP (Single Responsibility Principle) a SoC (Separation of Concerns). Začali sme aj tému závislostí.

V dnešnej lekcii dizajne softvéru sa budeme venovať tzv. Best practices. To sú všeobecne známe dobré praktiky v návrhu softvéru, ktoré sa počas rokov osvedčili a ak ich budeme poznať, ušetrí nám veľa nepríjemností. Všetci ste sa určite niekedy stretli so zle napísaným softvérom, pripomínajúcim domček z kariet. Akákoľvek zmena v takejto aplikácii je prácna a nebezpečná, pretože môže spôsobiť ďalšie chyby a ohroziť i budúcnosť projektu. Aby sme sa takýmto návrhom chybám vyvarovali, nemusíme vynájsť koleso, stačí sa poučiť zo známych chýb ostatných a predísť im. Dobrých praktík existuje pre návrh softvéru pomerne veľké množstvo, my si dnes predstavíme tie najzákladnejšie.

KISS

Pravidlo KISS vo vývoji softvéru - Best practices pre návrh softvéru

Začnime tými najjednoduchšími a postupne prejdeme ku komplexnejším poučkám. Pravidlo KISS je akronym pre "Keep It Simple, stupid!". Slovensky teda "Rob to jednoducho, hlupák!" KISS naznačuje, že často existuje riešenie, ktoré je jednoduché, relatívne málo pracné a prinesie uspokojivý výsledok. Tendenciu ku komplikovanému aplikácií majú najmä zákazníci, ktorí nerozumejú vnútornej štruktúre aplikácií a požiadavky si vymýšľajú ako je to napadne. Býva dobrým zvykom prediskutovať nutnosť alebo podobu aspoň niektorých požiadaviek. Často zistíte, že zákazník vlastne potrebuje niečo iné, čo viete vyriešiť elegantnejšie.

Príklad

Ako príklad si uveďme napr. Súkromné správy tu na ITnetwork. V čase ich programovanie mal Facebook u svojich súkromných správ nejaký javascriptový mechanizmus pre načítanie ďalších správ smerom nahor a udržiavanie formuláre pre písanie novej správy dole pod nimi. Opýtali sme sa sami seba, či toto naozaj potrebujeme programovať a vzápätí nás napadlo otočiť poradie správ. Formulár na novú správu bol bol hore a pre načítanie nových správ sa použil už existujúci skript, ktorý načíta dáta Ajaxu smerom nadol. Zrazu sme získali rovnakú funkcionalitu za zanedbateľný vývojový čas, len preto, že sa zmenil smer radenia. Toto sú presne situácie, kedy sa oplatí porozprávať so zákazníkom, ak neprogramuje softvér pre seba, prípadne zadanie ešte zvážiť.

Riešenie súkromných správ od Facebooku - Best practices pre návrh softvéru

Riešenie súkromných správ od Facebooku .<> Riešenie súkromných správ od ITnetwork - Best practices pre návrh softvéru

Riešenie súkromných správ od ITnetwork

Z vlastnej skúsenosti môžem potvrdiť, že softvér je stále zložitejším a zložitejšie, časom budete zisťovať, že vo svojej aplikácii potrebujete ďalšie a ďalšie funkčnosti. Keď je udržíte jednoduché, získate konkurenčnú výhodu nad firmami, ktoré všetko Bastl presne podľa predstavy niekoho, kto IT nerozumie, a vo svojom kóde sa už takmer nevyznajú.

Aug

Single Responsibility Principle, skrátene SRP, hovorí, že každý kus kódu, napr. Trieda, by mal byť zodpovedný za jednu konkrétnu vec. Keď zložíme aplikáciu zo súčastí, kedy sa každá súčasť zameriava na jednu funkčnosť a tú robí dobre, máme pomerne vysokú šancu na úspech.

SRP úzko súvisí s pridelením zodpovednosti. Tomu sme sa do hĺbky venovali vo skupine návrhových vzorov GRASPO.

Príklad

Praktizovanie SRP je napr. Tvorba manažérov pre rôzne entity v aplikácii, svoj kód rozdeľujeme medzi triedy SpravceZakazniku, SpravceFaktur, SpravceSkladu a podobne. Každá trieda je zodpovedná za svoje entity. Nemáme len jedného Spravce.

SRP môžeme praktizovať aj na metódy, aj keď to nie je základný princíp tejto poučky. Každá metóda by mala vykonávať jednu vec a jej činnosť by sme mali byť schopní popísať bez spojky "a". Ak si odpovieme niečo v zmysle "Táto metóda načíta, vyfiltruje a zobrazia výsledky", mala by sa metóda rozdelená na viac metód.

Soc

Separation Of Concerns, česky Rozdelenie záujmu, je princíp podobný SRP. Tu sa však spravidla zameriavame na širšej oblasti. Zatiaľ, čo SRP oddeľuje napr. Prácu s faktúrami od práce so zákazníkmi, SOC oddeľuje typicky aplikačnú logiku od prezentácie. To znamená, že logické operácie by mali byť sústredené v inej časti aplikácie, ako napr. Výpis dát užívateľovi. Určite viete, že sa hovorí o rozdelení aplikácie do vrstiev, o ktorom si môžete bližšie prečítať v kurze Softwarové architektúry a depencency injection. Známe architektúry ako MVC, MVP, MVVM a podobne sú všetko implementácie SOC.

Dry

Do not Repeat Yourself, česky Neopakujte sa, je jeden z najdôležitejších princípov v programovaní. Najmä začiatočníci majú tendenciu kopírovať kód z jedného miesta programu na druhý. Akonáhle sa vo vašej aplikácii vyskytujú kdekoľvek 2 rovnaké bloky kódu alebo napríklad aj 2 podobné kusy kódu, je automaticky zle.

Príklad

Táto chyba je tak častá, že využijeme časť jednej hry, ktorá nám bola do redakcie zaslaná. Konkrétne ide o prepínanie obrázkov (spritov) podľa smeru a veľkosti postavičky:

// smer doprava
if (smer == 0) {
    if (obrazek == 1)
        div.className += "spriteLiveRightL";
    if (obrazek == 2)
        div.className += "spriteLiveRightM";
    if (obrazek == 3)
        div.className += "spriteLiveRightS";

    div.style.left = -200 + "px";
}

// smer doleva
if (smer == 1) {
    if (obrazek == 1)
        div.className += "spriteLiveLeftL";
    if (obrazek == 2)
        div.className += "spriteLiveLeftM";
    if (obrazek == 3)
        div.className += "spriteLiveLeftS";

    div.style.left = sirkaObrazovky + 100 + "px";
}

Na prvý pohľad vidíme, že sa 2 bloky kódu líši minimálne. Kód je určite možné minimálne skrátiť len na:

if (smer == 0) {
    let nazevSmeru = "Right";
    div.style.left = -200 + "px";
}
else {
    let nazevSmeru = "Left";
    div.style.left = sirkaObrazovky + 100 + "px";
}

if (obrazek == 1)
    div.className += "spriteLive" + nazevSmeru + "L";
if (obrazek == 2)
    div.className += "spriteLive" + nazevSmeru + "M";
if (obrazek == 3)
    div.className += "spriteLive" + nazevSmeru + "S";

Kód vyššie funguje úplne rovnako, ale má oveľa menej duplicít. Predstavte si, že by sa zmenilo pomenovanie obrázku z "... Right ..." a "... Left ..." na "R" a "L". Pozrite sa, koľko kódu by sa muselo prepísať v príklade porušujúceho DRY a koľko u opraveného príklade. Kód však stále nie je ideálne.

DRY nie je len o duplicitným kódu, ale o opakovanie ako takom. Bezduchá dlhá vetvenia bývajú takmer vždy nahraditeľná múdrejšími konštrukciami, zvyčajne cykly alebo poľom. Urobme ďalšie úpravu:

if (smer == 0) {
    let nazevSmeru = "Right";
    div.style.left = -200 + "px";
}
else {
    let nazevSmeru = "Left";
    div.style.left = widthOfScreen + 100 + "px";
}

let obrazky = [1: "L", 2: "M", 3: "S"];
div.className += "spriteLive" + nazevSmeru + obrazky[obrazek];

V našom prípade sme si pomenovanie veľkosti postavičky "L", "M" a "S" uložili do slovníka pod číslo, ktorým sa veľkosť (obrázok) vyberá. Nie je potom nič jednoduchšie, než vybrať písmenko veľkosti podľa kľúča slovníka.

Teraz na kód aplikujme tiež pravidlo KISS. Obrázky môžeme totiž jednoducho pomenovať číselne, aby smer a veľkosť v ich názve súhlasili s reprezentáciou týchto hodnôt v kóde. Prečo to robiť zložito? Obrázky rovnako nie sú určené pre užívateľov. výsledok:

div.style.left = smer ? (sirkaObrazovky + 100 + "px") : (-200 + "px");
div.className += "spriteLive" + smer + "_" + obrazek;

Kód sa skrátil na 2 riadky z pôvodných 18 (!) A robí úplne to isté. To všetko len za pomoci KISS a DRY. Predstavte si, čo sa stane, keď Best practices aplikujete na celú aplikáciu. Zrazu nemusíte písať desiatky tisíc riadkov kódu a prevalcuje svoju konkurenciu za niekoľko mesiacov. Dobré praktiky určite nepodceňujte :)

Ukážkou DRY by mohli byť Carousel na ITnetwork, ktoré možno rôzne nastavovať:

Carousel na ITnetwork - Best practices pre návrh softvéru

Carousel s fotografiami .<> Carousel s iným nastavením na ITnetwork - Best practices pre návrh softvéru

Carousel s HTML obsahom

To iste ešte nie je nič veľkolepého. Vnútorne ale navyše tieto Carousel dedí z komponenty, ktorá prepína záložky:

Tabcontrol ako predok pre ITnetwork carousel - Best practices pre návrh softvéru

Tabcontrol so zdrojovými kódmi algoritmu pre rôzne jazyky

Mnoho programátorov by napadlo napísať carousel a záložky zvlášť, ale keď sa bližšie zamyslíte, robia v podstate to isté, len vyzerajú inak. Jedna komponenta je možné vytvoriť len menšie obmenou tej druhej.

Ďalšími príkladmi DRY by mohlo byť napr. Vytvorenie kvalitných všeobecných CSS štýlov, ktoré nie sú obmedzené na konkrétne prvky na stránke a možno ich parametrizovať, ako to má napr. CSS framework Bootstrap:

<table class="table table-striped">

Vyššie uvedený kód nastaví tabuľke základnej štýl a zároveň pruhovanie.

Shy

Možno poznáte poučku:

Keep it DRY, shy, and tell the other guy.
Slovensky voľne preložené ako "Neopakuj sa, píš hanblivo a povedz to ostatným." DRY a opakovanie sme si už vysvetlili, ale ako je to so hanblivým kódom? Hanblivý kód sa chová úplne rovnako, ako hanbliví ľudia. Komunikuje s ostatným kódom teda len keď je to nevyhnutne potrebné a nemá ani viac informácií o ostatných, než sám nevyhnutne potrebuje. SHY je vlastne iné označenie pre zákon Demeter, viď ďalej.

Lod

Law of Demeter, teda zákon Demeter, gréckej Bohyňa úrody, je v podstate o low / loose coupling, teda o udržiavanie najmenšieho možného počtu väzieb medzi komponentmi. Je definovaný troma pravidlami, kde zavádza pojem jednotka pre zapuzdrenou časť kódu, teda pre triedu:

  • Každá jednotka by mala mať obmedzenú znalosť o ostatných jednotkách, iba jednotkách, ktoré sú dané jednotke blízke.
  • Každá jednotka by mala "hovoriť" len so svojimi "priateľmi", nehovorte s cudzími.
  • Hovorte iba so svojimi priamymi priateľmi.

Z pravidiel je vidieť, že každý objekt by mal byť univerzálne a úplne odtienený od zvyšku aplikácie. Poznať minimum informácií o celku a zdieľať minimum informácií o sebe celku.

Príklad

Praktický príklad si určite dokážete predstaviť. Jedná sa o triedy s dobre zapuzdrenou vnútornou logikou a všeobecnou funkčnosťou, aby nemuseli poznať detaily konkrétneho systému a bolo ich možné použiť kdekoľvek. Napr. vytvoríte generátor objednávok tak, aby ho bolo možné 100% prispôsobiť a nebol závislý na potrebách jedného informačného systému. Možno vás napadá, či nie je plytvanie vývojovým časom a peniazmi vytvárať funkcie, ktoré v danom projekte nepotrebujete. To by plytvanie určite bolo, s týmito funkciami stačí len počítať a navrhovať komponenty tak, aby do ich išli v budúcnosti ľahko dopísať.

Loď sa týka aj odovzdávanie závislostí, ktorých by malo byť čo najmenej a trieda by mala závisieť od abstrakciou, nie konkrétnych triedach. O tom hovorí Dependency Inversion Principle, ktorý je súčasťou poučiek SOLID.

IOC

Princíp Inversion of Control by ste mali dobre poznať. Ide o skupinu návrhových vzorov, ktorej súčasťou je aj populárny Dependency Injection, jediný správny spôsob ako v objektových aplikáciách závislosti odovzdávať. IOC tvrdí, že objekty v aplikácii by mali byť riadené nejakým vyšším mechanizmom, ktorý vytvára inštancie tried a odovzdáva im potrebné závislosti. To je opačný prístup k staršiemu spôsobe práce so závislosťami, kedy si triedy svojej závislosti vyťahovali sami zo systému, napr. Cez Singleton alebo iné antipatterny. Keďže sa jedná o extrémne dôležitú problematiku, pripravili sme pre vás o DI samostatný kurz Softvérové architektúry a depencency injection, kde je podrobne vysvetlená na reálnych príkladoch.

Medzi populárne dobré praktiky patrí tiež poučky SOLID a STUPID, ktoré sú akronymy pre ďalšie praktiky a preto im je venovaný samostatný článok.

Máte nejaké poučky, ktoré s obľubou radi dodržiavate? Máte zaujímavú skúsenosť s best practices? Podeľte sa s ostatnými do komentárov pod článok :)

V ďalšej lekcii, Najčastejšie chyby programátorov - Na čo sú algoritmy? , sa uvedieme sveta algoritmov. Povieme si, čo to algoritmy vlastne sú a prečo by nás mali zaujímať.


 

Predchádzajúci článok
Najčastejšie chyby programátorov - Rozdelenie aplikácie do tried
Všetky články v sekcii
Best practices pre návrh softvéru
Preskočiť článok
(neodporúčame)
Najčastejšie chyby programátorov - Na čo sú algoritmy?
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity