PIA Flashcards
kvalita SW se da merit
pocet stiznosti od uzivatelu
pocet chyb nalezenych v produkci
cena za udrzbu
naklady na dalsi vyvoj
validace
= aplikace dela to co si zakaznik preje
dosazeno pomoci komunikace se zakaznikem
verifikace
overeni ze aplikace dela co rika specifikace
- dosazeno pomoci testovani
- je dulezity s tim jak aplikace roste
- je nutne mit dobry vyvojovy cyklus a automatizaci
testovani - cíl
nalezt chyby, rozbit aplikaci
debuggovani
cil: nalezt priciny chyb
- jednoduche pri vyvoji
- tezke na produkci
- nemuzeme si jen tak pripojit debugger
- aplikace uz obsahuje realna data
specifičnost webové aplikace při testování
- muze se rychle menit (HTML, …)
- prirozene je to vicevlaknova aplikace
- potencialni muze celit vyssi zatezi nez je ocekavano (DoS utok)
=> nutne zotaveni
Unit Testy
- testuji malou cast kodu (vetsinou funkci nebo metodu)
- vytvareny programatory
- mely by byt na sobe nezavisly
- idealne jedna mnozina unit testu testuje jednu tridu/modul
Unit Testy - co testují
- korektni vstup
- krajni hodnoty
- nekorektni vstup (vyhozeni vyjimek, …)
= jedna metoda vetsinou vyzaduje vice testu
Pokrytí testy a důsledky
> 90% aplikacni logiky
pomahaji pri refaktoringu, pridavani funkcionalit, …
specialni pripad je kdyz se testy pisou jeste pred zacatkem programovani - kriticke systemy, nuti nas premyslet o navrhu aplikace
pri zajisteni nezavislosti testu mame dva pristupy
stubs
mocks
stubs
- specialni implementace zavislosti, ktere metoda vyzaduje
- napriklad vlastni implementace DAO rozhrani -> ulozeni dat do pameti
- nevyhoda je kdyz mame velkou aplikaci -> muze se stat ze budeme mit velky pocet stubu (musime se snazit je napsat co nejvic genericke)
mocks
frameworky dynamicky za behu vytvari obrazy rozhrani (ktere potrebujeme) s dynamicky definovanym chovanim
musime mit dobrou architekturu (SoC)
je jednodussi vytvaret objektu nez volat primo HTTP pozadavky -> nemusime mit aktivni HTTP server
levne
netestuji funkcionalitu celeho systemu
funkci testy
- testovani funkcionality aplikace jako celku
- typicky se definuji use-casy, scenare
- testovani proti bezici aplikaci
- v jednodussich pripadech plni funkci i integtacniho testu -> pri testovani testujeme i komunikaci s DB atd
Funkční testy - možnost
testovaci scenare
automatizovane funkci testy
testovaci scenare
krok po kroku co ma uzivatel delat
kam ma kliknout, jaky data kam zadat, jaky vystup ma ocekavat
vyvojari by nemeli psat funkci testy protoze vi jak se aplikace ma chovat a za jakych okolnosti pada
mely by je psat lidi co nejsou seznameni s tim jak aplikace vnitrne funguje
automazitované funkční testy
- scripty
- levne pri dlouhodobem pouzivani (SW nedela chyby)
- nakladnejsi na napsani a udrzbu (ID v HTML, XPATH, atd se meni pomerne casto)
- jednodusi pro testovani API webove sluzby
- postman, insomnia
- vyzva pri testovani Weboveho rozhrani
- moderni frameworky umi simulovat browser (i headless mode - nemusi se vytvaret okno)
Selenium
- sada nastroju pro testovani aplikace s pouzitim prohlizece
- muzeme je bud nahrat (manualne naklikat) nebo napsat pomoci IDE
- musime pri navrhu stranek mit v pameti ze se budou testovat -> napr definovat ID
Robot framework
- dovoluje definovat tetovaci scenare bez programovani
- “vygeneruje” kod (pomoci klicovych slov)
- naprvni pohled je videt co ten test dela
integracni testy
testovani ze pripojeni a posilani zprav mezi dvouma systemama funguje tak jak ma
vykonostni testy
- mely by se pouste proti production-like prostredi
- overeni ze aplikace zvladne zatez jako pri realnem provozu
- overeni ze nove verze aplikaci nemaji vykonostni dopad
- overeni jak se aplikace chova pri velke zatezi
smoke testy
- podmnozina nasi testovaci sady
- jejich ukolem je overi ze nasazeni aplikace probehlo v poradku, aplikace odpovida (zda se ze funguje)
- nesnazime se aplikaci zatizit
- nechceme po sobe nechat data v DB
- pouziva se na produkci (nechceme poustet celou testovaci sadu)
testy “nepouzitelnosti”
- testovani jak jednoduche je pouziti daneho UI - user experience
- zeptame se nekolik uzivatelu jak se jim aplikace pouziva
- zjistime jak uzivatele pouzivaji nasi aplikaci (nemusi byt tak jak jsme ocekavali)
- nedaji se automatizovat
typy logu
- aplikacni logy - zpravy popisujici co se v aplikaci deje (jaka trida, jaka metoda, …)
=> info, warn, error, debug, trace - pristupovy logy - vsechny volani funkci aplikace z vnejsi site (ip, date, response, POST, GET, …)
=> neobsahuje data (mohou byt citlive) - auditacni logy - sledovani co dany uzivatel dela
=> mohou obsahovat i citlive udaje
=> nejsou pristupne vsem lidem ve firme
=> kdo, kdy, co za akci, kontext (muze obsahovat data/udaji)
Moderni logovani
- logy se neukladaji primo na aplikacni server
- logy ukladame do cloud storage
- ma smysl napriklad pri skalovani aplikace
- mame jedno misto kam ukladat logy
- audit logy NESMIME ztratit (aplikacni logy ani tolik nevadi)
HTTP
- bezstavovy (server si nepamatuje kdo kdy poslal jakej pozadavek - nijak se neovlivnuji)
- textovy protokol
Verze:
verze 1 - nejvice pouzivana
nevyhoda: pro kazde stazeni souboru, poslani pozadavku => jedno TCP spojeni (desitek css, js souboru)
verze 2 - umoznuje posilat vice pozadavku pres jedno TCP spojeni
verze 3 - bezi ne pres TCP ale UDP
HTTP request
…
Example:
GET /index.html HTTP/1.1
Host: www.kiv.zcu.cz
typy HTTP metod
GET, OPTIONS, HEAD, TRACE - nemeni stav
OPTIONS vraci jake metody jsou k dispozici
POST, PUT, DELETE - meni stav
priklady hlavicek v HTTP requestu
host (povinna) - jmeno serveru
origin - jmeno serveru ze ktereho by request poslan
Content-Type - JSON, HTML, TEXT, …
Authorization - jmeno/heslo
HTTP response
<code></code>
…
Example: HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 14 ... Hello, world!</code>
typy kodu odpovedi:
200 - OK 204 - OK, ale neposilam ti zpet zadny obsah (napr u POST) 301 - redirect 401 - unauthorized (musis se prihlasit) 403 - forbidden (nemas prava) 404 - stranka nenalezena 500 - chyba na strane serveru
Cookies:
- zavadeji stavovost do jinak bezstavoveho protokolu
- klient odesila cookie spolu s requestem -> server vi ze se jedna o daneho klienta a nacte jeho session (napr z distribuovane cache v pripade horizontalniho skalovani)
- pouziva se napr i k sledovani uzivatelu - viz reklamy
- cookie obsahuje session ID
- muze vest k bezpecnostnim rizikum - ukradeni cookie
nastavení cookie přes http hlavičku
Set-Cookie: name=value [; EXPIRES=dateValue]
[;DOMAIN=domainName][;PATH=pathName][;SECURE][;…]
- secure: odesli pouze pokud se jedna o HTTPS
- expires: doba platnosti cookie
- domain: nastavene browserem, napr zcu.cz, kdyz pujdu na FB tak se cookie posilat nebude
- path: cesta pro kterou se ma cookie odesilat napr zcu.cz/admin
=> klient posle vsechny cookie pokud sedi domena, cesta, nevyprsela doba platnosti a pripadne se jedna o HTTPS (ne jen HTTP)
HTML WebStorage API
alternativa misto cookie
aplikace si mohou ukladat data v prohlizeni
nemusi se posilat na sever s kazdym requestem (narozdil od cookie)
pristupne z JS
data jsou ulozena dokud nezanikne session/nezavre se tab
Window.localStorage sessionStorage.setItem('key', 'value'); let data = sessionStorage.getItem('key'); sessionStorage.removeItem('key'); sessionStorage.clear();
Forward proxy
requesty do externi site
nahrazuje IP addr zroje svoji IP
dovoluje restrikci kam se uzivatel pripojuje (napr z firemni site)
client → proxy → internet
Reverse proxy
requesty do externi site
nahrazuje IP addr zroje svoji IP
dovoluje restrikci kam se uzivatel pripojuje (napr z firemni site)
client → proxy → internet
Separation of Concerns
- kod ktery delat neco jinyho (jinou praci) by mel byt oddeleny (lepsi testovani, znovupouzitelnost, prehlednost)
- napr registrace uzivatele a validate stupnich dat by mely byt oddelene
Single Responsibility Principle
- kazda trida by mela zajistovat prave jednu cinnost
- mixovani funkcionalit vede ke spatnemu testovani, neprehlednosti, atd.
zapouzderni
- kazda instance ma svuj stav (dano hodnotamy atributu)
- zabranit prime zmene stavu instance tridy
- hodnoty atributu se maji menit vnitrne prostrednictvim definovaneho API
- automaticke generovani getteru/setteru porusuje princip zapouzdreni
- ve webovych applikacich komunikujeme pres rozhrani - nemusime znat implementaci
DRY
Don´t Repeat Yourself
- kopirovani kodu
- neustale prepisovani dokumentace
- prekreslovani schemat
- testovaci pripady
- po case nejsou synchronizovane s aktualnim stavem projektu
- > lepsi je puzit nastroj pro automaticke generovani
Dependency Inversion
trida A ma tesnou zavislost na tridu B:
- tezke nahradit tridu B za jinou
- lepsi mit zavislost pouze na rozhrani
- imlementaci pak muzeme zmenit
- velke urovne abstrakce by nemely zaviset na implementacnich detailech
Explicit Dependencies
- aplikace/moduly/tridy by mely specifikovat jake zavislosti potrebuji pro svuj beh
- napr Linux - balickovaci system, pip - requirements.txt, maven, …
- v pripade kodu je to konstruktor, parametry funkce
- funkce by mely mit jako parametr vsechny potrebne zavislosti pro sve vykonani
- tridy maji vsechny potrebne zavislosti definovane v konstruktoru - po jeji inicializaci je trida plne funkci - ma vsechny zavislosti; nepovinne zavislosti -> pres settery
Inversion of Control
- obecne nas kod neridi tok (beh) programu ale dela to napriklad nejaky framework
=> dependency injection - window GUI
- inversion of control != dependency injection
- dependency injection reprezentuje princip IoC a ne naopak
- priklad NEvyuziti IoC - platebni brana pozaduje unikatni ID kazde transakce - klient jej musi vygenerovat. Jak ma ale vedet ktere uz jsou zabrazene? -> generovani by mela dalat sama platebni brana
=> bylo by to v pohode v pripade jednoho zakaznika
=> mozne reseni: alokovat mnozinu ID pro daneho zakaznika ze kterych on bude => nahodne generovat unikatni ID
Dependency Injection
hlavni myslenka: oddeleni kodu pro vytvareni objektu a jejich nastavovani zavislosti od zbytku
- v kodu jsou nadefinovane zavislosti pomoci kontruktoru
- pak mame separatni konfiguracni tridu nebo soubor (napr xml nebo json) kde definujeme “naskladani” zavislosti jakych budeme potrebovat
- snadne nahraznovani zavislosti za jine (vime presne kam jit a kde to zmenit)
- napriklad pri testovani nahradime DB nejakou in-memory DB
- povinne zavilosti - pres konstruktor (@RequiredArgsContructor)
- dobrovolne zavislosti - settery (@Autowired)
- injectovani primo do atributu (nemusime vytvaret ani konstruktor ani setter) - ani-pattern (ve Springu @Autowired); spise nepouzivat
Service Lookup
- alternativa k DI
- existuje objekt ktery zna vsechny instance v danem projektu
- dao = applicationContext.getBean(“dao”) - vraci instance daneho rozhrani podle jmena ktery pak muzeme priradit jako hodnotu atributu v dane tride
Dependency Injection vs Service Lookup
- DI vyuziva princip IoC
- DI muze byt tezsi na debuggovani
- Service Lookup neni tak flexibilni ale je jednodussi na pouziti
kdybychom to implementovali sami - pouze mapa instanci - Service Lookup vyzaduje mit instanci na globalni objekt ktery drzi vsechny instance
=> v pripade knihoven vynutime uzivatele aby taky pouzival Service Locator
Web Application Architectures - dva pohledy
1) jak je aplikace nasazena - jeji repliky, skalovatelnost, atpd.
=> nasazeni + udrzba
2) jak je aplikace uvnitr organizovana - monolit, micro-services, …
Web Application Architectures - škálování
horizontalni skalovani - mame vice replik dane aplikace
vertikalni skalovani - tunime dany server - vic ram, vic CPU atd
Monoliticka aplikace
- aplikace je jeden funkci celek, ktery se sklada z vice modulu
- dela vice cinnosti napr registraci uzivatele, ucetnictvi, tisknuti dokumentu atd
- jednodussi na testovani, debuggovani, vyvoj - mame jen jedno IDE (repozitar), nasazeni
Monolitická aplikace - škálování
- v pripade skalovani musime skalovat celou aplikaci i kdyz jsou vytizenne napr jen nektere jeji casti
- horsi to zacne byt az se aplikace zacne zvetsovat
- neprehlednost kodu, prace vice programatoru
- vyzauje dobrou vnitrni architekturu a rozlozeni trid
- aplikace dlouho startuje
- cela aplikace musi byt napsana s pouzitim stejne technologie
- pri zmene frameworku musime celou app prepsat
SOA - popis
Service-Oriented Architecture
- pokus o vyreseni problemu s monolitickou aplikaci
- kazda service je black box
=> komunikujeme pouze pres rozhrani
SOA - typy komunikace, protokoly
Typy:
1) na primo
2) pres frontu zprav - odpoved je jen “jo dobry prijal jsem zpravu - nekdy ji zpracuju”
Protokoly:
HTTP, WebSocket, SOAP, AMQP, MQTT, Stomp
SOA - nevýhody (5x)
1) v pripade SOA komunikujeme pres sit
=> musime mit v pameti transakce (kdyz spadne pripojeni napr), bezpecnost (HTTPS)
- kazda service by mela byt bezstavova - bud vratime error nebo odpoved
2) tezsi debuggovani - danou sluzbu nemusime spravovat my
3) casto jedna aplikace = vice repozitaru, nestaci jedno IDE (ruzne technologie)
4) integracni testy jsou slozitejsi
=> NEJHORSI PRIPAD JE KDYZ DO TOHO INTEGRUJEME MONOLITICKOU APLIKACI - prinasi nevyhody obou reseni
5) pri nastartovani muze zalezet na poradi stupusteni jednotlivych sluzeb
Microservices - popis
- jedna aplikace rozdelena do vice malych sluzeb
- kazda sluzba je separatni proces ktery muze/nemusi bezet na stejnem stroji
- zalozeno na Unixove filozofii - deleje jednu vec a delej ji poradne
Mirkoservices - výhody (5x)
1) jednotlive mikro sluzby jsou jednoduche na vyvoj a udrzbu
2) mikro sluzby nemusi byt napsane ve stejne technologii
3) jednotlive mikrosluzby mohou spravovat jine tymy lidi
4) nemusime skalovat celou aplikaci ale jen dane vytizene mikro sluzby
5) pri aktualizaci nemusime vypinat celou aplikaci
Mikroservices - nevýhody (5x)
1) tezsi na nasezeni kvuli tomu jak je aplikace distribuovana
=> diky Dockeru mame testovaci prostredi (dost pomáhá)
2) vyzaduje intenzivni integracni testy
3) potencialne muze byt vice nakladna - vice serveru, pripojeni
4) kazda mikro sluzba by mela mit sve uloziste
5) use-casy mohou pokryvat vice mikrosluzeb -> nutna dobra komunikace jednotlivych tymu
Monolith vs Microservices
- zalezi jaky mame use-case
- monolit je lehci na vyvoj, nasazeni a udrzbu - dokud aplikace prilis nenaroste
- pro male aplikace se nevyplati komplexita mikro sluzeb
- pro velke aplikace uz ano
Common Web Application Design Principles
- kod aplikace je rozdelen do vrstev
- jednotlive vrstvy implementuje a zapouzdruji danou funkcionalitu
- komunikace mezi vrstvami probiha pres rozhrani -> jednodussi nahrazeni za jine implementace (napr jiny typ DB) a testovani
Application Layers – Clean Architecture
- hlavni pavidlo: zavislosti jdou vzdy ze shora dolu
- entities: data (objekty - napr objednavky) sdilene napric systemem
- Use Cases: co se da delat nad danyma objektama - aplikacni logika
- Controllers: pristup ven/dovnitr; rozhrani pro pristup k databazi; vytvareni DAO
- posledni vrstva: externi frameworky, drivery
bezne pouzite vrstvy architektury
1) prezentacni vrstva
2) aplikacni vrstva (aplikacni logika)
3) datova vrstva
dulezite mit na pameti
- bezpecnost
- transakce
- logovani
datova vrstva resi:
- format ukladani dat
- relacni schema v pripade relacnich DB, format v pripade souboru, …
- mapovani na aplikacni objekty (tridy - DTO, entity)
cteni/zapis
business logika resi:
- implementace aplikacni funkcionality
- zmena stavu entiti
- volani funkci datoveho uloziste (nizsi vrstvy)
prezentacni vrstva resi:
- vstup od uzivatele
- vola nizsi vrstvu (aplikacni logiku)
- prezentuje vysledky uzivateli
MVC
Model - data a aplikacni logika
View - zobrazuje data z modulu
Controller - zpracovava vstupy od uzivatele
User - uses -> Controller
Controller - manipulates -> Model
Model - updates -> View
View - sees -> User
Model-View-Presenter
- odebrani propojeni view a modelu
- Presenter je Controller ktery slouzi jako prostrednik mezi View a Modelem
View predstavuje jednotlive Widgety (tlacitka, input field, …)
=> kazdy widget ma vlastni presenter ktery obslouzi danou udalost a nastavi nova data na zobrazeni - napriklad kazdy formular mas svoji obsuznou funkce - Presenter, ktera se zavola pri odesilani formulare, data se odeslou na server a po prijeti odpovedi se zobrazi vysledek uzivateli
Model – View - ViewModel
dalsi zpusob oddeleni vazby mezi modelem a view (ASP.NET/WPF)
ViewModel poskytuje:
- data pro view
- formatuje data z interniho modelu na nejakou zobrazitelnou podobu
- Prikazy - reakce na vstup od uzivatele (prikazy jsou namapovane na tlacitka, input fieldy atd.)
- komunikace s View
- zmena view funguje pres DataBinding a Notifikace
- komunikace s Modelem
- ViewModel vola funkce module (aplikacni logika)
- ViewModel je zpusob implementace Clean Architecture na prezentacni vrstve
Cross-Cutting Concerns - architektura
jista funkcionalita je vyzadovana na vsech vrstvach
1) Bezpecnost - user authentication
=> nutnost implementovat jak na severu (operace nad daty)!! tak i na strane klienta (co vidi/nevidi)
2) Logování
=> vsude abychom vedeli co uzivatel a aplikace delaji
3) Trasnakce
=> aplikacni a datova vrstva musi zajistit atomicnost operaci
Naivni implementace techto veci ma za nasledek tezsi testovani, drahe zmeny, …
Cross-Cutting Concerns - přístupy
1) zavislost na rozhrani (API) + konfigurace
- aplikace je zavisla pouze na rozhrani loggeru a konkretni implementace je pote definovana v konfiguraci -> jednodussi testovani a vymena
- problem je napriklad kdybychom vyvijeli knihovnu -> nutili bychom uzivatele pouzivat konretni implementaci napr loggeru
2) Aspect-Oriented Programming (AOP)
AOP
Aspect-Oriented Programming
Co je to aspekt?
- module (typicky trida) co obsahuje kod ktery bychom museli rozkopirovavat do vsech trid (vsude kde ho chceme pouzit)
Frameworky zajustuji ze ten kod napiseme na jednom misto a on se pote dostane na vsechna mista kde ho chceme mit
- neco jako makra v C
- napriklad kdyz budeme logovat - cheme zalogovat casove razitko, nazev metody a logovaci zpravu => tenhle kod chceme napsat jenom jednou
- nebo napriklad bezpecnost - uzivatel musi mit urcitou roli kdyz chce volat konretni metodu - v jave se pouzivaji anotace