Kromě OpenShiftu, který mě zajímá řekněme profesionálně si teď hraju s různými SoC postavených na ARMu. A pro tyto čipy je Go celkem rozumná volba - rychlý překlad, ucházející rychlost výsledného programu, ne tolik ruční práce jako v Céčku. Na těch SoC střídám Go a Luu (LuaJIT), ale každý z těch jazyků pochopitelně na něco jiného.
> Mne by zajimalo, jestli se GO hodi na jednoduchou REST servisu (bezicim treba na RPI).
> Mam v hlave maly projekt pro domaci automatizaci, a nebranim se aplikaci nejakeho experimentu :)
Jděte do toho, když chcete investovat čas a energii, jste jediný kompetentní zodpovědět dotazy tohoto typu (zda pro Vás a konkrétní problém/prostředí se něco hodí či nehodí). Buďte sám sobě guruem ;-)
Pro mě je Go na takové věci výborný, ale když bych si způsobil mentální úraz např. v podobě:
- alergie na tabelátory
- nepředstavitelnosti TLS nezávislého na distribuci (zabudovaného do knihoven jazyka)
- neschopnosti žít ve světě bez výjimek
- představy pekla při psaní aplikační logiky v Go
- psychosomatických bolestí při zpracování strukturovaných dat v Go
- pocitu z břicha, že se mi nelíbí
tak pro mě Go v žádném případě nebude vhodný!
Nebo bych mohl mít nějaké racionálnější důvody pro něco jiného, dva příklady:
Potřeba ještě kratšího cyklu vývoje a potřeba ještě extrémnějšího minimalismu/elegance jazyka. Pak pro mě bude třeba Lua https://openresty.org/en/ https://luvit.io/
Viz také "František Fuka: Lua: Krása v jednoduchosti - DevFest Praha 2013" https://www.youtube.com/watch?v=0L1sA_abrkY
Potřeba větší odolnosti prostředí. Pak pro mě bude např. Erlang.
Pro mě velmi zajímavé hračky. Budu moc rád, když se podělíte o zkušenosti.
Potkal jste https://luvit.io/ ?
Updaty z distribucie ti netreba. Golang TLS implementacia (ludovo povedane SSL) nepouziva ziadnu kniznicu z distribucie - ziadna 3rd party zavislost. Ked chces security update, tak proste urobis novy build s poslednou stabilnou verziou Golangu (mam takto urobeny moju build pipeline kde buildujem s :latest golang imageom).
Popravde tych sec. problemov Golang zatial nema vela (20):
https://www.cvedetails.com/vendor/14185/Golang.html
Oproti takemu OpenSSL (192):
https://www.cvedetails.com/product/383/Openssl-Openssl.html
Ano, Golang vie pouzit aj HW akcelaraciu. Napr. kontroluje podporu AES-GCM HW a podlo dostupnosti zvoli vhodny cipher suite.
Od kdy docker anebo whatever jina kontejnerizace pouziva uvnitr kontejneru host libky? Spis jde o to, ze vy si vybuildite svou binarku a mohla by vyuzivat libky toho dockerkontejneru. Az se vyprdnete na updaty te vasi binarky, tak by mohl kdokoliv aspon prebuildit ten docker a mit to cerstve - teda samozrejme pokud budou vase zdrojaky k dispozici tak si to muze prebuildit nekdo jiny nekdy jindy..
"výsledkem by měly být rychlé a paměťově efektivní aplikace (alespoň teoreticky) srovnatelné s výsledky, které jsou produkované překladači jazyků C, C++, D či Rust"
https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/rust-go.html
Přesně tak, proto píšu teoreticky. V praxi je tam jeden problém: standardní Go dnes staví na vlastním překladači (protože se Go bootstrapuje), i když tedy existuje i gccgo. IMHO by bylo zajímavější ty benchmarky postavit na Go používajícím backend LLVM (llgo), protože v případě Go skutečně nejsou teoretické důvody, aby binárky byly pomalejší, zvláště u tak primitivních benchmarků, kde se GC ani nemusí projevit.
Go by mohlo být stejně rychle jako C/C++/Rust, pokud by mělo dokonalou escape analysis. Pokud se překladači nepodaří zjistit, že by proměnná mohla být na stacku a vytvoří ji zbytečně na heapu, je to velká režie navíc. Podle všeho má Go jen nějakou základní escape analysis: https://golang.org/doc/faq#stack_or_heap
Jj přesně tak. Právě proto si myslím, že by Go mohl pomoci ten překladač pro LLVM. Protože komunita okolo LLVM dokázala, že ví jak na to. Část o alokaci proměnných mám zatím rozpracovanou, ale oni se snaží cpát lokální proměnné na zásobníkové rámce, což by mělo pomoci právě v benchmarcích (klasika - počitadlo smyček, index do pole atd.).
Možná bys jim měl jít poradit jak na to. Tady je to samej erudovanej pseudovyvojar který hodnoti jazyk podle benchmarku. :)) Ti co uz neco napsali hodnotí i podle jinych kriterii jako produktivita, prenositelnost, citelnost, apod a tam přichází na scénu kompromisy. V realne aplikaci to visi na jinych operacich nez regexu, binarnich stromech. Doporucuju napr clanek od Roba Pika týkající se regexu. Je to mnohem komplikovanejsi a je to znovu o kompromisech. Lide co za go stoji zaklady zvladaji. Ver mi.
Ne, netýkalo. Jen jsem popletl autora. Už je to nějaký pátek co jsem to četl. Byl to Russ Cox. https://swtch.com/~rsc/regexp/regexp3.html
Pěkný úvod, díky.
Vypadá to, že není vůbec důležité, jaké jazyk používá závorky nebo odsazení, ale jaký styl myšlení svým programátorům navozuje. Pro mě je Go na nejlepší cestě být novodobou verzí Javy se všemi nectnostmi a nevýhodami. Java místo aby použila systémovou knihovnu a volala tak jiný jazyk, tak si raději všechno reimplementuje sama. Takže pak instalujete aktualizace cojávím úložiště certifikátů pro celý systém kromě Javy, a zvlášť pro Javu. Nebo konfigurace pro časové zóny - jednou pro systém, jednou pro Javu. Taky javoví programátoři fungují stylem "zkopíruju vše co potřebuju do svého projektu a už to nikdy neaktualizuju", namísto toho, aby věnovali minimální úsilí směrem k použití toho, co v systému už i tak je. No a program v Go v podstatě odpovídá staticky linkovanému programu v C, což byla doporučovaná forma sestavování programů tak někdy kolem roku 1990. Takže za mě - čím méně se Go rozšíří, tím lépe.
-Yenya https://www.fi.muni.cz/~kas/
To já samozřejmě nevím, mně by stačilo, kdyby Java byla aspoň natolik multiplatformní, abych nemusel ke každému Javovému programu složitě hledat přesně tu správnou verzi Javy, se kterou ho mám spouštět, aniž by blil na stderr tuny chybových hlášek a backtraců, nebo u některých aspoň aniž by padal a aspoň nějak fungoval.
-Yenya
Tak nějak všechny, které jsem měl příležitost spouštět. Například freemind. Nebo různé javové applety, které generují webové vizualizace různých technologických zařízení (vzduchotechnik, chlazení, záložního napájení a podobně).
Jako jo, _teoreticky_ jde nejspíš napsat Javový program který funguje správně na různých verzích Javy, neblije souvislý proud backtraců na stderr, a vůbec se chová způsobně. Problém je, že prakticky se takto javové programy podle mých zkušeností prostě nechovají.
-Yenya
No vidíte, a přitom je spousta zařízení, které koupite letos, v roce 2018, a u kterých se očekává funkčnost v řádech desítek let, a tato zařízení mají primární způsob ovládání ve formě toho údajně mrtvého Javového appletu. Ne že by na tom pět let stará zařízení (očekávaná doba provozu dalších minimálně 15 let) byla lépe. Je teda pravda, že když budete na dodavatele dostatečně drsní, tak většinou připustí i existenci nějakého Modbusu, SNMP nebo BACnetu, nebo aspoň RS232/422/485 s nějakým proprietárním ovládáním, ke kterému po další dávce výhružek je ochoten vydat i nějakou dokumentaci (nebo teda zbude reverse engineering komunikace toho appletu).
Ale to už fakt odbočujeme od tématu Go. O Javě můžeme diskutovat jinde.
Zpátky ke Go: s tímto jazykem jsem se potkal u jednoho relativně triviálního projektu (firmware uploader pro RC vysílačku), kde na githubu v repozitáři měli zdroják, ale taky .exe a linuxovou binárku(!}. Zdroják se nepodařilo přeložit, protože (pokud si dobře pamatuju) to mělo snahu stahovat nějakou knihovnu/balík, která ale v systému už byla nainstalovaná z repozitářů Fedory. Linuxová binárka fungovala (dokonce i .exe pod Wine fungoval), tak jsem to dál neřešil, jen jsem si učinil mentální poznámku, že Go asi není to co bych chtěl používat.
-Yenya
Nicméně aplikace na vzduchotechniku mají obrovskou setrvačnost a natolik specifické požadavky, že je nejlepší je pouštět na PC vyčleněném přímo pro ně. Nedivil bych se, kdyby běžely v nejlepším na 10 let staré Javě a Windows Serveru 2003 s admin právy a Internet Explorerem 6. Aspoň taková je moje dávná zkušenost, když jsem o ně zavadil.
Diky za info. Ty applety ... ok, ty neznam. Ale Freemind pouzivam od Javy 6 (Fedora, Mint, eeebuntu, Windows XP) a tedy nevsiml jsem si, ze by padal nebo vyzadoval konkretni verzi. Pise to jen par hlasek typu:
STDOUT: User patterns file /home/tester/.freemind/patterns.xml not found. STDOUT: User patterns file /home/tester/.freemind/patterns.xml not found.Nov 2
Já jsem freemind zkoušel používat tak kolem roku 2010, a nakonec jsem našel verzi Javy, se kterou fungoval, i když občas padal. Je pravda, že aktuálnější informace nemám. Pak jsem objevil vimoutliner, a od té doby pro podobné účely používám místo freemindu ten. Má to výhodu, že .otl soubor je lidsky čitelný a jde ho commitovat do gitového repozitáře tak, aby i jednotlivé změny v git diff dávaly smysl.
-Yenya
Potom i kradu, ze? Neprogramuji pro Javu. Ale musim nejake Java aplikace provozovat, tazke mam jen prakticke zkusenosti. Uz jsem se naucil, ze si musim pohlidat, aby dodavatel nemel aplikace prelozene poslednim kompilatorem, ale kompatibilni s nasazenou verzi Javy. A ti programatori to porad nechapou, porad maji predstavu, ze nejnovejsi je nejlepsi. A proto mam radsi skriptovaci jazyky... Nejvetsi riziko je, kdyz dodavaji jen "drobnou" opravu na starsi SW.
Podobnou zkusenost mam i s go, tam jen jeste nevim, co je zdrojem nekompatibility...
Pro programátory samozřejmě nejnovější je nejlepší, protože to má nejvíc vlastností, které jim něco usnadní – např. nemusí danou věc sami programovat, snáze se jim ladí, provádí další kontroly kódu apod. Výhody to má i pro uživatele, protože novější JVM má třeba lepší GC nebo lepší optimalizace. Takže pokud aplikace funguje s novější verzí JVM, snažil bych se používat co nejnovější. Samozřejmě pokud to jde, v posledních verzích se dost pročišťovalo a aplikace používající např. třeba nějaké interní implementace Oraclu/Sunu v novějších verzích nemusí fungovat.
golang ma, teoreticky, jen minimalni pozadavky na kernel, ale ty pozadavky jsou specifikovane velmi vagne (kernel novejsi nez 2.6.23). Dusledkem je, ze funkcni program prelozeny novejsi verzi prekladace prestava na casti systemu fungovat. Ten probem se objevuje znovu a znovu, zeptejte se Google na "runtime epoolwait failed". Ano, problem postihuje jen starsi systemy, takze pokud mate vzdy nejnovejsi distribuci, tak jste za vodou...
Ad 1) Hm, starší verze než 6 přijme jako platný argument, ale při kompilaci vypíše chybu. Zvláštní postup.
Ad 2) To s verzemi vůbec nesouvisí. JVM při startu samozřejmě nemůže kontrolovat, zda má k dispozici všechny třídy, protože neví, jaké všechny třídy budete používat. Kdyby nic jiného, můžete se pokusit třídu načíst přes reflexi.
Cache musí být při přepnutí procesů (aplikací) invalidována z bezpečnostních důvodů, obsahuje citlivá data procesu, ke kterým se nesmí dostat jiný proces. Cache přímo vyčíst nelze, ale postranními kanály ano. TLB v případě statického linkování žádnou režii nemá, protože celý kód je v rámci jednoho virtuálního adresového prostoru.
Co se týká výkonu, je statické linkování výhodnější než dynamické, protože se vůbec neuplatňuje dynamický linker, dohledávající funkce podle jména v dynamické knihovně. Taky se dají se statickým linkováním udělat některé optimalizace (https://en.wikipedia.org/wiki/Interprocedural_optimization), které s dynamickým linkováním nejsou možné.
> TLB v případě statického linkování žádnou režii nemá, protože celý kód je v rámci jednoho virtuálního adresového prostoru.
Opravdu? TLB přece figuruje při překladu virtuálních na fyzické adresy. Jeden virtuální adresový prostor mají jak staticky tak dynamicky linkované programy. A i ty staticky linkované musí přes tlb protáhnout záznam pro každou použitou stránku.
Je vedle sebe jen ve virtuálním adresovém prostoru, ne? Fyzicky jsou stránky rozstrkané po fyzické paměti dost náhodně. Takže statiké linkování ušetří akorát pár stránek na hranicích dynamických knihoven.
A u dynamického linkování je možné v tlb nechat kusy pro sdílené části adresového prostoru. Třeba libc a podobně. Při statickém linkování znamená každé přepnutí procesu kompletní výmaz tlb.
"Když se volá funkce, tak se statickým linkováním je nějaká pravděpodobnost, že bude ve stejné stránce. "
- Toto je snad ten nejhloupější argument, který jsem na téma static vs dynamic linking kdy slyšel. Ale můžeš v něm pokračovat a zkusit tu pravděpodobnost nějak dokázat a taky změřit jaký dopad to má celkově na výkon. Asi už znám výsledek - 0, protože procesor má cache (a instruction cache line je 64 bajtů a ne celá stránka) a je mu úplně jedno, kde ten kód je. Jo, kdybys zmínil např. .got (global offset table) overhead , TLS access overhead, a další věci, kde nastává overhead při dynamickém likování, tak bych to pochopil, ale stránkování IMO není problém a pokud tvoje aplikace nemá limit 4kB tak je to naprosto irelevantí.
Já ti to nebudu znovu vysvětlovat, když jsi to nepochopil. Zkus třeba i jiné zdroje, třeba ti to dojde: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.performance/when_dyn_linking_static_linking.htm
A more subtle effect is a reduction in "locality of reference." You may be interested in only a few of the routines in a library, and these routines may be scattered widely in the virtual address space of the library. Thus, the total number of pages you need to touch to access all of your routines is significantly higher than if these routines were all bound directly into your executable program. One impact of this situation is that, if you are the only user of these routines, you experience more page faults to get them all into real memory. In addition, because more pages are touched, there is a greater likelihood of causing an instruction translation lookaside buffer (TLB) miss.
Tak je pomerne drsny, kdyz clovek s doktoratem s MUNI, co tam vyucuje programovani v UNIXu napise takovy blabol.
Jednoduche proceduralni GO nema s objektovou Jawou (rizlou lambdama) spolecneho lautr nic.
To co je "v systemu" jsou vetsinou ceckove knihovny (Linux), ve woknech na winapi jeste .Net VM, v OS X treba navic Cocoa.
Tudiz pro potreby multiplatformniho jazyka vicemene nepouzitelne.
Java si svoje potreby reimplementuje sama, zrovna GO casto pouziva systemova volani via jeho interni C binding.
Zrovna nedavno jsem psal v GO program, ktery ovladak mys, klavesnici a snimal obrazovku.
Byla na to GO knihovna podporujici Lin/Win/Mac, ktera interne volala ceckove syscally.
Ostatne neni sebemensi problem si i v Jave owrapovat systemove volani, tim zrusit multiplatformnost a vystavit se bugum microsoftu - konkretne v pripade certifikatu
Viz https://www.oracle.com/technetwork/articles/javase/security-137537.html
https://stackoverflow.com/questions/34166304/accessing-windows-certificate-store-certs-via-java
Akorat nevim, k cemu to ma byt dobre, osbne si vlastni TrustManager pisu, jenom kdyz potrebuju ofejkovat kontroly certifikatu v rozjebanem systemovem prostredi, muj TrustManager rika OK na libovolny pozadavek.
Apropos, dnesni java programy se pisou s vyuzitim Mavenu, aktualizace knihoven v projektu je zmena jednoho cisilka v pom.xml.
Přijde mi, že mindset programátorů je více ovlivněn fenomény o kterých mluví "Uncle" Bob Martin v přednášce "The Future of Programming" https://www.youtube.com/watch?v=ecIWPzGEbFc (pozor, je to spíše historie, ale podle mě vysvětluje srozumitelně stávající stav) než jazykem, který používají.
Dříve jsem si myslel, že téměř nejdůležitější je dělat věci správě (např. programovat správě). Proto jsem nechápal, jak někdo může nepovažovat za nejrozumnější funkcionální programování a ANSI Common Lisp a stále "plýtváme" zdroji s procedurálním programováním (tam kde Alan Turing začal). Proč jsme se nebyli schopni reálně úrovní posunout ?
Nyní se přikláním k názoru, že mnohem důležitější než dělat věci správě, je dělat je srozumitelně a použitelně pro "hodně" lidí. To mě vede k přesvědčení, že minimalismus a "user space" samostatnost Go je jedou ze správných cest.
Ad "systémová knihovna" - co to vlastně je ? :-) Kernel (Linux) je také knihovna. Hranice mezi user space knihovnami a kernelem není ostrá (nezřídka dělají obdobné věci a umístění funkcionality kernel vs user space je dáno spíše historicky, mnohá funkcionalita se také překrývá - např. API logování). Budeme "kárat" user space knihovny a kernel za duplicity ?
Domnívám se, že běhové prostředí aplikace by měl mít aplikační programátor více pod kontrolou, čemuž "brání" stávající pojetí distribucí, kde běhové prostředí aplikace značně ovlivňuje package maintainer. No a proč nutit uživatele řešit závislosti knihoven, když nemá pro svou aplikaci balíček distribuce ? Nebo proč nutit dělat aplikačního programátora binárky (balíčky) pro řadu distribucí, když stačí binárka per architektura/platforma ?
Proč nám vlastně vadí spouštět binárky (důvěřovat autorovi aplikace), když důvěřujeme jeho kódu a kódu knihoven co aplikace používá ?
Je lepší mít hromadu verzí dynamických knihoven (a evidovat v distribuci závislosti) nebo je lepší aby každá aplikace měla běhové prostředí svoje, to co otestoval a připravil autor aplikace ? Mě přijdou lepší binární "aplikační kontejnery" (staticky linkované binárky), než noční můra závislostí, hromada mrtvého kódu (to co je v dynamicky linkovaných knihovnách) s nezbytností se o něj starat a patchovat všechny verze. Či bizáry typu Virtualenv pro Python. Nedejbože když je třeba stejná verze dynamické knihovny přeložená s jinými parametry - to už je teprve schiza :-(
Go samozřejmě umí využít "systémové" úložiště certifikátů, viz např. https://medium.com/@pierreprinetti/the-go-1-11-dockerfile-a3218319d191 Na úrovni clusterů je pak jistě lepší používat rozumnější správu konfigurace než distribuce na jednotlivých serverech - tedy něco jako etcd, Consul atp - k tomu budeš "systémové knihovny" přemlouvat těžko, ale v Go je to otázka cibulové struktury API (bez vlastní implementace knihoven by to bylo velmi obtížné).
Kontejnerově distribuované aplikace s minimalizací povrchu pro útoky je myslím také rozumná strategie.
Proto si dovolím nesouhlasit s přirovnáním k Javě a prohlásit čím více se Go rozšíří (obecněji strategie přístupu méně je více, osvobození od dynamických závislostí), tím lépe.
Když moje oblíbená distribuce nemá balíček pro aplikační program, je fajn když binárka "just works" a to i na několika platformách, dva malé příklady:
https://github.com/peco/peco
https://github.com/asciimoo/wuzz
Řada aplikací z https://github.com/avelino/awesome-go by tu asi nebyla nebo ne v tak skvělé formě.
Já např. mohu doporučit (všechny najde na GitHubu):
https://grafana.com/
https://www.influxdata.com/time-series-platform/
https://traefik.io/
https://prometheus.io/
https://emitter.io/
BTW sdílím tvoji bolest s běhovým prostředím Java.
K minimalizaci nepoužívaného kódu běhového prostředí (zejména pro menší devices) směřují další iniciativy i na úrovni kernelu, např. https://next.redhat.com/2018/11/14/ukl-a-unikernel-based-on-linux/
Michal Mühlpachr
SW i HW v leteckém průmyslu musí splnit regulační podmínky, což prakticky znamená že nesmí překročit určitou poruchovost, což se před regulátorem prokazuje velmi různorodým a rozsáhlým testováním s měřením metrik např. MTBF. Neboli SW do letadla nemusí pracovat správně, stačí když pracuje správně do určité míry (obdobně jako HW). Důležitější je, aby SW byl použitelný.
Použitelně pro "hodně" lidí nemusí znamenat "hodně instalací", může to znamenat hodně pasažérů, kteří létají na SW a HW co prošel kritérii regulátora (ten v případě leteckého průmyslu často SW ani nerozumí a není to zásadní problém, letecká doprava je nejspolehlivější).
Není mi znám postup/technologie umožňující vyrobit 100% spolehlivý HW (fyzikální zákony - termodynamika, atd).
U SW takové postupy existují a jsou matematicky prokazatelné (používají se např. pro důvěryhodné výpočetní báze).
Existují výrobci leteckého HW (např. GE s motory pro malá letadla), kteří se v produktech vyhýbají zařazení SW do smyček řízení leteckého HW, protože dosažení potřebné spolehlivosti se zařazením SW je neekonomické (neúměrně nákladné).
Kam až nás v zásadě jednoduchá úvaha odnesla ;-)
Golang je celkem dobrý na nízkoúrovňové programování. Jako náhrada C (na PC a v kontejnerech) je to pohodlné.
Ale právě tu náhradu Pythonu a spol nechápu.. vždyť psát v tom vysokoúrovňovou logiku je peklo (žádné list comprehensions / streamy / linq / ..), žádné numerické knihovny (numpy).. prostě nic!
Je tam potenciál, obzvláště pokud se podaří prosadit návrhy lepšího error handlingu a generik: https://go.googlesource.com/proposal/+/master/design/go2draft.md
Asi takhle, kdysi jsem v Pythonu pár drobností napsal, ale potřeboval jsem jednoho malého daemona. V podstatě bylo lepší se naučit Golang než znova objevovat kolo u Pythonu. Skoro každý řádek jsem musel doloval z dokumentace (jak se zapisuje hash, array, strlen atd). Díky rychlému cyklu kompilace - test se to ale blížilo spíše skriptování a posouval jsem se rychle. Navíc jsem měl základ v podobě již existujícího FOSS kódu který jsem jen modifikoval.
To je právě doména, pro kterou bylo Go navrženo. Takže jak jazyk, tak standardní knihovna poskytuje pro psaní daemonů pěkné nástroje. A navíc je tu výhoda pro kontejnery - teoretická menší spotřeba paměti a jedna statická binárka.
Nicméně když neumíte v Pythonu ani Go, tak se Vám to špatně srovnává. V Pythonu totiž existuje třeba socketserver [1], který skoro všechno abstrahuje taky. Na psaní jednoduchých REST aplikací se dá použít třeba Flask [2], který je už úplně triviální.
V Pythonu 3 s asyncio už to skoro jako golang i vypadá [3].
[1] https://docs.python.org/3.4/library/socketserver.html#socketserver-tcpserver-example
[2] http://flask.pocoo.org/
[3] https://asyncio.readthedocs.io/en/latest/tcp_echo.html
Je to otázka názoru. Mě se ten jejich masochismus prostě líbí, protože to zabraňuje lidem dělat prasárny. Už jsem měl tu čest se 700 řádky obalenými try/exceptem. Lidé jsou líní. Navíc, když už člověk ošetřuje error tak si to většinou rovnou i srozumitelně logne => lépe se to potom debuguje než nějaká generická hláška. Chtělo by to jen kratší zápisy těch error checků a na tom snad už pracují. Je plno věcí co go má a jiné jazyky zase nemají. Třeba takový defer budou Pythonáři hledat marně. Built-in testy/profilování/benchmarky a dokumentace přes comment markdown je taky užasná věc.
defer funkcionalitu nebudou hledat marně ani pythonisti (context managers [1]) ani javisti (try-with-resources [2]). Oba jazyky maji trošku jiný zápis toho samého s explicitním vyznačením bloku platnosti (u defer je to funkce).
Defer je jinak pěkný, ale taky se s ním musí opatrně.
[1] třeba tady https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/
[2] https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Jestli chapu spravne vyuziti defer v Go, je to v podstate nahrada try-finally (coz ma treba Python snad odjakziva), protoze, ted pozor, Go vyjimky nema, protoze nejsou potreba. Ale jasne, zase soudruzi v Go vynalezli kolo. Context manager (with) je kvalitativne o uroven vys.
Defer není úplně to samé jako jednoduché finally, i když je mu hodně blízko.
Defer funkce se totiž dá zaregistrovat až ve chvíli, kdy je co uklízet. Čímž řeší problém alokace více zdrojů s kontrolou selhání a úklidem v každém kroku. Finally si naopak musí samo zjistit co uklidit a co se už nezvládlo vytvořit.
Myslím si, že právě proto jsou with a try-with-resources tomu defer sémanticky nejblíž. Všechno je to syntaktický cukr, který programátorovi umožňuje po sobě uklidit a přitom neřešit jak a kdy blok/funkce skončí.
Souhlas, absence vyjimek a mizerna standardni knihovna je momentalne nejvetsi bolest golangu.
A pokud to nefixnou, golang na to zdechne.
Fakt nechapu, co ma byt jako problem.
A kdyz si clovek precte "zduvodneni" proc jako vyjimky ne, zacne pochybovat o dusevnim zdravi autoru:
https://golang.org/doc/faq#exceptions
Vzdyt je to prevelika krasa, po kazdem zavolani funkce pridat boilerplate checku:
Toto je z ofic go blogu. Pise se rok 1981 a vsude se tanci twist.
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
dst, err := os.Create(dstName)
if err != nil {
return
}
written, err = io.Copy(dst, src)
dst.Close()
src.Close()
return
}
Protože lidi začali používat výjimky pro ne úplně výjimečné stavy. Např. nechápu, proč bych měl vyhazovat výjimku při něčem tak očekávaném jako "soubor nenalezen" - to už je masochizmus. Pokud se bavíme o nějakém zjednodušení control-flow při výskytu chyby tak tam nemám nic proti tomu přizpůsobit tomu trochu jazyk nebo použít nějaký construct typu Result<>, Maybe<> atd. Problém Go je v tom, že nemá podporu generiky, takže to asi bude muset řešit nějak jinak, ale nesleduju to, protože staticky typovaný jazyk bez generiky me nezajímá (a navíc když vidím ten Go kód, tak mi to přijde jak pascal a bez těch středníků je takový smutný :).
Jinak trochu víc k věci. Např. Rust výjimky nemá a tomu jazyku to nijak nechybí - obecně pro multithread aplikace je to možná ten nejlepší přístup. V C++ komunitě se teď taky začalo diskutovat o tom, že by mělo dojít k přepracování výjimek, protože ten design není ok a dopad na výkon zpracování jednoho stavu navíc se stejně blíží nule (nechci se rozepisovat, toto bude stejně trvat dlouho, ale už jen to, že někdo připustil že máme problém, je celkem výhra).
Jinak to byl tak trochu troll-post pro ty co dávají rádi minus :)
@unicode
Ode mne mínus nemáš, sorry. Nevím jak je to v Rustu, takže to nekomentuju. Ptám se proto, protože nedávno jsem řešil aplikaci bez vyjímek a není skutečně nic lepšího než vracet přes zanoření šesti funkcí nejaký objekt (či něco) s errory, předávat ho mezi všemi třídami či funkcemi a po každém každičkém volání funkce kontrolovat jestli neskončila errorem, případně jakým, to se ani nebavím o externích knihovnách a jejich takových objektech. Ostatně takto je napsaná půlka všemi milovaného Wordpresu. To je můj pohled. Pletu se? Tak se rád přiučím - proto se ptám.
Já dělám hlavně v C/C++, js (node), a trochu se zajímám o rust. Vyhýbám se PHP a Javě. Bez pohledu na konkrétní kód je podle mě těžké se bavit o tom, jaký přístup je lepší nebo co by se dalo zlepšit. Použití výjimek záleží i na tom, ve kterém jazyce člověk dělá. Např. v C++ hodně záleží na projektu i na tom, které knihovny ten projekt používá.
Osobně si myslím, že exceptions nejsou silver bullet a člověk, který je chce používat úplně na všechno je jak to dítě s tím kladivem co vidí všude jen hřebíky :)
Jenomže výjimkou jsou silver bullets. Je řada stavů, které bez výjimek prostě rozumně neošetříte. Proto výjimky existují už na úrovni procesoru a strojového kódu, kde se jim říká přerušení.
Jazyky na hraní, jako je Go, to nikdy nezjistí. Ale jazyky, které mají zajistit nějakou spolehlivost se bez výjimek neobejdou.
Zdrojem chyb může být miliarda věcí od hardware, operačního systému, momentálních potíží v alokaci zdrojů, různých existujících/neexistujících práv kdekoli - a miliarda dalších věcí. I při otevírání souboru může docházet pamět, docházet místo na zásobníku, dojít k hardwarové chybě disku, mít problémy s právy, atd.
Za 30 let programátorské praxe jsem ještě nikdy neviděl dobře ošetřený kód bez výjimek ani při takové kravině, jako je otevírání souboru. Kód, který by skutečně kvalitně ošetřoval všechny možnosti. Nehledě k tomu, že různé chyby by se měly ošetřovat často na různých místech - ne vše může rozumně ošestřit ten, kdo volá fopen().
Většinou osoby zastávající nepoužívání výjimek končí tak, že většina lidí prostě chyby ignoruje. Počítá s tím, že nenastanou. Nebo je ošetřují jen někde. K nahlédnutí v tisících open source zdrojových kódech.
Vzpomínám si na to, jak programovací jazyk Ada urychleně přidával do nové normy výjimky. Zjistilo se, že ty sw prostě padají při řadě situací, a programátor bez výjimek s tím nic neudělá. Program při řadě chyb mohl jen udělat terminate(), a poslat do šrotu pár miliónů či miliard dolarů v družici kdesi mimo zemi. Najednou byly všechny námitky proti výjimkám bezpředmětné. A najednou šly ošetřit všechny stavy, a něco udělat.
Proboha jak mohlo být dopuštěno, že fungují embedded systémy (zdravotnictví, doprava, energetika, ... - většina PLC a to i řada speciálních "žlutých" emergency stop systémů), na kterých závisí životy a jsou implementované v ANSI C bez výjimek ?
Jak to, že jaderné elektrárny jsou řízeny Fortan kódem bez výjimek ?
Jak to, že vojenské zbraňové systémy jsou řízeny kódem bez výjimek ?
Proč toho je tolik bez "rozumného ošetření" ?
Jaký je zásadní rozdíl mezi kódem, který rozhoduje co s chybou (zpracovat, zkusit znovu, počkat, poslat výše, ...) s pomocí paradigma/syntaxe:
a) if/switch ...
b) try/catch ...
?
Zásadní mi přijde u try/catch proti if/switch možnost nepovšimnutého "probublání" chyb spodnějších slupek (knihoven) API do hornějších vrstev aniž hornější slupky vrstvených API mají tušení (resp. programátoři, kteří je používají), že se něco takového dole může stát a proto je to často "nahoře" chybně ošetřeno. Tedy pokud není v každé úrovni slupky postupováno s vědomým o možných stavech/chybách, čemuž přesně try/catch napomáhá.
Malý příklad, kdysi jsem potkal Python knihovnu pro čtení GPS. A stalo se, že implementátor navazujícího API si řekl, když čtení GPS vrací výjimku, stačí GPS reinicializovat a "ono se to spraví", to bude problém komunikace. "se to" má často zásadní roli u úvah tohoto typu ;-) Inu jakmile se GPS ocitla na druhé polokouli, tak toto "ošetření výjimky" se zcela míjelo účinkem, protože problém byl v chybném zpracování záporných WGS souřadnic.
Jsem "analfabet", co neumí číst a chápat řadu textů, na tom asi není nic objevného, proto mám takové pitomé otázky.
Proč u těchto systémů, kde investujeme enormní námahu, aby se nevysypaly (a je tam brutální overengineering) ve většině případů nejsou použity výjimky k obsluze chybových stavů (když by výjimky měly být "silver bullets", efektivní a rychlé na obsluhu, prostě to bez nich rozumně neošetříte) ?
Proč výjimky nejsou úplně to pravé ořechové pro kritické systémy ?
Co znamená, že výjimky jsou vhodné pro systémy, které se mohou vysypat (kde nevěnujeme enormní námahu, aby se nevysypaly) ?
Proč připouštíme plánovaně vadný SW a jaké dopady to má na uživatele, společnost ?
We are programmers who aspire to be worthy of the title of Craftsman. So what is a software craftsman? What promises do software craftsmen make to their fellow craftsmen, their employers, and society at large? https://www.youtube.com/watch?v=17vTLSkXTOo
Michal Mühlpachr: Protože ty kritické systémy jsou navrhované tak, aby bylo u všech variant běhu předem jasné (tj. že tu variantu opravdu někdo promýšlel, ne jen deterministické), co přesně se stane. Tyto systémy jsou pro to malé a jednoduché, protože není v lidských silách takhle podrobně analyzovat komplexní systém. A mimochodem ani u těch kritických systémů se často nepočítá s tím, že by byly bezchybné, takže třeba vedle sebe běží dvě různé implementace, je tam bezpečný komparátor a když se obě implementace neshodnou na výsledku, přejde se do nějakého bezpečného stavu (např. se zastaví linka).
Vedle těchto kritických systémů ale také máme mnoho daleko komplexnějších systémů, u kterých prostě nedokážeme předem promyslet všechny stavy. A tam jsou výjimky velice užitečné, protože zajišťují to, že výjimečný stav není ignorován. Což je právě problém jazyků, kde se chyby řeší např. návratovou hodnotou, kterou programátor může ale nemusí zkontrolovat – a jakmile jí na tom správném místě nezkontroluje, na ten výjimečný stav se zapomene a program běží dál, jako by se nechumelilo, a vrší na sebe další a další chyby. Přičemž to, že programátor vy takovém případě nezkontroluje, zda nedošlo k chybě, je nejčastější situace. Zrovna nedávno se na Abíčku pod zprávičkou o portaci Sysinternals utilit na Linux rozběhla diskuse neprogramátorů o tom, jak je ten kód hrozný, protože pravděpodobně poprvé v životě viděli kód v C, kde je většina možných chybových stavů ošetřena.
Proč připouštíme plánovaně vadný SW a jaké dopady to má na uživatele, společnost ?
To s výjimkami nijak nesouvisí. A nedokonalý software připouštíme proto, že jakékoli další přiblížení dokonalosti je stále dražší a dražší, zatímco přidaná hodnota je stále nižší a nižší. Lidé totiž odjakživa žijí v nedokonalém světě, takže si s nedokonalostmi dokáží docela dobře poradit, a radši žijí v barácích, i když občas nějaký spadne, než aby žili dál na stromech a čekali, až budeme umět postavit dokonalé baráky (zvlášť když i u těch stromu se občas nějaká větev ulomí).
Snažím se od tvrzení:
> A moderni jazyk bez vyjimek, to mi prijde uplne mimo.
> absence vyjimek a ... je momentalne nejvetsi bolest golangu.
> Jenomže výjimkou jsou silver bullets. Je řada stavů, které bez výjimek prostě rozumně neošetříte.
posunout k "výjimky nejsou jediné nezbytné a zázračné" paradigma.
Domnívám se, že výjimky jdou proti srozumitelnosti, z důvodu snadno nepostřehnutelných side efektů a snadno přehlédnutelného probublávání přes vrstvy API, čímž ale neříkám, že je nerozumné je používat.
Domnívám se, že podstatnější než typ paradigma zpracování chybových stavů je SW craftsmanship (odtud souvislost přes oslí můstek, kterého jsem se z lenosti dopustil).
Jinými slovy nástroj (kladivo - výjimky - předávání chyb v návratových hodnotách funkcí atd.) je méně důležitý než způsob(y), jakým s nástrojem pracujeme
(jsou místa s omezenými zdroji, kde se můžeme k tomuto tématu hodně naučit).
BTW když budeme důslední, i Golang má "výjimky" runtime, které lze zachytávat s pomocí defer mechanizmu
(ale má to svá omezení a špecifiká ;-).
> máme mnoho daleko komplexnějších systémů, u kterých prostě nedokážeme předem promyslet všechny stavy. A tam jsou výjimky velice užitečné, protože zajišťují to, že výjimečný stav není ignorován.
U výjimek se nezřídka stává, že je ignorováno rozlišení výjimečných stavů, což vede k jejich chybnému zpracování.
Když aplikační programátor chce ignorovat chyby, paradigma zpracování chyb mu v tom nezabrání, ani mu nepomůže chyby zpracovat lépe.
Z hlediska paradigmatu zpracování chyb je např. srovnatelné, pokud mám try catch os.exit nebo "univerzální" obalový handler ir err os.exit (takto je implementována významná část sw).
posunout k "výjimky nejsou jediné nezbytné a zázračné" paradigma.
S tím souhlasím.
U výjimek se nezřídka stává, že je ignorováno rozlišení výjimečných stavů, což vede k jejich chybnému zpracování.
To se samozřejmě může stát, každý nástroje je možné použít chybně. Ale rozdíl mezi volitelným čtením chyb z návratového kódu a výjimkami je ten, že když vývojář na ošetření zapomene, v prvním případě aplikace vesele pokračuje dál a páchá škody, zatímco v druhém případě výjimka probublává tak dlouho, dokud s ní někdo něco neudělá, nebo dokud nedorazí úplně nahoru, kde typicky způsobí ukončení zpracování, takže aplikace nepáchá škody. Ano, programátor může výjimku zachytit a zahodit, nebo jí zpracovat špatně, ale to už se musí aspoň trochu snažit. A programátoři mnohem méně často páchají škody záměrně, většinou prostě jen zapomenou. Proti zapomínání se navíc dá použít koncepce kontrolovaných výjimek, například její implementace v Javě se ale nesetkává moc s pochopením.
> programátoři ... většinou prostě jen zapomenou
Jak se mi v Go může stát, že zapomenu zpracovat chybu ?
Buďto ji zahazuji záměrně s pomocí _ (když nebude sedět počet návratových parametrů, tak mi Go vynadá) nebo ji do něčeho ukládám, řekněme třeba err a potom mi Go vynadá, když err zapomenu použít/zpracovat.
Go nikomu nevynadá, pokud err není nově deklarovaná, takže zpracování chyby pominout jde. Tady mimochodem býval v překladači bug jak Brno, error je sice rozhraní, ale pokud vrácená chyba byla instancí jiného typu než původní hodnota v err, program padal, protože se špatně aktualizovala dispatch tabulka.
Řekl bych, že je to trochu podobný případ, jako když v jazyce s kontrolovanými výjimkami jedna funkce vyhazuje kontrolovanou výjimku, programátor se rozhodne, že jí nebude řešit a nechá jí probublat dál – a pak zavolá jinou funkci, která vyhazuje stejný typ výjimky, ale tu už by ošetřit v daném místě měl. Rozdíl je v tom, že v případě výjimek se to neztratí, ale ta výjimka alespoň probublá výš. Ale samozřejmě to zase není binární rozdělení, že na ošetření chyb se buď zapomenout může nebo nemůže – opět je to škála, někde to jde snáze a někde hůře, a záleží i případ od případu.
@unicode
Souhlasím že bez znalosti konkrétního kódu je těžko se o tom bavit. Dodám, že záleží i na koncepci jazyka. Ovšem já nejsem ten kdo tu začal tvrdit, že vyjímky jsou špatně by default. A taky si nevzpomínám že by někdo tvrdil že jsou vyjímky silver bullet. Proč to musí být v IT pořád odezdi ke zdi: Když vyjímky, tak všude jinak jsou na prd a když ne, tak nikdy nikde ... ?
Pokud bych měl ale opravdu vznést nějaký obecný soud, tak jakmile se začne řešit aplikace kde je struktura používání tříd a volání funkcí hodně složitá do hloubky co se týče volání (např. komponenta která používá komponentu která používá několik příd které obsluhují několik tříd - ideálně ještě různých vendorů), tak tam začínají být vyjímky velkou výhodou. Ono totiž to tzv. probublání ušetří tunu kódu a je naprosto hned jasné co se tam děje.
AFAIK u každého manuálu k vyjímkám a u každého slušnějšího tutoriálu je napsané, že vyjímky neslouží křízení toku programu a nejsou náhradou za větvění.
Pokud je problém v tom, že je špatně používá část programátorů, tak asi není správný postup řešit to odstraněním vyjímek by default, nota bene ne proto, že nejsou silver bullet. Ostatně co je ... Když se někdo snaží, zprznit jde všechno ....
Moc nechápu ty co to brali doslova a nedokázali interpretovat toho smajlíka. Za mě je to např. tak, že v aplikaci (doména C++) mi výjimky nějak extrémně nevadí, ale ve sdílených knihovnách už ano. Druhá věc je, že místo toho, aby tady lidi psali argumenty o které se můžou opřít, tak tady opakujou dávno vyvrácené mýty a zrůrazňujou jak dlouho už programujou :)
Abych to rekapituloval. Celé to bylo o tom, že bez výjimek to dnes rozhodně jde a nové programovací jazyky je výslovně nepotřebují (viz Rust, Go), pokud jsou schopné poskytnout jiné prostředky pro error handling. Druhá věc je ta, že současný stav výjimek v C++ rozhodně není ideální (tak jak tu někteří tvrdí) a je to "the least portable feature". Např. embedded, emscripten, C interfaces / language bindings - zapomeňte na exceptions.
A např. jeden z nových návrhů, který chce řešit současnout nevyhovující situaci v C++ nazvaný "Zero-overhead deterministic exceptions: Throwing values".
- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r0.pdf
Nemám moc čas na žabomyší války, takže tímto bych to ukončil :)
Znám hlavně C++, Javu a Python používám velmi málo. V C++ jsou výjimky podle mě opravdu na naprosto výjimečné stavy, protože na první pohled nevím, jestli funkce něco takového vrací a jestli je to relativně normální stav. Dělat něco takového jakože výjimku odchytnu přes šest zanořených funkcí je podle mě spíš prasárna, ulehčí to práci, ale někdo může použít funkci na třetí úrovni zanoření jinde a zapomenout na to.
V ideálním světě aspoň existuje dokumentace ohledně toho jaké výjimky funkce vrací, ale stejně ji málokdo čte.
@pp
No ony totiž ty vyjímku jsou opravdu na vyjímečné stavy - je to takový v podstatě chytatelný exit. Paradigma je takové, že je to jako nouzová brzda, kterou ovšem můžeš vědomě odchytit a odbrzdit v momentě, kdy jsi schopný situaci zase dostat do normálu, resp. standartního běhu. Toho docílíš tak že nevěštíš co úrovně pod nebo nad mají či nemají dělat, co možná kdyby někdo, ale buď tě stav vyjímka zajímá a zpracuješ ho nebo to necháš letět (probublat) dál a pak třeba někdo kdo používá tvou knihovnu která nechá tuto vyjímku z jiné knihovny letět se rozhodne jestli ho zajímá nebo ji nechá letět dál, resp. výše ....
Nevím jak v C++, ale například v tom zlém a nanicovatém světě PHP je už v podstatě standard do anotací uvádět všechno co ta funkce může hodit, minimálně deklarace jména. Taky existuje určitý standart jak vyjímku pojmenovávat - asi nebudeš muset moc hledat v dokumentaci když v anotaci je throws InvalidArgumentException nebo throws ConnectionFailureException - řekl bych že to není nic nepředvídalného ani hrozného .... Třeba ve Wordpresu se ti vrátí "něco" nebo objekt Error - tam je fak super chceckovat jesti tam není nějaký který tě zajímá :-O
Heh, to jsou kecy.
Na tom ze: "lidi začali používat výjimky pro ne úplně výjimečné stavy" je spatneho konktretne co?
Co je to "ne úplně výjimečné stavy"?
Normalni lidi kolem me pisou program zkratka tak, ze implementuji algoritmus korektniho prubehu. a vyjimkama resi vsechny deviace od tohoto prubehu. Vcetne nexistujiciho souboru, ci spatneho loginu do DB.
Korektni prubeh je v try, zpracovani chyb v catch blocich. Netusim, co na tom ma byt masochistickeho.
A co se tyce blaboleni o Resut<> ci Optional<>, v cem je presne lepsi kontrola existence hodnoty v Optional<> lepsi, nez prosta C like kontrola chyboveho stavu hned po volani funkce?
A "Pokud se bavíme o nějakém zjednodušení control-flow při výskytu chyby" - tak zde prosim doporucuju zkratka implementovat vyjimky.
Tvoji reakci bych popsal asi takto:
When you have a hammer, you want everything to look like a nail.
A co se tyce blaboleni o Resut<> ci Optional<>, v cem je presne lepsi kontrola existence hodnoty v Optional<> lepsi?
Vždyť to je jen syntax. C/C++ nemá elegantní návrat dvou hodnot, tak se to řeší takto. Jazyk který to má to může řešit klidně i jinak.
Výjimky jsou výjimky ze standardního průběhu programu - nikoli pro výjimečné situace. Tedy člověk implementuje průběh, který očekává jako ideální, a ostatní ošetří pomocí výjimek. A zbytek - včetně těch neotevřených souborů, či cokoli jiného. Neuvěřitelně to zpřehledňuje program, pokud se to dělá dobře, a činí ho tisíckrát srozumitelnějším a tedy udržovatelnějším.
Dobře implementované výjimky navíc zrychlují program. Když se nepoužívají výjimky: Ony ty miliardy ifů ve standardní cestě po volání každého podprogramu také nejsou rychlostně zadarmo. Kromě toho je rozdíl, když funkce musí vracet 2 hodnoty namísto jedné, protože do jedné si strčí chybu - už jsou to další strojové instrukce navíc = další zpomalení.
Programovací jazyk bez výjimek je něco jako špatný vtip.
Tady je relevantní video o exception cost v C++:
https://www.youtube.com/watch?v=XVofgKH-uu4&feature=youtu.be&t=1h2m24s
Pokud má někdo něco co by ukazovalo opak, tak se rád podívám.
Zdá se, že si nepochopil o čem je ošetřování chybových stavů, a to včetně výjimek. Výjimky jsou o tom, že standardní cesta programu je rychlá, ošetřování výjimečného stavu je pomalé.
Dělat benchmarky rychlosti ošetřování chyb je skvělé, ale mám pro tebe jednu radu: Nejrychlejší ošetřování chyb je vůbec je neošetřovat - přesně tam míříš.
Lidi většinou zajímá, jak rychlý bude program, když nenastane chyba a problém. Když nastane chyba a problém (třeba výjimka), pak daleko zajímavější než rychlost je kvalita ošetření chyby - a tam výjimky excelují. Často se ta chyba dokonce někam loguje či otevírá dialogové okno se zprávou - a to už je rychlost úplně vepsí. Ale asi je to podle tebe chyba.
"Když nastane chyba a problém (třeba výjimka)"
A v tomhle je jádro sporu. Někteří diskutující hovoří o výjimce jako o chybě nebo problému. To bude váš případ a to bude i můj případ. Jenže pak jsou tu lidé, kteří výjimky považují za zcela běžný nástroj a používají ho i na věci, které nemají nic společného s chybou nebo problémem. Jejich programy jsou prolezlé výjimkami, protože oni nikdy netestují, zda soubor existuje, zda text je číslo apod. Oni to prostě ZKUSÍ a jedou dál. Jejich program neobsahuje kód "pokud existuje starší soubor, tak ho smaž". Jejich program obsahuje kód "smaž starší soubor a ignoruj výjimku FileNotFound".
Zde si vždy vzpomenu na jeden extrém, kde autor prostě procházel pole stylem "for(i = 0; true; i++)". Smyčku opouštěl tím, že to měl celé v TRY bloku a odchytával OutOfBounds exception. Je fakt, že pole má jen omezenou velikost, chyba nebo problém? Není to třebas samozřejmost? A co čtení souboru? Viděl jste, kolik lidí tam místo "while not eof" má prostě natvrdo čtení a chytá si výjimku "read beyond end of file"? Je snad skutečnost, že soubor má omezenou délku, chyba nebo problém? Nebo když testují, zda existuje záznam v tabulce, tak místo COUNT(*) tam dají prostě SELECT 1 INTO a odchytávají výjimku NO_DATA_FOUND. Některé zvrácenosti se už dostaly i do tutoriálů. Například že kontrola, zda řetězec obsahuje číslo, se provádí tak, že se v TRY prostě zkusí přetypovat.
PS: Pro chyby a problémy Go nástroj má. Viz Defer, Panic a Recover. Používá to právě na věci jako je čtení mimo rozsah pole. Můžete to použít také. Není to tak silné a pohodlné jako výjimky, ale možnost to je.
> Jenže pak jsou tu lidé, kteří výjimky považují za zcela běžný nástroj a používají ho i na věci, které nemají nic společného s chybou nebo problémem.
to je otázka konvence. Třeba používání vyjímek pro ukončení iterace.nebo pro vyskakování z rekurze je podle mě elegantnější než řešit speciální návratové hodnoty.
Rozdíl je v tom, jestli o takové situaci přemýšlejí jako o něčem, co může nastat. Vyhodit výjimku je jedna věc. Druhá věc je napsat veškerý nadřazený kód až po místo chycení tak, že s ní počítá. Dosáhnout aspoň základní "exception safety" (jak se to překládá?) není až taková sranda.
A vůbec tomu nepomáhá, že v kódu obvykle není poznat odkud to může a nemůže lítat. Výjimky (alespoň v obvyklé podobě) jsou neviditelné při běžném čtení. Musím se podívat na jednotlivé funkce abych věděl, jestli náhodou nehází. Ify jsou sice opruz, ale aspoň je hned vidět, kde to může selhat. A jak o tom při psaní autor uvažoval.
O výjimkách se říká, že se nedají ignorovat. Není to pravda. Mezi místy odkud vyletí a kde ji někdo chytí je spousta příležitostí pro její ignorování. Nebo spíš pro ignorování možnosti, že výjimečně může něco stát.
V tomhle se mi moc líbí nový návrh výjimek v C++. Pokud je nechytám, tak každý házející výraz musím označit pomocí "try". I při zběžném čtení bude vidět, že to může vyletět a že se to bude propagovat výš. Už se dá trochu líp přemýšlet o tom, jestli mi náhodou nějaká data nemůžou zůstat v nekonzistentním stavu.
Chovat se při programování jinak dle toho, zda si předtím prověřím, co tam může a nemůže lítat je dost krátkozraké. Co až tam někdo něco změní tak, že dřív to neházelo a dnes to hází? To ten volající kód přestane fungovat?
Dále - selhat může tolik věcí, že představa, že mám nějakou část zkontrolovanou je dost iluzorní. Selhat může třeba alokace paměti, což ve vyšších jazycích znamená, že to vylítne při spojení dvou stringů. To si opravdu prověřuješ, že se tam nikde nedějí takové věci?
Závěr - předpokládej, že to může vylítnout kdekoli a podle toho piš kód. Program jako celek musí být navržen tak, aby se s tím dobře vypořádal. Jako bonus dostaneš prostředí, ve kterém nemusíš řešit jednotlivě každý převod textu na číslo.
Alokace paměti tímhle způsobem takřka neselhává. Když dochází paměť, tak se dějou zajímavější věci. Na Windowsech se program obvykle uswapuje k smrti. Začne swapovat tak divoce, že vlastně prakticky zamrzne. Na Linuxu se to liší podle nastavení. Asi nejlepší je, když swapper náhodně vybere obětní proces a ten sejme. S overcommitem je taky sranda. Malloc alokuje virtuální adresový prostor bez fyzické paměti. Fyzické stránky se přidělují až při prvním přístupu. Takže to pak vypadá tak, že žádná výjimka nevyletí a program segfaultuje při přístupu do úspěšně alokované paměti. Řeknu na rovinu, že v posledních +-10 letech jsem bad_alloc nepotkal. Ale je možné, že některé jazyky tohle chování OS maskují a chovají se kultivovaněji.
> Závěr - předpokládej, že to může vylítnout kdekoli a podle toho piš kód.
Pokud to opravdu může vylítnout kdekoliv, tak se s tím nedá nic dělat. Leda tak doufat, že se to nestane a po chycení výjimky všechno zahodit a začít znova. Pro psaní exception-safe kódu je kritické mít místa, kde to vylítnout nemůže. Klasický obrat je vytvoření nových dat kde to může lítat + výměna původních dat kde to vylítnout nesmí. Pokud to může vyletět opravdu kdekoliv, pak se konzistence zaručit skoro nedá.
Ten úklid se musí dělat nejen po chycení výjimky. Ten úklid musí proběhnout po celé trase, kudy ta výjimka letí. Něco může uklidit garbage collector, ale třeba mutexy neodemkne. Nabízí se otázka, jestli i ten úklid může házet a co v takovém případě udělat. Tady se vedou vášnivé diskuze a shoda moc nepanuje.
A o co mi šlo je, že pokud může výjimka vyletět odkudkoliv, tak se to může stát zrovna ve chvíli, kdy nejsou splněné nějaké invarianty. Pokud se chci z chyby nějak zotavit, tak musím při chycení vědět, v jakém stavu se může objekt, odkud to vyletělo, nacházet. A pro to už je potřeba nějaký commit nebo rollback, který házet nemůže. Bez toho se nemůžu přesunout mezi validními stavy, ale můžu zůstat v nějakém polorozbořeném stavu, který ani nemusí jít korektně uklidit.
Minimálně nějaký swap/přiřazení a destrukce musí jít provést bez házení, jinak se nedá spolehnout ani na ten úklid.
@JSH
Chápu. Myslím že na to není přesná odpověď, protože to záleží na tom jaké jsou požadavky - minimálně na to jak se má SW, případně i HW, chovat navenek ... Jediné co se dá říct s jistotou je že musíš v kódu tak nebo onak ošetřit stavy všechny a s použitím vyjímek ošetřuješ jednak všechny normální průběhy - což ale po nefukčnosti jednoho celku může dále znamenat normální chod programu (třeba přechod na default config) - a druhak všechny errorové stavy.
Podle mě stavů a požadavků v projektu neubude ani nepřibude, jenom s použitím vyjímek je metodika trochu jiná. Např. když jsem nedávno dělal kus SW kde jsem chtěl aby celý běh proběhl tak nebo tak, případně skončil errorem a vypsal všechny vyjímky které posbíral po cestě, tak jsem Exceptions vůbec nepoužil. Až při volání tohoto kusu, protože pak už bylo potřeba vyexitovat s hláškou, kódem, a daty, zapsat všechny errory na výstup i do logu - tedy použiji vyjímku.
To je pak ale špatně vyhozená vyjímka. Ten catch, případně final, je tam proto aby se ošetřily ty stavy a vyjímka je takový lepší exit+notice, který se dá nějaké úrovni přerušit volajícím - tedy lepší variabilita. Že má jazyk vyjímky neznamená že musí letět vždy ...
A o tom celou dobu píši. Plho!
Že standardní cesta programu je rychlá jako raketa, pokud nenstane chyba. A že ošetřování výjimky je pomalé, velice pomalé. Což je přesně to co chceme - rychlý program, pokud vše jede jak má, a kvalitní ošetření chyba pokud se něco zadrhne.
Tady se nějak množí lidi, kteří neumí číst či co!
Výborně, takže se možná shodneme na tom, že za ošetření chyby jsme ochotni platit nějakým časem navíc, tedy v systémech, kde to jde (tudíž ne mission critical věci). Proč ale pořád píšete o nějakém otevírání souborů? To se skutečně dnes považuje za tak výjimečný stav, že se kvůli tomu musí tvořit objekt s výjimkou, používat RTTI, cold tables a kdoví co všechno jsem už zapomněl? Dokonce se vsadím, že mnoho lidí bude mít právě tu práci se soubory naprogramovanou blbě s použitím výjimek, než ti, co si poctivě projdou všemi možnými stavy.
U mission critical věcí sakra záleží daleko více na kvalitním ošetření chyb než na čemkoli jiném:
1) Představte si, že mission critical řízení atomové hlavice bude ošetřovat chyby rychle, ale zato nekvalitně. Takový unicode si vezme benchmark chyb, shlédne dvouhodinové video o rychlosti ošetřování chyb. Dále vezme nejrychlejší způsob, a ušetří při ošetření chyby tři nanosekundy. Následně zlikviduje Paříž chybným zaměřením cíle.
2) Nebo atomová elektrárna bude neočekávané stavy ošetřovat rychle - jen přitom vybouchne jako vedlejší efekt a zamoří půl Evropy jaderným spadem. Ale ušetřili jsme při ošetřování chyb jednu pikosekundu a to se vyplatí!
Mýty o tom, že se "výjimky mají používat jen pro výjimečné situace" tu šíří jiní - já tento mýtus a tuto hloupost nikdy nešířil. Tudíž ta otázka, zda je "otevírání souboru výjimečná situace" je směrem ke mně naprosto irelelvatní. Směřujete tuto otázku na špatnou osobu.
Výjimkou jsou pro jednoduše způsob, jak ošetřovat chyby a problémy - výjimečné i očekávatelné. Tudíž si neničím den ani mozek zcela zbytečnými filozofickými úvahami na téma co je a co není "výjimečná situace", protože tuto starost nechávám koňovi, který má větší hlavu. Já tyto věci k životu nepotřebuji.
> Na to že máte "30 let praxe" tu argumentujete jako malé dítě :)
"Promiňte, to je zajímavé, ale já když jdu s dětmi do lesa tak vždycky tleskám a dělám takové kšššc, abych případné zmije zaplašil."
"Tak to děláte zbytečně."
"Ale já to tak dělám už asi 20 let a věřte, že se mi to plně osvědčilo."
"Ano... to je úplně zbytečné."
U mission critical věcí se výjímky prakticky nepoužívají (viz třeba JSF C++).
Problém je v tom, že jak ta výjimka probublává nahoru, tak cestou toho může dost rozvrtat, nechat objekty v nekonzistentním stavu a podobně. A když není jasné, odkud všude může výjímka vyletět, tak se prakticky nedá napsat kód který nějaká výjímka z nižší úrovně nerozvrtá.
> Tudíž si neničím den ani mozek zcela zbytečnými filozofickými úvahami na téma co je a co není "výjimečná situace", protože tuto starost nechávám koňovi, který má větší hlavu. Já tyto věci k životu nepotřebuji.
A podle čeho se teda rozhodujete, zda danou věc obsloužíte mechanismem výjimek nebo "normálně"? Hodíte si kostkou?
Mimochodem, jako člověka, který se v průmyslové automatizaci pohybuje celý život, mě často baví laické představy o architektuře řídících systémů jaderných zařízení. Ale prozradím vám, že výjimky v tom smyslu, jaké je známe třeba v Javě, se tam rozhodně nepoužívají. Výjimky v hardwarovém smyslu ano, ale už jsme to tu spolu řešili - to není totéž. Rozlišování výjimka-přerušení zde má svůj smysl a to, co máte na mysli, je spíše hardwarové přerušení.
On celý ten embedded svět je trochu jiný a spousta těch vychytávek, jako objekty, výjimky apod. se tam ukazuje jako zbytečná a spíš nebezpečná, takže se volí raději podmnožiny možností nástrojů.
* A co se tyce blaboleni o Resut<> ci Optional<>, v cem je presne lepsi kontrola existence hodnoty v Optional<> lepsi, nez prosta C like kontrola chyboveho stavu hned po volani funkce?
Predpokladam, ze se specificky ptas na Result v Rustu (Option je v necem podobny pripad, ale vyuziti ma jinde). Vyhodou je, ze ta "uzitecna" navratova hodnota v pripade chyby neexistuje, neda se k ni nijak dostat a omylem ji nekde pouzivat. Pokud funkce vraci kod chyby a "uzitecnou" hodnotu, programator ma tu hodnotu k dispozici bez ohledu na to, jestli volana funkce indikuje chybu. Coz je spatne principialne a nebezpecne v praxi. Dava Ti to smysl?
A co se tyce blaboleni o Resut<> ci Optional<>, v cem je presne lepsi kontrola existence hodnoty v Optional<> lepsi, nez prosta C like kontrola chyboveho stavu hned po volani funkce?
Moderní IDE nebo kompilátor dělá (u jazyků, které mají null hodnoty) kontrolu flow dat a s pomocí anotací, návratových typů funkcí apod. se snaží odvodit, zda daný typ je nullable nebo not-null, a pokud je nullable a neuděláte kontrolu, vypíše vám varování. S Optional
je tahle analýza mnohem jednodušší, IDE ani kompilátor nemusí trasovat kód nijak daleko, prostě jen k deklaraci proměnné. Jakmile pak v kódu narazí na to, že voláte get()
bez kontroly, zda není Optional
prázdné, může vám vypsat důrazné varování, že je to asi špatně.
Ja ted predelaval jeden poctive napsany projekt z php4 na vyssi verzi a velmi se mi ulevilo, ze novejsi verze php pouzivaji vyjimky. Dost podstatne to zjednodusuje program. Protoze kdyz poctive osetrujete kazde volani funkce a predavate tuto informaci nadrazenym funkcim, zda nedoslo k chybe, tak 70 % programu se venuje jen tomuto zpusobu osetreni chyb.
Problém s vaším příkladem je, že jste zkopíroval protipříklad :-)
Korektní řešení je totiž:
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.Create(dstName)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}
V jazyce s výjimkami byste to musel korektně napsat nějak takto (příklad je v pseudojazyce):
func CopyFile(dstName, srcName string) int64 throws FileException {
src := os.Open(srcName)
try {
dst := os.Create(dstName)
try {
return io.Copy(dst, src)
} finally {
dst.Close()
}
} finally {
src.Close()
}
}
nebo
func CopyFile(dstName, srcName string) int64 throws FileException {
var src *os.File
var dst *os.File
try {
src = os.Open(srcName)
dst = os.Create(dstName)
return io.Copy(dst, src)
} finally {
if dst != nil {
dst.Close()
}
if src != nil {
src.Close()
}
}
}
Což bych se zdráhal označit za elegantnější řešení.
Samozřejmě lze nalézt příklady, kde budou výjimky výrazně elegantnější. Ale stejně tak lze najít příklady, kde to je opačně.
Tak to dopadá, když se programovací jazyk Go dělá jako nalepovák. Nejdříve jej udělají s nějakými základními věcmi a syntaxí, a pak - eventuálně někdy, možná... - až se k tomu autoři dostanou... - do Go nalepí další věci, jako jsou třeba generiky nebo výjimky (viz jejich FAQ).
Výsledkem bude nakonec nepoužitelný nalepovák, protože jazyk se má nejdříve navrhnout v základních rysech a pak implementovat. Až tam pár features do Go přidají, bude to nekonzistentní nalepovák ála Čapkova povídka když pejsek s kočičkou vařili dort.
Výjimky při šíření výjimečného stavu postupují nahoru po zásobníkových rámcích musejí uklízet lokální proměnné a rušit epilogy/prology funkcí. Je třeba při návrhu jazyku přemýšlet, jak to budete dělat, a co výjimky konkrétně v každém zásobníkovém rámci uklidí.
Například v C++ se budou automaticky volat destruktory objektů, tedy nějaké close() metody pořeší kompilátor při šíření výjimky, programátor se o to starat nemusí. Automaticky se dokonce i dealokuje paměť, pokud je použita pro pointery, které ještě nebyly nikam přiřazeny. Kód je pak velice přímočarý.
Mám spíše dojem, že Go je nešťatně navrhován. Autoři si myslí - a svůj omyl záhy pochopí - že featury lze snadno do programovacího jazyka evolučně přidávat. Není tomu tak, vznikají tak totálně nekonzistentní jazyky. Příkladem jak to dopadá můžete vidět v PHP.
Přesně tak, typický příklad nalepováku je C++. Také leccos nalepovali dodatečně - a leccos drhne. Odnesla to hlavně zbytečná složitost C++ jazyka.
Myslíte, že když jsem si mimo jiné pročetl FAQ přímo od autorů Go, a na základě toho si udělal názor - že jsem čerpal z neseriózního zdroje? Zkuste mi prosím doporučit serióznější zdroj než jsou autoři Go, abych nepoužíval podle vás špatné zdroje!
Go jako nekonzistentní nalepovák skončí, protože přesně takto si autoři představují výrobu a vývoj programovacího jazyka. V tomto stavu a množině vlastností autoři Go nechat nemůžou, takže budou muset časem vlastnosti přidávat, pokud má ten jazyk rozumně přežít.
Můžete mi říct, jak jste přišel na toto tvrzení? Pravdou je totiž přesný opak. Od verze 1.0 se totiž do jazyka nepřidala žádná nová konstrukce. Na úrovni jazyka jsou první a nejnovější verze zcela kompatibilní. Autoři se právě zdráhali přidat některé funkcionality, o kterých nebyli stoprocentně přesvědčeni, aby nevznikla potřeba něco v průběhu času měnit.
Rozhodně se nekoná žádné evoluční přidávání. Existují návrhy na podporu generik, ale ta budou případně zahrnuta do Go 2.0, což je označení milníku, který má obsahovat všechny změny jazyku.
Takže na wikipedii ve sloupci "Language changes" u změn verzí Go lžou?
https://en.wikipedia.org/wiki/Go_(programming_language)
Je to hrozné, jak se na wikipedii lže a kecá! A to má anglická wikipedii tolik editorů! Že to neopraví, lháři jedni a šiřitelé fake news o Go jazyce!
Mně hlavně připadá absurdní, že autoři Go byli frustrováni složitostí jazyků jako je C++ či Java, a přitom se vydávají zcela stejnou cestou, aby došli časem k témuž výsledku.
Na počátku v prvních verzích byly C++ i Java pěkné, jednoduché a nijak těžké ani komplexní jazyky. Ty dnešní obludy se z nich staly až časem, když se postupně přidávalo to a ono. U C++ i Javy to jde chápat, protože v době jejich vzniku nemohli předvídat vývoj, který nastane v programovacích jazycích.
Jediná cesta, jak udělat moderní jazyk bez složitostí je navrhnout ho od začátku se všemi koncepty, které tam dříve či později hodláte mít. Jinak jdete neomylnou cestou k molochům ála C++, Java či PHP.
Já už se těším, jak bude Go nalepovat třeba ta generika. To se najednou zjistí, co všechno v současné verzi Go se nedomyslelo a příliš neladí s generiky!
Výjimky v Go možná budou, možná nebudou přidána - to se uvidí. A zase bude problém, protože se na to nemyslelo od začátku!
Pěkný zástup tvrzení, pojďme se na ně trochu podívat ;-)
Prosím můžete upřesnit, kterou "první" verzi C++ (https://isocpp.org/std/status) považujete za "pěknou, jednoduchou a nijak těžkou ani komplexní" ?
Co z vlastností, které Rob Pike uvádí jako inspiraci z C++ projektů ke vzniku Go tato "první verze" C++ prosím neměla ?
Proč Vám počáteční referenční specifikace jazyka C++ přijde srovnatelná se stávající referenční specifikací jazyka Go (rozsah počáteční referenční specifikace C++ / rozsah aktuální referenční specifikace Go se má zhruba 10/1) ?
U kterých "moderních jazyků" se prosím podařil počáteční návrh se všemi koncepty (tedy kde dříve či později něco nepřibylo - aneb existuje alespoň jeden pozitivní příklad funkčnosti uvedené "knížecí rady") ?
> ... a mizerna standardni knihovna je momentalne nejvetsi bolest golangu ...
Které https://golang.org/pkg/ a v čem jsou prosím mizerné ?
Napriklad neumi Collections-Containers, neco jako tohle"
http://www.cplusplus.com/reference/stl/
Neumi ani takove zaklady jako je Set nebo OrderedMap, klidne by stacilo bez generik jenom drzet reference a vysledky pretypovavat, jako v Jawe 1.4.
Prakticky umi jenom array/slice a unordered map - konec srandy.
Libovolna manipulace se aspon trochu strukturovanymi daty je neskutecny pain-in-the-ass.
A co jsem si vsimnul, lidi to obcazej jak u blbejch na dvorku pres JSON.
> Neumi ani takove zaklady jako je Set nebo OrderedMap
Základy jsou pro mě typy, které umožňují srozumitelnou (případně elegantní) implementaci komplexnějších datových struktur. K tomu Go evidentně stačí array/slice a unordered map .. Důkazem budiž právě standardní knihovny (packages) Go a projekty v Go, kde s komplexními datovými strukturami pracují.
Základy mohou být ještě méně rozmáchnuté než u Go, např. seznam u Lispu či tabulka u Lua a oběma to stačí na JAKÉKOLIV komplexní datové struktury.
Podle mě jakákoliv sorted kolekce v základech jazyka vede spíše k nesprávnému užití (používám ji na něco, kde není třeba a zbytečně plýtvám zdroji) či neutěšenému designu (typ reprezentace sorted kolekce může být u stejného datového typu pro nějaký use case vhodný a pro řadu jiných zcela nevhodný).
Zařazování komplexních datových typů do základů jazyka vede k nepřehlednosti, naboptnalosti a zejména neortogonalitě jednotlivých vlastností jazyka (užití vlastností nejde zcela nezávisle kombinovat). Přijde mi, že nezařazování kontejnerů, vektorů, matic, tenzorů, ... do základů jazyka (pokud to není přímo domain specific jazyk jako třeba R) je přednost (nikoli vada) designu jazyka.
> Libovolna manipulace se aspon trochu strukturovanymi daty je neskutecny pain-in-the-ass
Pro programátora formovaného "objektovými" programovacími jazyky určitě, stejně jako pro něho bude tortura vzdát se přiřazování do proměnných a programovat funkcionálně - použití Lisp maker (princip kód a data jsou jedno a totéž) pro něj bude za úrovní nepochopitelné magie.
Jakmile si rozpustíme bariéry, co jsme si dobrovolně postavili a zkusíme pracovat v paradigma slupkových API s vrstvenými Go interfaces ala streamy, můžeme řadu bolestí převést na eleganci. Jestli to chceme je jiný typ problému ;-)
> Mna naozaj fascinuje ako ludia, co robia v Go doslova adoruju jeho nedostatky a nedorobky ako vyhodu
A: Preferuji cihly, vyhovuje mi jejich jednoduchost, proto jsem si je vybral.
B: Ale cihlám schází takové základní věci jako armovací dráty, úchyty na jeřáb, to panely normálně mají.
A: Já jsem spokojený s cihlami, dá se s nimi postavit to samé co z panelů a jsou flexibilnější.
C: Fascinuje mě, jak lidi co dělají s cihlami doslova adorují jejich nedostatky a nedodělky jako výhodu.
Ja bych se na tvem miste neomezoval na rigidni GO.
Co vsecko muzes udelat assemblerem!
Nejses omezenej nesmyslnyma konvencema int/int64/float apod.
Udelas si vsecko sam.
Treba, muj priklad z praxe z te pekelne slozite Jawy, uz jsem ho tu jednou daval.
Mam tabulku ciselniku cca 300 polozek (pair id-name), potrebuju vystavit jako combobox na webu, nebo jako REST.
V pekelne slozite Jawe jsou to tyto 2 radky kodu:
List<TtTypes> ttTypesList = this.sQLRepository.findTtTypesAll();
LinkedHashMap ttTypesCombo = ttTypesList.stream().collect(Collectors.toMap(TtTypes::getName, TtTypes::getId));
TtTypes je entity bean, jednoduchy bean obsahujici vsechny sloupce tabulky jako atributy + par JPA anotaci
Prvni prikaz rekne JPA provideru (v mem pripade Hibernate) aby nacet kompletni obcah tabulky a vratil je ve forme ordered listu.
Druhy command trasformuje ordered list na ordered map, ktery primo davam jako vstup Primefaces komponente pokud chci webovy combobox, nebo oanotuju, pokud porebuju REST.
V GO nic jako java LinkedHashMap nebo C++ std::map neexistuje, pouze unordered map. A dokonce je ta go mapa zamerne randomizovana, zrejme ze stejnych "logickych" duvodu, proc vyjimky ne-e.
D: Třeba potřebuješ do baráku okno, na to je přímo speciální panel z fabriky, hele tady tahle jedna položka z 1600 typů panelů co můžeš použít, cihly nic jako okna nemají.
A: Já na to používám předpřipravené stavební bloky, přivezou mi to taky sestavené, nepotřebuji to z fabriky na cihly (tam se soustředí na cihly a ty jsou pak fakt super), vozí mi to z fabriky na okna, víš já okna třeba do garáže nebo psí boudy nepotřebuji a představ si necpu je ani do sloupku na přivedení sítí.
D: Nebo když potřebuješ tu cihlu přepůlit, vždycky prdne na jiným místě.
A: Víš to je schválně, aby se na to lidi nespoléhali, protože když by řezy byly symetrické, stavěly by se z toho menší zdi a pak ty zdi nejdou dobře spojovat a napojovat.
D: Já bych se na tvém místě neomezoval na cihly, co všechno můžeš udělat s hlínou! Nejsi omezen nějakým debilním rozměrem, uděláš si všechno sám.
A: Asi by mě to nebavilo.
https://www.acara.cz/predpripraveny-vnitrni-roh-kerdi-schluter-e22560.htm
http://www.blokki.cz/
Library např. https://github.com/spf13/cobra
Jaké pojmenování prosím navrhujete, aby podle Vás dávalo smysl ?
Chápu význam slova "připravený", nechápu význam slova "předpřipravený". Co to má být? Jaký význam v té zkomolenině má ta nadbytečná předpona "před-"? Podobně úchylný mi připadá "podtácek" (on je taky nějaký nadtácek?), "20tý" nebo dokonce "40cet".
"Připravit" znamená nachystat k něčemu - tedy před něčím. "Předpřipravit" už tedy nedává smysl. To slovo, které hledáte, je prostě "připravit". Připadá vám málo sexy? To je snad nějaká úchylka... "Hmotnost" ani "váha" se nepozdává, ale líbí se mi "gramáž" - někde jsem to zaslechl, sice nevím, co to znamená, tak mrsk s tím do nabídky. Hmm.. "ukrást".. to zní hospodsky, "odcizit" - to zní slušněji, ale "zcizit" - to se mi líbí úplně nejvíc, to jsem už někde zaslechl, to bude asi vono. Hoodinky nebo holínky, hlavně že se použije nějaký hezký termit.
Díky za osvětu. Lingvisti ze mě nebudou mít radost, jsem opice co používá slova, která nějakým mechanizmem uvízla a bojuji s nedostatečnostmi jazyka - ať jde o moji slovní zásobu či vyjadřovací možnosti (čímž neříkám, že vím jak lépe na komunikaci). Často jsou to docela zkomoleniny, protože nezřídka hledám ekvivalenty z angličtiny, což asi byl i tento případ https://www.merriam-webster.com/dictionary/preprepared
Akademický slovník současné češtiny nějak zrovna nejel nebo co, tak jsem to tam jen tak mrsknul ;-)
Za nesrozumitelnost anglikanismů a dalších nesmyslů se omlouvám, naštěstí se najdou laskaví čtenáři, kteří vstřícně pomohou. Dokonce vědí jak mi to připadá sexy, že mám úchylky, jak se mi to pozdává či líbí, že nevím co to znamená nebo jak mi to zní a chci to mít hlavně hezké. Nad takovou moudrostí se skláním, já bych si tohle všechno vůbec neuvědomil!
"prepripraveny" je myslim docela jasne, wocogo.
kdyz je neco "pripravene", tak to proste vezmu jak je a vrazim, kam patri.
ale kdyz to je jeste treba mirne doladit, ne vsechno, jenom male detaily, aby to zapadlo, tak je to "prepripravene"
neco jako polotovar, ci sablona - taky polotovary nejime jenom tak, ale je jeste DOupravujeme, a sablony taky jeste DOvyplnujeme ...
podobne je to i s vyrazem "pos.rany" (vyznam asi neni treba vysvetlovat) a s vyrazem "predpos.rany" :)
Kiwi: To „tedy před něčím“ jste si tam doplnil vy. „Gramáž“ je normální termín označující hmotnost jednoho metru čtverečního dané věci, je to tedy něco jiného, než hmotnost či váha. Odcizit a zcizit jsou právní termíny, zcizit znamená „změnit majitele“, odcizit pak je „ukrást“. Nadtácek nemáme, ale máme tácek, která znamená něco jiného, než podtácek. Mohl byste takto rozebrat i váš text a ptát se, proč píšete „nachystat“, když máme slovo „přichystat“, proč „nadbytečná“, když existuje slovo „zbytečná“.
Vy se na něco připravujete až po "tom"? Tomu se u nás říká s křížkem po funuse. Připravuje se vždy v očekávání něčeho budoucího, tedy časově před něčím. Proto je předpona "před-" naprosto zbytečná, protože sémantika něčeho předcházejícího je nedílnou součástí slova "připravit".
Na to jsem právě poukazoval. "Gramáž masa je před tepelnou úpravou." "Pachatel zcizil kolo." Proč ti lidi prostě nepoužili slova, která znají, a vymýšlejí si novotvary, jimiž se nevědomky trefují do již zavedených pojmů, které ale znamenají něco úplně jiného?
Další podobné patvary jako "předpřipravit" jsou "nejaktuálnější", "nejoptimálnější" apod. To je jak "lepšejší". Prosím, když takto žvatlají předškolní dítka, může to být i roztomilé.
> Mohl byste takto rozebrat i váš text a ptát se, proč píšete „nachystat“, když máme slovo „přichystat“, proč „nadbytečná“, když existuje slovo „zbytečná“.
Vidím, že vám naprosto chybí cit pro jazyk a jeho logiku a poukazujete na něco úplně jiného. "Chystat" je imperfektivní kořen a k němu se pojící předpony mají perfektivizující význam, jinak jsou synonymické. "Předpřichystat" už by byl opět nesmysl. U kořene "pravit" ale mají předpony navíc i sémantický význam: při-pravit, na-pravit, vy-pravit, po-pravit, o-pravit, s-pravit, z-pravit... Předřazování dalších předpon je v češtině možné, ale musí dále modifikovat smysl: roz-pro-střít, za-po-šít, při-po-strčit, ne-před-po-s.aný
E: Za to si mohou autoři cihel sami. Když omezili cihly jen na stěny, oblouky, pilíře, plochy. Když by hned od začátku udělali cihly jako pořádné panely, tak už se dají cihly dávno svařovat stejně jako panely a není potřeba malta se všemi omezeními které má.
A: Borci, všimli jste si, že popisuji proč mi vyhovují cihly a nikomu je nenutím ani neimplikuji že musí vyhovovat někomu dalšímu ? Jsem rád za pestrost světa a speciálně za panely, je z nich spousta staveb, nebýt frustrace autorů cihel z panelů nevznikly by cihly, hromadě lidí panely vyhovují. Užijme si jak stavění z cihel, tak z panelů a podívejme se, kam nás to zavede. Občas sáhnu po panelu a necítím se z toho provinile ;-) Proč máte takovou neodolatelnou potřebu radit ostatním co je pro ně dobré/nejlepší (přesvědčení že víte co je "správná" cesta pro ostatní) ?
X: Jenže panely jsou rychlejší.
X: A taky mají odvodňovací kanály, to cihly nemají.
X: Panely
X: Panely
X: Panely
...
Výjimky v Go nikdy nebudou, Rob se vyjádřil opakovaně. Oni na ně nezapomněli, oni je tam nedali schválně (stejně jako hromadu jiných věcí). Stejně tak nebude hodně dlouho ani Go 2 - vylepšení ošetření chyb a možná i generika budou součástí 1.x. Jsem za to rád, pokud někdo chce N-tou variaci Javy, C++, C# nebo Rustu tak ať si vybere jiný jazyk, možnost volby tu je. Díkybohu Go zůstane čisté, to je totiž ta nejdůležitější vlastnost co má. A autoři to moc dobře ví.
Tenhle jazyk opravdu má budoucnost, pokud k tomu budou takto přistupovat i nadále.
Čerstvá přednáška od Roba na toto téma: https://www.youtube.com/watch?v=RIvL2ONhFBI
> Povšimněte si, že [..] funkce [..] nemá žádné parametry ani návratovou hodnotu
Myslim ze Leonhard Euler sa v hrobe obracia a Alan Turing si trha vlasy. Priatelia, technologie prichadzaju a odchadzaju, matematika je tu navzdy, takze Go jazykom sa zapodievat neoplati. Zelam pekny zvysok vecera.
Pretoze "computer" znamena "pocitadlo", neviem ako vas ale mna ucili pocitat na hodinach matiky od nejakych 6 rokov... Nebolo to easy, dava to vsak zmysel!
Okolo pocitacov sa vsak kruti kopa ludi co si myslia ze matika sa nejako da odsunut nabok, nejak ocikat, proste strcit hlavu do piesku lebo "komplikovane"... Dopadlo to tak ze si kazde 2 tyzdne musim stiahnut nejakych 50MB security updatov, lebo inak mi hacknu este aj hajzel papier! :(
ale jak to souvisí s funkcemi bez parametrů a návratové hodnoty? Není to matematická funkce, tak co. Navíc existují další zvěrstva:
1) funkce s parametry, která nic nevrací (print)
2) funkce bez parametrů vracející náhodné číslo (random)
3) funkce měnící globální stav aplikace
hrůza...
> 1) funkce s parametry, která nic nevrací (print)
Ak to nevracia ziadnu hodnotu nie je to funkcia!
> 2) funkce bez parametrů vracející náhodné číslo (random)
Ak to nevracia pre rovnaky vstup tu istu hodnotu nie je to funkcia!
> 3) funkce měnící globální stav aplikace
Ak to meni globalny stav nie je to funkcia!
Tu nie je o com diskutovat. Autori Go-Jazyka sa ucili, tak ako ja, a tiez vsetci, zdoraznujem VSETCI ucastnici tejto diskusie niekedy v 5. / 6. triede zakladnej skoly, co je to funkcia a co nie je funkcia. Prosim zvazte ukoncenie kariery programatora / inziniera ak mate problem porozumiet takymto veciam.
ah, moje FUNKCE programátora je tímto ohrožena :-) Vlastně není, protože kromě pojmu matematické funkce dokážu zvládnout i funkce v programovacím jazyce, uff to jsem si oddychl. Dávám + za pobavení.
...
[https://sk.wikipedia.org/wiki/Funkcia]
ono to je nekdy takove (z)mateni pojmu: od zacatku pocitacoveho programovani se zavedly ruzne variace: funkce, metody, rutiny, sub-rutiny, ... (urcite jich najdete dalsi)
v celku jde stale o to same: cast samostatneho kodu s (vicemene) pevne danym ucelem, ktery muze neco vracet, muze neco iniciovat, muze neco volat, ... muze probihat sekvencne (hlavni program ceka na dokonceni), nebo paralelne ...
nazvoslovi, pouziti a pouziti nazvoslovi zalezi na systemu, na generaci kdo to pouziva/pojmenovava, na pouzitem jazyce, ...
je dobre nekdy se snazit nebazirovat na uplne presnem smyslu pouziteho ''terminus-technikus, jak ho najdeme na wiki, nebo jak si predsavujeme, ze jeho definice presne zni, ale je lepsi nekdy spis pochopit toho druheho, v jakem kontextu to pouziva, ale hlavne, co se snazi rict.
protoze toto slovickareni pak vede jenom k nekonecnemu placani a vrseni jednoho nesmyslu na druhy
V téhle vzrušené ( a na můj vkus až zbytečně vyhrocené diskusi) zapadla jedna vlastnost, kterou autor článku nezmínil.
Jedním z cílů autorů jazyka byla i rychlost kompilace. Existuje žert, že Go vzniklo během kompilace a linkování jednoho většího C/C++ projektu. A to je taky jeden z důvodů, proč tolik programátorů z prostředí dynamických jazyků tak snadno na Go přechází. Kompilace je totiž "near" real time. Kompilace a spuštění běžného projektu je v řádu nízkých jednotek sekund, v podstatě téměř nepoznáte rozdíl, proti spuštění skriptu v node.js nebo Pythonu. Na první pohled to může vypadat jako bezvýznamná věc, ale v realitě je to obrovská výhoda.
Obrovska vyhoda? Jo, nekdo tady taky resil, ze musi kazdych 5 minut kompilovat nejaky projekt ktereho kompilace trva 10 minut... Za me je ten clovek ale idiot a mel by spise upravit styl prace kdyz musi po kazdem radku kompilovat projekt jestli mu to jeste funguje... Pamatuji si casy, kdy programatori klidne par dnu psali program a pak ho skompilovali a obvykle na prvni dobrou. V dnesni dobe mi prijde ze programatora dela kazdy idiot ktery pro jistotu potrebuje kompilovat program po kazde zmene v kode...
Není to žert, Rob to v přednášce https://www.youtube.com/watch?v=RIvL2ONhFBI zmiňuje. První myšlenka prý vznikla při 45minutové kompilaci C++ projektu kdy šli do enklávy namalovat pár tipů na nový jazyk na whiteboard s kolegou. Ukázali to těm nahoře a oni řekli jděte na to. Nebo tak nějak už se nepamatuju přesně :-)
Zdrojáky Golang i gccgo jsou plně vlastněny Googlem a kdokoliv chce přispět, musí podepsat contributor agreement, že jim předává autorská práva. Moc nechápu, že gccgo se distribuuje jako součást GCC, protože GCC mission statement říká "Copyrights for the compilers are to be held by the FSF." tady něco nesedí....
jakozto 'skeptik z praxe' jsem se nejak podvedome vyhybal novym jazykum, ale ze zvedavosti jsem otevrel tento clanek o GOLANG: prekvapil mne.
tedy jak vyborne napsany clanek (tesim se na pokracovani), tak vlastne i samotny jazyk. ma moje symfonie svoji filozofii (inklinuji k low level jazykum, a hlavne k minimalismu)
k tem exceptions: mne osobne nechybi. cokoliv jsem psal, udelal jsem modul ala my_error_handlling - kam jsem presmeroval veskere neocekavane stavy. osvedcila se mi postupnost: korektni stav, ocekavana chyba, neocekavana chyba. pricemz do toho modulu se posilaly jenom ty neocekavane stavy.
dokazu pochopit, ze nekteri uz bez vyjymek si svet programovani nedokazi pochopit - jenomze to je presne ten typ programmovani, kdy nekdo naplaca narychlo nejaky kus kodu, co zhavaruje na kdejake banalite a pak testeri (pokud se to k nim vubec dostane) neustale pisou reporty, co jsou rejectovane, protoze to nejsou chyby, ale 'jenom' vyjimky.
proste misto poradneho navrhu, slepe spolehani na system vyjimek.
mluvim o zkusenostech z praxe, kdy treba aplikace na dotaz 'datum narozeni' pri zadani 'trhni si nohou' zhavaruje a vyhodi excetion.
BTW: zasadne mluvim za sebe, nejsem zadnym oficialnim mluvcim zadne skupin. ani neoficialnim. netusim, kam takovy dotaz smeruje.
vyjadril jsem nazor na exception v low level jazycich - pro javu, a podobne, chapu, ze je to potreba.
Záleží na tom, jak je aplikace napsaná a co bylo účelem. Někdo by zase mohl nadávat, že místo aby mu to vyhodilo vyjímku s hláškou co je špatně a chytal to až třeba na úrovni celé aplikace nebo kde chce, tak mu to vrátí třeba -10 a on si pak musí returnovat error přes 15 volaných funkcí.
Kde je tady něco o low-level jazycích nebo zásadně o tobě?
"dokazu pochopit, ze nekteri uz bez vyjymek si svet programovani nedokazi pochopit - jenomze to je presne ten typ programmovani, kdy nekdo naplaca narychlo nejaky kus kodu, co zhavaruje na kdejake banalite a pak testeri (pokud se to k nim vubec dostane) neustale pisou reporty, co jsou rejectovane, protoze to nejsou chyby, ale 'jenom' vyjimky.
proste misto poradneho navrhu, slepe spolehani na system vyjimek."
naposled a pomalu:
"mne osobne nechybi"
"dokazu pochopit, ze nekteri uz bez vyjimek si svet programovani nedokazi pochopit"
"mluvim o zkusenostech z praxe"
"vyjadril jsem nazor na exception"
mas pocit, ze generalizuji a vnucuji svuj nazor nekomu dalsimu?
(basnicka otazka, nevyzadujici odpoved)
Jedna z hlavních výhod jazyka, zmiňovaná v úvodu, je garbage collector. Jak je to v porovnání s dnešním C++11 a výš, který všude tlačí smart pointery?
Raw pointer už se v moderním kódu C++ téměř nevyskytuje, new a delete se díky smart pointerům také upozaďuje, takže z mého C++ pohledu mi přijde, že funkci garbage collectoru zde řeší správa paměti smart pointerů samotných.
Oboje má trochu jiné vlastnosti, i když s projevují až v extrémnějších situacích.
GC má rychlejší alokaci, jen se přičte k pointeru. Moc tam nehrozí fragmentace paměti. malloc musí hledat volný blok paměti a i uvolňování chvíli trvá. Zase tam nejsou pauzy na GC, i když pauzy jsou u novějších generačních GC omezené. A i fragmentace u novějších implementací haldy není až tak zlá. Stručně, u malloc je drahá alokace/dealokace paměti, u GC je nákladné dlouhé držení alokované paměti. Jak dobrý GC má teď go netuším, ale v začátcích byl dost špatný.
U smart pointerů je třeba si dát pozor na cykly. Tvrdí se, že GC tím netrpí, ale není to úplně pravda. Stačí nějaký callback a i jazyk s GC může leakovat.
Co u GC jazyka nehrozí je přetečení zásobníku při uvolňování dlouhého řetězu smart pointerů. Pokud je v C++ problém rekurzivní volání řady destruktorů, pak je třeba to uvolňování ručně přepsat na smyčku. Ale u běžných datových struktur nebývají úrovně zanoření takové, aby to nějak moc nastávalo.
Co jsou to "malé pauzy" dost záleží na kontextu. Tam, kde se pohybuju já, jsou jednotky ms sakra hodně. Ale já rozhodně nedělám věci, na které je go navržené. :)
S tím callbackem jsem to myslel tak, že skrz callbacky do jiných knihoven můžou vzniknout cykly které GC neuklidí. Ony ty hranice do jiných jazyků jsou problematické tak nějak obecně.