Jak efektivně studovat programování?

Re:Jak efektivně studovat programování?
« Odpověď #30 kdy: 27. 10. 2020, 08:56:56 »
Ono to ošetřování chyb v GO má svoji logiku (i když, přiznávám, jako Javista jsem tomu nepřišel na chuť :)).

Funkce typicky vrací dvojici hodnot - výsledek a chybu (result, err). Takto jsou napsané interní funkce a většinou se tak píšou i všechny ostatní. Obojí člověk musí do nějaké proměnné přiřadit  (result, err := func() ). A když už  něco do proměnné přiřadí, musí ji v kódu použít (jinak chyba, hlídá to kompilátor). Existuje ale placeholder "_" kdy můžu explicitně říct, že chybu ignoruju (result, _  := func() ). Takto explicitně kompilátoru řeknu, že chybový výstup funkce mě nezajímá a nechci ho ošetřit vůbec. Další možnost je  chybu ošetřít v kódu v místě vzniku nebo "poslat dál" v návratovém kódu funkce. Vždyť je to v jádru podobný mechanismus jako checked exceptions v javě (akorát s primitivnější konstrukcí).

Filozofie GO je, že chyba je jedna z možností, jak volání funkce může dopadnout. Je to plnohodnotná (a očekávaná!) alternativa k tomu, že funkce vrátí výsledek. Nikoliv něco jako corner case. Něco co "SE nějak" pořeší (frameworkem atp.). Rovnocenná varianta, která si zaslouží stejnou pozornost jako to, že funkce vrátila nějaký výsledek.

Ono v GO se typicky píšou ty mikroslužby, nástroje na automatizaci, síťoví klienti... Různé chyby spojení atd. tu nejsou výjimka ale regulérní věc, která prostě nastává. (tečka.)

A teď proč jsem si jako Javista nezvykl. Samozřejmě runtime exception. Ty jsou hodně oblíbené. Ty totiž nepřikazují, že se musí chyba řešit (buď ošetřit, poslat dál nebo prostě ignorovat (sic)) v místě vzniku.Tahle vlastnost checked exceptions je pro spoustu lidí tak silné omezení že je odchytávají a obalují do runtime a "posílají dál". Na nejpoužívanějších frameworcích v javě je to vidět. Checked exceptions jsou tak nějak demodé, nechtěný člen jazyka, na který se hledá jak to obejít. 

 No jo, je to návykové. Mít možnost chybu nechat bublat stackem, "chytit" ji o mnoho kroků dál a neřešit při každém volání něčeho "co když.."

Ano, pohodlně se s tím žije. Ale někdy je těžké (narozdíl od toho explicitního ošetřování) říct, co se stane, když... třeba server, který volám neopdoví. Data nejde načíst. Vstup je špatný...  Ono "SE" to vyřeší. Někdo tu výjimku ošetří, co na tom, že klient dostane divný návratový kód (nejlépe i se stack trace :)), v databázi (a jiných distribuovaných úložištích) zůstane nekonzistentní binec..  I tohle jsme mockrát viděli. Takže jako všechno se to musí používat s rozmyslem. Což se často neděje a proto vzniká výše uvedené. Bohužel jazyk a konstrukce neošetřených výjimek k tomu vybízí. Nejsem žádný evangelista check exceptions nebo stylu ale GO/C, jen jsem chtěl zkusit přiblížit co je pod tím za záměr.

Ono vynucovaná "štábní kultura" v GO je něco, co hodně lidí pobuřuje/omezuje. Prosté přiřazení proměnné bez dalšího použití v kódu je chyba. Chyba kompilaci (ne varování IDE). Ano, chybový výstup funkce můžu "dát do podtžítka" (ignorovat) ale okamžitě je vidět jaké jsem prase (a kde může být zdroj chyby). Dobře, buďme objektivnější - okamžitě je vidět, kde jsem se explicitně a po zralé úvaze :) rozhodl, že chybu ošetřím zrovna takhle.

Ještě jedna věc k tomu, že v GO je za trest psát větší projekt. Kubernetes je top repozitář na githubu. Nejoblíbenější open source produkt a veliký projekt v GO současně (trocha bulvárního jazyka neuškodí). Kdyby to bylo za trest, asi by to nebylo tak oblíbené.
« Poslední změna: 27. 10. 2020, 09:03:33 od premekv »


alex6bbc

  • *****
  • 1 690
    • Zobrazit profil
    • E-mail
Re:Jak efektivně studovat programování?
« Odpověď #31 kdy: 27. 10. 2020, 09:18:51 »
mi se libi v GO navratove hodnoty s chybou, kde se chyba stala tam se osetri.
excepsny se mi nelibi vubec, presunuje to reseni chyby jinam, a kvuli takove blbosti musi byt v C++ noexcept.

Re:Jak efektivně studovat programování?
« Odpověď #32 kdy: 27. 10. 2020, 09:59:43 »
Funkce typicky vrací dvojici hodnot - výsledek a chybu (result, err). Takto jsou napsané interní funkce a většinou se tak píšou i všechny ostatní. Obojí člověk musí do nějaké proměnné přiřadit  (result, err := func() ). A když už  něco do proměnné přiřadí, musí ji v kódu použít (jinak chyba, hlídá to kompilátor). Existuje ale placeholder "_" kdy můžu explicitně říct, že chybu ignoruju (result, _  := func() ). Takto explicitně kompilátoru řeknu, že chybový výstup funkce mě nezajímá a nechci ho ošetřit vůbec. Další možnost je  chybu ošetřít v kódu v místě vzniku nebo "poslat dál" v návratovém kódu funkce. Vždyť je to v jádru podobný mechanismus jako checked exceptions v javě (akorát s primitivnější konstrukcí).

Reseni GO je jenom znpouzectnost a vynucovani pouziti Err je rovnak na ohybak.
V Jave taky muzes vracet errory primo z metody (tedy ne primo dve hodnoty ale bean s dvema atributy valu,err)
A mas to samy co v GO. Nikdo to nepouziva protoze je to k nicemu.

Vyjimky oddeluji business kod od error handlingu, kdyz potrebuju resit chybu inplace, vyresim ji inplace.
Nechat probublavat exception neni zadna lenost ale obri vyhoda.
Zrovna ted jsem psal jeden loader, ktery dostal na vstupu obri JSON s e seznamem itemu s atributy, ten v cyklu zoracovaval a behem kazdeho cyklu provadel obri hromadu checku, tahani tad z externiho API a cteni  z DB.
A LIBOVOLNA chyba v tom slozitem procezu znamenala proste ukonceni procesu a zalogovani log.error("Item XXX loading failed: " + e.getMessage()
V mym kodu nebyl ZADNY error handling, krome finalniho catch bloku v ramci for cyklu pro vsechny itemy.
Tohle samy v GO nebetycny oser s preposilanim chyby manulane vejs a vejs a s totalne zamaglajzovanym a necitelym kodem

V jave je oddelen business kod od error handlingu a to je velice dobre.
Kdyz chci resit business kod, rezim try blok, kdyz resim error handling, resim catch blok. Jednoduche, ucelne.

Java example:

Kód: [Vybrat]
try {
  a1 = action1();
  a2 = action2();
  a3 = action3();
  a4 = action4();
  a5 = action5();
} catch (Exception e) {
  log.error("Je to rozbity")
  System.exist();
}

To samy v GO je necitelny maglajz a kdyz se k tomu pridaji deferred, je bordel dokonaly:

Kód: [Vybrat]
a1,err := action1()
if (err != nil) {
 log.error("Je to rozbity");
 exit();
}
a2,err := action2()
if (err != nil) {
 log.error("Je to rozbity");
 exit();
}
a3,err := action3()
if (err != nil) {
 log.error("Je to rozbity");
 exit();
}
a4,err := action4()
if (err != nil) {
 log.error("Je to rozbity");
 exit();
}
a5,err := action5()
if (err != nil) {
 log.error("Je to rozbity");
 exit();
}


 

L..

  • ****
  • 310
    • Zobrazit profil
    • E-mail
Re:Jak efektivně studovat programování?
« Odpověď #33 kdy: 27. 10. 2020, 10:29:11 »
Puvodni JSP se scriptlety je peklo.
Udelat ale web postaveny ja bootstrap+jQuery, kde v Jave servlet pripravi data, strci je jako Java objekty do response, ve vlastni JSP strance jenom predam tyto data jQuery a jinym javascript widgetum - elegantni a ciste reseni.

Ano, protože to JSP prakticky nepoužijete, tak to jde :-D

Kdyz ale to JSF nekdo umravni ve stylu https://www.primefaces.org/showcase/ , da se s tim velice pekne pracovat.

Zkoušel jsem. Showcase vypadá hezky, ale ve skutečnosti je to naleštěná hromada hnoje, pod ní větší hromada hnoje a pod ní úplně největší hromada hnoje. Všechno tohle mi připomíná jako kdyby někdo vzal součásti, zkusil je dát k sobě, zjistil, že tak úplně nepasují, tak je prostě brutálně omotal duck tapou, takže "nějak" drží, ale ve skutečnosti je to past vedle pasti.

Jak jsem psal, pokud Java framework, tak Wicket, ten na to jde dobře, komponenty se tam dělají hezky, ajax aktualizace fungují skoro bezešvě... Ale samozřejmě, pořád je to server-side.

No a dneska bych se pro nove veci snazil udelat v Angularu, Java jenom na REST API backend

Angular má jednu zásadní výhodu:

- Je filozofií hodně blízký Java frameworkům. Takže lidé přecházející z Java světa se v něm rychle orientují.

Také má ale jednu zásadní nevýhodu:

- Je filozofií hodně blízký Java frameworkům. Takže je postavený poněkud zastarale a nedokáže využít nové možnosti.


Re:Jak efektivně studovat programování?
« Odpověď #34 kdy: 27. 10. 2020, 10:43:45 »

Reseni GO je jenom znpouzectnost a vynucovani pouziti Err je rovnak na ohybak.
V Jave taky muzes vracet errory primo z metody (tedy ne primo dve hodnoty ale bean s dvema atributy valu,err)
A mas to samy co v GO. Nikdo to nepouziva protoze je to k nicemu.

Vyjimky oddeluji business kod od error handlingu, kdyz potrebuju resit chybu inplace, vyresim ji inplace.
Nechat probublavat exception neni zadna lenost ale obri vyhoda.
..

imho je to úhel pohledu/názoru a toho, na co se člověk naučí. Sám jsem dlouholetý javista, v GO jenom "poučený laik" a mechanismus výjimek je mi blízký (a GO přístup pro mne nezvyk).

try..catch..finally je elegantnější a líp použitelná konstrukce, to bych souhlasil. Znovu ale jenom jsem psal, že runtime exceptions -- ač mají tyhle výhody v jednoduchosti použití atp. -- vedou k tomu, že chybu řešit nemusím, a to ani inplace, ani v catch bloku ani v signatuře metody a to je pro mne s otazníkem. Že možná očekávaná (!) chyba není součástí kontraktu. Že ji volající klient může ignorovat a nechat řešit "automagií" (tedy probublat z metody ven, což je jen jedna z možností jak tu chybu ošetřit a ta se za mě vybere automaticky). Že vlastně ani nemusí na první dobrou vidět, že taková očekávaná chyba nastává. Možná je to úleva lenosti na úkor bezpečnosti kódu :) Ignorovat a  neošetřovat chyby ("SE" to vyřeší) je nízko visící ovoce. Pak nastávají ty situace (nejlépe až na produkci) co jsem popisoval.  Mluvím z praxe.

Jinak tenhl ekonkrétní případ by se v GO dal určitě napsat líp. GO umí funkce vyššího řádu a můžu si připravit šablonu (funkci), a volání té funkce dát do ní. Já vím... můžeme to prohlásit za narovnávák na..  Ale takhle ošklivě by to pak nevypadalo.


jano6

Re:Jak efektivně studovat programování?
« Odpověď #35 kdy: 27. 10. 2020, 11:07:56 »
Citace
Java example:

Kód: [Vybrat]
try {
  a1 = action1();
  a2 = action2();
  a3 = action3();
  a4 = action4();
  a5 = action5();
} catch (Exception e) {
  log.error("Je to rozbity")
  System.exist();
}

Ono to ale v praxi takto pekne rozhodne nevyzera.

Kód: [Vybrat]
       try {

...

        } catch (SQLException ex) {
           ...
        } finally {

            DBUtils.closeResultSet(rs);
            DBUtils.closeStatement(pst);
            DBUtils.closeConnection(con);
        }
    }

a potom

Kód: [Vybrat]
    public static void closeResultSet(ResultSet rs) {

        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException ex) {
                logger.log(Level.FINEST, "Could not close JDBC ResultSet", ex);
            } catch (Throwable ex) {
                // We don't trust the JDBC driver: It might throw RuntimeException or Error.
                logger.log(Level.FINEST, "Unexpected exception on closing JDBC ResultSet", ex);
            }
        }
    }

Jedna vynimka moze generovat dalsiu, a ta dalsia potom dalsiu. Z toho je potom poriadne kosaty kod,
ktory ma daleko k dobrej citatelnosti. Ta poznamka "We don't trust the driver" pochadza zo Springu;
to pridava kodu dalsiu uroven komplexnosti a zamotanosti. Je z toho potom uplny binec.  Mne Java
naopak vynimky poriadne znechutila.

Go ma svoje podivnosti, ako je vyssia spominana chyba, ked sa premenna nevyuziva, vynucovane
taby, Go slice, Github importy, formatovanie casu (to som chvilu zazeral, pokial mi to doslo, pouziva sa namiesto
formatovacich specifikatorov natvrdo retazec datumu a casu.)

Avsak vo svojej oblasti je genialny; vyborne sa hodi na mnostvo taskov na ktore Python nestaci a
Rust je velmi komplikovany. Chcete importovat data z Excelu, efektivne spustat web requesty, pochrumat
obrovske mnostvo dat --> na to je Go ako stvorene, portabilny, malicke binarky a vyrazne jednoduchsie
riesenie ako trebars v tom Ruste, pricom rychlost Go je len o nieco mensia ako pri Ruste.

Ja by som najradsej na vsetko pouzil F#, ale ked zbuildovany Hello World ma 30MB, tak to Go ma svoje
caro.

Re:Jak efektivně studovat programování?
« Odpověď #36 kdy: 27. 10. 2020, 11:17:43 »
K tématu tazateli: na různé skripty/řádkové tooly se mi nejlépe osvědčil Python. To je také jazyk, který "frčí" ve strojovém učení, big data, v automatizaci atd. Takže se znalost určitě neztratí. Syntax je elegantní, čitelná (i pro laika nebo člověka přicházejícího z jiného jazyka). Dají se v tom dělat i weby (django, flask) ale s tím nemám zkušenost.

Web má backend (práce s databází, business logika) a frontend část.

Pro backend  je moje volba Java. Jak bylo řečeno, ekosystém a komunita jsou obrovské, vyspělé, mnoha lety utvářené. IDE pro javu od IntelliJ je top (programuje za mne kolikrát líp než já ala "simplify this code"). Jazyk se dá rychle naučit. Strmější křivku učení vidím v knihovnách/frameworcích bez kterých se v praxi člověk neobejde.

Ve velké většině případů v souvislosti s javou uslyšíš o Spring/Hibernate. Tyhle dva frameworky se dlouhá léta pro vývoj používají a je to dospělé, robustní a funknčí řešení. Je to také velice pohodlné na použití. Jako takové SUV audi, sedneš, nastartuješ (možná přečteš pár základních pouček) a jedeš. Všechno se zdá snadné, všude samí asistenti, řídí se to samo. Ale jako se vším tady je druhá strana mince. Zejména ten Hibernate/JPA považuju za hodně komplexní věc, která na jednu stranu extrémně urychluje vývoj, na druhou stranu je to procházka polem plným vidlí. Každou chvíli na nějakou člověk může šlápnout a praštit se do hlavy. A ve finále ten nadšený začátečník zjistí, že chtěl výši platu pana Pepy, ale stahuje kvůli tomu z databáze všechny účetní knihy, data všech zaměstnanců, sklad výrobků a dokonce kompletní jízdní řád českých drah (evergreen). Nebo že dostane místo toho čísla divnou chybu (něco o "líném začátku" nebo tak). Napálí se na to každý. Opravdu každý kdo si s Hibernate něco začne :) Rozhodně používat (používá to každý), ale je potřeba k tomu přistupovat s respektem, studovat specifikaci, vědět jak to funguje a číst také články o best practices s používáním tohoto frameworku. Skutečným machrem na JPA (ale relační databáze obecně) je Vlad Mihalcea, doporučuju jeho články.

Jinak proč ten hibernate používá (skoro) každý - nikomu se nechce pořád dokola psát SQL příkazy na vytažení dat/updaty z/do dtabáze. Tak je za sebe nechává psát framewrok. Je to složitější, ale princip je tenhle.

Spring zase během chvilku umožní nasetovat aplikcai (přístup do databáze, spuštění webového kontextu atd.) řeší takový ten "boiler plate" kód (který nijak nepomáhá tomu, co dělá aplikace, ale je to nutné zlo, aby to celé fungovlao dohromady). Spring je dle mého méně zákeřný a více se dá používat jako "černá krychle" která pod pokličkou nějak funguje a dělá co má. Ale do jisté míry platí totéž co pro ten Hibernate.

Frontend nevím, není to úplně moje parketa.  Jednodušší web se dá udělat v javě (tedy všechno na server straně). Modernějí a lépe na mě než JSP působí Thymeleaf. Spring má perfektní podporu. Ale v praxi jsem to nepoužil.

Re:Jak efektivně studovat programování?
« Odpověď #37 kdy: 27. 10. 2020, 11:31:35 »

Jedna vynimka moze generovat dalsiu, a ta dalsia potom dalsiu. Z toho je potom poriadne kosaty kod,
ktory ma daleko k dobrej citatelnosti. Ta poznamka "We don't trust the driver" pochadza zo Springu;
to pridava kodu dalsiu uroven komplexnosti a zamotanosti. Je z toho potom uplny binec.  Mne Java
naopak vynimky poriadne znechutila.


Priklad s JDBC driverem je presne ten pripad stareho marasu v Jave, ktery nikdo soudny nepouziva.
Dneska pouzivat primo JDBC a a manualne mapovat hodnoty z resultsetu do beanu je prace pro masochisty.
Dneska proste reknu Springovi at mi pribali JPA, tam ale volam native queries (JSQL neumi vyuzit moznosti DB a casto to vede k divokym dotazum), Hibernate vespod mi rovnou vraci Listy naplnenejch beanu, neresim zadne konektovani ci spravu DB poolu. Prakticky jedine, co si musim hlidat, je korektni @Id v JPA beanu.

Takze nekde uvnitr Springu je schovana tvoje konstrukce s vyjimkama na vyjimky, lec who cares?
Zkratka mam v package "persitence" interface a tridu, co provolava moje nativni SQL queries a vraci List<Bean> a normalne vyhazuje SQLException.

alex6bbc

  • *****
  • 1 690
    • Zobrazit profil
    • E-mail
Re:Jak efektivně studovat programování?
« Odpověď #38 kdy: 27. 10. 2020, 12:07:20 »
bezne delam v C/C++ a musel jsem pouzivat Python.
takze zjeveni GO je pro me super, a pouziva se mi lepe nez Python.

Re:Jak efektivně studovat programování?
« Odpověď #39 kdy: 27. 10. 2020, 12:19:03 »
Za me je rozdil mezi Javou a Go asi takovy....
Oba dva ve finale daji stejny vysledek ale...

Dotaz: "Byl jsi vcera v hospode"
Java odpoved: " Pojdme se zamyslet, co to znamena vcera. Myslite tim minus 24 hodin, nebo interval mezi 0 az 24 hodin? Jeste bude potreba zavola Karlovi, co si o tom mysli a pak ... " a tak dale.
Go odpoved: "Ano" anebo "Ne"

Re:Jak efektivně studovat programování?
« Odpověď #40 kdy: 27. 10. 2020, 12:26:10 »
Za me je rozdil mezi Javou a Go asi takovy....
Oba dva ve finale daji stejny vysledek ale...

Dotaz: "Byl jsi vcera v hospode"
Java odpoved: " Pojdme se zamyslet, co to znamena vcera. Myslite tim minus 24 hodin, nebo interval mezi 0 az 24 hodin? Jeste bude potreba zavola Karlovi, co si o tom mysli a pak ... " a tak dale.
Go odpoved: "Ano" anebo "Ne"

Potreboval bych optimalizovanou typove bezpecnou multimapu.
Java: No problem.
Go: Jeblo ti?

Re:Jak efektivně studovat programování?
« Odpověď #41 kdy: 27. 10. 2020, 13:50:52 »
Go je jednoduché, Java komplexní
Tím pádem je Go na jednoduché věci, Java na komplexní.

BoneFlute

  • *****
  • 1 987
    • Zobrazit profil
Re:Jak efektivně studovat programování?
« Odpověď #42 kdy: 27. 10. 2020, 16:44:26 »
Ono to ošetřování chyb v GO má svoji logiku (i když, přiznávám, jako Javista jsem tomu nepřišel na chuť :)).

Funkce typicky vrací dvojici hodnot - výsledek a chybu (result, err). Takto jsou napsané interní funkce a většinou se tak píšou i všechny ostatní. Obojí člověk musí do nějaké proměnné přiřadit  (result, err := func() ). A když už  něco do proměnné přiřadí, musí ji v kódu použít (jinak chyba, hlídá to kompilátor). Existuje ale placeholder "_" kdy můžu explicitně říct, že chybu ignoruju (result, _  := func() ). Takto explicitně kompilátoru řeknu, že chybový výstup funkce mě nezajímá a nechci ho ošetřit vůbec. Další možnost je  chybu ošetřít v kódu v místě vzniku nebo "poslat dál" v návratovém kódu funkce. Vždyť je to v jádru podobný mechanismus jako checked exceptions v javě (akorát s primitivnější konstrukcí).

Filozofie GO je, že chyba je jedna z možností, jak volání funkce může dopadnout. Je to plnohodnotná (a očekávaná!) alternativa k tomu, že funkce vrátí výsledek. Nikoliv něco jako corner case. Něco co "SE nějak" pořeší (frameworkem atp.). Rovnocenná varianta, která si zaslouží stejnou pozornost jako to, že funkce vrátila nějaký výsledek.

...

Ano, pohodlně se s tím žije. Ale někdy je těžké (narozdíl od toho explicitního ošetřování) říct, co se stane, když... třeba server, který volám neopdoví. Data nejde načíst. Vstup je špatný... 

Hezky shrnuto. V mnohém souhlasím.

Zdrůraznil bych:
- Výjimky byli vymyšleny, aby se dalo psát toto:
Kód: [Vybrat]
if (((countOfFilesIn(dir1) + countOfFilesIn(dir2)) / countOfFilesIn(dir3)) == 0) { ... }. Což bez nich prostě nejde.
- Nevynucovat odchytávání - tedy unchecked exceptions jsou zlo, a celé to to kazí.
- Výjimky jsou naprosto regulérní návratový stav. Jen jinou cestou. Problém je jen v tom, když jazyk nevynucuje jejich zpracování.
- To co dělá GO je stejnej mechanisumus jako mají funkcionální jazyky (Haskell). Jen je to takové odlehčené.

borekz

  • ****
  • 493
    • Zobrazit profil
    • E-mail
Re:Jak efektivně studovat programování?
« Odpověď #43 kdy: 27. 10. 2020, 17:04:58 »
Potreboval bych optimalizovanou typove bezpecnou multimapu.
Java: No problem.
Go: Jeblo ti?
Jak to udělám jednoduše v Javě bez knihoven třetích stran ?

Silná stránka C++ jsou šablony, které fungují jinak než v Javě. Šablony v Javě jsou jen syntax sugar místo castování. Šablony v C++ generují zdrojový kód jako makro a tím jednak umožňují v kontejnerech uložit zadaný typ přímo bez balení do objektu a navíc instance šablony ten typ zná a proto jej může instanciovat metoda v šabloně. Kontejner v šabloně může jen ukládat reference na objekty vytvořené mimo kontejner.
Kód: [Vybrat]
map<int,vector<int>> multimapa;
multimapa[5].push_back(6);  // operátor [] najde existující vector nebo automaticky vytvoří nový

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Jak efektivně studovat programování?
« Odpověď #44 kdy: 27. 10. 2020, 17:59:59 »
- Výjimky byli vymyšleny, aby se dalo psát toto:
Kód: [Vybrat]
if (((countOfFilesIn(dir1) + countOfFilesIn(dir2)) / countOfFilesIn(dir3)) == 0) { ... }. Což bez nich prostě nejde.
Ve funkcionálních jazycích to jde ;) Akorát dá o dost víc práce pochopit, jak kód v takovém případě funguje.