Tipy a triky

V tejto sekcii nájdete praktické rady a odporúčania, ako efektívne využívať kurzy cez úrad práce na získanie nových zručností. Tipy a triky sú navrhnuté tak, aby vám pomohli zvládnuť bežné úlohy rýchlejšie a efektívnejšie. Táto kategória je skvelým miestom pre tých, ktorí hľadajú spôsob, ako sa neustále zlepšovať.

Java najnovšie verzie (Java 9): príkazový riadok JShell (2. časť)
Tipy a triky
21.03.2019
Skillmea

Java najnovšie verzie (Java 9): príkazový riadok JShell (2. časť)

Java príkazový riadokJShell Command Line je nástroj, kde môžeme skúšať spúšťať kód bez toho, aby sme museli vytvoriť novú triedu s main metódou.[Image] JShell spustíme z bin adresára, kde máme nainštalovanú javu jdk vo verzii 9 a viac. Pri učení sa preferuje použiť verbose mód jshellu, čo nám poskytne čo najviac spätnej väzby pri práci s konzolou.  jshell –v  Ak si spustil jshell bez –v môžeš jshell vyponúť s príkazom /exit a potom spustiť znovu s –v nastavením. Teraz môžeš zadávať výrazy. Prvý spôsob je zadeklarovať premennú s hodnotou a následne hodnotu vypísať:[Image] Alebo môžeš rovno napísať výraz, ktorý sa vyhodnotí a výsledok sa zapíše do premennej, ktorá dostane poradové číslo. [Image] Je možné deklarovať metódy. Pri písaní príkazov, ak jshell zistí, že príkaz nie je ukončený, napríklad si napísal kučeravú zátvorku a stlačíš enter, tak sa vytvorí nový riadok na ktorého začiatku budú špeciálne znaky ...> čo znamená, že pokračuješ v písaní kódu a výraz sa ešte nevyhodnotí.[Image] Metódu potom voláš klasicky:[Image] Ak by si chcel prepísať metódu, respektíve čo robí vo vnútri, tak ju vieš napísať znovu a ona sa prepíše a platná bude posledná napísaná. Je možné aj prepísať typ premennej. Ak na začiatku bude x číslo, tak neskôr môže byť String. [Image] Pod výpismi máme vždy aj poznámky o tom, čo sa deje na pozadí. Napríklad, že premenná x bola nahradená za String.  Môžeš napísať metódu, ktorá vo vnútri používa premenné alebo metódy, ktoré ešte neboli zadefinované. Fungovať budú až keď všetko zadefinuješ.  Príkazom /list si zobrazíš kód, ktorý si napísal. Každý vstup má číslo, čo predstavuje id vstupu. Tieto id slúžia aj pri výnimkách. Napíšme si príkaz, ktorý spadne a vypíše sa výnimka.[Image] Po výpise /list zistíme čo znamenajú čísla vo výpise. Po prvé tam máme: at divide (#15:2), čo znamená, že chyba nastala na príkaze s id 15 a riadku 2 toho príkazu. Po druhé at (#16:1) je ďalšie miesto, kde sa metóda volala – klasický stack trace, ale s odkazom na /list výpis.[Image] Jshell ponúka aj možnosti na doplnenie, keď stlačíme tab. Ak do konzoly napíšem Sy a stlačím tab, tak mi ponúkne možnosti. Potom ak napíšem System. a stlačím tab, tak mám ďalšie možnosti vypísané. A tak ďalej.  [Image] Tu sa dostávame k tomu, že vieme používať klasické dostupné api. Ako napríklad String metódy. V konzole som napísal prázdny String bodku a stlačil tabulátor.  [Image] Ak niektoré triedy nie sú dostupné, tak ich vieme importnúť. Pri písaní vieme typu stlačíme Shift + Tab a potom písmeno i, ak chceme importnúť. Potom máme možnosť urobiť nič, alebo importnúť. [Image] Do shellu vieme písať aj shell špecifické prkazy. Stretli sme sa už s /list. Existujú aj ďalšie, napríklad /methods na výpis dostupných metód, /vars na výpis dostupných premenných, alebo /list –all na výpis všetkého aj importov aj chybne zadaných príkazov.  Všetko, čo sme napísali, úspešne si vieme uložiť do súboru pomocou príkazu /save nazovSuboru.txt. Tento súbor je uložený v priečinku bin, kde sme spustili jshell, ak nezadáme inak. Znovu vieme tento program otvoriť pomocou /open a názva súboru. Aj pri týchto príkazoch funguje dopĺňanie po stlačení tabulátoru.[Image] Je možné písať skratky príkazov, ak sú tie skratky unikátne. Jediný príkaz, ktorý začína na písmeno l je list, teda jemožné napísať /l. To isté platí aj pre príkazy pre /l ak dáme pomlčku a tab, tak dostanem možnosti. Príkaz, ktorý začína na a je len jeden tak môžem napísať /l –a namiesto /list –all.[Image] Tento príkaz som spustil nad čistou novou jshell, tak si môžeme pozrieť, čo je importnuté ako default.  Priblížili sme si základné možnosti nastavenia príkazového riadku JShell, je ich ale ďaleko viac. Ak máš záujem sa do tejto problematiky “zavŕtať” hlbšie, môžeš si pozrieť kompletný tutoriál. A napíš niečo do komentárov, poteším sa. Pýtaš sa “prečo Java”? Java je jeden z najpoužívanejších programovacích jazykov na svete. Ak sa o Javu zaujímaš (je jedno, či si začiatočník, alebo už programuješ), pripravili sme pre teba mnoho kurzov na https://skillmea.sk.
Ako sa nepredávkovať návodmi
Tipy a triky
10.02.2019
Lubo Herkoo

Ako sa nepredávkovať návodmi

Tak. Rozhodol si sa naučiť programovať (na Skillmea si správne!). Je jedno, či chceš byť Web Developer (FrontEnd, BackEnd), chceš sa vzdelávať v konkrétnom jazyku (PHP, JavaScript, Java, C#), alebo si sa ešte nerozhodol, a chceš sa len naučiť programovať. Aj keď kniha má svoje čaro, môžeš ju čítať aj elektronicky, s videom to však ide najrýchlejšie. Tvoji rodičia si pri pohľade na Teba možno myslia, že mrháš časom, Ty však vieš, že investuješ do seba. Správne! Nad kurzami môžeš stráviť dlhé hodiny. Niektoré z nich majú aj viac modulov. Každý má však aj svoj koniec. Zámer autora kurzu predsa nebol získať sledovanosť pre jeho videá, ale chcel ťa niečo naučiť. Možno si sa už ocitol v tom začarovanom kruhu, kedy po ukončení jedného kurzu hľadáš hneď ďalší, ktorý ťa posunie na vyššiu úroveň. A potom ďalší a ďalší.. Na vyššiu úroveň však už tutoriály a prepisovanie kódu z obrazovky nestačí. Ani jednoduché zadania lektorov z video kurzov nie sú postačujúce. Na vyššiu úroveň treba prax, treba tvoriť, pracovať na projektoch, vytvárať portfólio. [Ak sa chceš naozaj posunúť v programovaní vpred, pusti sa do zaujímavého projektu.] Portfólio programátoraV zaujímavom CV nemusí byť veľa projektov. Ten, kto ho bude čítať vie, či Tvoje portfólio obsahuje zaujímavé projekty, kde si sa stretol s nejakými výzvami. Pri absolvovaní kurzov si možno vytvoril jednoduchú aplikáciu na správu poznámok v Markdown formáte. Alebo sociálnu sieť, Twitter podľa tvojej chuti. Všetko sú to však projekty, ktoré každý pozná a vie, že nájdeš kopec zdrojov ako takúto aplikáciu napísať a tvorba takéhoto projektu bola len akýmsi light fitness pre tvoju hlavu. Najdôležitejšie na tom však je, že tie projekty nie sú tvoje. Tvoj projekt predsa začína prázdnym priečinkom, možno vytvorením index.html súboru, pokračuje nekonečným Google hľadaním riešení tvojich front-end alebo back-end problémov, implementáciami tvojich vylepšení, tvojich riešení, testov a refactoringu tvojho kódu. V repozitári vidieť, ako dlho si na projekte pracoval a ako sa projekt vyvíjal. [Pri práci na projektoch nestojíš na jednom mieste, ale tvoríš, učíš sa a rastieš.] Na čom teda začať makať?Každý programátor si dobré nápady na aplikácie chráni. Návšteva programátorského fóra s otázkou typu “Nemáte náhodou nápad na nejaký zaujímavý projekt?” bude skôr cieľom posmechu ako zdrojom nápadov pre tvoje projekty. Nezúfaj, mám pre Teba niekoľko rád ako svoj mozog nenechať oddychovať príliš dlho. Projekty som nevymyslel sám, väčšinou sú to projekty inšpirované existujúcimi aplikáciami, alebo všeobecne známe zadania. Pridal som k nim však aj odkazy na dokumentáciu, aby si netrávil čas hľadaním kde a ako začať. Niektoré projekty možno nekorešpondujú s tvojou ideovou predstavou a môžu byť menej zaujímavé, keď sa však rozhodneš na ňom pracovať získaš hneď niekoľko výhod: • Nestojíš na jednom mieste, ale tvoríš, učíš sa, rastieš, • stretávaš sa s problémami (ver mi, bude ich čím ďalej tým menej), na ktoré hľadáš riešenia, • objavuješ nové spôsoby riešenia problémov, tvoje staré riešenia už nestačia, alebo sú neefektívne. Level 1 - jednoduché projektyLunch picker • Takáto appka už existuje, ale urob vlastnú verziu. Podstata je, že vždy keď sa nevieš rozhodnúť, kam s kamošmi pôjdeš na pivo, nechaj to na výpočtovú silu. • Zadanie môže mať dve úrovne: Prvá úroveň je, že databázu miest na "zábavu" si vytvoríš sám a appka náhodne vyberie niektorú z nich. Druhá úroveň by bola, ak použiješ niektoré existujúce API (Google Reviews), ktoré ťa vie lokalizovať a databázu získaš odtiaľ. Collection tracker • Publikuj svoju zbierku "čohokoľvek" vo forme katalógu. Premysli štruktúru kažej položky, skús ich kategorizovať, implementovať vyhľadávanie. Jednoduchý projektík o niečom, čo ťa skutočne baví. • Zadanie môže mať dve úrovne: Prvá vo forme jednoduchej MVC aplikácie s Bootstrapom, napísaná v Laraveli alebo RubyOnRails. Väčší skiller si môže trúfnuť navrhnúť API a dizajn implementovať v niektorej JS library - VueJS, React.  Spoiler blocker pre clanky • Poznáš to - píšeš recenziu niektorého obľúbeného filmu alebo knihy a nechceš čitateľa tvojho textu nepríjemne prekvapiť vyzradením deja, alebo kľúčovej informácie. Podobne ako fungujú "Zobraziť viac" odkazy, môžeš takúto informáciu ukryť aj pod "Spoiler alert" odkaz. Spoiler v texte môžeš oddeliť pomocou data atribútu pre tvoj <p> element: <p data-spoiler="true">Spoiler text...</p>. • Zadanie môže mať dve úrovne: Prvá vo forme jednoduchého inline javascriptu, ktorý spustíš niekde na konci svojho textu pomocou <script> tagu. Druhá úroveň vo forme malej knižnice s využitím Module Pattern, ktorú môže použiť vo svojom Wordpresse ktokoľvek. Tax forecaster • Aj keď politici sa nás snažia presvedčiť, že si zaslúžime istoty, jedinou istotou v živote sú dane. Navrhni nejakú jednoduchú appku, ktorá bude zbierať sumy tvojich freelance faktúr na základe vzorca, ktorý zistíš online (a naučíš sa pritom aj prečo platíš toľko na daniach). • Zadanie môže mať dve úrovne: Prvá úroveň je samotný jednoduchý výpočet - zadáš číslo a dostaneš hodnotu, ktorú zaplatíš štátu. Druhou úrovňou môže byť databáza s históriou tvojich FA a implementácia grafov, kde môžeš s pomocou knižnice D3.js vykresliť pekné reporty, koľko si zarobil a ako sa tvoj zárobok vyvíjal. Ak ťa vystrašila dokumentácia D3.js, môžeš sa skúsiť pohrabať v knižniciach, ktoré používanie D3js zjednodušujú. FlashCard generator • Ak si v štádiu učenia sa (čo by si mal byť neustále) a snažíš sa zapamätať si niektoré dôležité informácie, koncepty alebo čokoľvek, osvedčená technika pamätania si vecí sú FlashCards. Navrhni appku, ktorá si z databázy, alebo JSON objektu vyberie pole dvojíc, kde prvým prvkom dvojice bude nejaký stručný popis a druhým prvkom bude informácia, ktorú si máš zapamätať. Tu je inšpirácia. • Zadanie môže mať dve úrovne: Prvou je implementácia, akú použili v ThoughtBot - teda informácia, ktorú sa snažíš naučiť sa len objaví pod heslom. Druhou úrovňou môže byť využitie CSS na zaujímavú animáciu, aby to vizuálne vypadalo ako ozajstné "otočenie karty". Level 2 - stredne náročné projektyBring your umbrella • Ak nestíhaš ráno sledovať počasie, automatizuj to. Napíš appku (najviac sa asi hodí mobilná appka, ale užitočná môže byť aj webová aplikácia), ktorá ťa lokalizuje a s využitím API ti pripomenie, aby si si nezabudol zobrať zo sebou dáždnik - v okolí tvojej lokality bude totiž pršať. Webová appka ti môže poslať e-mail notifikáciu. • Zadanie môže mať dve úrovne: Prvou môže byť aplikácia bez grafického rozhrania. Druhou môže byť plnohodnotná weather appka prispôsobená tvojim potrebám a grafickým nárokom. Music suggestion app • Spotify má tiež svoje API. To môžeš použiť na vytvorenie zoznamu skladieb, ktorý budeš tvoriť na základe počúvaných skladieb, ich žánru a iných dostupných dát. Takto získaš dáta o skladbe, ktorú používateľ práve počúva. Tu je dokumentácia, ako pracovať s playlistom. Expense tracker • Vo forme mobilnej appky alebo webovej aplikácie môžeš vytvoriť aj svoj tracker príjmov a výdavkov. Ich kategorizácia a kreslenie grafov by malo byť samozrejmosťou. Ak sa ti podarí vyriešiť problém manuálneho zadávania bločkov, daj mi vedieť - do takej aplikácie rád zainvestujem. V Datamolino už vedia ako na to. • Najväčšou challenge pri tomto projekte je asi UI/UX - aplikácia by sa mohla učiť moje zvyky a inteligentne mi podsúvať dáta (kategorizáciu, tagy) podľa histórie mojich nákupov pri vytváraní jednotlivých položiek. Na základe týchto tagov a kategórií mi oznámiť, kde by som mohol nabudúce ušetriť.  Downtime tracker • Ak máš obľúbený web, alebo plánuješ niekoľko svojich projektov, môžeš testovať, či náhodou tvoje aplikácie nemajú nejaký problém. Jednoduchým scriptom pristúpiš na URL svojej aplikácie a ak skript nevráti HTTP Response 200, tak ťa tracker notifikuje emailom, že sa niečo deje. • Zadanie môže mať dve úrovne: Prvou úrovňou môže byť notifikácia emailom. Druhou úrovňou môže byť notifikácia pomocou SMS brány (Twilio), alebo web hook do tvojho Slacku - ak používaš slack. Level 3 - náročnejšie projektySlack bot • Ak poznáš Slack a inšpiruje ťa automatizácia, programovanie botov je teraz in. Niektoré vývojárske tímy denne absolvujú "standup" - odpovedia na jednoduché otázky týkajúce sa aktuálneho projektu/zadania (na čom pracujú, v akom sú štádiu, či sa na niečom zdržali a podobne). S pomocou Slack API môžeš vytvoriť jednoduchého bota, ktorý kontaktuje vývojárov z tvojho teamu a opýta sa ich zopár otázok. Ich odpovede môžeš zozbierať a vyhodnotiť v jednej správe, ktorú odošleš do #dev kanála.  Microlearning app • Denne by si mal venovať nejaký čas svojmu vzdelávaniu - aby si ako programátor rástol. Ak sa účíš napríklad React, alebo VueJS - môžeš skúsiť použiť (alebo napísať vlastný) web scrapper a získať tak jednotlivé sekcie dokumentácie. Denne ti tvoja microlearning aplikácia môže poslať jednu sekciu/stránku z tejto dokumentácie e-mailom na štúdium. Web scraper • Nájdi svoj obľúbený e-shop a skús vytvoriť vlastnú databázu jeho produktov, kategórií spolu s obrázkami. Web scraping je zaujímavou a nie jednoduchou témou pre programátorov, pretože ku každému webu, ktorý chceme scrapovať musíme pristupovať individuálne. • Hint: Pred tým, ako sa pustíš do scrapovania niektorej domény, skontroluj v nazov-domeny.sk/robots.txt, či náhodou doména nemá blokovaných niektorých botov. Quiz Maker • Ak sa nudíš, môžeš prispieť aj k efektivite nášho školstva. Keď som učil ja, učitelia používali Hot Potatoes ako ich testovaciu platformu. Alebo vytlačené testy s kolonkami. Vstupom do tvojej quiz platformy môže byť JSON, ktorý bude obsahovať vhodne zvolenú štruktúru testovacích otázok, možných odpovedí a označenia správnej odpovede. • Zadanie môže mať tri úrovne: Prvou môže byť vygenerovanie testu z holého .json súboru. Druhou môže byť vytvorenie adminstračného rozhrania, kde si testujúci otázky a možné odpovede vykliká vo formulári. Treťou úrovňou môže byť implementácia rôzneho typu testovacej otázky (jedna správna odpoveď, viac správnych odpovedí, dopísanie správnej odpovede, zoradenie do správneho poradia, vytvorenie správnych párov, ...) Browser extension • Naštuduj si ako pracujú browser pluginy a zvýš svoju produktivitu blogovaním distraktorov. Inšpiráciou ti môže byť BlockSite - výborný extension na blokovanie stránok. • Blokovanie stránok však nemusí byť jediný tip na doplnok do prehliadača. Doplnky sú fajn na zvýšenie produktivity, teda rôzne poznámkové doplnky, časovače (pomodoro), vytvorenie snímky z aktuálnej stránky a všeličo možné. Programátorské výzvy - algoritmické úlohyAk nehľadáš nápad na projekt, ale radšej by si sa zdokonalil v riešení algoritmických úloh, mám tu niečo aj pre Teba: 1. Advent of code • Adventný kalendár programátora (každý rok obsahuje nové zadania). Obsahuje 25 zadaní orientovaných na precvičovanie algoritmického myslenia. Ideálne na raňajšie prebudenie mozgu, niektoré úlohy však môžu zabrať viac času. Súčasťou je aj leaderboard, tam sa ja radšej ale nepozerám. • Zadania môžeš riešiť v ktoromkoľvek jazyku 2. Project Euler • Podobne ako Advent of Code, aj toto je zbierka zadaní, ktoré sú však už len archívom. To však neznamená, že neobsahuje dostatok zadaní - je ich tam takmer 650. Pri každom zadaní je uvedený aj počet ľudí, ktorí zadanie vyriešili. • Zadania môžeš riešiť v ktoromkoľvek jazyku 3. Daily Coding Problem • Toto je mailinglist, ktorý ti každý deň pošle jeden programátorský problém, ktorý môžeš rozlúsknuť. Problémy z tejto banky pochádzajú z pracovných pohovorov vo firmách, ako sú Google, AirBnB, Facebook, Apple a rôzne iné. Ich obtiažnosť je preto niekedy dosť vysoká. Ak sa ale pripravuješ na pracovný pohovor, tieto úlohy ti môžu pomôcť. • Nevýhodou je, že k riešeniam sa dostaneš až ak si ich predplatíš. Aby sme to zhrnuli. Hodnota každého programátora sa ukrýva v jeho portfóliu. Sú to práve tvoje vlastné projekty, ktoré ťa budú reprezentovať na pohovore, ktoré ťa odlíšia od konkurencie. V článku sme ti poskytli tipy na zaujímavé projekty, ktoré obohatia tvoje CV, ale predovšetkým posunú ťa ďalej, postavia pred nové výzvy a prekážky. A to ako dobrý programátor určite potrebuješ.
Java persistence – JPA, Hibernate, ORM
Tipy a triky
05.02.2019
Skillmea

Java persistence – JPA, Hibernate, ORM

JPA je java persistence api špecifikácia. Na to, aby si mohol používať JPA v skutočnej aplikácii, potrebuješ implementáciu JPA. Buď použiješ servery, ktoré už ponúkajú implementáciu JPA, ako napríklad GlassFish, alebo použiješ implementáciu, ktorú ti poskytuje framework Hibernate alebo EclipseLink. Ak používame JPA štandardy, tak je v budúcnosti úplne jedno, akú implementáciu JPA budeme používať. Pri programovaní budeme používať JPA anotácie, ktoré pochádzajú z balíka javax.persistence. V budúcnosti môžeš nasadiť aplikáciu na GlassFish, ktorý pozná javax.persistence a vie s tým pracovať alebo na Tomcat s použitím Hibernate, ktorý tiež pozná javax.persistence a vie s tým pracovať.  Čo je Persistence?Ak vytvoríš hocijaký jednoduchý objekt, čo sa stane? Napríklad objekt Adresa? Vytvorí sa v halde – v pamäti. Objekt môže mať nasetované nejaké dáta – informácie. Ak sa ale stratí referencia v javovskom kóde na tento objekt v halde – tak sa zmaže.  Ak si chceme uchovať tieto informácie, tak ich môžeme uložiť do databázy a najlepšie, aby po vytiahnutí z databázy mali tieto dáta tú istú formu – teda formu objektu Adresa.  Tomuto sa hovorí, že persistujeme (uchováme stálosť) objekt do databázy. Akoby tento objekt existoval aj mimo java programu. Tento objekt sa uchová v úložisku a znovu sa vytvorí, ak bude treba.  Čo je ORM?Klasické databázy ako Oracle, MySql a podobne sú relačné databázy, ktoré majú dáta uložené vo forme tabuliek. V jave ukladáme dáta vo forme objektov, v databáze vo forme tabuliek. Ale čo majú podobné? V relačnej databáze máme stĺpce, ktoré majú názvy a v riadkoch máme hodnoty. Niečo ako klúč hodnota – to isté platí aj pre objekty v jave – tam máme názov premennej a hodnotu v nej uloženú.  Tu prichádza pod ruku ORM – teda object relational mapping. Je to niečo ako objektovo relačné mapovanie. My naše java objekty namapujeme na tabuľky relačnej databázy. Aby sme vedeli, že tento field v javovskom objekte patrí do tohto stĺpca.   Objekty v jave sú medzi sebou prepojené pomocou uloženia referencie na daný objekt. Napríklad človek má field Adresa, kde je uložená referencia na objekt Adresa.  Relačné tabuľky majú medzi sebou tiež väzby. Buď máme v tabuľke pre človeka stĺpec adresa, kde bude uložený identifikátor adresy a na základe tohto identifikátora nájdeme danú adresu. Alebo existuje špeciálna tabuľka, kde budú dva stĺpce jeden pre identifikátor adresy a druhý pre identifikátor človeka. My potom vieme nájsť, aké adresy má človek nastavené, alebo pre akého človeka je nastavená daná adresa.[Image] Problém s JDBC prístupom – výhoda ORMV kurze Java pre pokročilých, ak si tento kurz videl, sme si ukazovali prístup k databáze cez JDBC. Čo sme spravili? Otvorili sme konekciu na databázu, napísali sme sql príkaz, ktorý sme následne poslali do databázy na vykonanie. Databáza nám vrátila výsledok vo forme result setu.  Predstav si, že máš len 5 až 10 tabuliek. Nad každou tabuľkou máš napríklad 4 rôzne sql príkazy – to máme približne 20 – 40 sql príkazov. Ak sa ti stane, že musíš zmeniť databázu – napríklad zmeníš názov stĺpca v tabuľke? Čo musíš spraviť? Musíš prepísať názov tohto stĺpcu na xy miestach – na 20 až 40 miestach – a to sme len v malej aplikácii – čo ak by to bolo na 100 miestach?.  Bol by v tom neporiadok a mohli by nastať problémy.  Ak ale použijeme ORM, tak v jave pracujeme s naším kódom, tak ako bežne. Vytvoríme si objekty typu Clovek, nastavíme mu nejaké hodnoty. Ďalej si vytvoríme kolekciu Adries pre daného človeka. Nakoniec v ORM frameworku povieme len persistni mi tento objekt. ORM sa potom postará o všetko uloženie týchto objektov do databázy na základe mapovania, ktoré mu poskytneme.  Clovek clovek = new Clovek(); clovek.setMeno("Jaro"); clovek.setPriezvisko("Beno"); Adresa adresa1 = new Adresa(); adresa1.setUlica("Nejaka 5"); adresa1.setPSC("94404"); Adresa adresa2 = new Adresa(); adresa2 = new Adresa(); adresa2.setUlica("Nejaka 5"); adresa2.setPSC("94404"); List<Adresa> adresaList = Arrays.asList(adresa1, adresa2); clovek.setAdresaList(adresaList); orm.persist(clovek); Ak by sme nepoužili ORM, sami by sme museli napísať metódu, ktorá nám otvorí konekciu na databázu, museli by sme napísať INSERT SQL príkaz pre človeka a potom aj pre jeho adresy a museli by sme zabezpečiť, aby sme nastavili všade dáta tam kde majú byť a musíme sa postarať aj o prepojenia medzi týmito dvoma objektami.  Ak ale použijeme ORM, tak sa nemusíme starať o tento balast kódu, ale sústrediť sa najmä na to, čo predáva a to je business logika aplikácie.  Nevýhody JDBC prístupu sú teda, že máme príliš veľa SQL príkazov, veľmi veľa kópie kódu, ručne sa musíme postarať o nastavenie dát do správnych stĺpcov.  Výhodou ORM je, že nemusíme robiť tieto veci z predchádzajúcej vety. ORM nám umožní používať java objekty na reprezentáciu relačnej databázy. ORM sa nám postará aj o prepojenie závislostí. ORM spojí výhody relačnej databázy a objektového modelu v jave plus schová všetku komplexitu SQL príkazov.  Čo je Hibernate? Hibernate je ORM – object relational mapping framework, ktorý slúži na mapovanie java objektov na tabuľky relačných databáz.  Java programátori sú zvyknutí písať kód v objektoch, prečo teda potrebujú ďalší jazyk – sql – na získanie dát z databázy? Hibernate na pozadí sám vytvára sql príkazy nad databázou a preto nemusíme písať sql príkazy my.  Ak chceme uložiť mapu objektov, napríklad Cloveka, ktorý ma Adresu, alebo aj viac objektov typu Adries, tak nemusíme písať všetky sql príkazy. Stačí, ak zavoláme jednoduchú metódu na uloženie objektu do databázy a hibernate sa postará o zvyšok.  Hibernate je aj implementácia JPA. [Image] Čo je JPA?Skratka JPA je Java Persistence API. Čo to znamená? V jednoduchosti povedané – je to štandard. Trošku zložitejšie povedané – je to špecifikácia pre OR mapovanie a je súčasťou Java EE, ale môžeme ju používať aj v Java SE projektoch.  Niektoré servery poskytujú vlastnú implementáciu JPA a niektoré nie – v tom prípade použijeme napríklad Hibernate implementáciu.  Predstav si, že celý tvoj kód používa veci z JPA. Teraz je na tebe, kam nasadíš svoju aplikáciu. Ak ju nasadíš na Glassfish nemusíš prerábať svoj kód, ktorý používa JPA – Glassfish ho pozná. Ak svoju aplikáciu nasadíš na Tomcat, tak mu prihodíš Hibernate, ktorý tiež pozná JPA. Potom tvoj kód bude fungovať všade – lebo používa štandardy JPA.  Je možné aby sme používali len Hibernate – teda by sme nepoužívali nič zo štandardov. Žiadne anotácie z javax.persistence a podobne – to ale neodporúčam.  Pýtal som saNapadlo mi, že by nebolo od veci spýtať sa kolegov developerov, čo si myslia o JPA a Hibernate. Ak by si si chcel prečítať ich názory, nech sa páči – bez cenzúry, citujem:  Tak toto je náročná téma a navyše zložitá.  JPA resp. ORM všeobecne (a teda aj Hibernate) sú vždy zložitejšie, než si používatelia (t.j. vývojári) uvedomujú. Výsledkom sú často nenápadné chybičky, lazy load exceptions, ktoré vedú k anti-patternom ako je OSIV (open session in view) alebo k výkonovým problémom (n+1 problem).  Týchto problémov je typicky o to viacej, o čo zložitejšie je mapovanie – a pritom práve na riešenie zložitého mapovania bolo ORM vymyslené. Aby sme mohli namapovať doménu do DB. Na to, sa často používajú aj “mimojazykové” triky ako reflection na private polia, takže objekty sú implicitne zviazané s ORM riešením, aj keď napr. mapovanie je oddelené do XML namiesto anotácii, čo samo o sebe je tiež nepraktické.  Okrem toho majú obe hlavne implementácie dosť bugov na to, aby na ne človek narazil, aj keď postupuje v súlade so špecifikáciou – stačí len chcieť trosku viacej a na nejaký bug určite narazíte. Takže potom to je kľučkovanie medzi bugmi a často komplikovaná možnosť vymeniť ORM providera.  Čo sa mi na ORM páči je lepšie mapovanie typov, možnosť customizovať mapovanie a podobne. Preto používam JPA aj na jednoduché mapovačky namiesto JDBC.  Navyše s JPA používam rad Querydsl, ktoré je lepšie/intuitívnejšie, než JPA štandardné Criteria API.  Hibernate používam dlho ale pravdu povediac nikdy som sa veľmi nezamýšľal nad výhodami. Zatiaľ som nemal výraznejší problém, ktorý by som nevedel vyriešiť, prípadne nejako obísť.  Plusy:  - ľahko sa robí mapovanie do DB s anotáciami aj pre začiatočníka bez veľkých znalostí databázy, zároveň ale bez znalosti DB môže byť mapovanie neefektívne  - je open source, takže ak potrebujem, viem pozrieť zdrojáky ako funguje  Mínus:  - asociácia OneToOne fetch=lazy nefunguje  Na používaní Hibernate/JPA (celkovo ORM vrstve) sa mi páči:  A) Abstrakcia od fyzického dátového modelu. Vývoj nad doménovým/logickým (entitno-relačným dátovým modelom) - bližšie k biznis vrstve. Čiže zjednodušené práca s objektami namiesto tabuliek.  B) Možnosť využívať rôzne pokročilejšie techniky získavania dát (napr. Spring Data JPA, ale aj zjednodušujúce Hibernate Query by example)  C) Agnostické od konkrétnej databázovej technológie (Oracle, MySql, ...)  D) Cachovanie a optimalizácia (napr. lazy loading)     Nevýhody:  A) Niekedy náročný (až nemožný) performance tuning.  B) Pri niektorých technológiách pomalšia krivka učenia.  C) Aj napriek používaniu JPA/Hibernate, je takmer nevyhnutné, aby developer poznal aj (native) SQL jazyk a jeho použitie.  ZáverPodarilo sa ti nazrieť do problematiky objektovo relačného prístupu k databáze a pochopil si, čo to znamená. Ak sa však chceš dostať ešte o level ďalej, pripravili sme pre teba samostatný kurz Java persistence – JPA a Hibernate. Ak chceš ešte viac, tak klikaj:👍 Viac o mne: http://www.jaroslavbeno.sk/  👍 Kurzy (java, git, maven, bootstrap, Asp .Net,): Learn2Code moje kurzy 👍 Free kurzy: YouTube kanál JaroslavBeno
Manuálne vs. automatizované testovanie
Tipy a triky
25.01.2019
Skillmea

Manuálne vs. automatizované testovanie

Rád si v detstve všetko rozoberal, špekuloval a škodoradosť hrala v divadle tvojich ranných emócií prím? Si tu správne. Pretože presne to sú hlavné črty testera. Len opatrne s tou škodoradosťou 😉 Manuálne testovanie nie je hanba!Neexistuje nič horšie, ako robiť stále to isté dookola. Našťastie, o tom manuálne testovanie nie je. Ale pekne postupne. Nepoznám krajší pocit v práci (okrem piatkového fajrontu) ako keď ja, človek, ktorý študoval dojivosť kráv a hektárový výnos pšenice, nachytá programátora s nejakou chybou. Manuálne testovanie znamená zobrať novú časť aplikácie, usúdiť či zodpovedá tomu, čo si zákazník želal a popri tom nachytať programátorov. Pri testovaní postupuj rovnako ako pri boji s mafiou. Najskôr ideš po veľkých rybách - chybách, ktoré spravia najviac škody, malé si nevšímaš alebo ich preskočíš, pretože nie je čas. Nech narobíš programátorom dosť roboty. Potom ideš po tých menších, dizajnových vychytávkach, pretože majú rovnakú váhu ako predvčerajšia instastory každej druhej makeup artistky . Vymýšľaš, čo si ešte nevymyslel a ideš po chodníčkoch aplikácie, kadiaľ by sa normálny používateľ nikdy nevydal. Ale Jožo Pročko hovoril 20 rokov dozadu, že nikdy nehovor nikdy. Ako tester to nehovor ani ty. Rozum maká zozačiatku viac ako ruky, a to je fajn. Fajn to byť prestane, keď sa karta obráti a nedajboh, aby si musel dvakrát robiť to isté. Alebo 3-krát. Alebo 4-krát. Alebo furt. Si odsúdený na večnosť regresne testovať celú aplikáciu. Pretože ak sa zmení kód, je potrebné to celé preklikať. A v tento moment mozog vypínaš a pracujú len ruky. Spomínaš si, keď ti ako malému povedali, že ak sa nebudeš učiť, budeš kopať kanále? Toto je to isté, akurát sedíš v bizniscentre s ďalšími korporátnymi kopačmi. Našťastie tú robotu môžeš prenechať počítaču, pretože na rad prichádza... Automatizované testovanie je programovanie!Nechaj zase mozog makať a ruky oddychovať. Automatizované testovanie je o tom, že ty naprogramuješ robota, aby chodil po určitej dráhe, cestičke v aplikácii a on to bude robiť vždy, keď mu prikážeš. Nepredstavuj si robota ako terminátora, ktorý za teba sedí v kancli. A ani takto to nevyzerá:[Image] Ty vidíš, že stránka sa otvorí, ale kliká po nej robot na pozadí, ktorého NIEKTO naprogramoval. A tým niekým si TY. Si programátor so všetkou tou pompou a slávou, píšeš kód napr. v JAVA a vyvíjaš si vlastnú aplikáciu, logiku, ktorá testuje softvér namiesto teba. Zo začiatku je to trošku ťažkopádne ako štartovanie V3S-ky, ale keď tú mašinu raz rozbehneš, práca ti neúmerne až zázračne klesá. A o tom je automatizované testovanie. Robotu, ktorá sa tebe nechce nenecháš na kolegu, ktorý sa vrátil z dovolenky. Ani ju nenaučíš masturbovať, aby sa spravila sama. (cit. Vtipnejší vyhráva 09/1994) Ale prenecháš ju počítaču. A on sa nepomýli, nevynadá ti, nezoberie sa o 16:00 domov a neochorie, keď polovica kancelárie zalieva zázvor vriacou vodou. Nevýhodou však je, že počítač vidí len toľko, koľko ho ty naučíš. Nie je inteligentný a nevidí veci v súvislostiach. Nevie si niečo všimnúť. Povieš mu slová František a Lászlo a on sa nezasmeje. Ani ty sa dúfam nesmeješ. A ešte si dávaj pozor, ako píšeš kód, aby si ho nemusel po sebe 30x opravovať, ak sa na stránke niečo zmení. Pretože to je tiež bolesť, neustále dohľadávať chyby v testoch. Poďme si porovnať manuál a automat. Výhody, nevýhody, kedy ktoré použiť.Manuálne testovanie+ hľadanie nových chýb v aplikácii, exploratory testing + objavenie dizajnových prešľapov + rýchla odpoveď na stav softvéru + improvizácia - nákladné - nevhodné na regresné testovanie - časovo náročné - nespoľahlivé (časový stres, prehliadneš chyby) - ako aplikácia rastie, rastú aj náklady na manuálne testovanie Automatizované testovanie+ regresné testovanie (pred vydaním do produkcie, po každej zmene) + rýchle + spoľahlivé + práca ti postupne ubúda - vyššie vstupné náklady (kým spustíš prvý test) - robot nové chyby nenájde - musíš vedieť programovať - údržba ZáverManuálne testovanie nemôže byť nahradené automatizovaným. Ak si manuálny tester, kľudne si vydýchni. A vydýchni si znovu, pretože ťa viem odbremeniť od tortúry, ktorú ti spôsobuje testovanie po každej jednej zmene. Naučím ťa programovať robota. Základy programovania a automatizovaného testovania ťa naučím v kurze s Batmanom: http://bit.ly/batmanKurz Ako písať efektívny kód, vedieť si postaviť Maven projekt, rozbehať jenkins, to ťa naučím v tomto kurze: http://bit.ly/jokerKurz A ako ten kód pekne zabaliť do jagavého pozlátka, aby mu každý rozumel ťa naučím v kurze s uhorkou: http://bit.ly/cucumberKurz Autorom blogu je Martin "Furby" Škarbala. Keď ťa zaujíma oblasť testovania softvéru, určite daj lajk na jeho Facebook stránku.
Čísla a znaky v Jave
Tipy a triky
28.10.2018
Skillmea

Čísla a znaky v Jave

V tomto článku sa spolu pozrieme na základy práce s číslami a znakmi v programovacom jazyku Java.  Čísla[Image] Prečo používať Numbers a nie primitívne dátové typy? Ak nejaká metóda príjma ako parameter Object, tak jej neviem podsunúť primitívny dátový typ. Môžeš použiť konštanty, ako napríklad MIN_VALUE alebo MAX_VALUE. Môžeme používať metódy na konverziu do a z primitívnych dátových typov ako aj zo String.  Byte b = 127; Byte b2 = 128; //error Byte len do 127Pre všetky typy máme metódy, ktoré z textu vedia vyloviť daný typ. Tu si treba dať pozor, lebo ak chcem zo Stringu dostať Integer – ale zadám tam text, tak to bude chyba. String decimal = "2.5"; double d1 = Double.parseDouble(decimal); decimal = "2.5a"; double d; d = Double.parseDouble(decimal); //chyba Keď hovoríme o číslach, tak nemôžme nespomenúť modulo. Plus, mínus poznáme, ale modulo by nám mohlo robiť problém. private static void modulo() { for(int i = 0; i < 32; i++){ rozdajHracoviKartu(i%4,i); } } private static void rozdajHracoviKartu(int hrac, int karta) { System.out.println("rozdavam hracovi "+hrac+", kartu cislo "+karta); }V tomto príklade výsledok modula nebude nikdy viac ako 3 a menej ako 0. Teda sa karty rozdajú medzi všetkých hráčov v hre. Skús si to pomeniť sám.  Matematické operácie Pre veľa matematických operácií máme triedu Math, ktorá obsahuje množstvo statických metód. Názvy sú samo vysvetľujúce, alebo si pozri nižšie komentáre: System.out.println("a "+a+" abs "+ Math.abs(a)); //absolútna hodnota System.out.println("b "+b+" ceil "+Math.ceil(b)); //zaokrúhli nahor System.out.println("b "+b+" floor "+Math.floor(b)); //zaokrúhli nadol System.out.println("b "+b+" rint "+Math.rint(b)); //klasicke zaokruhovanie zmen b ... vracia double hodnotu intu System.out.println("b "+b+" round "+Math.round(b)); //klasicke zaokruhovanie zmen b ... vracia int alebo long ... int round(float f) System.out.println("c "+c+" a d "+d+" max "+Math.max(c, d)); System.out.println("c "+c+" a d "+d+" min "+Math.min(c, d)); Náhodné číslo V Math triede máme metódu random. Vracia hodnotu od 0.0 po 1.0 . Krátením vieš zvätsit a musíš pretypovať na int ak chceš celé čísla. private static void randomNumbers() { int number = (int)(Math.random() * 100); System.out.println(number); }ZnakyPrimitívny dátový typ char sa používa na uchovanie jedného znaku. Pri char máme tak isto možnosť použiť jeho alternatívu objektovú a to Character V jave existujú escape sekvencie. To sú znaky, teda char, pred ktorým je spätné lomítko. Tieto sekvencie majú pre kompilátor zvláštny zmysel. Neberú sa ako nejaký jednoduchý text.  \t    -  vloží tab  \b   -   vloží backspace  \n   -   vloží nový riadok  \r    -   vloží carriage return  \f    -   vloží formfeed  \'    -    vloží jednu uvodzovku  \"    -   vloží dvojitú uvodzovku  \\    -   vloží spätné lomítko  Máme množstvo pomocných metód: Character ch3 = 'a'; System.out.println("char "+ch); System.out.println("isLetter "+Character.isLetter(ch)); System.out.println("isDigit "+Character.isDigit(ch)); System.out.println("isWhitespace "+Character.isWhitespace(ch)); System.out.println("isUpperCase "+Character.isUpperCase(ch)); System.out.println("isLowerCase "+Character.isLowerCase(ch)); System.out.println("toUpperCase "+Character.toUpperCase(ch)); System.out.println("toLowerCase "+Character.toLowerCase(ch)); System.out.println("toString "+Character.toString(ch));Takýmto spôsobom vieš vložiť aj špeciálne znaky z hora:System.out.println("Some \t nice text. tab"); System.out.println("Some \t\b nice text. backspace"); System.out.println("Some \n nice text. new line"); // je to niečo ako na starom písacom stroji kedy si sa presunul na začiatok riadku //ak nedáš ale nový riadok, tak ti prepíše to čo tam už máš napísané System.out.println("Some \r nice text. carriage return"); System.out.println("Some \r\n nice text. carriage return a new line"); System.out.println("Some \' nice text. "); Ak chceš zadať špeciálnu hodnotu, tak musíš zadať pred daný špeciálny znak lomítko. char uvodzovka = '''; //error char uvodzovka = '\''; System.out.println("Some " nice text."); //error System.out.println("Some \" nice text."); System.out.println("Some \ nice text."); //error System.out.println("Some \\ nice text.");ZáverAk ťa zaujíma Java, tak si tu na https://skillmea.sk pohľadaj kurzy, ktoré sa venujú programovaniu v Jave a nauč sa viac. Ja som Jaro a dúfam sa vidíme pri ďalšom článku alebo videu.
Websockety - message board
Tipy a triky
04.10.2018
Miroslav Beka

Websockety - message board

Ahoj, naposledy sme hovorili o websocketoch vo flasku. Používali sme knižnicu flask-socketio a prešli sme si základnú funkcionalitu. Táto knižnica používa koncept miestností alebo rooms, ktorý slúži na to, aby sme vedeli adresovať klientov v nejakých skupinách. Tento koncept sa používa v chatových aplikáciách, kde používatelia vidia správy len v miestnosti, v ktorej sa nachádzajú. Nedostanú správy zo žiadnej inej. Pozrieme sa teda na tento koncept a aby sme spravili aj nejaký reálny príklad, spravíme vlastnú chatovaciu appku. Používatelia sa budú môcť pridať do existujúcej miestnosti, chatovať s ostatnými, vytvárať nové miestnosti a podobne. Bude to veľmi jednoduchý message board.[Image] Základ projektuZačne tým, že si vytvoríme virtualenv! Bez toho sa ani nepohneme. $ mkdir websockets_message_board $ cd websockets_message_board $ virtualenv venv $ . venv/bin/activateInštalujeme závislosti. Budeme používať to isté, čo v predchádzajúcom článku (venv)$ pip install flask, flask-socketioIdeme na boilerplate pre našu appku. Štruktúra vyzerá asi takto: ▾ websockets_message_board/ ▾ static/ ▾ css/ main.css ▾ js/ main.js ▾ templates/ board.jinja ▸ venv/ server.pySúbory main.css a main.js sú zatiaľ prázdne, slúžia len ako placeholder. Pokračujeme teda so súborom server.py a ideme ho naplniť kódom. from flask import Flask from flask import render_template from flask import redirect from flask import url_for from flask_socketio import SocketIO app = Flask(__name__) app.config['SECRET_KEY'] = '\xfe\x060|\xfb\xf3\xe9F\x0c\x93\x95\xc4\xbfJ\x12gu\xf1\x0cP\xd8\n\xd5' socketio = SocketIO(app) ### WEB CONTROLLER @app.route("/") def index(): return redirect(url_for("view_board")) @app.route("/board/") def view_board(): return render_template("board.jinja") if __name__ == '__main__': socketio.run(app, debug=True)Rozdiel oproti minimálnej flask appke je ten, že ju inak spúšťame. Nepoužijeme if __name__ == '__main__': app.run()ale budeme ju spúšťať cez socketIO. if __name__ == '__main__': socketio.run(app, debug=True)To preto, aby aplikácia vedela spustiť viacero vlákien pre každého používateľa. Tak isto je dobré vedieť, že deployment na produkčný server takejto aplikácie je trošku komplikovanejší ako keď máme klasickú flask appku. Obsah základného templejtu board.jinja (aj jediného, ktorý budeme používať) je nasledovný: <!DOCTYPE HTML> <html> <head> <title>Short Term Memory Message Board</title> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script> <script type="text/javascript" src="{{ url_for("static", filename="js/main.js")}}"></script> <link rel="stylesheet" type="text/css" href={{url_for("static", filename="css/main.css")}}> </head> <body> Hello </body> </html>máme tam zopár dôležitých importov ako socket.io, jquery a tak isto aj css a js súbory našej appky. Takýto jednoduchý základ môžeme spustiť a uvidíme, či všetko šlape ako má $(venv) python server.py WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance. * Serving Flask app "server" (lazy loading) * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance. * Debugger is active! * Debugger PIN: 112-998-522FaceliftTento krok nie je vôbec potrebný, ale keďže všetci majú radi pekné veci, nainštalujeme si css framework zvaný semantic-ui. Je to fajn framework, mám s ním dobré skúsenosti. Dokumentácia je možno trošku tažšia na pochopenie, ale okrem toho to funguje a hlavne vyzerá veľmi pekne. [Image] Stačí stiahnuť toto zipko a integrovať do svojho projektu. Je to veľmi jednoduché. Zip rozbalíme a prekopírujeme nasledovné súbory • themes -> websockets_message_board/static/css/ • semantic.min.css -> websockets_message_board/static/css/ • semantic.min.js -> websockets_message_board/static/js/ Súbory semantic.min.js a semantic.min.css musím includnuť na svoju stránku, takže bežím do board.jinja a prihodím do hlavičky ďalšie riadky: <head> <title>Short Term Memory Message Board</title> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script> <script type="text/javascript" src="{{ url_for("static", filename="js/semantic.min.js")}}"></script> <script type="text/javascript" src="{{ url_for("static", filename="js/main.js")}}"></script> <link rel="stylesheet" type="text/css" href={{url_for("static", filename="css/semantic.min.css")}}> <link rel="stylesheet" type="text/css" href={{url_for("static", filename="css/main.css")}}> </head>Je dôležité dať si pozor, aby sme najprv pridali jquery a až potom semantic.min.js, inak sa mi semantic-ui bude sťažovať, že nevie nájsť jquery knižnicu. V priečinku themes sú hlavne ikony a nejaké obrázky, ktoré semantic-uiposkytuje. Po inštalácií css frameworku môžem hneď vidieť zmenu v podobe iného fontu na mojej smutnej stránke. Nič iné tam ešte nieje. UISpravíme teraz približný náčrt UI, aby som vedel, ako appka asi bude vyzerať a aké funkcie jej vlastne spravíme. Nebude to nič svetoborné. Budeme mať jednu stránku ktorú rozdelím na 3 sekcie. Hlavná bude obsahovať správy, takže to bude môj message board. Bočný panel bude obsahovať zoznam miestností, do ktorých sa budem vedieť prepínať. No a na spodnej lište bude input pre moju správu.[Image] Zhmotním túto svoju predstavu do kódu. Otvorím board.jinja a nahádžem tam nejaké <div> elementy. Keďže používame semnatic-ui ako náš css framework, budem rovno používať triedy v html. Použijeme grid systém, ktorý nám zjednoduší prácu pri ukladaní ui elementov. <body class="ui container"> <div class="ui grid"> <div class="ten wide column"> message board </div> {# end ten wide column #} <div class="six wide column"> rooms </div> {# end six wide column #} </div> {# end grid #} <footer> text input </footer> </body>Môžem skúsiť naplniť tieto časti aj nejakým obsahom. Len tak zo zvedavosti, ako to bude vyzerať. Všetko bude zatiaľ len tak naoko (prototypovanie). Začneme tým najhlavnejším: message boardom <div class="ten wide column"> <h1 id="room_heading" class="ui header">Johny @ Music room</h1> <div id="msg_board"> <div class="ui mini icon message"> <i class="comment icon"></i> <div class="content"> <div class="header">Johny</div> <p>Hello there</p> </div> </div> <div class="ui mini icon message"> <i class="comment icon"></i> <div class="content"> <div class="header">Tommy</div> <p>Hi!</p> </div> </div> <div class="ui mini icon message"> <i class="comment icon"></i> <div class="content"> <div class="header">Tommy</div> <p>What's up?</p> </div> </div> </div> {# end msg board #} </div> {# end ten wide column #}Všetky správy som obalil do div s id msg_board aby som potom jednoducho vedel pridávať nové správy do tohto elementu.[Image] Spravíme to isté pre zoznam miestností. Rozhodol som sa, že do tohto bočného panelu strčíme aj formulár na zmenu mena používateľa. Ten by mal mať možnosť zmeniť svoje meno. Bude to vyzerať asi takto: <div class="six wide column"> <h4 class="ui dividing header">Change username</h4> <form id="choose_username" class="ui form" method="post"> <div class="field"> <div class="ui action input"> <input type="text" id="user_name" placeholder="username..."> <button class="ui button">Change</button> </div> </div> </form> <h4 class="ui dividing header">Rooms</h4> <form id="choose_room" class="ui form" method="post"> <div class="grouped fields"> <label for="fruit">Select available room:</label> <div id="room_list"> <div class="field"> <div class="ui radio checkbox"> <input type="radio" name="room" class="hidden" value="Lobby"> <label>Lobby</label> </div> </div> <div class="field"> <div class="ui radio checkbox"> <input type="radio" name="room" class="hidden" value="Music"> <label>Music</label> </div> </div> <div class="field"> <div class="ui radio checkbox"> <input type="radio" name="room" class="hidden" value="Movies"> <label>Movies</label> </div> </div> </div> <div class="field"> <input type="text" id="new_room" placeholder="create new room"> </div> <button class="ui button"> Change Room</button> </div> </form> </div> {# end six wide column #}[Image] Tak isto som pridal aj <input /> na vytváranie nových miestností. Myslím, že takúto možnosť by používateľ mohol mať. Poslednou skladačkou bude input pre naše správy. <footer> <form id="send_msg_to_room" class="ui form" method="post"> <div class="field"> <div class="ui fluid action input"> <input type="text" id="msg_input" placeholder="message..."/> <button class="ui button" value="send">send</button> </div> </div> </form> </footer>[Image] Momentálne mi nebudú fungovať radio buttony, pretože semantic-ui potrebuje tieto inicializovať v javascripte. Pome teda na to. Otvoríme main.js a píšeme $(document).ready(function(){ // UI HANDLERS $('.ui.radio.checkbox').checkbox(); });Tak isto môžeme rovno vybaviť iniciálne spojenie cez websockety medzi klientom a serverom. $(document).ready(function(){ var url = location.protocol + "//" + document.domain + ":" + location.port; socket = io.connect(url); // UI HANDLERS $('.ui.radio.checkbox').checkbox(); });Posielanie správ môžem rovno aj vyskúšať v konzole prehliadača. Stačí otvoriť developer tools, prejsť na záložku console a tam už môžeme písať socket.emit("test", "hello there")[Image] Avšak, nič sa nedeje, pretože môj backend ešte nie je vôbec pripravený. Vrhneme sa teda na server side a implementujeme miestnosti - room. RoomsPresunieme sa do súboru server.py a pridáme handler pre základné eventy ktoré budeme používať: join, leave, msg_board, username_change ... from flask_socketio import send, emit from flask_socketio import join_room, leave_room ... ### WEB CONTROLLER @app.route("/") def index(): return redirect(url_for("view_board")) @app.route("/board/") def view_board(): return render_template("board.jinja") ## SOCKET CONTROLLER @socketio.on("join") def on_join(data): username = data["user_name"] room = data["room_name"] join_room(room) send("{} has entered the room: {}".format(username, room), room=room) @socketio.on("leave") def on_leave(data): username = data["user_name"] room = data["room_name"] leave_room(room) send("{} has left the room: {}".format(username, room), room=room) @socketio.on("msg_board") def handle_messages(msg_data): emit("msg_board", msg_data, room=msg_data["room_name"]) @socketio.on("username_change") def username_change(data): msg = "user \"{}\" changed name to \"{}\"".format( data["old_name"], data["new_name"]) send(msg, broadcast=True) ...Eventy join, leave a username_change fungujú veľmi jednoducho. Zakaždým sa pozriem na dáta, ktoré mi prišli (premenná data) a vytvorím jednoduchú správu, ktorú potom broadcastujem na všetkých používateľov v tej danej miestnosti. Ak si už poriadne nepamätáš, čo robil ten broadcast, pospomínaj z minulého blogu. Dôležité je použitie funkcií join_room a leave_room. Tieto pochádzajú z knižnice flask-socketio, ktorú sme inštalovali na začiatku. Slúžia na to aby sme priradili danú session do nejakej miestnosti. Potom, keď pošlem správu do miestnosti, dostanú ju všetci v tej miestnosti. Je to fajn mechanizmus ako kontaktovať iných klientov a usporiadať si ich do nejakých kategórií. rooms nemusím nevyhnutne používať len na chatovú funkcionalitu. Môžem to použiť na to, aby som si zoradil používateľov do nejakej spoločnej skupiny, ktorej posielam barsjaké dáta. Dajme tomu, že by som mal appku o počasí, a nejaká skupina používateľov by mala záujem o notifikácie, či bude pršať. Tak týchto by som hodil do spoločnej skupiny - miestnosti - a notifikácie by som posielal len im. Využitie je teda všakovaké. JavaScriptBackend bol v tomto prípade celkom jednoduchý a nepotrebovali sme toho veľa implementovať. Správy sa od nášho backendu len odrážajú ako od relátka, ktorý ich ďalej rozposiela klientom. Na strane klienta toho bude trošku viacej. Pokračujeme v súbore main.js. Teraz sa pokúsime implementovať posielanie správy a zobrazenie prichádzajúcej správy na messageboard. $(document).ready(function() { ... // generate random user name if needed setRandomNameAndRoom(); // join default room joinRoom(socket); // UI HANDLERS $('.ui.radio.checkbox').checkbox(); // send message $("form#send_msg_to_room").submit(function(event) { userName = sessionStorage.getItem("userName"); roomName = sessionStorage.getItem("roomName"); msg = $("#msg_input").val(); sendMessage(socket, userName, roomName, msg); this.reset(); return false; }); // handle new message socket.on("msg_board", function(data){ msg = '<div class="ui mini icon message">'; msg += '<i class="comment icon"></i>'; msg += '<div class="content">'; msg += '<div class="header">'+data["user_name"]+'</div>'; msg += '<p>' + data["msg"] + '</p>'; msg += '</div>'; msg += '</div>'; $("#msg_board").append(msg); }); }); // HELPERS function setRandomNameAndRoom(){ if (sessionStorage.getItem("userName") == null){ randomName = "user" + Math.floor((Math.random() * 100) + 1); sessionStorage.setItem("userName", randomName); sessionStorage.setItem("roomName", "Lobby"); }; }; function joinRoom(socket){ data = { "room_name" : sessionStorage.getItem("roomName"), "user_name" : sessionStorage.getItem("userName") }; socket.emit("join", data); }; function sendMessage(socket, userName, roomName, message){ data = { "user_name" : userName, "room_name" : roomName, "msg" : msg }; socket.emit("msg_board", data); }; Na začiatok vytvoríme nejaké random meno používateľa a zvolíme default miestnosť "Lobby". To aby sme s týmto nemali starosti zatiaľ. Používame na to pomocné funkcie, ktoré si implementujeme bokom, aby nám nezavadzali. Meno používateľa a názov aktuálnej miestnosti si udržiavam v sessionStorage, čo je fajn dočasné úložisko v prehliadači. Prežije aj reload stránky a navyše sa mi tento spôsob viacej páči ako udržiavať informáciu v cookies. Keď máme potrebné dáta, môžeme sa hneď na začiatku buchnúť do nejakej miestnosti. V javascripte používame knižnicu socket.io, ktorá ale žiadny koncept miestností nepozná. Ak sa pozrieš do dokumentácie (pozor! otvor si client api), zistíš, že nič také ako rooms sa tam nespomína. Takže to je vecička knižnice flask-socketio. Použijeme teda klasický emit na handler join, ktorý existuje na servery. Tento riadok $("form#send_msg_to_room").submit( sa pomocou jquery napichne na formulár a zachytí odoslanie formuláru. Potom môžem robiť čo sa mi zachce a nakoniec vrátim false, takže formulár sa reálne ani neodošle. Odoslanie správy je priamočiare. Zistím UserName, zistím RoomName, vytiahnem si text správy a všetko pošlem do funkcie sendMessage. Táto už zabezpečí zabalanie informácií do jsonu a posielam pomocou funkcie emit. Posielam na handler msg_board, ktorý som si spravil pred chvíľkou. Ostáva mi vyriešiť prijatie správy. To robím pomocou funkcie socket.on, kde dám kód, ktorý sa vykoná pri prijatí správy. Tu si jednoducho (ale zato strašne škaredo) pozliepam kus HTML, ktoré potom strčím na koniec elementu s id msg_board. Predtým, ako to budeš skúšať, je fajn si ešte vymazať tie fejkové správy, ktoré sme tam dali natvrdo do HTML. Takže mažeme tieto riadky <div class="ten wide column"> <h1 id="room_heading" class="ui header">Johny @ Music room</h1> <div id="msg_board"> ---> <div class="ui mini icon message"> ---> <i class="comment icon"></i> ---> <div class="content"> ---> <div class="header">Johny</div> ---> <p>Hello there</p> ---> </div> ---> </div> ---> <div class="ui mini icon message"> ---> <i class="comment icon"></i> ---> <div class="content"> ---> <div class="header">Tommy</div> ---> <p>Hi!</p> ---> </div> ---> </div> ---> <div class="ui mini icon message"> ---> <i class="comment icon"></i> ---> <div class="content"> ---> <div class="header">Tommy</div> ---> <p>What's up?</p> ---> </div> ---> </div> </div> {# end msg board #} </div> {# end ten wide column #}Pome teda ako ďalšiu vec vybaviť zmenu používateľského mena. $(document).ready(function(){ ... // set heading updateHeading(); // set user name handler $("form#choose_username").submit(function(event){ // get old and new name var oldName = sessionStorage.getItem("userName"); var newName = $("#user_name").val(); //save username to local storage sessionStorage.setItem("userName", newName); // change ui updateHeading(); // notify others notifyNameChange(socket, oldName, newName); //clear form this.reset(); return false }); }); function updateHeading(){ roomName = sessionStorage.getItem("roomName"); userName = sessionStorage.getItem("userName"); $("#room_heading").text(userName + " @ " + roomName); }; function notifyNameChange(socket, oldName, newName){ data = { "old_name" : oldName, "new_name" : newName } socket.emit("username_change", data); };Tak ako pri posielaní správy, napichnem sa na HTML formulár a spracujem ho ešte pred odoslaním. Zmeny uložím do sessionStorage. Pridal som ešte 2 vychytávky. • funkcia updateHeading nastaví aktuálny názov miestnosti a používateľa ako hlavičku stránky, • notifyNameChange dá všetkým používateľom vedieť, že si niekto zmenil meno. Meno si už môžem meniť, ale notifikáciu o zmene som nedostal. Na to ešte musíme doplniť jeden event handler na message $(document).ready(function(){ ... // system message socket.on("message", function(data){ msg = '<div class="ui mini icon info message">'; msg += '<i class="bell icon"></i>'; msg += '<div class="content">'; msg += '<p>' + data + '</p>'; msg += '</div>'; msg += '</div>'; $("#msg_board").append(msg); }); }); ...Teraz sa nám začnú zobrazovať aj systémové notifikácie o tom, čo sa deje. Kto vošiel do miestnosti, kto ju opustil alebo kto si zmenil meno. Poslednou vecou, ktorú musíme spraviť, je selekcia miestností. Toto bude vyžadovať trošku viacej práce. Zoznam existujúcich miestností si musíme udržiavať na backende. Ani na klientskej časti ani na backende z knižnice flask-socketio neviem získať zoznam všetkých miestností. Musím si ho teda udržiavať sám. from flask import g ... DEFAULT_ROOMS = ["Lobby"] ... @app.route("/board/") def view_board(): all_rooms = getattr(g, "rooms", DEFAULT_ROOMS) return render_template("board.jinja", rooms=all_rooms) ... ### SOCKET CONTROLLER @socketio.on("join") def on_join(data): username = data["user_name"] room = data["room_name"] all_rooms = getattr(g, "rooms", DEFAULT_ROOMS) if room not in all_rooms: all_rooms.append(room) emit("handle_new_room", {"room_name" : room}, broadcast=True) join_room(room) send("{} has entered the room: {}".format(username, room), room=room)Do templejtu board.jinja som si začal posielať nejaké dáta. Vyhodím teda tie fejkové, ktoré sú tam natvrdo, a spravíme loop, v ktorom pridám všetky existujúce miestnosti. <div id="room_list"> {% for room in rooms %} <div class="field"> <div class="ui radio checkbox"> <input type="radio" name="room" class="hidden" value="{{room}}"> <label>{{room}}</label> </div> </div> {% endfor %} </div>Pokračujem v súbore main.js, kde si vytvorím funkcie, ktoré sa postarajú o zmenu miestnosti + ak bola vytvorená nová, tak ju pridám do zoznamu. $(document).ready(function(){ ... // set room name heading selectCurrentRoom(); updateHeading(); ... // set room handler $("form#choose_room").submit(function(event){ newRoom = getRoomName(); // first leave current room leaveRoom(socket); // set new room sessionStorage.setItem("roomName", newRoom); updateHeading(); // join new room joinRoom(socket); //clear input newRoom = $("#new_room").val(""); //clear message board $("#msg_board").text(""); return false; }); socket.on("handle_new_room", function(data){ item = '<div class="field">'; item += '<div class="ui radio checkbox">'; item += '<input type="radio" name="room" class="hidden" value="'+ data["room_name"] + '">'; item += '<label>' + data["room_name"] + '</label>'; item += '</div>' item += '</div>' $("div#room_list").append(item); selectCurrentRoom(); }); }); ... function leaveRoom(socket){ data = { "room_name" : sessionStorage.getItem("roomName"), "user_name" : sessionStorage.getItem("userName") }; socket.emit("leave", data); }; function selectCurrentRoom(){ currentRoom = sessionStorage.getItem("roomName") $(".ui.radio.checkbox").checkbox().each(function(){ var value = $(this).find("input").val(); if (value == currentRoom){ $(this).checkbox("set checked"); }; }); }; function getRoomName(){ roomName = $("#new_room").val(); if (roomName == ""){ roomName = $("input[type='radio'][name='room']:checked").val(); }; return roomName; };Je tu viacero pomocných funkcií, ktoré mi pomáhajú pri výbere miestnosti alebo pri vytváraní novej. Problematické časti nastávajú práve v tedy, keď chcem miestnosť aj vytvárať. V podstate ale nejde o žiadne komplikované veci. Funkcia selectCurrentRoom mi pomôže prehodiť radio button pri zmene miestnosti. Tým, že používame semantic-ui tak sa nám to tiež trošku skomplikovalo, ale výsledok stojí za to.[Image] ZáverPostavili sme takzvaný proof of concept, spravili sme chatovaciu appku len pomocou websocketov. Nie je to dokonalé a určite je tam veľa múch, to nám však nebránilo pochopiť ako fungujú websockety. Všetky správy žijú len v prehliadači používateľa a nie sú uložené na žiadnom serveri. Niekto to môže považovať za chybu, niekto za fičúru. To už nechám na vás. Celý projekt sa dá stiahnuť tu. Onedlho sa opäť vrhneme na nejakú zaujímavú tému ;)
Java 8
Tipy a triky
19.09.2018
Skillmea

Java 8

Java 8 je veľký balíček novej funkcionality oproti Java 9 a java 10. Tie sú menšie a odzrkadľujú taktiku tvorcov javy vydávať nové verzie častejšie s menším balíkom novej funkcionality. V tomto článku si povieme najvýraznejšie zmeny z Java 8. Funkcionálne rozhraniaRozhranie, ktoré má len jednu abstraktnú metódu je považované za funkcionálne rozhranie. Pre lepšie načrtnutie v kóde môžeme a je odporúčané pridať anotáciu @FunctionalInterface.  import java.lang.FunctionalInterface;   @FunctionalInterface public interface FunctionalInterfaceExample {     void print(); }  Lambda výrazyOk, chceme pridať do javy možnosť definovať funkcionalitu bez toho aby patrila špecificky pod nejakú triedu. Tieto funkcie chceme vkladať do metód ako parametre. Čo spravíme? Tvorcovia javy sa asi takto nezamýšľali, ale my sme sa takto zamysleli a odpoveď je – použijeme lambda výrazy.  Každá lambda má ako typ funkcionálne rozhranie s jej odpovedajúcou metódou. V príklade vyššie máme rozhranie s metódou print. Táto metóda nevracia nič a neprijíma žiadne parametre. Musíme vytvoriť aj taký lambda výraz – teda nebude obsahovať return a nebudeme mať žiadne návratové hodnoty.  () -> System.out.println("Hello Word")Takto vložíš lambda výraz do metódy:  printHelloWord(() -> System.out.println("Hello Word"));Samotná metóda prijíma na vstupe práve dané funkcionálne rozhranie:  public void printHelloWord2(FunctionalInterfaceExample printHello)Viac o lambda výrazoch sa dozvieš z môjho online kurzu Java pre pokročilých, videá o lambda výrazoch sú zadarmo. StreamsStreamy poskytujú zjednodušenú prácu s dátovými kolekciami. Poskytujú viacero užitočných metód ako sú napríklad filter, sorted, map a iné. Ak stream préjde cez všetky elementy v kolekcii, tak bude prázdny. Teda ak chcem znovu použiť ten istý stream, tak zbytočne, lebo tam už nebudú dáta. Musíš si vytvoriť nový stream.  Nový stream vytvoríš napríklad pomocou stream metódy nad kolekciami.  List<Osoba> osoby = Arrays.asList( null, new Osoba("Jaro", "Beno", 30), new Osoba("Peter", "Kridlo", 55), new Osoba("Karol", "Otko", 18), new Osoba("Karol", "Beno", 18), new Osoba("Peter", "Otko", 20), new Osoba("Fedor", "Ronald", 84) ); osoby.stream();Máš zoznam osôb a chceš z daného zoznamu získať všetky veky osôb starších ako 50 rokov a majú byť zoradené podľa veku. Čo spravíš? Použiješ stream a jeho metódy – tieto metódy akceptujú funkcionálne rozhrania, teda tam dáš lambda výrazy.  List<Integer> veky = osoby.stream() .filter(osoba -> osoba.getVek() < 50) .sorted(Comparator.comparing(Osoba::getVek)) .map(Osoba::getVek) .collect(Collectors.toList());Kolekcie, ktoré sú iterovateľné, majú metódu forEach – ktorá získa stream a prejde všetky elementy.  veky.forEach(System.out::println);   Method referencePo slovensky referencia na metódu. Všimni si príklad z hora: Osoba::getVek. Znamená to, že z triedy Osoba použi metódu getVek. To isté sa dá zapísať aj pomocou lambda výrazu takto osoba -> osoba.getVek(). Ale pomocou referencie si to zjednodušíme lebo java vie, aký je vstupný parameter – je to osoba a vie, že voláš getVek. Tak stačí napísať Osoba::getVek. Metódu voláš bez zátvoriek.  Ďalší článok o Jave už čoskor. Prihlás sa k odberu noviniek a nezmeškaj žiadný nový blog.   
Websockety vo Flasku
Tipy a triky
15.08.2018
Miroslav Beka

Websockety vo Flasku

Websockety vo Flasku Ak si sa niekedy stretol s výrazom websocket a chcel by si sa dozvedieť, čo to vlastne je a ako sa to používa v Python aplikácii, tak tento článok je práve pre teba. Štandardne tvoj prehliadač komunikuje na webe pomocou http protokolu. Klasický http protokol ponúka jednoduchú komunikáciu. Pošle sa request a ako odpoveď dostanem response. Tento klasický komunikačný spôsob nebol dostatočný pre dnešné moderné aplikácie. Bola potreba pre komunikačný kanál, ktorý bude slúžiť na obojsmernú komunikáciu. HTTP by mal byť viac-menej bezstavový a klient a server medzi sebou komunikujú iba keď treba, inak je spojenie medzi nimi uzavreté. Navyše, prehliadač (klient) musí požiadať server o komunikáciu a server môže na túto žiadosť odpovedať. Tá žiadosť, to je ten http request. Inak server nevie kontaktovať klienta len tak sám od seba. Pri websocketoch je to inak. Ide o komunikačný kanál, ktorý sa otvorí raz, na začiatku a potom sa používa na komunikáciu klienta a servera v oboch stranách. To znamená, že server môže posielať dáta zároveň čo klient posiela dáta na server. Toto sa odborne volá full-duplex. Web socket má menší overheat prenosu dát, vie byť real-time a hlavne, server môže posielať dáta na klienta bez toho, aby si ich klient musel explicitne vyžiadať requestom. Toto je užitočné napríklad pri aplikáciách, ktoré zobrazujú real time dáta a server posiela tieto dáta klientovi. Takže ak nastane nejaká zmena dát, server ich proste pošle na klienta. Toto predtým nebolo možné spraviť iba pomocou http protokolu. Minimálny príkladNajlepšie je vyskúšať si tieto koncepty v praxi. Dnes budeme pracovať s Flaskom, knižnicou SocketIO a javascript knižnicami socket.io a jQuery. Budem predpokladať, že Flask aplikácie aspoň trochu poznáš. Začneme tým, že si vytvoríme nové virtuálne prostredie: $ mkdir websockets_primer $ cd websockets_primer $ virtualenv venv $ . venv/bin/activate (venv) $Nainštalujeme závislosti, ktoré budeme potrebovať: (venv)$ pip install flask, flask-socketioV čase písania tohto článku som používal verzie Flask==1.0.2 a Flask-SocketIO=3.0.1. Keď už máme pripravené prostredie a nainštalované závislosti, spravíme nový súbor server.py from flask import Flask from flask import render_template from flask_socketio import SocketIO app = Flask(__name__) app.config["SECRET_KEY"] = "secret" socketio = SocketIO(app) @app.route("/") def index(): return render_template("index.jinja") @socketio.on("event") def handle_event(data): print(data) if __name__ == '__main__': socketio.run(app, debug=True)Na začiatku máme importy ako pre každú inú Flask aplikáciu, avšak pribudlo nám tam from flask_socketio import SocketIO. Tento naimportovaný modul je v podstate to isté ako iné Flask rozšírenia. Inicializáciu websocketov vo Flask aplikácií spravíme pomocou riadku socketio = SocketIO(app). Pomocou tohto objektu socketio budeme príjmať a odosielať správy. Minimálna aplikácia by mala mať aspoň jednu stránku. V našom prípade to bude index.jinja. Toto je treba pretože musíme poskytnúť aj klientskú časť našej aplikácie. Tam bude javascript knižnica socketio a nejaké ďalšie funkcie. Websockety vedia prijímať a posielať správy. Spravíme zatiaľ len prijímanie správ. Pomocou riadku socketio.on("event")definujem handler pre udalosť event. V tomto prípade jednoducho vypíšem dáta na konzolu. @socketio.on("event") def handle_event(data): print(data)Posielanie a prijímanie dát na oboch stranách (klient a server) prebieha ako event. Toto je dôležitý fakt, pretože architektúra aplikácie založenej na eventoch (event driven architecture) funguje trošku inak ako klasické volanie funkcie. Nehovorím, aby si mal z toho paniku teraz, ale maj to na pamäti. Ak poznáš Flask aplikácie, tak spustenie appky vyzerá zväčša takto if __name__ == "__main__": app.run("0.0.0.0", debug=True)My ale musíme appku spustiť inak, pretože používame websockety. Spustíme ju pomocou objektu socketio, ktorý sme si vytvorili na začiatku. if __name__ == '__main__': socketio.run(app, debug=True)Teraz musíme ešte vytvoriť 2 súbory. Snažíme sa renderovať index.jinja a taktiež musíme vytvoriť hlavný javascript súbor, do ktorého budeme písať klientskú časť našej websocketovej ukážky. Vytvorím priečinok templates a do neho súbor index.jinja <!DOCTYPE HTML> <html> <head> <title>Websockets test</title> <script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script> <script type="text/javascript" src="{{ url_for("static", filename="js/main.js")}}"></script> </head> <body> <form id="emit_event" method="post"> <input type="submit" value="emit"> </form> </body> </html>Dôležité sú 3 importy v hlavičke html dokumentu. Prvý importuje jQuery, druhý importuje knižnicu na prácu so socketmi socketio a posledný import je pre náš main.js súbor, ktorý musíme ešte vytvoriť. Inak, tento html dokument obsahuje len jeden formulár s jedným tlačítkom. To budeme používať na posielanie správy cez websocket. Vytvoríme priečinok static v ňom js a v ňom už konečne súbor main.js Obsah bude vyzerať asi takto: $(document).ready(function() { var url = location.protocol + "//" + document.domain + ":" + location.port var socket = io.connect(url); $("form#emit_event").submit(function(event) { socket.emit("event", "test message"); return false; }); });Toto je hlavná logika klientskej časti. Z tadeto budeme prijímať a posielať správy cez websockety tak isto ako na serverovej časti. Pomocou riadku var socket = io.connect(url); sa pripojím na môj server. Následne pomocou jQuery upravím správanie buttonu, aby pri stlačení poslal správu. Na to slúži funkcia socket.emit() Okej, základ máme hotový a môžeme teraz skúšať posielať správy. Aplikáciu spustím pomocou príkazu: (venv)$ python server.py WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance. * Serving Flask app "server" (lazy loading) * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance. * Debugger is active! * Debugger PIN: 478-618-530Otvorím prehliadač na http://localhost:5000 a zobrazí sa mi jeden button. Keď ho stlačím na konzole mi vyskočí: test messagePoďme teda preskúmať, aké možnosti nám poskytuje táto knižnica socketio. Príjmanie správAko som už spomínal, prijímanie správ na oboch stranách prebieha ako event. V Pythone musíme pre takýto event definovať handler. V javascripte používame tzv. callbacky. V princípe ide o to isté, ale každý jazyk má svoje vlastné technické riešenie a my si toho musíme byť vedomí. Každý event, ktorý chcem prijať musím mať nejaké meno. V príklade sme mali názov event. Môžem ale použiť čokoľvek @socketio.on("foobar") def handle_data(data): print(type(data)) print(data)Taktiež dáta sa automaticky menia na príslušný typ. Ak v javascripte pošlem string, tak string dostanem aj na serveri. Tak isto to platí pre iné dátové typy ... $("form#emit_event").submit(function(event) { socket.emit("foobar", "message"); socket.emit("foobar", [1,2,3,]); socket.emit("foobar", {data : "message"}); return false; }); ...Po odoslaní udalostí dostanem výpis na serveri <class 'str'> message <class 'list'> [1, 2, 3] <class 'dict'> {'data': 'message'}Handler taktiež môže mať viacero argumentov @socketio.on("sum") def handle_sum(arg1, arg2): print(arg1 + arg2)Upravíme javascriptovú časť a zavoléme event s viacerými argumentami ... $("form#emit_event").submit(function(event) { socket.emit("sum", 23, 47); return false; }); ...Namespace patrí medzi ďalšie funkcie, ktoré mám knižnica SocketIO ponúka. Každý event si môžeme rozdeliť podľa namespaceov. To nám dáva ďalšie možnosti organizácie eventov. @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): print(arg1 + arg2)Avšak pozor! Na strane klienta sa musíme teraz pripojiť na inú url $(document).ready(function() { var namespace = "/math"; var url = location.protocol + "//" + document.domain + ":" + location.port; var socket = io.connect(url + namespace); $("form#emit_event").submit(function(event) { socket.emit("sum", 23, 47); return false; }); });Ďalšia vychytávka je to, že každý event, ktorý pošleme, vie zavolať callback potom, čo sa vykonal. Napríklad z javascriptu pošlem nejaké dáta na server a server mi ešte dodatočne potvrdí, že dáta boli spracované. Aha takto ... $("form#emit_event").submit(function(event) { var ack = function(arg){console.log(arg)}; socket.emit("sum", 23, 47, ack); return false; }); ...Ak chcem, aby sa callback zavolal, musím v Pythone vrátiť nejakú hodnotu z vykonaného handlera => return True @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): print(arg1 + arg2) return TrueMusím si otvoriť v prehliadači konzolu (ja používam chrome) a keď stlačím tlačítko, dostanem výpis na konzolu [Image] Posielanie správPosielať eventy sme už posielali, ale iba z javascriptu. V Pythone to vyzerá veľmi podobne. Používame 2 funkcie send a emit medzi ktorými je zásadný rozdiel. Najprv musíme importovať z knižnice flask-socketio from flask_socketio import send from flask_socketio import emitupravíme funkciu na sčítavanie @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): value = arg1 + arg2 print("{} + {} = {}".format(arg1, arg2, value)) send(value)a pridáme handler v javascripte aby sme mohli tento event zachytiť. ... $("form#emit_event").submit(function(event) { socket.emit("sum", 23, 47); return false; }); socket.on("message", function(data){ console.log("received message: " + data) }); ...Všimni si, že teraz som použil handler, ktorý spracováva event s názvom message. Nie je to náhoda. Ide totiž o to, že funkcia send posiela tzv. unnamed event. Tieto eventy sa vždy posielajú na handler, ktorý spracúva message. Narozdiel od funkcie send, funkcia emit posiela už konkrétny event a musíš mu dať názov. Skúsme teda pozmeniť náš príklad @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): value = arg1 + arg2 print("{} + {} = {}".format(arg1, arg2, value)) emit("result", value)... socket.on("result", function(data){ console.log("sum is: " + data) }); ...BroadcastingVeľmi užitočná funkcia je broadcastovanie, čo už z názvu vyplýva, že eventy sa budú vysielať na všetkých pripojených klientov. Dajme tomu, že zmeníme funciu emit na broadcastovanie @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): value = arg1 + arg2 print("{} + {} = {}".format(arg1, arg2, value)) emit("result", value, broadcast=False)Teraz, keď si otvoríš 2 prehliadače a v jednom stlačíš button, výsledok súčtu sa ukáže vo všetkých prehliadačoch[Image] note: callbacky sa pri broadcastovaní nebudú vykonávať ZáverWebsockety majú mnoho využití. Tento článok bol len úvod a prehľad niektorých základných funkcií. V budúcom blogu spravíme malú aplikáciu postavenú na websocketoch. Máš nejaké otázky k článku? Napíš ju do komentára.
7 dôvodov, prečo sa ľudia na vašom webe neregistrujú
Tipy a triky
06.06.2018
Skillmea

7 dôvodov, prečo sa ľudia na vašom webe neregistrujú

Weby sú o biznise. A teraz nemám na mysli vývojárske firmy a mladé dynamické “desing studios”. Hovorím o biznise ako takom - o činnosti, pri ktorej sa vymieňajú hodnoty (ako peniaze a tovar) k vzájomnej spokojnosti oboch strán. Vy máte super obsah, návštevníci vašich stránok zase svoje kontaktné údaje. Tak si podáte ruky a dohodnete obchod. Moje články za tvoj e-mail. Jednoduché, nie? Nie. Registračný proces je vcelku zložitá záležitosť a nie vždy funguje tak, ako by sme si predstavovali. Web môže mať veľa návštevníkov, no len veľmi málo sa aj zaregistruje. Prečo? Nuž, keď sme web vymýšľali, mohli sme nevedomky urobiť pár chýb. Tak po prvé… 1. Sme v tom, že registračný proces rovná sa registračný formulár Samozrejme, že je dôležité mať pekný a použiteľný formulár. Názvy nad inputmi pre vertikálne skenovanie, absencia CAPTCHA pre duševný kľud, poznáme. Ale registrácia nezačína vypĺňaním políčok. Ak sme návštevníka dostali až sem, máme už vlastne spolovice vyhraté - registračný proces formulárom nezačína, ale končí. Ďalšou chybou teda môže byť, že… 2. Zabúdame na to, že registračný proces rovná sa motivácia “Ahoj, sme Triad a robíme efektívny digitálny marketing tak, aby to bavilo nás aj našich klientov”. Nejako takto by mohla vyzerať vaša value proposition (nechce sa mi hľadať slovenský preklad), ak by ste boli Triad. Lenže nie ste, tak si vymyslite vlastnú. Pamätajte, že návštevníci stránok sú sebci a zaujíma ich len to, čo im prinesiete. Kašlú na vašu misiu, víziu a počet šálok kávy vypitých od začiatku roku. Prečo by s vami mali robiť biznis, keď im nedáte jasne najavo, akú hodnotu im prinášate? Prečo by sa mali registrovať práve u vás? Povedzte im to. Jednoducho, zrozumiteľne, hlavne nepreháňajte. S tým súvisí ďalší bod. 3. Neosobné a nudné webové copy Ako hovorí Adam Javůrek, vo webovom copy sú sväté 3 slová: vy, váš a zdarma. Schválne, skúste použiť všetky. Buďte priateľskí, s užívateľmi sa rozprávajte. Gombík “Registrujte sa” je prívetivejší ako “Registrovať”, alebo “Registrácia”. Vyznačte dôležité časti, text štruktúrujte. Oh, a skráťte ho. Na polovicu. A potom ešte raz. To, čo je na vás super musíte vedieť povedať počas krátkej cesty výťahom. Je váš produkt alebo obsah zdarma? Povedzte to. A ešte raz - nie ste najlepší, najkrajší a neviete všetko. Svojim návštevníkom dajte jasný a zrozumiteľný dôvod, prečo sa u vás majú registrovať. Bez preháňania. Všetky kecy na svete však nenahradia osobnú skúsenosť - občas na to pozabudneme a potom vzniká… 4. Obsah skrytý pod registračnou hradbou To je tak. Kliknem na nadpis článku alebo odkaz v zmysle “zistiť viac” (moje obľúbené, BTW, keď nejdem ďalej čítať, ale “zisťovať”). Vyskočí na mňa modálne okno s formulárom a vrieska po mne čosi o registrácii. Skúsim ďalší odkaz, situácia sa opakuje. Odchádzam.  Povedzme, že zháňate cukríky a narazíte na dvoch predavačov. Benďo a Jožo. Benďo bude svoje cukríky vynášať do neba a opisovať ich úžasnú chuť. Jožo otvorí balíček a rovno vás ponúkne. Od koho si cukríky kúpite? Jožova prefíkaná obchodná taktika stojí na princípe reciprocity - ak dáš najprv niečo ty mne, ja budem viac ochotný dať niečo tebe. Preto ak máte super obsah, neskrývajte ho pred návštevníkmi. Ukážte im ho. S tým, že keď ho budú chcieť vidieť celý, nech sa zaregistrujú. Svoj e-mail vám poskytnú veľmi radi, ak budú vedieť, do čoho idú. Apropo, do čoho idú… 5. Príliš veľký záväzok Registrácia na webe je veľké rozhodnutie. Nie, vážne. Sú to cudzie stránky, neviem, kto ich vlastní. Komu dávam svoj e-mail? Na čo všetko ho použije? Čaká ma spambox plný super piluliek a členov nigérijskej kráľovskej rodiny? A načo chcú moje telefónne číslo? PSČ? Zbláznili sa? Tak. Buďte transparentní. Ľudia nemajú radi záväzky, ukážte im teda, že sa nemajú čoho báť. Budete im posielať newsletter? Tak im ho ukážte. Ako vyzerá, čo obsahuje a hlavne - ako často sa naňho môžu tešiť. Môžu si účet kedykoľvek zrušiť? Povedzte im to. Pridajte aj vetu o tom, že informácie neposkytnete tretej strane (a skúste to aj dodržať). A uistite ich, že to celé nezaberie viac ako minútu ich času. Ešte jedna vec. Veľa webov prichádza o obrovský zdroj dôvery v očiach ich potencionálnych užívateľov - robia jednu zásadnú chybu… 6. Skrývanie ostatných užívateľov Máte super web plný super obsahu, kde chodí veľa super ľudí? Ukážte ich. Čo všetko tam robia? Jožo práve číta článok o červených pandách? Benďo v špeciálnej aplikácii zistil, kde v jeho okolí sa pandy dajú skvelo pozorovať? Prečo sa nepochváliť? Možno tam dokonca nájdem nejakých kamošov z Facebooku. A prečo by som sa neregistroval, keď tam už sú moji známi, ktorí to preverili za mňa? Volá sa to social proof a viac o ňom zistíte v Googli. Nejaké knihy o tom zoženiete aj na Amazone. A vôbec, keď už o nich hovorím. Títo veľkí hráči míňajú milióny na UX testovanie, musia mať super premakanú registráciu. Spravíme to ako oni. Nemôže to dopadnúť zle. Alebo hej? 7. Opakovanie po ostatných Ak sa nevoláte Bezos (čo určite nie, lebo čítate článok v slovenčine), zapíšte si za uši: nie ste Amazon. Ani Google, ani Alza ani lokálny opravár plynových bojlerov. Vy ste vy. Pri navrhovaní registračného procesu treba vždy vychádzať z vlastnej situácie a vlastných skúseností. Internetoví giganti majú určite veľmi dobre zvládnutý registračný proces, no nikto z nás nevidí do ich cieľov, štatistík a stratégie. To čo funguje pre nich nemusí fungovať pre vás. Na druhej strane, inšpirovať sa niekde treba, takže…  Trochu inšpirácie Tu je niekoľko známych webových produktov, ktoré majú podľa mňa vynikajúco zvládnutý registračný proces. Čo majú spoločné, je predovšetkým jednoduchosť - jasne komunikujú, ako mi pomôžu (či už pomocou textu alebo obrázkov) a okamžite mi ponúknu možnosť ich bezbolestne začať používať. • Intercom • Basecamp • Dropbox Autorom blogu je Roman Pittner, lektor online kurzu Dizajn pre obrazovky. Ak máš k blogu otázky, neváhaj ich napísať do komentárov.
Ako vie programátor samouk dobehnúť tých, čo študovali na univerzite
Tipy a triky
03.04.2018
Martin Lipták

Ako vie programátor samouk dobehnúť tých, čo študovali na univerzite

Čo sa učia na univerzitáchSi programátor samouk a rozmýšľaš, ako to vyzerá na univerzite? Už si videl všetky online kurzy, máš za sebou 10 vlastných projektov a začínaš v novej práci ako Web developer. Ako dobehnúť ľudí, ktorí 5 rokov študovali informatiku? Dá sa to vôbec?  Pred 3 rokmi som skončil FIIT (Fakulta informatiky a informačných technológií) na STU v Bratislave a tiež som rozmýšľal, čo všetko mi škola dala. Je toho veľa a som veľmi rád, že som si vybral takú cestu. Na druhej strane, keby som túto možnosť nemal, väčšinu vecí by som sa naučil aj inde. Čo boli pre mňa tie najdôležitejšie veci? Asi už tušíš, že je to celé veľmi subjektívne a určite neber tento článok ako univerzálny návod. Študentský životBýval som na intrákoch v Mlynskej doline a jeden semester som strávil na programe Erazmus v Španielsku. Boli to kamarátstva a zážitky, na ktoré sa dá spomínať celý život. Pre samoukov: Ak si študoval na akejkoľvek vysokej škole, vieš o čom hovorím. Inšpiratívni ľudiaSpoznal som veľa spolužiakov a učiteľov, ktorí ma vo veľa veciach posunuli ďalej. S mnohými som doteraz v kontakte a môžem sa na nich spoľahnúť, keby som potreboval pomoc.  Pre samoukov: Skvelých ľudí nájdeš aj v pracovných kolektívoch. Obklop sa takými, ktorí sú lepší ako ty sám.  Na škole sa organizovalo veľké množstvo podujatí a učitelia nás motivovali chodiť na stretnutia programátorov mimo školy, kde som spoznal veľa ďalších ľudí. Pre samoukov: Hľadaj si kamarátov na rôznych udalostiach pre programátorov, ktorých je viac než dosť v každom väčšom meste (napríklad taká Rubyslava alebo Reactive meetups a veľa ďalších). SamostatnosťOd intrákov a štúdia v zahraničí, až po prácu na zadaniach, projektoch a záverečných prácach. Aspoň na FIIT to bolo tak, že ťahať to musel sám študent a učiteľ mu len pomáhal alebo niekedy aj nepomáhal. Zasekol si sa pri zadaní a termín je zajtra? Použi Google, alebo sa poraď so spolužiakmi, ale vyrieš to. Ak tvoje zadanie nebude do 00:00 CEST v odovzdávacom systéme, nikoho nebudú zaujímať tvoje výhovorky a predmet si zopakuješ ďalší rok. Ak sa ti nazbiera takýchto predmetov viac, letíš zo školy. Pre samoukov: Tak ako si spravil tých 10 vlastných projektov, aj v práci budú očakávať, že sa vecí chytíš a dotiahneš ich samostatne do konca. To ale neznamená, že sa nemáš pýtať (najskôrskús Google) a požiadať o pomoc, keď ju potrebuješ. [Image] Práca v tímeNa mnohých školských projektoch som nepracoval sám. Na tímovom projekte sme boli až 7 a museli sme sa vysporiadať s odlišnými názormi a dokonca cieľmi v projekte.  Pre samoukov: Máš za sebou tých 10 projektov, pri ktorých si sa naučil samostatnosti. V práci budeš obklopený ľuďmi a musíte spolu čo najlepšie vychádzať. Volá sa to soft skills a dá sa to natrénovať.[Image] VedomostiNa čo všetko si spomeniem 3 roky po skončení školy? O čom boli všetky tie predmety? • Ako funguje počítačový hardvér a ako sa z jednotiek a núl stanú programy - logické obvody a počítačové architektúry. • Ako funguje operačný systém - ovládače zariadení, IO, systémové volania, procesy, vlákna (threads), synchronizácia, správa unixových systémov a shell skripty. • Ako funguje Internet a čo je HTTPS, DNS, POP3, IP a Ethernet - 7 vrstiev počítačových sietí a ako spolu súvisia všetky tieto protokoly. • V čom sa líšia paradigmy programovania - procedurálne programovanie v C, objektovo-orientované v Jave, funkcionálne v Lispe a logické v Prologu. Pozri môj prvý projekt v C, ktorý som nahral do školského systému na automatické testovanie :) • Čo znamená zápis O(n) a ako určiť zložitosť algoritmov? Ako môže efektívny algoritmus vypočítať výsledok za 1 milisekundu a neefektívny by to počítal týždne? Vyvážené binárne stromy, hashing, grafy a iné dátové štruktúry. • Čo je to Turingov stroj? Prečo sú regulárne výrazy regulárne? Čo je abstraktný syntaktický strom? Základná teória informatiky, na ktorej stoja všetky programovacie jazyky. • Je umelá inteligencia naozaj inteligentná? Hrubá sila a heuristiky, ktoré riešia zložité problémy, neurónové siete, genetické algoritmy a odvodzovacie stroje. • Aké sú výzvy paralelného programovania? Klasické problémy synchronizácie, vlákna, mutexy a semafory. • Čo je to databáza? Návrh dátových modelov, písanie dopytov (queries), optimalizácia indexmi a kedy použiť NoSQL. • Úvod do analýzy dát (data science). Lineárna regresia, neurónové siete, support vector machines, clustering a časové rady. • Ako manažovať softvérové projekty? Vodopád alebo agilné metodológie, dôležitosť testovania a dokumentácie, návrh požívateľských rozhraní, kvalita kódu a návrhové vzory. • Ako robiť výskum? Návrh hypotéz, ich vyhodnocovanie experimentmi, meranie dát, písanie a zverejňovanie výskumných článkov. • Zopár predmetov o ekonómii, práve a psychológii bolo príjemným oddychom od technických vecí. • Webový vývoj v Ruby on Rails. Toto je to, čomu sa teraz venujem v práci. Pre samoukov: Vyzerá to ako veľmi dlhý zoznam, ale väčšinu z týchto vecí sa vieš naučiť v praxi. Sú však veci, ku ktorým sa nedostaneš. Ak sa od začiatku zameriavaš na webový vývoj v PHP, asi sa nebudeš do hĺbky zaoberať hardvérom, prekladačmi (compilers) a operačnými systémami. A väčšina ľudí sa asi nebude zaoberať výskumom.[Image] Takže ako dobehnúť tých, ktorí študovali FIIT?• Obklop sa ľuďmi, od ktorých sa môžeš veľa naučiť. Nájdeš ich v práci a na stretnutiach programátorov. • Nečakaj, že ti vždy povedia ako máš veci robiť. Samostatnosť je ale aj vedieť požiadať o pomoc, keď ju potrebuješ. • Aj keď to tak na prvý pohľad nevyzerá, programovanie je viac o ľuďoch ako o počítačoch. Pracuj na svojich soft skills a komunikácii v tíme. • Snaž sa porozumieť veciam do hĺbky. Ako fungujú regulárne výrazy? Prečo potrebuje databáza indexy? Aký je rozdiel medzi http:// a https://? V čom sú výhody SCRUM-u? • Uč sa veci mimo tvojej špecializácie. Vyvíjaš weby? Skús spraviť natívnu mobilnú aplikáciu. Čo tak si cez víkend naprogramovať ovládač do operačného systému alebo kompilátor? Máš otázky k tomuto blogu? Neváhaj ich napísať do komentárov.
Ako naprogramovať hru Čierny Peter v Jave
Tipy a triky
26.10.2017
Skillmea

Ako naprogramovať hru Čierny Peter v Jave

Programovanie hry Čierny Peter v JaveV tomto tutoriáli si spolu naprogramujeme kartovú hru Čierny Peter. Použijeme programovací jazyk Java a zameriame sa na to, aby sme použili OOP prístup, teda objektovo-orientované programovanie. Pravidlá hryNajskôr si musíme zanalyzovať danú hru. To spravíme tak, že si povieme a určíme pravidlá. V hre je 33 kariet. Jedna karta nemá pár, ostatné ho majú. Hru môže hrať 3 až 6 hráčov. Všetky karty sa rozdajú medzi hráčov. Automaticky si hráči vytriedia z ruky karty, ktoré majú páry. S ostatnými sa začína hra. Ten, čo má najviac kariet, nechá ťahať hráča po svojej pravici. Ak ten hráč získal pár, tak ho vyloží a ďalší hráč od neho ťahá kartu. Ak hráč prišiel o všetky karty, už viac nehrá. Komu ostane posledná karta, ten prehral hru. Analýza hry – vytváranie objektovTeraz je čas pripraviť si popis našich tried, rozhraní a podobne. V skratke, uvažujeme nad pravidlami, okolnosťami a členmi danej hry a chceme ich pretvoriť na objekty.  Čím všeobecnejšie napíšeme naše objekty, tým lepšie pre ich znovupoužiteľnosť. Ak by sme chceli niekedy naprogramovať karty žolíkové, sedmové alebo hocijaké iné, tak si nechajme túto možnosť. Teda napríklad vytváranie inštancií kariet nedávajme do triedy balíku, ale inde.  Postup: 1. vytvorím kartu  2. vytvorím balík kariet  3. vytvorím hráča  4. interakciu s používateľom  5. správu hry  6. logiku hry Čierny Peter  KartaKaždá hracia všeobecná karta má nejaké špecifikum. Je to kráľ srdcový, kráľ pikový a podobne. V našom prípade máme páry a každá karta v páre je iná, spoločné majú to, že sú pár. Ako napríklad v žolíkových kartách máme 4 kráľov. Každý je iný, ale majú spoločné, že sú to králi.  package sk.jaro.CiernyPeter; public class Karta { private int cisloKarty; //každá karta ma iné číslo private int cisloParu; //každý prá má iné číslo, len dve karty majú to isté číslo páru public Karta(int cisloKarty, int cisloParu) { this.cisloKarty = cisloKarty; this.cisloParu = cisloParu; } public int getCisloKarty() { return cisloKarty; } public int getCisloParu() { return cisloParu; } } Balík karietĎalej budeme potrebovať tieto karty uložiť do balíku. Každá hra má niekoľko kariet, ktoré tvoria balík. Takže náš balík bude obsahovať zoznam kariet. Čo sa dá robiť s balíkom? Napríklad miešať karty, alebo z balíku môžeme vybrať kartu. Keď vyberám karty alebo miešam karty, tak tam musia nejaké byť. Lebo ak vyberiem postupne všetky karty z balíku, tak nakoniec budem mať balík prázdny. Skúste miešať prázdny balík kariet :) Preto si vytvorím aj pomocnú metódu, ktorá zistí, či je balík prázdny alebo nie. package sk.jaro.CiernyPeter; import java.util.Collections; import java.util.List; public class BalikKariet { private List<Karta> karty; //implementacia listu pre zachovanie poradia public BalikKariet(List<Karta> karty) { this.karty = karty; } public List<Karta> getKarty() { return karty; } public void zamiesajKarty(){ if(!jeBalikPrazdny()) Collections.shuffle(karty); } private boolean jeBalikPrazdny(){ return karty == null || karty.isEmpty(); } public Karta getKartu(){ Karta karta = null; if(!jeBalikPrazdny()) { karta = karty.get(0); //vytiahnem prvú kartu karty.remove(karta); //kartu odstránim z balíku } return karta; } }HráčDo každej hry potrebujem hráča, teda niekoho kto bude danú hru hrať. Rozhodol som sa, že hráčovi dám meno a karty v ruke. Keď vytváram nového hráča pomocou new, tak sa zavolá konštruktor danej triedy a tam si všimni, že som mu do ruky nedal nič, teda tam má prázdno. To preto, lebo ešte nedostal nijakú kartu pri rozdávaní, ale musí mať nejaké úložisko kde mu ich dám :) Je tam ešte metóda, ktorá má na starosti odstrániť z ruky hráča všetky páry. Kto by si to chcel nejako zovšeobecniť, tak môže. Teda do objektu Hrac, by dal len metódu na odstránenie jednej karty, alebo zoznamu kariet. A ktoré karty to budú to nechá na iný objekt, ktorý spravuje pravidlá hry Čierny Peter.  package sk.jaro.CiernyPeter; import java.util.ArrayList; import java.util.List; public class Hrac { private String meno; private List<Karta> kartyVRuke; public Hrac(String meno) { this.meno = meno; this.kartyVRuke = new ArrayList<>(); } public String getMeno() { return meno; } public List<Karta> getKartyVRuke() { return kartyVRuke; } public void odstranParyZRuky() { ArrayList<Karta> akeKartyOdstraniZRuky = new ArrayList<>(); for(Karta karta : kartyVRuke){ try { for (Karta k : kartyVRuke) { if (karta.getCisloParu() == k.getCisloParu() && karta.getCisloKarty() != k.getCisloKarty()) { akeKartyOdstraniZRuky.add(karta); akeKartyOdstraniZRuky.add(k); break; } } }catch (Exception e){ e.printStackTrace(); } } kartyVRuke.removeAll(akeKartyOdstraniZRuky); } }Ovládanie hryAkú chceš spraviť aplikáciu? Ako chceš komunikovať s používateľom? Cez grafické rozhranie? Cez konzolu, alebo inak? Teraz budeme robiť konzolovú interakciu, ale ak by si chcel robiť v budúcnosti grafické rozhranie, tak je vynikajúca idea spraviť interface, teda rozhranie, kde popíšem metódy aké chcem používať na interakciu s používateľom. Potom keď budeš robiť grafické rozhranie, tak si len zaimplementuješ toto nové rozhranie a niekde v kóde hry povieš, že teraz používať túto implemntáciu, a nemusíš prepisovať aj celú hru, lebo metódy sú tam rovnaké, len z iného zdroja.  Čo potrebujeme vypísať používateľovi, alebo čo od neho chcem získať? Počet hráčov, ich mená, akú kartu chceme hráčovi zobrať a chceme vypísať koniec hry. Ak chceš niečo viac, tak si to kľudne dorob.  package sk.jaro.CiernyPeter.rozhrania; import sk.jaro.CiernyPeter.Hra; import sk.jaro.CiernyPeter.Hrac; public interface IOvladanieHry { int vyberPocetHracov(); Hrac getMenoHraca(int i); int zoberKartu(Hrac hrac1, Hrac hrac2); void vypisKtoPrehral(Hra hra); }Teraz si musíme zaimplementovať toto rozhranie. Teraz máme len predpis metód ale nie ich vnútro. Budeme používať konzolu, ktorú budeme čítať pomocou scanneru a na konci hry si uzavrieme scanner. Každá metóda je jednoduchá, vypíšem na konzolu čo chcem a potom nechám používateľa, aby mi to napísal.  Všimni si, keď berieš nextInt(), tak sa to pokúsi zobrať číslo. Ak nájde niečo iné je to chyba a tú ošetríme. Kľudne si dorob viac ošetrení, podmienok a výpisov. Potom ale musíš zobrať aj zvyšok. Lebo čo spravil používateľ? Zadal číslo a stlačil enter. Ty si zobral len to číslo, ale nie aj enter. Preto tam máme ešte nextLine – to nám zoberie zvyšok riadku aj s enterom.  Čierny Peter bude hráč, ktorý ostal posledný v hre.  package sk.jaro.CiernyPeter.gui; import sk.jaro.CiernyPeter.Hra; import sk.jaro.CiernyPeter.Hrac; import sk.jaro.CiernyPeter.rozhrania.IOvladanieHry; import java.util.Scanner; public class OvladanieHry implements IOvladanieHry { Scanner scanner = new Scanner(System.in); @Override public int vyberPocetHracov() { int pocetHracov = 0; System.out.println("Zadaj počet hráčov (3 až 6):"); try { pocetHracov = scanner.nextInt(); scanner.nextLine(); } catch (Exception ex) { System.out.println("Nepodarilo sa načítať počet hráčov. Zadal si správne číslo?"); pocetHracov = vyberPocetHracov(); } return pocetHracov; } @Override public Hrac getMenoHraca(int i) { Hrac hrac = null; System.out.println(String.format("Zadaj meno pre hráča %d :", i)); String meno = scanner.next(); scanner.nextLine(); if (meno.equals("") || meno.equals(" ")) { System.out.println(String.format("Prosím znovu zadajte meno pre hráča %d :", i)); hrac = getMenoHraca(i); } else { hrac = new Hrac(meno); } return hrac; } @Override public int zoberKartu(Hrac hrac1, Hrac hrac2) { int zoberKartuCislo = 0; System.out.print(hrac1.getMeno() + " ,ktorú kartu cheš zobrať hračovi "+hrac2.getMeno()+"?: "); for(int i = 0; i < hrac2.getKartyVRuke().size(); i++){ System.out.print(i+", "); } try { zoberKartuCislo = scanner.nextInt(); scanner.nextLine(); } catch (Exception ex) { System.out.println("Nepodarilo sa získať akú kartu chceš zobrať. Zadal si správne číslo?"); zoberKartuCislo = zoberKartu(hrac1,hrac2); } return zoberKartuCislo; } @Override public void vypisKtoPrehral(Hra hra) { System.out.println("Čierny Peter je hráč "+hra.getHraci().get(0).getMeno()); scanner.close(); } }HraKaždá hra má niekoľko hráčov, má balík kariet s ktorými sa hrá a má aj ovládanie. Toto si zadefinujeme.  public class Hra{ private BalikKariet balikKariet; private int pocetHracov; private List<Hrac> hraci; private OvladanieHry ovladanieHry;V konštruktore tejto Hry si nastavíme to, čo vieme:  public Hra() { this.ovladanieHry = new OvladanieHry(); this.pocetHracov = ovladanieHry.vyberPocetHracov(); this.hraci = vytvorHracov(); }Nestavili sme balík kariet, pretože, ten je špecifický pre každý typ hry iný. V našom prípade sú to karty pre hru Čierny Peter. Tak tie si vytvorím neskôr.  V kuse kódu vyššie sme si vytvorili inštanciu ovládania hry a hneď sme ju aj použili pri výbere počtu hráčov. Metóda výber hráčov je jednoduchá, používateľa aplikácie sa pýtam ako sa volajú a rovno ich vytvorím a dám do zoznamu.  public List<Hrac> vytvorHracov() { ArrayList<Hrac> hraci = new ArrayList<>(); for(int i = 0; i < pocetHracov; i++){ Hrac hrac = ovladanieHry.getMenoHraca(i+1); hraci.add(hrac); } return hraci; }Logiku hry spustím a teda začnem ju hrať keď zavolám metódu zacniHrat.  public void zacniHru() { HraCiernyPeter ciernyPeter = new HraCiernyPeter(); //vseobecna logika ku kazdej hre balikKariet = vytvorBalik(ciernyPeter.vytvorKarty()); balikKariet.zamiesajKarty(); //rozdaj karty z baliku ciernyPeter.rozdajKarty(this); // pre hru urcim prveho hraca // v ciernom petrovi je to hrac s najviac kartami a ten zacina tahat Hrac prvyHrac = ciernyPeter.getHracaSNajviacKartami(getHraci()); //vsobecne na zaklade prveho hraca zistim jeho poradie v zozname hracov v hre int prvyHracIndex = getHraci().indexOf(prvyHrac); ciernyPeter.zlozHracomParyZRuky(this); ciernyPeter.odstranHracovZHry(this); if(!ciernyPeter.jeKoniecHry(this)){ //idu do kruhu az kym hraju aspon dvaja hraci ciernyPeter.kolobehHry(this,prvyHracIndex); } }Tu si vytvorím inštanciu triedy HraCiernyPeter, ktorá má na starosti logiku, ktorá je špecifická práve pre tento typ hry. Tú si vytvoríme neskôr.  Na tomto mieste si vytvorím aj balík kariet pomocou kariet, ktoré sa vytvárajú v triede HraCiernyPeter. Keďže som zvolil názvy metód také, aby sa ľahko chápali, tak tušíme čo dané metódy robia. Keď vytvorím balík a idem hrať, tak karty pomiešam, potom ich rozdám hráčom.  Musím si určiť, ktorý hráč začína ako prvý. V čiernom petrovi je to ten, čo má najviac kariet.  Ako sme si povedali na začiatku, tak keď majú hráči rozdané karty, tak si zložia všetky páry a tým sa zbavia nejakých kariet. Skontrolujem či azda niekto nemal všetko páry na ruke a tým pádom skončil v hre. Spýtam sa, či je koniec hry – či ostal len jeden hráč, ktorý má čierneho petra – lebo táto karta nemá pár. Ak nie, tak začnem kolobeh hry.  V tejto triede mám aj iné pomocné triedy. Skús si ich prejsť sám.  package sk.jaro.CiernyPeter; import sk.jaro.CiernyPeter.gui.OvladanieHry; import java.util.ArrayList; import java.util.List; public class Hra{ private BalikKariet balikKariet; private int pocetHracov; private List<Hrac> hraci; private OvladanieHry ovladanieHry; public Hra() { this.ovladanieHry = new OvladanieHry(); this.pocetHracov = ovladanieHry.vyberPocetHracov(); this.hraci = vytvorHracov(); } public BalikKariet getBalikKariet() { return balikKariet; } public List<Hrac> getHraci() { return hraci; } public OvladanieHry getOvladanieHry() { return ovladanieHry; } public List<Hrac> vytvorHracov() { ArrayList<Hrac> hraci = new ArrayList<>(); for(int i = 0; i < pocetHracov; i++){ Hrac hrac = ovladanieHry.getMenoHraca(i+1); hraci.add(hrac); } return hraci; } public BalikKariet vytvorBalik(List<Karta> karty) { return new BalikKariet(karty); } public void odstranHracaZHry(Hrac hrac) { //ak ma prazdnu ruku odstranim ho if(hrac.getKartyVRuke().isEmpty()){ getHraci().remove(hrac); } } public void ukonciHru() { ovladanieHry.vypisKtoPrehral(this); } public void zacniHru() { HraCiernyPeter ciernyPeter = new HraCiernyPeter(); //vseobecna logika ku kazdej hre balikKariet = vytvorBalik(ciernyPeter.vytvorKarty()); balikKariet.zamiesajKarty(); //rozdaj karty z baliku ciernyPeter.rozdajKarty(this); // pre hru urcim prveho hraca // v ciernom petrovi je to hrac s najviac kartami a ten zacina tahat Hrac prvyHrac = ciernyPeter.getHracaSNajviacKartami(getHraci()); //vsobecne na zaklade prveho hraca zistim jeho poradie v zozname hracov v hre int prvyHracIndex = getHraci().indexOf(prvyHrac); ciernyPeter.zlozHracomParyZRuky(this); ciernyPeter.odstranHracovZHry(this); if(!ciernyPeter.jeKoniecHry(this)){ //idu do kruhu az kym hraju aspon dvaja hraci ciernyPeter.kolobehHry(this,prvyHracIndex); } } }Logika hry Čierny PeterV tejto časti si vytvoríme karty špecifické pre túto hru. Teda 16 párov a jedného čierneho petra.  public List<Karta> vytvorKarty() { ArrayList<Karta> karty = new ArrayList<>(); int j = 1; for(int i = 0; i < 16; i++, j=j+2){ karty.add(new Karta(j, i)); karty.add(new Karta(j+1, i)); } karty.add(new Karta(33,-1)); //Čierny Peter return karty; }Keď rozdávam karty, tak ich rozdávam po jednej. Táto metóda by mohla byť aj v triede Hra, ale teoreticky pre iné typy hier by sa karty rozdávali inak. Tu rozdávam všetky karty.  Z balíku kariet zoberiem prvú kartu, z balíka ju odstránim a dám ju hráčovi do ruky. Tu je taký fígeľ, že idem cez všetky karty a robím modulo nad poradím karty s počtom hráčov, to mi zaručí, že budem dookola prechádzať hráčov až kým neskončí balík.  public void rozdajKarty(Hra hra) { BalikKariet balikKariet = hra.getBalikKariet(); List<Hrac> hraci = hra.getHraci(); int pocetKariet = balikKariet.getKarty().size(); for(int i = 0; i<pocetKariet;i++){ Hrac hrac = hraci.get(i%hraci.size()); hrac.getKartyVRuke().add(balikKariet.getKartu()); } }Keď sa chystám odstrániť hráčov z hry (keď nemajú už žiadne karty na ruke), tak ich nemôžem odstrániť počas toho ako cez nich prechádzam (iterujem). Preto si ich dávam do pomocného zoznamu a až po iterácii ich odstránim.  public void odstranHracovZHry(Hra hra) { //nemôžem mazať hraca z kolekcie ak cez nu prechadzam, preto si vytvorim novy zoznam a odstranim potom ArrayList<Hrac> hraciNaOdstranenie = new ArrayList<>(); for(Hrac hrac : hra.getHraci()){ //skontrolujem ci uz niekto neskoncil, teda ma prazdnu ruku //ak ano odstranim ho z hry if(hrac.getKartyVRuke().isEmpty()){ hraciNaOdstranenie.add(hrac); } } for(Hrac hrac : hraciNaOdstranenie){ hra.odstranHracaZHry(hrac); } }Keď niekomu zoberiem kartu z ruky, tak každému z tých hráčov pomiešam karty. Jednému hráčovi zoberiem kartu z kolekcie kartičiek čo má na ruke a druhému pridám do kolekcie ďalšiu kartu.  public void zoberHracoviKartu(Hrac hrac1, Hrac hrac2, Hra hra) { int poradieZobranejKarty = hra.getOvladanieHry().zoberKartu(hrac1,hrac2); Karta vzataKarta = hrac2.getKartyVRuke().get(poradieZobranejKarty); hrac1.getKartyVRuke().add(vzataKarta); hrac2.getKartyVRuke().remove(vzataKarta); //pomiesam karty v ruke Collections.shuffle(hrac1.getKartyVRuke()); Collections.shuffle(hrac2.getKartyVRuke()); }Samozrejme kolobeh hry ide nasledovne. Hráme dovtedy, kým nám v hre ostanú aspoň dvaja hráči. Začínam u prvého hráča, ktorý zoberie kartu druhému hráčovi. A tu som si natrafil na chybu. Predsa hráč s najväčším počtom kariet neťahá ale malo by sa ťahať jemu teda, ten čo je za ním ťahá od neho. Tak tu si to môžete opraviť, to nechám na vás. Pomôcka: upravte index prvého hráča v triede Hra, ak si pamätáte, tam sme ho určili.  public void kolobehHry(Hra hra, int prvyHracIndex) { while (hra.getHraci().size() > 1) { int pocetHracov = hra.getHraci().size(); Hrac hrac1 = hra.getHraci().get(prvyHracIndex%pocetHracov); Hrac hrac2 = hra.getHraci().get((prvyHracIndex + 1)%pocetHracov); zoberHracoviKartu(hrac1, hrac2,hra); zlozHracomParyZRuky(hra); odstranHracovZHry(hra); if(jeKoniecHry(hra)) { break; } prvyHracIndex++; } }Tu je potom celý kód triedy aj s inými pomocnými metódami.  package sk.jaro.CiernyPeter; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class HraCiernyPeter { public List<Karta> vytvorKarty() { ArrayList<Karta> karty = new ArrayList<>(); int j = 1; for(int i = 0; i < 16; i++, j=j+2){ karty.add(new Karta(j, i)); karty.add(new Karta(j+1, i)); } karty.add(new Karta(33,-1)); //Čierny Peter return karty; } public void rozdajKarty(Hra hra) { BalikKariet balikKariet = hra.getBalikKariet(); List<Hrac> hraci = hra.getHraci(); int pocetKariet = balikKariet.getKarty().size(); for(int i = 0; i<pocetKariet;i++){ Hrac hrac = hraci.get(i%hraci.size()); hrac.getKartyVRuke().add(balikKariet.getKartu()); } } public Hrac getHracaSNajviacKartami(List<Hrac> hraci) { int max = 0; Hrac hracMax = null; for(Hrac hrac : hraci){ int size = hrac.getKartyVRuke().size(); if(max < size){ max = size; hracMax = hrac; } } return hracMax; } public void zlozHracomParyZRuky(Hra hra) { for(Hrac hrac : hra.getHraci()) { hrac.odstranParyZRuky(); } } public void odstranHracovZHry(Hra hra) { //nemôžem mazať hraca z kolekcie ak cez nu prechadzam, preto si vytvorim novy zoznam a odstranim potom ArrayList<Hrac> hraciNaOdstranenie = new ArrayList<>(); for(Hrac hrac : hra.getHraci()){ //skontrolujem ci uz niekto neskoncil, teda ma prazdnu ruku //ak ano odstranim ho z hry if(hrac.getKartyVRuke().isEmpty()){ hraciNaOdstranenie.add(hrac); } } for(Hrac hrac : hraciNaOdstranenie){ hra.odstranHracaZHry(hrac); } } public boolean jeKoniecHry(Hra hra) { if(hra.getHraci().size() < 2){ hra.ukonciHru(); return true; } return false; } public void zoberHracoviKartu(Hrac hrac1, Hrac hrac2, Hra hra) { int poradieZobranejKarty = hra.getOvladanieHry().zoberKartu(hrac1,hrac2); Karta vzataKarta = hrac2.getKartyVRuke().get(poradieZobranejKarty); hrac1.getKartyVRuke().add(vzataKarta); hrac2.getKartyVRuke().remove(vzataKarta); //pomiesam karty v ruke Collections.shuffle(hrac1.getKartyVRuke()); Collections.shuffle(hrac2.getKartyVRuke()); } public void kolobehHry(Hra hra, int prvyHracIndex) { while (hra.getHraci().size() > 1) { int pocetHracov = hra.getHraci().size(); Hrac hrac1 = hra.getHraci().get(prvyHracIndex%pocetHracov); Hrac hrac2 = hra.getHraci().get((prvyHracIndex + 1)%pocetHracov); zoberHracoviKartu(hrac1, hrac2,hra); zlozHracomParyZRuky(hra); odstranHracovZHry(hra); if(jeKoniecHry(hra)) { break; } prvyHracIndex++; } } }[Image]MainNakoniec som si vytvoril triedu s jednou main metódou, ktorá sa nám bude volať pri spustení programu.  public static void main(String[] args) { Hra hra = new Hra(); hra.zacniHru(); } Celý Java program si vieš stiahnuť odtiaľto. TODO - úloha pre tebaDorobte výpis, aké karty boli hráčovi odstránené z ruky, keď zložil páry. Spravte ďalšie podmienky pri zadávaní údajov od používateľa, aby nebral karty, ktoré niekto nemá v ruke a podobne.   Autorom tohto blogu je Jaro Beňo, autor Java online kurzu, ktorý môžeš na Learn2Code študovať zadarmo.
Klávesové skratky v Exceli
Tipy a triky
05.07.2017
Skillmea

Klávesové skratky v Exceli

Pripravili sme pre teba zoznam klávesových skratiek pre Excel 2010. Tento blog popisuje najpoužívanejšie klávesové skratky, funkčné klávesy a niektoré ďalšie bežné klávesové skratky pre Microsoft Excel 2010 pre Windows. Ak používaš Mac, namiesto Ctrl je potrebné použiť klávesu Cmd. Kopírování Ctrl + C Kopírování Ctrl+X Vystřižení Ctrl + V Přilepení Formátování Ctrl+B Změní text na tlustý Ctrl+I Změní text na kurzívu Ctrl + U Podtrhne text Ctrl + = Přidá vnější orámování Práce se souborem F12 Uložit jako Ctrl + O Otevření stávajícího sešitu Ctrl+N Vytvoření nového sešitu Ctrl+S Uložení sešitu Výběr buněk Ctrl+Home Přesune kurzor do první buňky Podržte Ctrl a můžete označit více objektů najednou Shift Označte první objekt, podržte Shift a označte poslední objekt Ctrl + A Označí celou tabulku ve které se nachází právě označená buňka Ctrl + ← Přesune kurzor doleva na začátek tabulky Ctrl + → Přesune kurzor doprava na konec tabulky Ctrl + ↑ Přesune kurzor nahoru na začátek tabulky Ctrl+↓ Přesune kurzor dolů na konec tabulky Ctrl + mezera Označí celý sloupec Shift + mezera Označí řádek F2 Úprava textu právě označené buňky Různé Ctrl + F Najde nebe nahradí text Ctrl+Z Přesune o 1 krok dozadu Ctrl+Y Přesune o 1 krok dopředu F4 Změní adresu buňky z relativní na absolutní a naopak Ctrl + , Zobrazí nebo skryje všechny vzorce F1 Zobrazí nápovědu Ctrl + F1 Zobrazí nebo skryje pásy na hlavním panelu Alt + F8 Otevře nabídku pro nahrávání maker Shift + F2 Vloží do buňky komentář Súbor s klávesovými skratkami v Exceli si môžeš stiahnuť odtiaľto. Plus bonusová časť: videotutoriál, ako si upraviť vzhľad Excelu podľa svojich preferencií.