Tipy a triky

V této sekci naleznete praktické rady a doporučení, jak efektivně využívat vzdělávací kurzy přes úřad práce k získání nových dovedností. Tipy a triky jsou navrženy tak, aby vám pomohly zvládnout běžné úkoly rychleji a efektivněji. Tato kategorie je skvělým místem pro ty, kteří hledají způsob, jak se neustále zlepšovat.

Java nejnovější verze (Java 9): příkazový řádek JShell (2. část)
Tipy a triky
21.03.2019
Skillmea

Java nejnovější verze (Java 9): příkazový řádek JShell (2. část)

Java příkazový řádekJShell Command Line je nástroj, kde můžeme zkoušet spouštět kód, aniž bychom museli vytvořit novou třídu s main metodou.[Image]JShell spustíme z bin adresáře, kde máme nainstalovanou jevu jdk ve verzi 9 a více. Při učení se preferuje použít verbose mód jshellu, což nám poskytne co nejvíce zpětné vazby při práci s konzolí. jshell –v Pokud jshell spustil bez –v můžeš jshell vypnout s příkazem /exit a pak spustit znovu s –v nastavením. Nyní můžeš zadávat výrazy. První způsob je zadeklarovat proměnnou s hodnotou a následně hodnotu vypsat:[Image]Nebo můžeš rovnou napsat výraz, který se vyhodnotí a výsledek se zapíše do proměnné, která obdrží pořadové číslo.[Image] Je možné deklarovat metody. Při psaní příkazů, pokud jshell zjistí, že příkaz není ukončen, například si napsal kadeřavou závorku a zmáčkneš enter, tak se vytvoří nový řádek na jehož začátku budou speciální znaky ...> což znamená, že pokračuješ v psaní kódu a výraz se ještě nevyhodnotí.[Image] Metodu pak voláš klasicky:[Image] Pokud bys chtěl přepsat metodu, respektive co dělá uvnitř, tak ji umíš napsat znovu a ona se přepíše a platná bude poslední napsaná. Lze také přepsat typ proměnné. Pokud na začátku bude x číslo, tak později může být String.[Image]Pod výpisy máme vždy i poznámky o tom, co se děje na pozadí. Například, že proměnná x byla nahrazena za String. Můžeš napsat metodu, která uvnitř používá proměnné nebo metody, které ještě nebyly definovány. Fungovat budou až když všechno zadefinuješ. Příkazem /list si zobrazíš kód, který jsi napsal. Každý vstup má číslo, což představuje id vstupu. Tyto id slouží i při výjimkách. Napište si příkaz, který spadne a vypíše se výjimka.[Image]Po výpisu /list zjistíme co znamenají čísla ve výpisu. Za prvé tam máme: at divide (#15:2), což znamená, že chyba nastala na příkazu s id 15 a řádku 2 toho příkazu. Za druhé at (#16:1) je další místo, kde se metoda jmenovala – klasický stack trace, ale s odkazem na /list výpis.[Image]Jshell nabízí také možnosti k doplnění, když stiskneme tab. Pokud do konzole napíšu Sy a zmáčknu tab, tak mi nabídne možnosti. Pak napíšu-li System. a zmáčknu tab, tak mám další možnosti vypsány. A tak dále.[Image]Zde se dostáváme k tomu, že umíme používat klasické dostupné api. Jako například String metody. V konzole jsem napsal prázdný String tečku a stiskl tabulátor.  [Image]Pokud některé třídy nejsou dostupné, tak je umíme importnout. Při psaní umíme typu stiskneme Shift + Tab a pak písmeno i, chceme-li importnout. Potom máme možnost udělat nic nebo importovat.[Image]Do shellu umíme psát i shell specifické prkazy. Setkali jsme se už s /list. Existují i další, například /methods pro výpis dostupných metod, /vars pro výpis dostupných proměnných, nebo /list –all pro výpis všeho i importů i chybně zadaných příkazů. Všechno, co jsme napsali, úspěšně si umíme uložit do souboru pomocí příkazu /save nazevSouboru.txt. Tento soubor je uložen ve složce bin, kde jsme spustili jshell, pokud nezadáme jinak. Znovu umíme tento program otevřít pomocí /open a název souboru. I u těchto příkazů funguje doplňování po stisku tabulátoru.[Image]Je možné psát zkratky příkazů, jsou-li ty zkratky unikátní. Jediný příkaz, který začíná na písmeno l je dopis, tedy lze napsat /l. Totéž platí i pro příkazy pro /l pokud dáme pomlčku a tab, tak dostanu možnosti. Příkaz, který začíná na a je jen jeden tak můžu napsat /l –a místo /list –all.[Image] Tento příkaz jsem spustil nad čistou novou jshell, tak si můžeme prohlédnout, co je importováno jako default. Přiblížili jsme si základní možnosti nastavení příkazové řádky JShell, je jich ale daleko více. Pokud máš zájem se do této problematiky "zavrtat" hlouběji, můžeš si prohlédnout kompletní tutoriál.  Ptáš se „proč Java“? Java je jeden z nejpoužívanějších programovacích jazyků na světě. Pokud se o Javu zajímáš (je jedno, jestli jsi začátečník, nebo už programuješ), připravili jsme pro tebe mnoho kurzů.
Jak se nepředávkovat návody
Tipy a triky
10.02.2019
Lubo Herkoo

Jak se nepředávkovat návody

Tak. Rozhodl ses naučit programovat (na learn2code jsi správně!). Je jedno, jestli chceš být Web Developer (FrontEnd, BackEnd), chceš se vzdělávat v konkrétním jazyce (PHP, JavaScript, Java, C#), nebo ses ještě nerozhodl, a chceš se jen naučit programovat. I když kniha má své kouzlo, můžeš ji číst i elektronicky, s videem to však jde nejrychleji. Tvoji rodiče si při pohledu na Tebe možná myslí, že mrháš časem, Ty však víš, že investuješ do sebe. Správně! Nad kurzy můžeš strávit dlouhé hodiny. Některé z nich mají i více modulů. Každý má však i svůj konec. Záměr autora kurzu přece nebyl získat sledovanost pro jeho videa, ale chtěl tě něco naučit. Možná ses už ocitl v tom začarovaném kruhu, kdy po ukončení jednoho kurzu hledáš hned další, který tě posune na vyšší úroveň. A pak další a další.. Na vyšší úroveň však už tutoriály a přepisování kódu z obrazovky nestačí. Ani jednoduché zadání lektorů z video kurzů nejsou dostačující. Na vyšší úroveň je třeba praxe, je třeba tvořit, pracovat na projektech, vytvářet portfolio.[Pokud se chceš opravdu posunout v programování vpřed, pusti se do zajímavého projektu.] Portfolio programátoraV zajímavém CV nemusí být mnoho projektů. Ten, kdo ho bude číst ví, jestli Tvé portfolio obsahuje zajímavé projekty, kde ses setkal s nějakými výzvami. Při absolvování kurzů si možná vytvořil jednoduchou aplikaci pro správu poznámek v Markdown formátu. Nebo sociální síť, Twitter podle tvé chuti. Všechno jsou to však projekty, které každý zná a ví, že najdeš kopec zdrojů jako takovou aplikaci napsat a tvorba takového projektu byla jen jakýmsi light fitness pro tvou hlavu. Nejdůležitější na tom však je, že ty projekty nejsou tvé. Tvůj projekt přece začíná prázdnou složkou, možná vytvořením index.html souboru, pokračuje nekonečným Google hledáním řešení tvých front-end nebo back-end problémů, implementacemi tvých vylepšení, tvých řešení, testů a refactoringu tvého kódu. V repozitáři vidět, jak dlouho jsi na projektu pracoval a jak se projekt vyvíjel. Při práci na projektech nestojíš na jednom místě, ale tvoříš, učíš se a rosteš.[Při práci na projektech nestojíš na jednom místě, ale tvoříš, učíš se a rosteš.] Na čem tedy začít makat?Každý programátor si dobré nápady na aplikace chrání. Návštěva programátorského fóra s otázkou typu “Nemáte náhodou nápad na nějaký zajímavý projekt?” bude spíše cílem posměchu než zdrojem nápadů pro tvé projekty. Nezoufej, mám pro Tebe několik rad, jak svůj mozek nenechat oddychovat příliš dlouho. Projekty jsem nevymyslel sám, většinou jsou to projekty inspirované stávajícími aplikacemi nebo všeobecně známá zadání. Přidal jsem k nim však také odkazy na dokumentaci, aby si netrávil čas hledáním kde a jak začít. Některé projekty možná nekorespondují s tvojí ideovou představou a mohou být méně zajímavé, když se však rozhodneš na něm pracovat získáš hned několik výhod: • Nestojíš na jednom místě, ale tvoříš, učíš se, rosteš, • setkáváš se s problémy (věř mi, bude jich čím dál tím méně), na které hledáš řešení, • objevuješ nové způsoby řešení problémů, tvoje stará řešení už nestačí, nebo jsou neefektivní. Level 1 - jednoduché projektyLunch picker • Taková appka již existuje, ale udělej vlastní verzi. Podstata je, že vždy když se neumíš rozhodnout, kam s kámoši půjdeš na pivo, nech to na výpočetní sílu. • Zadanie môže mať dve úrovne: První úroveň je, že databázi míst na „zábavu“ si vytvoříš sám a appka náhodně vybere některou z nich. Druhá úroveň by byla, pokud použiješ některé stávající API (Google Reviews), které tě umí lokalizovat a databázi získáš odtamtud. Collection tracker • Publikuj svou sbírku "čehokoli" ve formě katalogu. Promysli strukturu každé položky, zkus je kategorizovat, implementovat vyhledávání. Jednoduchý projektík o něčem, co tě skutečně baví. • Zadání může mít dvě úrovně: První ve formě jednoduché MVC aplikáce s Bootstrapom, napsaná v Laraveli nebo RubyOnRails. Větší skiller si může troufnout navrhnout API a design implementovat v některé JS library - VueJS, React.  Spoiler blocker pro články • Znáš to – píšeš recenzi některého oblíbeného filmu nebo knihy a nechceš čtenáře tvého textu nepříjemně překvapit vyzrazením děje, nebo klíčové informace. Podobně jako fungují "Zobrazit více" odkazy, můžeš takovou informaci ukrýt i pod "Spoiler alert" odkaz. Spoiler v textu můžeš oddělit pomocí data atributu pro tvůj <p> element: <p data-spoiler="true">Spoiler text...</p>. • Zadání může mít dvě úrovně: První ve formě jednoduchého inline javascriptu, který spustíš někde na konci svého textu pomocí <script> tagu. Druhá úroveň ve formě malé knihovny s využitím Module Pattern, kterou může použít ve svém Wordpressu kdokoli. Tax forecaster • I když politici se nás snaží přesvědčit, že si zasloužíme jistoty, jedinou jistotou v životě jsou daně. Navrhni nějakou jednoduchou appku, která bude sbírat částky tvých freelance faktur na základě vzorce, který zjistíš online (a naučíš se přitom i proč platíš tolik na daních). • Zadání může mít dvě úrovně: První úroveň je samotný jednoduchý výpočet – zadáš číslo a dostaneš hodnotu, kterou zaplatíš státu. Druhou úrovní může být databáze s historií tvých FA a implementace grafů, kde můžeš s pomocí knihovny D3.js vylíčit pěkné reporty, kolik jsi vydělal a jak se tvůj výdělek vyvíjel. Pokud tě vystrašila dokumentace D3.js, můžeš se zkusit pohrabat v knihovnách, které používání D3js zjednodušují. FlashCard generator • Pokud jsi ve stádiu učení (co bys měl být neustále) a snažíš se zapamatovat si některé důležité informace, koncepty nebo cokoli, osvědčená technika pamatování si věcí jsou FlashCards. Navrhni appku, která si z databáze nebo JSON objektu vybere pole dvojic, kde prvním prvkem dvojice bude nějaký stručný popis a druhým prvkem bude informace, kterou si máš zapamatovat. Zde je inspirace. • Zadání může mít dvě úrovně: První je implementace, jakou použili v ThoughtBot – tedy informace, kterou se snažíš naučit se jen objeví pod heslem. Druhou úrovní může být využití CSS pro zajímavou animaci, aby to vizuálně vypadalo jako opravdové „otočení karty“. Level 2 - středně náročné projektyBring your umbrella • Pokud nestíháš ráno sledovat počasí, automatizuj to. Napiš appku (nejvíce se asi hodí mobilní appka, ale užitečná může být i webová aplikace), která tě lokalizuje as využitím API ti připomene, aby sis nezapomněl vzít sebou deštník - v okolí tvé lokality bude totiž pršet. Webová appka ti může poslat e-mail oznámení. • Zadání může mít dvě úrovně: První může být aplikace bez grafického rozhraní. Druhou může být plnohodnotná weather appka přizpůsobená tvým potřebám a grafickým nárokům. Music suggestion app • Spotify má také své API. To můžeš použít k vytvoření seznamu skladeb, který budeš tvořit na základě poslouchaných skladeb, jejich žánru a jiných dostupných dat. Takhle získáš data o skladbě, kterou uživatel právě poslouchá. Tu je dokumentace, jak pracovat s playlistem. Expense tracker • Ve formě mobilní appky nebo webové aplikace můžeš vytvořit také svůj tracker příjmů a výdajů. Jejich kategorizace a kreslení grafů by mělo být samozřejmostí. Pokud se ti podaří vyřešit problém manuálního zadávání bločků, dej mi vědět – do takové aplikace rád zainvestuji. V Datamolino už vědí jak na to. • Největší challenge u tohoto projektu je asi UI/UX – aplikace by se mohla učit mé zvyky a inteligentně mi podsouvat data (kategorizaci, tagy) podle historie mých nákupů při vytváření jednotlivých položek. Na základě těchto tagů a kategorií mi oznámit, kde bych mohl příště ušetřit. Downtime tracker • Pokud máš oblíbený web, nebo plánuješ několik svých projektů, můžeš testovat, jestli náhodou tvé aplikace nemají nějaký problém. Jednoduchým scriptem přistoupíš na URL své aplikace a pokud skript nevrátí HTTP Response 200, tak tě tracker notifikuje emailem, že se něco děje. • Zadání může mít dvě úrovně: První úrovní může být notifikace emailem. Druhou úrovní může být notifikace pomocí SMS brány (Twilio), nebo web hook do tvého Slacku - pokud používáš slack. Level 3 - náročnější projektySlack bot • Znáš-li Slack a inspiruje tě automatizace, programování botů je nyní in. Některé vývojářské týmy denně absolvují "standup" - odpoví na jednoduché otázky týkající se aktuálního projektu/zadání (na čem pracují, v jakém jsou stádiu, zda se na něčem zdrželi a podobně). S pomocí Slack API můžeš vytvořit jednoduchého bota, který kontaktuje vývojáře z tvého týmu a zeptá se jich pár otázek. Jejich odpovědi můžeš sesbírat a vyhodnotit v jedné zprávě, kterou odešleš do #dev kanálu. Microlearning app • Denně bys měl věnovat nějaký čas svému vzdělávání – abys jako programátor rostl. Pokud se učíš například React nebo VueJS - můžeš zkusit použít (nebo napsat vlastní) web scrapper a získat tak jednotlivé sekce dokumentace. Denně ti tvoje microlearning aplikace může poslat jednu sekci/stránku z této dokumentace e-mailem ke studiu. Web scraper • Najdi svůj oblíbený e-shop a zkus vytvořit vlastní databázi jeho produktů, kategorií spolu s obrázky. Web scraping je zajímavým a ne jednoduchým tématem pro programátory, protože ke každému webu, který chceme scrapovat musíme přistupovat individuálně. Hint: Před tím, než se pustíš do scrapování některé domény, zkontroluj v nazev-domeny.cz/robots.txt, zda náhodou doména nemá blokovaných některých botů. Quiz Maker • Pokud se nudíš, můžeš přispět ik efektivitě našeho školství. Když jsem učil já, učitelé používali Hot Potatoes jako jejich testovací platformu. Nebo vytištěné testy s kolonkami. Vstupem do tvé quiz platformy může být JSON, který bude obsahovat vhodně zvolenou strukturu testovacích otázek, možných odpovědí a označení správné odpovědi. • Zadání může mít tři úrovně: První může být vygenerování testu z holého .json souboru. Druhou může být vytvoření administračního rozhraní, kde si testující dotazy a možné odpovědi vykliká ve formuláři. Třetí úrovní může být implementace různého typu testovací otázky (jedna správná odpověď, více správných odpovědí, dopsání správné odpovědi, seřazení do správného pořadí, vytvoření správných párů, ...) Browser extension • Nastuduj jak pracují browser pluginy a zvýš svou produktivitu blogováním distraktorů. Inspirací ti může být BlockSite – výborný extension pro blokování stránek. Blokování stránek však nemusí být jediný tip na doplněk do prohlížeče. Doplňky jsou fajn pro zvýšení produktivity, tedy různé poznámkové doplňky, časovače (pomodoro), pořízení snímku z aktuální stránky a leccos možné. Programátorské výzvy - algoritmické úkolyPokud nehledáš nápad na projekt, ale raději by ses zdokonalil v řešení algoritmických úkolů, mám tu něco i pro Tebe: 1. Advent of code • Adventní kalendář programátora (každý rok obsahuje nová zadání). Obsahuje 25 zadání orientovaných na procvičování algoritmického myšlení. Ideální pro ranní probuzení mozku, některé úkoly však mohou zabrat více času. Součástí je i leaderboard, tam se já raději ale nedívám. • Zadání můžeš řešit v kterémkoli jazyce 2. Project Euler • Podobně jako Advent of Code, i toto je sbírka zadání, která jsou však už jen archivem. To ovšem neznamená, že neobsahuje dostatek zadání - je jich tam téměř 650. Při každém zadání je uveden i počet lidí, kteří zadání vyřešili. • Zadání můžeš řešit v kterémkoli jazyce 3. Daily Coding Problem • Toto je mailinglist, který ti každý den pošle jeden programátorský problém, který můžeš rozlousknout. Problémy z této banky pocházejí z pracovních pohovorů ve firmách, jako jsou Google, AirBnB, Facebook, Apple a různé jiné. Jejich obtížnost je proto někdy dosti vysoká. Pokud se ale připravuješ na pracovní pohovor, tyto úkoly ti mohou pomoci. • Nevýhodou je, že k řešením se dostaneš až když si je předplatíš. Abychom to shrnuli. Hodnota každého programátora se ukrývá v jeho portfoliu. Jsou to právě tvé vlastní projekty, které tě budou reprezentovat na pohovoru, které tě odliší od konkurence. V článku jsme ti poskytli tipy na zajímavé projekty, které obohatí tvé CV, ale především posunou tě dál, postaví před nové výzvy a překážky. A to jako dobrý programátor určitě potřebuješ.
Java persistence – JPA, Hibernate, ORM
Tipy a triky
05.02.2019
Skillmea

Java persistence – JPA, Hibernate, ORM

JPA je java persistence api specifikace. K tomu, abys mohl používat JPA ve skutečné aplikaci, potřebuješ implementaci JPA. Buď použiješ servery, které již nabízejí implementaci JPA, jako například GlassFish, nebo použiješ implementaci, kterou ti poskytuje framework Hibernate nebo EclipseLink. Pokud používáme JPA standardy, tak je v budoucnu úplně jedno, jakou implementaci JPA budeme používat. Při programování budeme používat JPA anotace, které pocházejí z balíku javax.persistence. V budoucnu můžeš nasadit aplikaci na GlassFish, který zná javax.persistence a umí s tím pracovat nebo na Tomcat s použitím Hibernate, který také zná javax.persistence a umí s tím pracovat. Co je Persistence?Pokud vytvoříš ledajaký jednoduchý objekt, co se stane? Například objekt Adresa? Vytvoří se v haldě – v paměti. Objekt může mít nasetována nějaká data – informace. Pokud se ale ztratí reference v javovském kódu na tento objekt v haldě - tak se smaže. Pokud si chceme uchovat tyto informace, tak je můžeme uložit do databáze a nejlépe, aby po vytažení z databáze měla tato data stejnou formu – tedy formu objektu Adresa. Tomu se říká, že persistujeme (uchováme stálost) objekt do databáze. Jako by tento objekt existoval i mimo java programu. Tento objekt se uchová v úložišti a znovu se vytvoří, bude-li třeba. Co je ORM?Klasické databáze jako Oracle, MySql a podobně jsou relační databáze, které mají data uložena ve formě tabulek. V jevu ukládáme data ve formě objektů, v databázi ve formě tabulek. Ale co mají podobné? V relační databázi máme sloupce, které mají názvy a v řádcích máme hodnoty. Něco jako klíč hodnota – totéž platí i pro objekty v jevu – tam máme název proměnné a hodnotu v ní uloženou. Tady přichází pod ruku ORM – tedy object relational mapping. Je to něco jako objektově relační mapování. My naše java objekty namapujeme na tabulky relační databáze. Abychom věděli, že toto pole v javovském objektu patří do tohoto sloupce.  Objekty v jevu jsou mezi sebou propojeny pomocí uložení reference na daný objekt. Například člověk má field Adresa, kde je uložena reference na objekt Adresa. Relační tabulky mají mezi sebou také vazby. Buď máme v tabulce pro člověka sloupec adresa, kde bude uložen identifikátor adresy a na základě tohoto identifikátoru najdeme danou adresu. Nebo existuje speciální tabulka, kde budou dva sloupce jeden pro identifikátor adresy a druhý pro identifikátor člověka. My pak umíme najít, jaké adresy má člověk nastaveno, nebo pro jakého člověka je nastavena daná adresa. [Image] Problém s JDBC přístupem – výhoda ORMV kurzu Java pro pokročilé , pokud jsi tento kurz viděl, jsme si ukazovali přístup k databázi přes JDBC. Co jsme udělali? Otevřeli jsme konekci na databázi, napsali jsme sql příkaz, který jsme následně poslali do databáze k provedení. Databáze nám vrátila výsledek ve formě result setu. Představ si, že máš jen 5 až 10 tabulek. Nad každou tabulkou máš například 4 různé sql příkazy - to máme přibližně 20 - 40 sql příkazů. Pokud se ti stane, že musíš změnit databázi – například změníš název sloupce v tabulce? Co musíš udělat? Musíš přepsat název tohoto sloupce na xy místech – na 20 až 40 místech – a to jsme jen v malé aplikaci – co kdyby to bylo na 100 místech?. Byl by v tom nepořádek a mohly by nastat problémy. Pokud ale použijeme ORM, tak v jevu pracujeme s naším kódem, tak jako běžně. Vytvoříme si objekty typu Clovek, nastavíme mu nějaké hodnoty. Dále si vytvoříme kolekci adres pro daného člověka. Nakonec v ORM frameworku řekneme jen persistní mi tento objekt. ORM se pak postará o veškeré uložení těchto objektů do databáze na základě mapování, které 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); Pokud bychom nepoužili ORM, sami bychom museli napsat metodu, která nám otevře konekci na databázi, museli bychom napsat INSERT SQL příkaz pro člověka a poté i pro jeho adresy a museli bychom zajistit, abychom nastavili všude data tam, kde mají být a musíme se postarat io propojení mezi těmito dvěma objekty. Pokud ale použijeme ORM, tak se nemusíme starat o tento balast kódu, ale soustředit se zejména na to, co prodává a to je business logika aplikace. Nevýhody JDBC přístupu jsou tedy, že máme příliš mnoho SQL příkazů, velmi mnoho kopie kódu, ručně se musíme postarat o nastavení dat do správných sloupců. Výhodou ORM je, že nemusíme dělat tyto věci z předchozí věty. ORM nám umožní používat java objekty k reprezentaci relační databáze. ORM se nám postará io propojení závislostí. ORM spojí výhody relační databáze a objektového modelu v jevu plus schová veškerou komplexitu SQL příkazů. Co je Hibernate?Hibernate je ORM – object relational mapping framework, který slouží k mapování java objektů na tabulky relačních databází. Java programátoři jsou zvyklí psát kód v objektech, proč tedy potřebují další jazyk – sql – k získání dat z databáze? Hibernate na pozadí sám vytváří sql příkazy nad databází a proto nemusíme psát sql příkazy my. Pokud chceme uložit mapu objektů, například Cloveka, který má Adresu, nebo i více objektů typu Adres, tak nemusíme psát všechny sql příkazy. Stačí, když zavoláme jednoduchou metodu pro uložení objektu do databáze a hibernate se postará o zbytek. Hibernate je také implementace JPA.  [Image] Co je JPA?Zkratka JPA je Java Persistence API. Co to znamená? V jednoduchosti řečeno - je to standard. Poněkud složitěji řečeno – je to specifikace pro OR mapování a je součástí Java EE, ale můžeme ji používat i v Java SE projektech. Některé servery poskytují vlastní implementaci JPA a některé ne – v tom případě použijeme například Hibernate implementaci. Představ si, že celý tvůj kód používá věci z JPA. Nyní je na tobě, kam nasadíš svoji aplikaci. Pokud ji nasadíš na Glassfish nemusíš předělávat svůj kód, který používá JPA – Glassfish ho zná. Pokud svou aplikaci nasadíš na Tomcat, tak mu přihodíš Hibernate, který také zná JPA. Potom tvůj kód bude fungovat všude – neboť používá standardy JPA. Je možné, abychom používali jen Hibernate – tedy bychom nepoužívali nic ze standardů. Žádné anotace z javax.persistence a podobně – to ale nedoporučuji. Ptal jsem seNapadlo mě, že by nebylo od věci zeptat se kolegů developerů, co si myslí o JPA a Hibernatě. Pokud by sis chtěl přečíst jejich názory, ať se líbí – bez cenzury, cituji: Tak toto je náročné téma a navíc složité. JPA resp. ORM obecně (a tedy i Hibernate) jsou vždy složitější, než si uživatelé (tj. vývojáři) uvědomují. Výsledkem jsou často nenápadné chybičky, lazy load exceptions, které vedou k anti-patternům jako je OSIV (open session in view) nebo k výkonovým problémům (n+1 problem). Těchto problémů je typicky o to více, o co složitější je mapování – a přitom právě na řešení složitého mapování bylo ORM vymyšleno. Abychom mohli namapovat doménu do DB. K tomu se často používají i „mimojazykové“ triky jako reflection na private pole, takže objekty jsou implicitně svázány s ORM řešením, i když například. mapování je odděleno do XML namísto anotací, což samo o sobě je také nepraktické. Kromě toho mají obě hlavně implementace dost bugů na to, aby na ně člověk narazil, i když postupuje v souladu se specifikací – stačí jen chtít trosku víc a na nějaký bug určitě narazíte. Takže pak to je kličkování mezi bugy a často komplikovaná možnost vyměnit ORM providera. Co se mi na ORM líbí je lepší mapování typů, možnost customizovat mapování a podobně. Proto používám JPA i na jednoduché mapovačky namísto JDBC. Navíc s JPA používám řadu Querydsl, které je lepší/intuitivnější, než JPA standardní Criteria API. Hibernate používám dlouho ale po pravdě řečeno nikdy jsem se moc nezamýšlel nad výhodami. Zatím jsem neměl výraznější problém, který bych neuměl vyřešit, případně nějak obejít. Plusy : - snadno se provádí mapování do DB s anotacemi i pro začátečníka bez velkých znalostí databáze, zároveň ale bez znalosti DB může být mapování neefektivní - je open source, takže pokud potřebuji, umím podívat zdrojáky jak funguje Minusy : - asociace OneToOne fetch=lazy nefunguje Na používání Hibernate/JPA (celkově ORM vrstvě) se mi líbí : A) Abstrakce od fyzického datového modelu. Vývoj nad doménovým/logickým (entitně-relačním datovým modelem) - blíže k byznys vrstvě. Čili zjednodušené práce s objekty namísto tabulek. B) Možnost využívat různé pokročilejší techniky získávání dat (např. Spring Data JPA, ale také zjednodušující Hibernate Query by example) C) Agnostické od konkrétní databázové technologie (Oracle, MySql, ...) D) Cachování a optimalizace (např. lazy loading) Nevýhody : A) Někdy náročný (až nemožný) performance tuning. B) U některých technologií pomalejší křivka učení. C) I přes používání JPA/Hibernate, je téměř nezbytné, aby developer znal i (native) SQL jazyk a jeho použití. ZávěrPodařilo se ti nahlédnout do problematiky objektově relačního přístupu k databázi a pochopil jsi, co to znamená. Pokud se však chceš dostat ještě o level dál, připravili jsme pro tebe samostatný kurz Java persistence - JPA a Hibernate . Pokud chceš ještě víc, tak klikej:👍 Více o mně:  http://www.jaroslavbeno.cz/   👍 Kurzy (java, git, maven, bootstrap, Asp .Net,):  Learn2Code moje kurzy 👍 Free kurzy:  YouTube kanál JaroslavBeno
Manuální vs. automatizované testování
Tipy a triky
25.01.2019
Skillmea

Manuální vs. automatizované testování

Rád si v dětství všechno rozebíral, spekuloval a škodolibost hrála v divadle tvých ranních emocí prim? Jsi tady správně. Protože přesně to jsou hlavní rysy testeru. Jen opatrně s tou škodolibostí 😉 Manuální testování není ostuda!Neexistuje nic horšího, než dělat stále to samé dokola. Naštěstí o tom manuální testování není. Ale pěkně postupně. Neznám hezčí pocit v práci (kromě pátečního fajrontu) než když já, člověk, který studoval dojivost krav a hektarový výnos pšenice, nachytá programátora s nějakou chybou. Manuální testování znamená vzít novou část aplikace, usoudit či odpovídá tomu, co si zákazník přál a přitom nachytat programátory. Při testování postupuj stejně jako při boji s mafií. Nejprve jdeš po velkých rybách - chybách, které udělají nejvíce škody, malé si nevšímáš nebo je přeskočíš, protože není čas. Ať naděláš programátorům dost roboty. Pak jdeš po těch menších, designových vychytávkách, protože mají stejnou váhu jako předvčerejší instastory každé druhé makeup artistky. Vymýšlíš, co jsi ještě nevymyslel a jedeš po chodníčcích aplikace, kudy by se normální uživatel nikdy nevydal. Ale Jožo Pročko říkal 20 let dozadu, že nikdy neříkej nikdy. Jako tester to neříkej ani ty. Rozum maká zpočátku víc než ruce, a to je fajn. Fajn to být přestane, když se karta obrátí a nedejbůh, abys musel dvakrát dělat totéž. Nebo 3krát. Nebo 4krát. Nebo furt. Jsi odsouzen k věčnosti regresně testovat celou aplikaci. Protože pokud se změní kód, je třeba to celé proklikat. A v tento moment mozek vypínáš a pracují jen ruce. Vzpomínáš si, když ti jako malému řekli, že pokud se nebudeš učit, budeš kopat kanály? Toto je totéž, akorát sedíš v byznyscentru s dalšími korporátními kopači. Naštěstí tu robotu můžeš přenechat počítači, protože na řadu přichází... Automatizované testování je programování!Nech zase mozek makat a ruce odpočívat. Automatizované testování je o tom, že ty naprogramuješ robota, aby chodil po určité dráze, cestičce v aplikaci a on to bude dělat vždy, když mu přikážeš. Nepředstavuj si robota jako terminátora, který za tebe sedí v kanclu. A ani takhle to nevypadá:[Image] Ty vidíš, že stránka se otevře, ale kliká po ní robot na pozadí, kterého NĚKDO naprogramoval. A tím někým jsi TY. Jsi programátor se vší tou pompou a slávou, píšeš kód např. v JAVĚ a vyvíjíš si vlastní aplikaci, logiku, která testuje software namísto tebe. Ze začátku je to trošku těžkopádné jako startování V3S-ky, ale když tu mašinu jednou rozjedeš, práce ti neúměrně až zázračně klesá. A o tom je automatizované testování. Robotu, která se tobě nechce nenecháš na kolegu, který se vrátil z dovolené. Ani ji nenaučíš masturbovat, aby se udělala sama. (cit. Vtipnější vyhrává 09/1994) Ale přenecháš ji počítači. A on se nesplete, nevynadá ti, nesebere se v 16:00 domů a neonemocní, když polovina kanceláře zalévá zázvor vařící vodou. Nevýhodou však je, že počítač vidí jen tolik, kolik ho ty naučíš. Není inteligentní a nevidí věci v souvislostech. Neumí si něčeho všimnout. Řekneš mu slova František a Lászlo a on se nezasměje. Ani ty se doufám nesměješ. A ještě si dávej pozor, jak píšeš kód, abys ho nemusel po sobě 30x opravovat, pokud se na stránce něco změní. Protože to je také bolest, neustále dohledávat chyby v testech. Pojďme si porovnat manuál a automat. Výhody, nevýhody, kdy které použít.Manuální testování+ hledání nových chyb v aplikaci, exploratory testing + objevení designových přešlapů + rychlá odpověď na stav softwaru + improvizace - nákladné - nevhodné pro regresní testování - časově náročné - nespolehlivé (časový stres, přehlédneš chyby) - jak aplikace roste, rostou i náklady na manuální testování Automatizované testování+ regresní testování (před vydáním do produkce, po každé změně) + rychlé + spolehlivé + práce ti postupně ubývá - vyšší vstupní náklady (dokud spustíš první test) - robot nové chyby nenajde - musíš umět programovat - údržba ZávěrManuální testování nemůže být nahrazeno automatizovaným. Pokud jsi manuální tester, klidně si vydechni. A vydechni si znovu, protože tě umím ulehčit od tortury, kterou ti způsobuje testování po každé jedné změně. Naučím tě programovat robota. Základy programování a automatizovaného testování tě naučím v kurzu s Batmanem: http://bit.ly/batmanKurz Jak psát efektivní kód, umět si postavit Maven projekt, rozběhat jenkins, to tě naučím v tomto kurzu: http://bit.ly/jokerKurz A jak ten kód pěkně zabalit do třpytivého pozlátka, aby mu každý rozuměl tě naučím v kurzu s okurkou: http://bit.ly/cucumberKurz Autorem blogu je Martin "Furby" Škarbala. Když tě zajímá oblast testování softwaru, určitě dej lajk na jeho Facebook stránku.
Čísla a znaky v Javě
Tipy a triky
28.10.2018
Skillmea

Čísla a znaky v Javě

V tomto článku se spolu podíváme na základy práce s čísly a znaky v programovacím jazyce Java.  Čísla[Image]Proč používat Numbers a ne primitivní datové typy? Pokud nějaká metoda přijímá jako parametr Object, tak jí neumím podsunout primitivní datový typ. Můžeš použít konstanty, jako například MIN_VALUE nebo MAX_VALUE. Můžeme používat metody pro konverzi do a z primitivních datových typů i ze String. Byte b = 127; Byte b2 = 128; //error Byte len do 127Pro všechny typy máme metody, které z textu umí vylovit daný typ. Zde je třeba si dát pozor, protože pokud chci ze Stringu dostat 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 Když mluvíme o číslech, tak nemůžeme nezmínit modulo. Plus, minus známe, ale modulo by nám mohlo dělat 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 příkladu výsledek modulu nebude nikdy více než 3 a méně než 0. Tedy se karty rozdají mezi všechny hráče ve hře. Zkus si to poměnit sám. Matematické operácePro mnoho matematických operací máme třídu Math, která obsahuje řadu statických metod. Názvy jsou samo vysvětlující, nebo si viz níže komentáře: 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í čísloV Math třídě máme metodu random. Vrací hodnotu od 0.0 do 1.0 . Krácením umíš zvětšit a musíš přetypovat na int pokud chceš celá čísla. private static void randomNumbers() { int number = (int)(Math.random() * 100); System.out.println(number); }ZnakyPrimitivní datový typ char se používá k uchování jednoho znaku. U char máme také možnost použít jeho alternativu objektovou a to Character V jevu existují escape sekvence. To jsou znaky, tedy char, před kterým je zpětné lomítko. Tyto sekvence mají pro kompilátor zvláštní smysl. Neberou se jako nějaký jednoduchý text. \t - vloží tab \b - vloží backspace \n - vloží nový řádek \r - vloží carriage return \f - vloží formfeed \' - vloží jednu uvozovku \" - vloží dvojitou uvozovku \\ - vloží zpětné lomítko Máme řadu pomocných metod: 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));Tímto způsobem umíš vložit také speciální 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. ");Pokud chceš zadat speciální hodnotu, tak musíš zadat před daný speciální 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ávěrPokud tě zajímá Java, tak jsi tady na https://skillmea.\cz pohledej kurzy, které se věnují programování v Javě a nauč se víc. Já jsem Jaro a doufám se vidíme při dalším článku nebo videu.
Websockety - message board
Tipy a triky
04.10.2018
Miroslav Beka

Websockety - message board

 Ahoj, naposledy jsme mluvili o websocketech ve flasku. Používali jsme knihovnu flask-socketio a prošli jsme základní funkcionalitu. Tato knihovna používá koncept místností nebo rooms, který slouží k tomu, abychom uměli adresovat klienty v nějakých skupinách. Tento koncept se používá v chatových aplikacích, kde uživatelé vidí zprávy jen v místnosti, ve které se nacházejí. Nedostanou zprávy z žádné jiné. Podíváme se tedy na tento koncept a abychom udělali i nějaký reálný příklad, uděláme vlastní chatovací appku. Uživatelé se budou moci přidat do stávající místnosti, chatovat s ostatními, vytvářet nové místnosti a podobně. Bude to velice jednoduchý message board. 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/activateInstalujeme závislosti. Budeme používat totéž, co v předchozím článku. (venv)$ pip install flask, flask-socketioJedeme na boilerplatě pro naši appku. Struktura vypadá asi takto: ▾ websockets_message_board/ ▾ static/ ▾ css/ main.css ▾ js/ main.js ▾ templates/ board.jinja ▸ venv/ server.pySoubory main.css a main.js jsou zatím prázdné, slouží pouze jako placeholder. Pokračujeme tedy se souborem server.py a lze jej naplnit kódem. 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)Rozdíl oproti minimální flask appke je ten, že ji jinak spouštíme. Nepoužijeme if __name__ == '__main__': app.run()ale budeme ji spouštět přes socketIO. if __name__ == '__main__': socketio.run(app, debug=True)To proto, aby aplikace uměla spustit více vláken pro každého uživatele. Stejně tak je dobré vědět, že deployment na produkční server takové aplikace je trošku komplikovanější než když máme klasickou flask appku. Obsah základního templejtu board.jinja (i jediného, který budeme používat) je následující: <!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 pár důležitých importů jako socket.io, jquery a také css a js soubory naší appky. Takový jednoduchý základ můžeme spustit a uvidíme, jestli všechno šlape jak 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 není vůbec potřebný, ale jelikož všichni mají rádi hezké věci, nainstalujeme si css framework zvaný semantic-ui. Je to fajn framework, mám s ním dobré zkušenosti. Dokumentace je možná trošku těžší na pochopení, ale kromě toho to funguje a hlavně vypadá moc hezky. [Image] Stačí stáhnout toto zipko a integrovat do svého projektu. Je to velmi jednoduché. Zip rozbalíme a překopírujeme následující soubory • themes -> websockets_message_board/static/css/ • semantic.min.css -> websockets_message_board/static/css/ • semantic.min.js -> websockets_message_board/static/js/ Soubory semantic.min.js a semantic.min.css musím includnout na svou stránku, takže běžím do board.jinja a přihodím do hlavičky další řádky: <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é dát si pozor, abychom nejprve přidali jquery a až pak semantic.min.js, jinak se mi semantic-ui bude stěžovat, že neví najít jquery knihovnu. Ve složce themes jsou hlavně ikony a nějaké obrázky, které semantic-ui poskytuje. Po instalaci css frameworku můžu hned vidět změnu v podobě jiného fontu na mé smutné stránce. Nic jiného tam ještě není. UIUděláme nyní přibližný náčrt UI, abych věděl, jak appka asi bude vypadat a jaké funkce jí vlastně uděláme. Nebude to nic světoborného. Budeme mít jednu stránku kterou rozdělím na 3 sekce. Hlavní bude obsahovat zprávy, takže to bude můj message board. Boční panel bude obsahovat seznam místností, do kterých se budu umět přepínat. No a na spodní liště bude input pro moji zprávu.[Image] Zhmotním tuto svou představu do kódu. Otevřu board.jinja a naházím tam nějaké <div> elementy. Jelikož používáme semnatic-ui jako náš css framework, budu rovnou používat třídy v html. Použijeme grid systém, který nám usnadní práci při ukládání ui elementů. <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ůžu zkusit naplnit tyto části i nějakým obsahem. Jen tak ze zvědavosti, jak to bude vypadat. Všechno bude zatím jen tak naoko (prototypování). Začneme tím nejhlavnějším: message boardem <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šechny zprávy jsem obalil do div s id msg_board, abych pak jednoduše uměl přidávat nové zprávy do tohoto elementu.[Image] Uděláme totéž pro seznam místností. Rozhodl jsem se, že do tohoto postranního panelu strčíme i formulář pro změnu jména uživatele. Ten by měl mít možnost změnit své jméno. Bude to vypadat 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é jsem přidal <input /> na vytváření nových místností. Myslím, že takovou možnost by uživatel mohl mít. Poslední skládačkou bude input pro naše zprá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álně mi nebudou fungovat radio buttony, protože semantic-ui potřebuje tyto inicializovat v javascriptu. Pome tedy na to. Otevřeme main.js a píšeme $(document).ready(function(){ // UI HANDLERS $('.ui.radio.checkbox').checkbox(); });Stejně tak můžeme rovnou vybavit iniciální spojení přes websockety mezi klientem a serverem. $(document).ready(function(){ var url = location.protocol + "//" + document.domain + ":" + location.port; socket = io.connect(url); // UI HANDLERS $('.ui.radio.checkbox').checkbox(); });Posílání zpráv mohu rovnou i vyzkoušet v konzoli prohlížeče. Stačí otevřít developer tools, přejít na záložku console a tam už můžeme psát socket.emit("test", "hello there")[Image] Nicméně, nic se neděje, protože můj backend dosud není vůbec připraven. Vrhneme se tedy na server side a implementujeme místnosti – room. RoomsPřesuneme se do souboru server.py a přidáme handler pro základní eventy které budeme používat: 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í velmi jednoduše. Pokaždé se podívám na data, která mi přišla (proměnná data) a vytvořím jednoduchou zprávu, kterou pak broadcastuji na všechny uživatele v té dané místnosti. Pokud si už pořádně nepamatuješ, co dělal ten broadcast, vzpomínej z minulého blogu. Důležité je použití funkcí join_room a leave_room. Tyto pocházejí z knihovny flask-socketio, kterou jsme instalovali na začátku. Slouží k tomu, abychom přiřadili danou session do nějaké místnosti. Potom, když pošlu zprávu do místnosti, dostanou ji všichni v té místnosti. Je to fajn mechanismus jak kontaktovat jiné klienty a uspořádat si je do nějakých kategorií. rooms nemusím nutně používat jen na chatovou funkcionalitu. Mohu to použít k tomu, abych si seřadil uživatele do nějaké společné skupiny, které posílám barsjaká data. Dejme tomu, že bych měl appku o počasí, a nějaká skupina uživatelů by měla zájem o notifikace, jestli bude pršet. Tak tyto bych hodil do společné skupiny - místnosti - a notifikace bych posílal jen jim. Využití je tedy všelijaké. JavaScriptBackend byl v tomto případě docela jednoduchý a nepotřebovali jsme toho mnoho implementovat. Zprávy se od našeho backendu jen odrážejí jako od relátka, který je dále rozesílá klientům. Na straně klienta toho bude trošku více. Pokračujeme v souboru main.js. Nyní se pokusíme implementovat posílání zprávy a zobrazení příchozí zprá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čátek vytvoříme nějaké random uživatelské jméno a zvolíme default místnost "Lobby". To abychom s tímto neměli starosti zatím. Používáme k tomu pomocné funkce, které si implementujeme stranou, aby nám nezavazovaly. Jméno uživatele a název aktuální místnosti si udržuji v sessionStorage, což je fajn dočasné úložiště v prohlížeči. Přežije také reload stránky a navíc se mi tento způsob více líbí jak udržovat informaci v cookies. Když máme potřebná data, můžeme se hned na začátku bouchnout do nějaké místnosti. V javascriptu používáme knihovnu socket.io, která ale žádný koncept místností nezná. Pokud se podíváš do dokumentace(pozor! otevři si client api), zjistíš, že nic takového jako rooms se tam nezmiňuje. Takže to je věcička knihovny flask-socketio. Použijeme tedy klasický emit na handler join, který existuje na serveru. Tento řádek $("form#send_msg_to_room").submit( se pomocí jquery napíchne na formulář a zachytí odeslání formuláře. Pak můžu dělat co se mi zachce a nakonec vrátím false, takže formulář se reálně ani neodešle. Odeslání zprávy je přímočaré. Zjistím UserName, zjistím RoomName, vytáhnu si text zprávy a vše pošlu do funkce sendMessage. Tato již zajistí zabalení informací do jsonu a posílám pomocí funkce emit. Posílám na handler msg_board, který jsem si udělal před chvilkou. Zbývá mi vyřešit přijetí zprávy. To dělám pomocí funkce socket.on, kde dám kód, který bude proveden při přijetí zprávy. Tady si jednoduše (ale zato strašně ošklivě) slepím kus HTML, které pak strčím na konec elementu s id msg_board. Než to budeš zkoušet, je fajn si ještě vymazat ty fejkové zprávy, které jsme tam dali natvrdo do HTML. Takže mažeme tyto řádky <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 tedy jako další věc vybavit změnu uživatelského jména. $(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 jako při posílání zprávy, napíchnu se na HTML formulář a zpracuji ho ještě před odesláním. Změny uložím do sessionStorage. Přidal jsem ještě 2 vychytávky. • funkce updateHeading nastaví aktuální název místnosti a uživatele jako hlavičku stránky, • notifyNameChange dá všem uživatelům vědět, že si někdo změnil jméno. Jméno si už můžu měnit, ale oznámení o změně jsem nedostal. Na to ještě musíme doplnit 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); }); }); ...Nyní se nám začnou zobrazovat i systémové notifikace o tom, co se děje. Kdo vešel do místnosti, kdo ji opustil nebo kdo si změnil jméno. Poslední věcí, kterou musíme udělat, je selekce místností. Toto bude vyžadovat trošku více práce. Seznam stávajících místností si musíme udržovat na backendu. Ani na klientské části ani na backendu z knihovny flask-socketio neumím získat seznam všech místností. Musím si ho tedy udržovat 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 jsem si začal posílat nějaká data. Vyhodím tedy ty fejkové, které jsou tam natvrdo, a uděláme loop, ve kterém přidám všechny stávající místnosti. <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čuji v souboru main.js, kde si vytvořím funkce, které se postarají o změnu místnosti + pokud byla vytvořena nová, tak ji přidám do seznamu. $(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 zde několik pomocných funkcí, které mi pomáhají při výběru místnosti nebo při vytváření nové. Problematické části nastávají právě tehdy, když chci místnost i vytvářet. V podstatě ale nejde o žádné komplikované věci. Funkce selectCurrentRoom mi pomůže přehodit radio button při změně místnosti. Tím, že používáme semantic-ui, tak se nám to také trošku zkomplikovalo, ale výsledek stojí za to.[Image] ZávěrPostavili jsme takzvaný proof of concept, udělali jsme chatovací appku jen pomocí websocketů. Není to dokonalé a určitě je tam spousta much, to nám však nebránilo pochopit jak fungují websockety. Všechny zprávy žijí pouze v prohlížeči uživatele a nejsou uloženy na žádném serveru. Někdo to může považovat za chybu, někdo za fičúru. To už nechám na vás. Celý projekt se dá stáhnout zde. Zanedlouho se opět vrhneme na nějaké zajímavé téma ;)
Java 8
Tipy a triky
19.09.2018
Skillmea

Java 8

Java 8 je velký balíček nové funkcionality oproti Java 9 a java 10. Ty jsou menší a odrážejí taktiku tvůrců jevy vydávat nové verze častěji s menším balíkem nové funkcionality. V tomto článku si řekneme nejvýraznější změny z Java 8. Funkcionální rozhraníRozhraní, které má jen jednu abstraktní metodu je považováno za funkcionální rozhraní. Pro lepší nastínění v kódu můžeme a je doporučeno přidat anotaci @FunctionalInterface. import java.lang.FunctionalInterface;   @FunctionalInterface public interface FunctionalInterfaceExample { void print(); } Lambda výrazyOk, chceme přidat do jevy možnost definovat funkcionalitu, aniž by patřila specificky pod nějakou třídu. Tyto funkce chceme vkládat do metod jako parametry. Co uděláme? Tvůrci jevy se asi takhle nezamýšleli, ale my jsme se takto zamysleli a odpověď je – použijeme lambda výrazy. Každá lambda má jako typ funkcionální rozhraní s její odpovídající metodou. V příkladu výše máme rozhraní s metodou print. Tato metoda nevrací nic a nepřijímá žádné parametry. Musíme vytvořit i takový lambda výraz – tedy nebude obsahovat return a nebudeme mít žádné návratové hodnoty. () -> System.out.println("Hello Word")Takto vložíš lambda výraz do metody: printHelloWord(() -> System.out.println("Hello Word"));Samotná metoda přijímá na vstupu právě dané funkcionální rozhraní: public void printHelloWord2(FunctionalInterfaceExample printHello)Více o lambda výrazech se dozvíš z mého online kurzu Java pro pokročilé, videa o lambda výrazech jsou zdarma. StreamsStreamy poskytují zjednodušenou práci s datovými kolekcemi. Poskytují několik užitečných metod jako jsou filtr, sorted, map a jiné. Pokud stream přejede přes všechny elementy v kolekci, tak bude prázdný. Tedy pokud chci znovu použít tentýž stream, tak zbytečně, neboť tam už nebudou data. Musíš si vytvořit nový stream. Nový stream vytvoříš například pomocí stream metody nad kolekcemi.  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áš seznam osob a chceš z daného seznamu získat všechny věky osob starších 50 let a mají být seřazeny podle věku. Co uděláš? Použiješ stream a jeho metody – tyto metody akceptují funkcionální rozhraní, tedy 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());Kolekce, které jsou iterovatelné, mají metodu forEach – která získá stream a projde všechny elementy. veky.forEach(System.out::println);   Method referenceČesky reference na metodu. Všimni si příkladu shora: Osoba::getVěk. Znamená to, že ze třídy Osoba použij metodu getVek. Totéž lze zapsat i pomocí lambda výrazu takto osoba -> osoba.getVek(). Ale pomocí reference si to zjednodušíme neboť java ví, jaký je vstupní parametr – je to osoba a ví, že voláš getVek. Tak stačí napsat Osoba::getVek. Metodu voláš bez závorek. Další článek o Javě již brzy. Přihlas se k odběru novinek a nezmeškej žádný nový blog.
Websockety ve Flasku
Tipy a triky
15.08.2018
Miroslav Beka

Websockety ve Flasku

Websockety ve Flasku Pokud ses někdy setkal s výrazem websocket a chtěl by ses dozvědět, co to vlastně je a jak se to používá v Python aplikaci, tak tento článek je právě pro tebe. Standardně tvůj prohlížeč komunikuje na webu pomocí http protokolu. Klasický http protokol nabízí jednoduchou komunikaci. Pošle se request a jako odpověď dostanu response. Tento klasický komunikační způsob nebyl dostačující pro dnešní moderní aplikace. Byla potřeba pro komunikační kanál, který bude sloužit k obousměrné komunikaci. HTTP by měl být víceméně bezstavový a klient a server mezi sebou komunikují jen když je třeba, jinak je spojení mezi nimi uzavřeno. Navíc, prohlížeč (klient) musí požádat server o komunikaci a server může na tuto žádost odpovědět. Ta žádost, to je ten http request. Jinak server neumí kontaktovat klienta jen tak sám od sebe. U websocketů je tomu jinak. Jedná se o komunikační kanál, který se otevře jednou, na začátku a poté se používá ke komunikaci klienta a serveru v obou stranách. To znamená, že server může posílat data zároveň co klient posílá data na server. Toto se odborně jmenuje full-duplex. Web socket má menší overheat přenosu dat, umí být real-time a hlavně, server může posílat data na klienta, aniž by si je klient musel explicitně vyžádat requestem. Toto je užitečné například u aplikací, které zobrazují real time data a server posílá tato data klientovi. Takže pokud nastane nějaká změna dat, server je prostě pošle na klienta. Toto dříve nebylo možné provést pouze pomocí http protokolu. Minimální pří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: Nejlepší je vyzkoušet si tyto koncepty v praxi. Dnes budeme pracovat s Flaskem, knihovnou SocketIO a javascript knihovnami socket.io a jQuery. Budu předpokládat, že Flask aplikace alespoň trochu znáš. Začneme tím, že si vytvoříme nové virtuální prostředí: $ mkdir websockets_primer $ cd websockets_primer $ virtualenv venv $ . venv/bin/activate (venv) $Nainstalujeme závislosti, které budeme potřebovat: (venv)$ pip install flask, flask-socketioV době psaní tohoto článku jsem používal verze Flask==1.0.2 a Flask-SocketIO=3.0.1. Když už máme připravené prostředí a nainstalované závislosti, uděláme nový soubor 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čátku máme importy jako pro každou jinou Flask aplikaci, avšak přibylo nám tam  from flask_socketio import SocketIO. Tento naimportovaný modul je v podstatě totéž jako jiné  Flask rozšíření . Inicializaci websocketů ve Flask aplikací provedeme pomocí řádku  socketio = SocketIO(app). Pomocí tohoto objektu  socketio budeme přijímat a odesílat zprávy. Minimální aplikace by měla mít alespoň jednu stránku. V našem případě to bude  index.jinja. Toto je třeba, protože musíme poskytnout i klientskou část naší aplikace. Tam bude javascript knihovna  socketio  a nějaké další funkce. Websockety umí přijímat a posílat zprávy. Provedeme zatím jen přijímání zpráv. Pomocí řádku  socketio.on("event")definuji handler pro událost  event. V tomto případě jednoduše vypíšu data na konzoli. @socketio.on("event") def handle_event(data): print(data) Posílání a přijímání dat na obou stranách (klient a server) probíhá jako event. Toto je důležitý fakt, protože architektura aplikace založené na eventech ( event driven architecture ) funguje trošku jinak než klasické volání funkce. Neříkám, abys měl z toho paniku teď, ale měj to na paměti. Pokud znáš Flask aplikace, tak spuštění appky vypadá většinou takto if __name__ == "__main__": app.run("0.0.0.0", debug=True) My ale musíme appku spustit jinak, jelikož používáme websockety. Spustíme ji pomocí objektu socketio, který jsme si vytvořili na začátku. if __name__ == '__main__': socketio.run(app, debug=True) Nyní musíme ještě vytvořit 2 soubory. Snažíme se renderovat  index.jinja a také musíme vytvořit hlavní javascript soubor, do kterého budeme psát klientskou část naší websocketové ukázky. Vytvořím složku  templates a do ní soubor 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é jsou 3 importy v hlavičce html dokumentu. První importuje  jQuery , druhý importuje knihovnu pro práci se sockety  socketio  a poslední import je pro náš  main.js  soubor, který musíme ještě vytvořit. Jinak tento html dokument obsahuje pouze jeden formulář s jedním tlačítkem. To budeme používat k posílání zprávy přes websocket. Vytvoříme složku  static v ní  js a v ní už konečně soubor main.js Obsah bude vypadat 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 klientské části. Z tadeto budeme přijímat a posílat zprávy přes websockety stejně jako na serverové části. Pomocí řádku  var socket = io.connect(url); se připojím na můj server. Následně pomocí  jQuery  upravím chování buttonu, aby při stisku poslal zprávu. K tomu slouží funkce socket.emit() Okej, základ máme hotový a můžeme nyní zkoušet posílat zprávy. Aplikaci spustím pomocí pří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-530Otevřu prohlížeč na  http://localhost:5000  a zobrazí se mi jeden button. Když ho zmáčknu na konzole mi vyskočí: test messagePojďme tedy prozkoumat, jaké možnosti nám poskytuje tato knihovna  socketio. Přijímání zprávJak jsem již zmiňoval, přijímání zpráv na obou stranách probíhá jako event. V Pythonu musíme pro takovýto event definovat handler. V javascriptu používáme tvz. callbacky. V principu jde o totéž, ale každý jazyk má své vlastní technické řešení a my si toho musíme být vědomi. Každý event, který chci přijmout musím mít nějaké jméno. V příkladu jsme měli název  event. Mohu ale použít cokoli @socketio.on("foobar") def handle_data(data): print(type(data)) print(data)Také data se automaticky mění na příslušný typ. Pokud v javascriptu pošlu string, tak string dostanu i na serveru. Totéž platí pro jiné datové 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 odeslání událostí dostanu výpis na serveru <class 'str'> message <class 'list'> [1, 2, 3] <class 'dict'> {'data': 'message'}Handler také může mít několik argumentů @socketio.on("sum") def handle_sum(arg1, arg2): print(arg1 + arg2)Upravíme javascriptovou část a zavoleme event s více argumenty ... $("form#emit_event").submit(function(event) { socket.emit("sum", 23, 47); return false; }); ...Namespace patří mezi další funkce, které mám knihovna SocketIO nabízí. Každý event si můžeme rozdělit podle namespace. To nám dává další možnosti organizace eventov. @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): print(arg1 + arg2)Ovšem pozor! Na straně klienta se musíme nyní připojit na jinou 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; }); });Další vychytávka je to, že každý event, který pošleme, umí zavolat callback poté, co byl proveden. Například z javascriptu pošlu nějaká data na server a server mi ještě dodatečně potvrdí, že data byla zpracována. Aha takhle ... $("form#emit_event").submit(function(event) { var ack = function(arg){console.log(arg)}; socket.emit("sum", 23, 47, ack); return false; }); ...Pokud chci, aby se callback zavolal, musím v Pythonu vrátit nějakou hodnotu z provedeného handleru => return True @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): print(arg1 + arg2) return TrueMusím si otevřít v prohlížeči konzoli (já používám chrome) a když zmáčknu tlačítko, dostanu výpis na konzoli[Image] Posílání zprávZasílat eventy jsme již posílali, ale pouze z javascriptu. V Pythonu to vypadá velmi podobně. Používáme 2 funkce  send a  emit mezi nimiž je zásadní rozdíl. Nejprve musíme importovat z knihovny flask-socketio from flask_socketio import send from flask_socketio import emitupravíme funkci na sčítání @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): value = arg1 + arg2 print("{} + {} = {}".format(arg1, arg2, value)) send(value)a přidáme handler v javascriptu abychom mohli tento event zachytit. ... $("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 teď jsem použil handler, který zpracovává event s názvem  message. Není to náhoda. Jde totiž o to, že funkce  send posílá tvz. unnamed event . Tyto eventy se vždy posílají na handler, který zpracovává  message. Narozdíl od funkce  send, funkce  emit posílá již konkrétní event a musíš mu dát název. Zkusme tedy pozměnit náš pří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) }); ...BroadcastingVelmi užitečná funkce je broadcastování, což už z názvu vyplývá, že eventy se budou vysílat na všechny připojené klienty. Dejme tomu, že změníme funkci  emit na broadcastování @socketio.on("sum", namespace="/math") def handle_sum(arg1, arg2): value = arg1 + arg2 print("{} + {} = {}".format(arg1, arg2, value)) emit("result", value, broadcast=False)Nyní, když si otevřeš 2 prohlížeče a v jednom zmáčkneš button, výsledek součtu se ukáže ve všech prohlížečích[Image] note: callbacky se při broadcastování nebudou provádět ZávěrWebsockety mají mnoho využití. Tento článek byl jen úvod a přehled některých základních funkcí. V příštím blogu uděláme malou aplikaci postavenou na websocketech. Máš nějaké dotazy k článku? Napiš ji do komentáře.
7 důvodů, proč se lidé na vašem webu neregistrují
Tipy a triky
06.06.2018
Skillmea

7 důvodů, proč se lidé na vašem webu neregistrují

Weby jsou o byznysu. A teď nemám na mysli vývojářské firmy a mladé dynamické „desing studios“. Mluvím o byznysu jako takovém - o činnosti, při které se vyměňují hodnoty (jako peníze a zboží) ke vzájemné spokojenosti obou stran. Vy máte super obsah, návštěvníci vašich stránek zase své kontaktní údaje. Tak si podáte ruce a domluvíte obchod. Mé články za tvůj e-mail. Jednoduché, ne? Ne. Registrační proces je vcelku složitá záležitost a ne vždy funguje tak, jak bychom si představovali. Web může mít mnoho návštěvníků, ale jen velmi málo se i zaregistruje. Proč? Inu, když jsme web vymýšleli, mohli jsme nevědomky udělat pár chyb. Tak zaprvé… 1. Jsme v tom, že registrační proces rovná se registrační formulář Samozřejmě, že je důležité mít pěkný a použitelný formulář. Názvy nad inputy pro vertikální skenování, absence CAPTCHA pro duševní klid, známe. Ale registrace nezačíná vyplňováním políček. Pokud jsme návštěvníka dostali až sem, máme už vlastně zpola vyhráno - registrační proces formulářem nezačíná, ale končí. Další chybou tedy může být, že… 2. Zapomínáme na to, že registrační proces rovná se motivace „Ahoj, jsme Triad a děláme efektivní digitální marketing tak, aby to bavilo nás i naše klienty“. Nějak takhle by mohla vypadat vaše value proposition (nechce se mi hledat český překlad), kdybyste byli Triad. Jenže nejste, tak si vymyslete vlastní. Pamatujte, že návštěvníci stránek jsou sobci a zajímá je jen to, co jim přinesete. Kašlou na vaši misi, vizi a počet šálků kávy vypitých od začátku roku. Proč by s vámi měli dělat byznys, když jim nedáte jasně najevo, jakou hodnotu jim přinášíte? Proč by se měli registrovat právě u vás? Řekněte jim to. Jednoduše, srozumitelně, hlavně nepřehánějte. S tím souvisí další bod. 3. Neosobní a nudné webové copy Jak říká Adam Javůrek, ve webovém copy jsou svatá 3 slova: vy, váš a zdarma. Schválně, zkuste použít všechny. Buďte přátelští, s uživateli si povídejte. Knoflík “Registrujte se” je přívětivější než “Registrovat”, nebo “Registrace”. Vyznačte důležité části, text strukturujte. Oh, a zkraťte ho. Na polovinu. A pak ještě jednou. To, co je na vás super musíte umět sdělit během krátké cesty výtahem. Je váš produkt nebo obsah zdarma? Řekněte to. A ještě jednou - nejste nejlepší, nejkrásnější a nevíte všechno. Svým návštěvníkům dejte jasný a srozumitelný důvod, proč se u vás mají registrovat. Bez nadsázky. Všechny kecy na světě však nenahradí osobní zkušenost - občas na to pozapomeneme a pak vzniká… 4. Obsah skrytý pod registrační hradbou To je tak. Kliknu na nadpis článku nebo odkaz ve smyslu “zjistit více” (moje oblíbené, BTW, když nejdu dále číst, ale “zjišťovat”). Vyskočí na mě modální okno s formulářem a vříská po mně cosi o registraci. Zkusím další odkaz, situace se opakuje. Odcházím. Řekněme, že sháníte bonbóny a narazíte na dva prodavače. Benďo a Jožo. Benďo bude své bonbóny vynášet do nebe a popisovat jejich úžasnou chuť. Jožo otevře balíček a rovnou vás nabídne. Od koho si bonbóny koupíte? Jožova mazaná obchodní taktika stojí na principu reciprocity - pokud dáš nejprve něco ty mně, já budu víc ochoten dát něco tobě. Proto pokud máte super obsah, neskrývejte jej před návštěvníky. Ukažte jim ho. S tím, že když ho budou chtít vidět celý, ať se zaregistrují. Svůj e-mail vám poskytnou velmi rádi, budou-li vědět, do čeho jdou. Apropo, do čeho jdou… 5. Příliš velký závazek Registrace na webu je velké rozhodnutí. Ne, vážně. Jsou to cizí stránky, nevím, kdo je vlastní. Komu dávám svůj e-mail? Na co všechno jej použije? Čeká mě spambox plný super pilulek a členů nigerijské královské rodiny? A k čemu chtějí mé telefonní číslo? PSČ? Zbláznili se? Tak. Buďte transparentní. Lidé nemají rádi závazky, ukažte jim tedy, že se nemají čeho bát. Budete jim posílat newsletter? Tak jim ho ukažte. Jak vypadá, co obsahuje a hlavně – jak často se na něj mohou těšit. Mohou si účet kdykoli zrušit? Řekněte jim to. Přidejte také větu o tom, že informace neposkytnete třetí straně (a zkuste to i dodržet). A ujistěte je, že to celé nezabere více než minutu jejich času. Ještě jedna věc. Spousta webů přichází o obrovský zdroj důvěry v očích jejich potencionálních uživatelů - dělají jednu zásadní chybu… 6. Skrývání ostatních uživatelů Máte super web plný super obsahu, kde chodí spousta super lidí? Ukažte je. Co všechno tam dělají? Jožo právě čte článek o červených pandách? Benďo ve speciální aplikaci zjistil, kde v jeho okolí se pandy dají skvěle pozorovat? Proč se nepochlubit? Možná tam dokonce najdu nějaké kámoše z Facebooku. A proč bych se neregistroval, když tam už jsou moji známí, kteří to prověřili za mě? Jmenuje se to social proof a více o něm zjistíte v Googlu. Nějaké knihy o tom seženete i na Amazonu. A vůbec, když už o nich mluvím. Tito velcí hráči utrácejí miliony na UX testování, musí mít super promakanou registraci. Uděláme to jako oni. Nemůže to dopadnout špatně. Nebo hej? 7. Opakování po ostatních Pokud se nevoláte Bezos (což určitě ne, neboť čtete článek v češtině), zapište si za uši: nejste Amazon. Ani Google, ani Alza ani lokální opravář plynových bojlerů. Vy jste vy. Při navrhování registračního procesu je třeba vždy vycházet z vlastní situace a vlastních zkušeností. Internetoví giganti mají určitě velmi dobře zvládnutý registrační proces, ale nikdo z nás nevidí do jejich cílů, statistik a strategie. To co funguje pro ně nemusí fungovat pro vás. Na druhé straně, inspirovat se někde třeba, takže… Trochu inspirace Zde je několik známých webových produktů, které mají podle mě skvěle zvládnutý registrační proces. Co mají společného, ​​je především jednoduchost – jasně komunikují, jak mi pomohou (ať už pomocí textu nebo obrázků) a okamžitě mi nabídnou možnost je bezbolestně začít používat. • Intercom • Basecamp • Dropbox Autorem blogu je Roman Pittner , lektor online kurzu Design pro obrazovky . Pokud máš k blogu dotazy, neváhej je napsat do komentářů.
Jak umí programátor samouk dohnat ty, co studovali na univerzitě
Tipy a triky
03.04.2018
Martin Lipták

Jak umí programátor samouk dohnat ty, co studovali na univerzitě

Co se učí na univerzitáchJsi programátor samouk a přemýšlíš, jak to vypadá na univerzitě? Už jsi viděl všechny online kurzy , máš za sebou 10 vlastních projektů a začínáš v nové práci jako Web developer. Jak dohnat lidi, kteří 5 let studovali informatiku? Dá se to vůbec?  Před 3 lety jsem skončil FIIT ( Fakulta informatiky a informačních technologií ) na STU v Bratislavě a také jsem přemýšlel, co všechno mi škola dala. Je toho hodně a jsem velmi rád, že jsem si vybral takovou cestu. Na druhou stranu, kdybych tuto možnost neměl, většinu věcí bych se naučil i jinde. Co pro mě byly ty nejdůležitější věci? Asi už tušíš, že je to celé velmi subjektivní a určitě neber tento článek jako univerzální návod. Studentský životBydlel jsem na intrácích v Mlýnské dolině a jeden semestr jsem strávil na programu Erasmus ve Španělsku. Byly to kamarádství a zážitky, na které lze vzpomínat celý život. Pro samouky: Pokud jsi studoval na jakékoli vysoké škole, víš o čem mluvím. Inspirativní lidéPoznal jsem mnoho spolužáků a učitelů, kteří mě v mnoha věcech posunuli dál. S mnoha jsem dosud v kontaktu a můžu se na ně spolehnout, kdybych potřeboval pomoc.  Pro samouky: Skvělé lidi najdeš iv pracovních kolektivech. Obklop se takovými, kteří jsou lepší než ty sám.  Na škole se organizovalo velké množství akcí a učitelé nás motivovali chodit na setkání programátorů mimo školu, kde jsem poznal mnoho dalších lidí. Pro samouky: Hledej si kamarády na různých událostech pro programátory, kterých je více než dost v každém větším městě (například taková Rubyslava nebo Reactive meetups a mnoho dalších). SamostatnostOd intráků a studia v zahraničí, až po práci na zadáních, projektech a závěrečných pracích. Alespoň na FIIT to bylo tak, že táhnout to musel sám student a učitel mu jen pomáhal nebo někdy i nepomáhal. Zasekl ses při zadání a termín je zítra? Použij Google, nebo se poraď se spolužáky, ale vyřeš to. Pokud tvé zadání nebude do 00:00 CEST v předávacím systému, nikoho nebudou zajímat tvé výmluvy a předmět si zopakuješ další rok. Pokud se ti nasbírá takových předmětů více, letíš ze školy. Pro samouky: Tak jako jsi udělal těch 10 vlastních projektů, i v práci budou očekávat, že se věcí chytíš a dotáhneš je samostatně do konce. To ale neznamená, že se nemáš ptát (nejdříve Google) a požádat o pomoc, když ji potřebuješ. [Image] Práce v týmuNa mnoha školních projektech jsem nepracoval sám. Na týmovém projektu jsme byli až 7 a museli jsme se vypořádat s odlišnými názory a dokonce cíli v projektu.  Pro samouky: Máš za sebou těch 10 projektů, při kterých ses naučil samostatnosti. V práci budeš obklopen lidmi a musíte spolu co nejlépe vycházet. Jmenuje se to soft skills a dá se to natrénovat. [Image] VědomostiNa co všechno si vzpomenu 3 roky po skončení školy? O čem byly všechny ty předměty? • Jak funguje počítačový hardware a jak se z jednotek a nul stanou programy – logické obvody a počítačové architektury. • Jak funguje operační systém - ovladače zařízení, IO, systémová volání, procesy, vlákna (threads), synchronizace, správa unixových systémů a shell skripty. • Jak funguje Internet a co je HTTPS, DNS, POP3, IP a Ethernet – 7 vrstev počítačových sítí a jak spolu souvisí všechny tyto protokoly. • V čem se liší paradigmata programování - procedurální programování v C, objektově orientované v Javě, funkcionální v Lispě a logické v Prologu. Viz můj první projekt v C , který jsem nahrál do školního systému pro automatické testování :) • Co znamená zápis O(n) a jak určit složitost algoritmů? Jak může efektivní algoritmus vypočítat výsledek za 1 milisekundu a neefektivní by to počítal týdny? Vyvážené binární stromy, hashing, grafy a jiné datové struktury. • Co je to Turingův stroj? Proč jsou regulární výrazy regulární? Co je abstraktní syntaktický strom? Základní teorie informatiky, na které stojí všechny programovací jazyky. • Je umělá inteligence opravdu inteligentní? Hrubá síla a heuristiky, které řeší složité problémy, neuronové sítě, genetické algoritmy a odvozovací stroje. • Jaké jsou výzvy paralelního programování? Klasické problémy synchronizace, vlákna, mutexy a semafory. • Co je databáze? Návrh datových modelů, psaní dotazů (queries), optimalizace indexy a kdy použít NoSQL. • Úvod do analýzy dat (data science). Lineární regrese, neuronové sítě, support vector machines, clustering a časové řady. • Jak spravovat softwarové projekty? Vodopád nebo agilní metodologie, důležitost testování a dokumentace, návrh poživatelských rozhraní, kvalita kódu a návrhové vzory. • Jak dělat výzkum? Návrh hypotéz, jejich vyhodnocování experimenty, měření dat, psaní a zveřejňování výzkumných článků. • Pár předmětů o ekonomii, právu a psychologii bylo příjemným odpočinkem od technických věcí. • Webový vývoj v Ruby on Rails. Toto je to, čemu se nyní věnuji v práci. Pro samouky: Vypadá to jako velmi dlouhý seznam, ale většinu z těchto věcí se umíš naučit v praxi. Jsou však věci, ke kterým se nedostaneš. Pokud se od začátku zaměřuješ na webový vývoj v PHP , asi se nebudeš do hloubky zabývat hardwarem, překladači (compilers) a operačními systémy. A většina lidí se asi nebude zabývat výzkumem. [Image] Takže jak dohnat ty, kteří studovali FIIT?• Obklop se lidmi, od kterých se můžeš hodně naučit. Najdeš je v práci a na setkáních programátorů. • Nečekej, že ti vždy řeknou, jak máš věci dělat. Samostatnost je ale také umět požádat o pomoc, když ji potřebuješ. • I když to tak na první pohled nevypadá, programování je víc o lidech než o počítačích. Pracuj na svých soft skills a komunikaci v týmu. • Snaž se porozumět věcem do hloubky. Jak fungují regulární výrazy? Proč potřebuje databáze indexy? Jaký je rozdíl mezi http:// a https://? V čem jsou výhody SCRUM-u? • Uč se věci mimo tvé specializace. Vyvíjíš weby? Zkus udělat nativní mobilní aplikaci. Co takhle si o víkendu naprogramovat ovladač do operačního systému nebo kompilátor? Máš dotazy k tomuto blogu? Neváhej je napsat do komentářů.
Ako naprogramovať hru Čierny Peter v Jave
Tipy a triky
26.10.2017
Skillmea

Ako naprogramovať hru Čierny Peter v Jave

Programování hry Černý Peter v JavěV tomto tutoriálu si spolu naprogramujeme karetní hru Černý Petr. Použijeme programovací jazyk Java a zaměříme se na to, abychom použili OOP přístup, tedy objektově orientované programování. Pravidla hryNejprve si musíme zanalyzovat danou hru. To uděláme tak, že si řekneme a určíme pravidla. Ve hře je 33 karet. Jedna karta nemá pár, ostatní ho mají. Hru může hrát 3 až 6 hráčů. Všechny karty se rozdají mezi hráče. Automaticky si hráči vytřídí z ruky karty, které mají páry. S ostatními začíná hra. Ten, co má nejvíc karet, nechá táhnout hráče po své pravici. Pokud ten hráč získal pár, tak ho vyloží a další hráč od něj táhne kartu. Pokud hráč přišel o všechny karty, už víc nehraje. Komu zůstane poslední karta, ten prohrál hru. Analýza hry - vytváření objektůNyní je čas připravit si popis našich tříd, rozhraní a podobně. Ve zkratce, uvažujeme nad pravidly, okolnostmi a členy dané hry a chceme je přetvořit na objekty. Čím obecněji napíšeme naše objekty, tím lépe pro jejich znovupoužitelnost. Pokud bychom chtěli někdy naprogramovat karty žolíkové, sedmové nebo ledajaké jiné, tak si nechme tuto možnost. Tedy například vytváření instancí karet nedávejme do třídy balíku, ale jinde. Postup: 1. vytvořím kartu 2. vytvořím balík karet 3. vytvořím hráče 4. interakci s uživatelem 5. správu hry 6. logiku hry Černý Peter KartaKaždá hrací všeobecná karta má nějaké specifikum. Je to král srdeční, král pikový a podobně. V našem případě máme páry a každá karta v páru je jiná, společné mají to, že jsou páry. Jako například v žolíkových kartách máme 4 krále. Každý je jiný, ale mají společné, že jsou to králové. 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íček karetDále budeme potřebovat tyto karty uložit do balíčku. Každá hra má několik karet, které tvoří balíček. Takže náš balíček bude obsahovat seznam karet. Co lze dělat s balíkem? Například míchat karty, nebo z balíku můžeme vyjmout kartu. Když vybírám karty nebo míchám karty, tak tam musí nějaké být. Protože pokud vyberu postupně všechny karty z balíku, tak nakonec budu mít balík prázdný. Zkuste míchat prázdný balík karet :) Proto si vytvořím i pomocnou metodu, která zjistí, zda je balík prázdný nebo ne. 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ždé hry potřebuji hráče, tedy někoho, kdo bude danou hru hrát. Rozhodl jsem se, že hráči dám jméno a karty v ruce. Když vytvářím nového hráče pomocí new, tak se zavolá konstruktor dané třídy a tam si všimni, že jsem mu do ruky nedal nic, tedy tam má prázdno. To proto, že ještě nedostal žádnou kartu při rozdávání, ale musí mít nějaké úložiště kde mu je dám :) Je tam ještě metoda, která má na starosti odstranit z ruky hráče všechny páry. Kdo by si to chtěl nějak zobecnit, tak může. Tedy do objektu Hrac, by dal jen metodu pro odstranění jedné karty, nebo seznamu karet. A které karty to budou to nechá na jiný objekt, který spravuje pravidla hry Černý 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ádání hryJakou chceš udělat aplikaci? Jak chceš komunikovat s uživatelem? Přes grafické rozhraní? Přes konzoli, nebo jinak? Nyní budeme dělat konzolovou interakci , ale pokud bys chtěl dělat v budoucnu grafické rozhraní, tak je vynikající idea udělat interface, tedy rozhraní, kde popíšu metody jaké chci používat pro interakci s uživatelem. Potom když budeš dělat grafické rozhraní, tak si jen zaimplementuješ toto nové rozhraní a někde v kódu hry řekneš, že nyní používat tuto implementaci, a nemusíš přepisovat i celou hru, neboť metody jsou tam stejné, jen z jiného zdroje. Co potřebujeme vypsat uživateli, nebo co od něj chci získat? Počet hráčů, jejich jména, jakou kartu chceme hráči vzít a chceme vypsat konec hry. Pokud chceš něco víc, tak si to klidně dodělej. 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); } Nyní si musíme zaimplementovat toto rozhraní. Nyní máme jen předpis metod ale ne jejich nitro. Budeme používat konzoli, kterou budeme číst pomocí scanneru a na konci hry si uzavřeme scanner. Každá metoda je jednoduchá, vypíšu na konzoli co chci a potom nechám uživatele, aby mi to napsal. Všimni si, když bereš nextInt(), tak se to pokusí vzít číslo. Pokud najde něco jiného je to chyba a tu ošetříme. Klidně si dodělej více ošetření, podmínek a výpisů. Potom ale musíš vzít i zbytek. Nebo co udělal uživatel? Zadal číslo a stiskl enter. Ty jsi vzal jen to číslo, ale ne i enter. Proto tam máme ještě nextLine - to nám vezme zbytek řádku is enterem. Černý Peter bude hráč, který zůstal poslední ve hře. 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á několik hráčů, má balíček karet se kterými si hraje a má také ovládání. Toto si definujeme. public class Hra{ private BalikKariet balikKariet; private int pocetHracov; private List<Hrac> hraci; private OvladanieHry ovladanieHry;V konstruktoru této Hry si nastavíme to, co víme: public Hra() { this.ovladanieHry = new OvladanieHry(); this.pocetHracov = ovladanieHry.vyberPocetHracov(); this.hraci = vytvorHracov(); } Nestavili jsme balíček karet, protože ten je specifický pro každý typ hry jiný. V našem případě jsou to karty pro hru Černý Peter. Tak ty si vytvořím později. V kuse kódu výše jsme si vytvořili instanci ovládání hry a hned jsme ji také použili při výběru počtu hráčů. Metoda výběr hráčů je jednoduchá, uživatele aplikace se ptám jak se jmenují a rovnou je vytvořím a dám do seznamu. 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 tedy začnu ji hrát když zavolám metodu 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); } }Zde si vytvořím instanci třídy HraCiernyPeter, která má na starosti logiku, která je specifická právě pro tento typ hry. Tu si vytvoříme později. Na tomto místě si vytvořím také balík karet pomocí karet, které se vytvářejí ve třídě HraCiernyPeter. Jelikož jsem zvolil názvy metod takové, aby se snadno chápaly, tak tušíme co dané metody dělají. Když vytvořím balíček a jdu hrát, tak karty pomíchám, pak je rozdám hráčům. Musím si určit, který hráč začíná jako první. V černém petrovi je to ten, co má nejvíc karet. Jak jsme si řekli na začátku, tak když mají hráči rozdané karty, tak si složí všechny páry a tím se zbaví nějakých karet. Zkontroluji jestli snad někdo neměl všechno páry na ruce a tím pádem skončil ve hře. Zeptám se, jestli je konec hry - zda zůstal jen jeden hráč, který má černého petra - neboť tato karta nemá pár. Pokud ne, tak začnu koloběh hry. V této třídě mám i jiné pomocné třídy. Zkus si je projít 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 Černý PeterV této části si vytvoříme karty specifické pro tuto hru. Tedy 16 párů a jednoho černého 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; } Když rozdávám karty, tak je rozdávám po jedné. Tato metoda by mohla být také ve třídě Hra, ale teoreticky pro jiné typy her by se karty rozdávaly jinak. Tady rozdávám všechny karty. Z balíku karet vezmu první kartu, z balíku ji odstraním a dám ji hráči do ruky. Tady je takový fígl, že jdu přes všechny karty a dělám modulo nad pořadím karty s počtem hráčů, to mi zaručí, že budu dokola procházet hráče dokud 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()); } }Když se chystám odstranit hráče ze hry (když nemají už žádné karty na ruce), tak je nemohu odstranit během toho, jak přes ně procházím (iteruji). Proto si je dávám do pomocného seznamu a až po iteraci je odstraním. 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); } }Když někomu vezmu kartu z ruky, tak každému z těch hráčů pomíchám karty. Jednomu hráči vezmu kartu z kolekce kartiček, což má na ruce a druhému přidám do kolekce další 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()); }Samozřejmě koloběh hry jede následovně. Hrajeme do té doby, než nám ve hře zůstanou alespoň dva hráči. Začínám u prvního hráče, který vezme kartu druhému hráči. A tady jsem si natrefil na chybu. Přece hráč s největším počtem karet netáhne ale mělo by se táhnout jemu tedy, ten co je za ním táhne od něj. Tak tady si to můžete opravit, to nechám na vás. Pomůcka: upravte index prvního hráče ve třídě Hra, pokud si pamatujete, tam jsme 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++; } }Tady je pak celý kód třídy is jinými pomocnými metodami. 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]MainNakonec jsem si vytvořil třídu s jednou main metodou, která se nám bude jmenovat při spuštění programu. public static void main(String[] args) { Hra hra = new Hra(); hra.zacniHru(); }Celý Java program si umíš stáhnout odsud . TODO - úkol pro tebeDodělejte výpis, jaké karty byly hráči odstraněny z ruky, když složil páry. Udělejte další podmínky při zadávání údajů od uživatele, aby nebral karty, které někdo nemá v ruce a podobně.  Autorem tohoto blogu je Jaro Beňo , autor Java online kurzu , který můžeš na Learn2Code studovat zdarma.
Klávesové zkratky v Excelu
Tipy a triky
05.07.2017
Skillmea

Klávesové zkratky v Excelu

Připravili jsme pro tebe seznam klávesových zkratek pro Excel 2010. Tento blog popisuje nejpoužívanější klávesové zkratky, funkční klávesy a některé další běžné klávesové zkratky pro Microsoft Excel 2010 pro Windows. Pokud používáš Mac, místo Ctrl je třeba použít 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 nebo 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ář Soubor s klávesovými zkratkami v Excelu si můžeš stáhnout odsud . Plus bonusová část:  videotutoriál, jak upravit vzhled Excelu podle svých preferencí.