Java programátor expert
Kvalitný návrh softvéru stojí na jasných princípoch. Ak chýbajú, projekt sa skomplikuje skôr, než začne rásť. V článku sa dozvieš základné princípy návrhu softvéru a praktické postupy, ktoré sa v praxi osvedčili pri malých i veľkých projektoch. Vďaka nim budeš navrhovať riešenia, ktoré sú stabilné, udržateľné a pripravené na reálne požiadavky zákazníkov.

V článku sa dozvieš:
Návrh softvéru je rovnako dôležitý ako pevné základy budovy. Bez nich to jednoducho nejde. Ak by mrakodrap nemal kvalitné základy, stavbári nedokážu postaviť štyridsiate poschodie. Podobne je to aj pri softvéri. Ak chceš dosiahnuť škálovateľnosť projektu, musíš začať stavať na tom, čo bolo otestované a už dobre funguje. Pridanie novej funkcionality jednoducho nemôže pokaziť starú.
Predstav si situáciu: Začínaš s projektom, ktorý má meškanie, nerozumieš štruktúre kódu a architektúre systému. Každá zmena navyše vyžaduje dešifrovanie záhadných názvov. Dokonca aj implementovanie jednoduchej funkcionality znamená zložité zásahy do kódu. V takom momente si uvedomíš, že niekto fatálne podcenil návrh softvéru a celý projekt teraz balansuje na hlinených nohách a každá ďalšia funkcionalita ohrozuje stabilitu celého systému.
Princípy návrhu softvéru (Software Design Principles) predstavujú osvedčené postupy v oblasti softvérového inžinierstva, ktoré sa používajú pri tvorbe softvéru, aby sme dosiahli jeho kvalitu. To znamená predovšetkým funkčný, modulárny, škálovateľný a ľahko udržiavateľný softvér.
Tieto princípy tiež pomáhajú dosiahnuť, aby bol proces návrhu štruktúrovaný, zrozumiteľný a ľahko rozšíriteľný. Snahou je čo najviac eliminovať potenciálne chyby, ktoré spôsobujú nárast nákladov a stratu drahocenného času na ich odstránenie.
Všeobecné princípy návrhu softvéru sú univerzálne aplikovateľné pravidlá, ktoré sa dajú využiť nielen pri návrhu, ale používajú sa aj v iných oblastiach, napríklad v marketingu. My si však jednotlivé odporúčania postupne vysvetlíme a pozrieme sa na to, ako sa dajú aplikovať.
K najznámejším princípom návrhu softvéru patria:
Princíp KISS hovorí, že by si mal svoj návrh aj kód udržiavať čo najjednoduchší. Komplikované riešenia sú nielen ťažšie na pochopenie, testovanie a údržbu, ale často vedú k väčšiemu počtu chýb. Keď potrebuješ pridať novú funkciu, najprv si polož otázku: „Je táto nová funkcionalita naozaj nevyhnutná?“ Ak áno, navrhni ju čo najjednoduchším, priamočiarym spôsobom, bez zbytočných vrstiev abstrakcie či komplikovaných štruktúr.
Tento prístup podporuje clean code (čistý kód) a uľahčuje neskorší refactoring. Navyše jednoduchosť ti ušetrí čas a nervy pri ďalšom rozširovaní kódu v spolupráci s tímom.
„Veci by mali byť zjednodušené čo najviac, ale nie natoľko, aby stratili svoj zmysel.“
Princíp YAGNI hovorí, že by si nemal predvídať a implementovať funkcionalitu či písať kód, ktorý dnes nepotrebuješ, aby zostal celkový návrh riešenia čo najdlhšie jednoduchý. Ak príde nápad na „čo keby sme tu pridali ešte toto…“, odlož ho, kým sa nepreukáže skutočná potreba. Tým znížiš množstvo nevyužitého kódu, ušetríš čas pri vývoji softvéru a udržiavaní a zamedzíš zbytočným chybám.
„Každý riadok kódu, ktorý nemusíme napísať, šetrí peniaze a vracia nám späť čas.“
Princíp DRY hovorí, že by si nikdy nemal duplikovať rovnaký kód alebo logiku na viacero miest. Namiesto kopírovania vytvor jednu funkciu, triedu alebo modul, ktorý túto činnosť vykoná, a volaj ho všade tam, kde to potrebuješ. Keď sa niečo zmení, opravíš to len na jednom mieste, čím znížiš riziko chýb, ušetríš čas a kód zostane prehľadnejší a ľahšie sa udržuje.
„Opakovanie je zdrojom všetkého zla v softvéri.“
Princíp „Pravidlo skauta“ hovorí, že zakaždým, keď pracuješ na nejakom kúsku kódu, mal by si ho zanechať v o niečo lepšom stave, než si ho našiel. To znamená napríklad vylepšiť pomenovania premenných, odstrániť zbytočné komentáre alebo refaktorovať malú časť kódu, ktorá je neprehľadná. Nemusíš hneď robiť veľké zmeny, stačia aj malé vylepšenia. Postupne sa tak celý projekt stane čistejší, prehľadnejší a jednoduchší na ďalšiu údržbu.
„Zanechať neporiadok v kóde by malo byť rovnako neprijateľné, ako hádzať odpadky na zem.“
Princíp „rýchleho zlyhania“ hovorí, že by program, resp. systém mal upozorniť na chybu okamžite v momente, keď nastane, namiesto toho, aby pokračoval s neplatnými alebo nekonzistentnými dátami. Čím skôr je používateľ (alebo iný systém) upozornený na problém so spracovaním jeho vstupu, tým lepšie. Systém bude reagovať rýchlejšie a spotrebuje menej zdrojov na spracovanie vstupov, ktoré nakoniec povedú k chybám alebo zlyhaniu systému. Pre vývojára to znamená, že pred spracovaním dát by ich mal validovať a nespoliehať sa na to, že sú správne.
Tento princíp zároveň zjednodušuje testovanie softvéru aj debugging v prípade chýb. Ak zistíš, že si na vstupe dostal nesprávne, neúplné alebo poškodené dáta, siahni po okamžitom vyvolaní výnimky v kóde. Často je jednoduchšie dáta opraviť, ako zabrániť nepredvídateľným následkom chybných dát ďalej v kóde.
„Odmenou za nezachytenie chýb včas je debugovanie.“
Tento princíp známy aj ako „Law of Demeter“ hovorí, že objekt by mal volať metódy iba: na sebe, svojich vlastných atribútoch (poliach), parametroch metódy alebo objektoch, ktoré sám vytvoril, rozhodne nie na objektoch, ktoré získa cez reťazené volania. Inak povedané, „nevyzvedaj si veci o veciach“, napr. namiesto volania order.getCustomer().getAddress().getCity(), radšej volaj order.getCustomerCity(). Tým znižuješ previazanosť kódu (coupling), zvyšuješ jeho čitateľnosť a uľahčuješ testovanie.
„Neexistujú tu žiadni cudzinci, iba priatelia, ktorých si ešte nestretol.“
Pri objektovo orientovanom programovaní (OOP) sa často využívajú SOLID princípy. Ide o päť základných pravidiel: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation a Dependency Inversion, ktoré pomáhajú vytvárať flexibilný a ľahko udržiavateľný kód.
Aj pri návrhu grafického rozhrania sa odporúča dodržiavať zásady preverené praxou. Pozri sa, ktoré z nich je dôležité zvážiť.
Princíp minimálneho prekvapenia (PoLA) znamená, že rozhranie (či už API alebo užívateľské) by sa malo správať tak, ako to používateľ očakáva na základe bežných zvyklostí. Ak voláš funkciu alebo klikneš na tlačidlo, výsledok by mal byť predvídateľný, intuitívny a konzistentný s tým, čo už poznáš. Nemá to byť niečo nečakané alebo prekvapujúce. Vďaka tomu sa ľahšie učíš pracovať s novou aplikáciou (alebo kódom) a minimalizuješ chyby vyplývajúce z nejasných či nezvyčajných správaní. Vždy sa snaž poskytnúť používateľovi jasné vysvetlenie alebo popis toho, čo môžu očakávať.
Princíp konzistentnosti znamená, že všetky časti systému, či už názvy funkcií, štruktúra objektov alebo používateľské rozhranie by mali používať rovnaké vzory, štýly a konvencie. Ak je kód alebo UI konzistentné, nový člen tímu rýchlejšie pochopí, ako všetko funguje a ani ty sa nestratíš pri prepínaní medzi rôznymi časťami projektu. Konzistentné rozhranie tiež zabraňuje zámene a znižuje riziko chýb, pretože vieš presne, čo očakávať od každej funkcie či obrazovky.
Príkladom konzistentnosti je vypisovanie kritických chýb používateľovi červenou farbou, varovaní oranžovou farbou a informačných hlášok zelenou, konzistentne, na všetkých dialógoch aplikácie rovnako.
Princíp prívetivosti k používateľovi sa zameriava na to, aby prvky rozhrania (tlačidlá, odkazy, vstupné polia) vizuálne naznačovali svoju funkciu. Napríklad tlačidlo by malo pôsobiť „stlačiteľne“ (vykrojené, s tieňovaním) a pole na zadávanie textu by malo mať jasný rámček. Keď používateľ vidí prvok, okamžite vie, čo sa stane po jeho interakcii, bez potreby dodatočných inštrukcií. Prívetivosť užívateľského rozhrania skracuje krivku učenia a znižuje chyby spôsobené nesprávnym používaním rozhrania.
Princíp spätnej väzby hovorí, že po každej interakcii používateľa by mal systém okamžite a zrozumiteľne dať spätnú väzbu, čo sa práve stalo. Napríklad po kliknutí na tlačidlo sa tlačidlo deaktivuje (aby používateľ neklikol naň opakovane) a zobrazí sa animácia progressbaru. Je potrebné informovať používateľa, na čom aplikácia aktuálne pracuje a kedy asi bude hotová.
Pri odoslaní formulára môžeme vypísať potvrdenie „Úspešne odoslané“ alebo zobraziť chybovú správu pri nesprávne zadaných údajoch. Vďaka správnemu a včasnému feedbacku používateľ vidí, že aplikácia stále reaguje a je informovaný, či jeho interakcia bola úspešná, alebo či bude musieť svoju akciu zopakovať.
Princíp predchádzania chybám hovorí, že treba robiť všetko pre to, aby sa chyby v aplikácii nestali, a ak sa predsa objavia, umožniť ich ľahké opravenie. Ako príklad by som spomenul validovanie vstupných dát (napr. formát e-mailu alebo rozsah čísel) ešte pred odoslaním. Šikovným trikom je deaktivovať tlačidlo Odoslať, až kým nie sú všetky povinné polia vyplnené a dáta skontrolované.
Všetky používateľom zadané údaje by si mal systém zapamätať, aby používateľ v prípade problému nemusel začať vypĺňať údaje odznova. Tu platí rovnako pravidlo, že všetky údaje sa vypýtajú iba raz a rovnako treba ponúknuť používateľovi možnosť sa opraviť, napr. pri preklepe pri zle zadanej ulici. Týmto prístupom znižuješ frustráciu používateľa a zvyšuješ dôveru v spoľahlivosť svojho rozhrania.
Princíp postupného odhaľovania možností znamená, že používateľovi ukazuješ najprv len to najdôležitejšie a až na požiadanie odkrývaš ďalšie detaily či pokročilé možnosti. Tým udržíš rozhranie prehľadné a nezaťažuješ ho množstvom informácií naraz. Napríklad v nastaveniach skryješ pokročilé možnosti za záložku Rozšírené, aby sa do nich dostali len tí, čo ich naozaj potrebujú.
Tieto princípy sa zameriavajú najmä na štruktúru aplikácie, vzťahy medzi jednotlivými časťami kódu a bezpečnosť systému. Pomáhajú navrhovať softvér tak, aby bol flexibilný, odolný voči zmenám a menej náchylný na chyby pri ďalšom rozširovaní alebo údržbe.
Princíp oddelenia zodpovedností znamená rozdeliť aplikáciu na jasne vymedzené časti, z ktorých každá rieši iný problém či vrstvu. V softvérovej architektúre existuje 5 hlavných vrstiev: prezentačná, aplikačná, logická, perzistentná a databázová. Jednoduchšiu aplikáciu môžeme rozdeliť do troch vrstiev:
Vďaka rozdeleniu architektúry programu do vrstiev môžeš meniť, testovať a udržiavať každú časť vrstvy nezávisle. Napríklad používateľské rozhranie sa dá prerobiť bez rizika, že rozbiješ biznis logiku, alebo vieš vymeniť databázu za inú bez zásahu do UI.
Tento princíp odporúča prednostne využívať kompozíciu objektov pred dedičnosťou všade, kde je to možné. Kompozícia je vytváranie funkcionality skladaním objektov z iných objektov a umožňuje flexibilnejší a opakovane využiteľný kód v kontraste s hierarchiou dedičnosti, ktorá je trochu rigidná a náchylnejšia na chyby, hlavne ak máme dočinenia s mnohoúrovňovou zreťazenou dedičnosťou.
Zmena rodičovskej triedy môže ovplyvniť potomkov, ktorí z nej dedia. Samozrejme, či už kompozícia alebo dedičnosť majú svoje miesto. Ak sa dá daný problém riešiť kompozíciou, mali by sme ju uprednostniť. Týmto prístupom dosiahneš čistejšiu architektúru, kde jednotlivé časti kódu zostávajú prehľadné a znovupoužiteľné.
Princíp najmenších právomocí je koncept informačnej bezpečnosti a hovorí, že každý modul, používateľ alebo proces by mal mať len tie oprávnenia, ktoré skutočne potrebuje na svoju prácu a nič viac. Tým minimalizuješ riziko, že pri chybe alebo útoku získa útočník prístup k citlivým funkciám či dátam, ktoré modul nikdy nepoužíval. Zároveň zjednodušuješ audit a správu bezpečnosti, keďže presne vieš, kto a čo môže v systéme robiť.
Pamätaj, kvalitný softvér nezačína kódom, ale rozhodnutiami, ktoré k nemu vedú. Dodržiavaním princípov pri návrhu softvéru alebo jeho implementácii dosiahneš, že tvoj program bude postavený na silných, stabilných základoch. Je to ako stavať tehlový dom, kde každá trieda, funkcia predstavuje jednu tehlu a patrí na svoje vopred stanovené miesto, aby mohla spolupracovať s okolitými tehlami. Len tak dokáže tvoj projekt rásť do výšky bez rizika, že sa zrúti pri príchode nových požiadaviek.
Súvisiace články