Díky za zajímavý článek. Upřímně řečeno, kontrola chyb mi připadá jako možná nejslabší vlastnost Go. Má stejný zásadní problém, jako ta v C: nejsnazším, nejsvůdnějším a tedy bohužel i nejčastějším řešením je vratné chybové hodnoty prostě ignorovat a předpokládat, že k chybě nedošlo. Vynucený odchyt výjimek v Javě, nebo chybové typy jako používá Rust, mi proto připadají lepší - oba mají své plus a mínus, ale to je zase na úplně jinou diskusi.
26. 9. 2019, 03:28 editováno autorem komentáře
To je pravda. Sice se oproti céčku mnohé zlepšilo (už jen proto, že se nemusí mixovat návratový a chybový kód nebo řešit errno), ale někdy je prostě zbytečně zdlouhavé řešit všechny chybové stavy, tak to člověk neděla a není jazykem přinucen to dělat. Osobně bych asi byl pro obě možnosti, protože se tak sémanticky oddělí "očekávané chyby" (například se budu snažit o převod řetězce na číslo a někdy tam prostě budou jiné znaky) a skutečné výjimky (čtení ze souboru selhalo kvůli externím problémům), ale tvůrci Go se snaží zachovat minimalistický jazyk, takže uvidíme.
Změny se možná dočkáme v Go 2, protože návrhy na úpravy jazyka tímto směrem zatím nejsou zavřeny - https://github.com/golang/go/issues?page=1&q=is%3Aissue+is%3Aopen+label%3Aproposal+label%3AGo2&utf8=%E2%9C%93
Vecna poznamka - on Rust umi Result z main az od 1.26, coz neni tak dlouho. A potom jeste neni doreseno toto https://github.com/rust-lang/rust/issues/48711. Coz znamena, ze mainu bez Result bude porad jeste dost, protoze kazdy radeji sahne po std::process::exit.
„...V programovacím jazyce Go je ovšem situace zcela odlišná, protože v tomto jazyku existují pouze dvě pravdivostní hodnoty – true a false, které jsou typu bool. Žádné další hodnoty se nesmí v rozhodovací konstrukci if, v podmínce smyčky for atd., vyskytovat. ...mohlo by se zdát, že se jedná o přílišnou rigiditu...“
Asi záleží na úhlu pohledu. Jako C++ programátor spatřuji jednu z největších slabin jazyka právě ty spousty implicitních konverzí, nejen v rámci bool, takže jakýkoliv jazyk, který je v tomto co nejpřísnější, má u mě plus.
Navíc by se mi hodně líbilo mít něco jako „typedef“, jehož alias bude kompilátorem považován za naprosto odlišný typ, tedy např.
typedef uint16_t UserId;
UserId currentUser = someSystem.GetLoggedUserId();
uint16_t value = currentUser; // Compile error! Cannot implicitly cast from UserId to uint16_t!
Jsem si vědom toho, že je to možné řešit šablonami, ale asi je vidět, že to není úplně ideální. A třeba v C# to nelze vůbec (tam kdykoliv, kdy opravdu potřebuji izolovat typ, si implementuji strukturu, ale je to otravný copy-paste).
To je jistě častá reakce, taky jsem se s ní setkal. Jenže... obecně se řadím ke škole, která říká, že překladač by měl "buzerovat" pokud možno co nejvíc. Je to zcela v rozporu s představami o agilním vývoji a tzv "produktivitě", jenže zrovna před pár týdny jsem řešil source code review pro jistého klienta, který následkem zranitelnosti v nepochybně velmi "agilně" vyvinutém kódu (byl to python) přišel o cca osm set tisíc australských dolarů...
Omlouvám se, pokud se mýlím, ale přijde mi, že jste si sám odpověděl na otázku. Je naprosto běžné (nebo aspoň co se týče mých zkušeností), že na prototypu se staví výsledný produkt, přesně, jak píšete. Proto bych se neodvažoval dělat prototyp v něčem jiném, než by měla být ostrá verze, jedině s výjimkou, kdyby bylo jasné, že prototyp nebude takto použitelný. Aktuálně mne ale napadá jen jeden takový příklad z praxe - když Nintendo dělalo jejich poslední hru ze série Legend of Zelda (Breath of the Wild), nejprve mechaniky implementovali v prototypu s jednoduchou 2D grafikou, takže pak hru museli začít from scratch. (Zda ale použili různé programovací jazyky, to ale netuším.)
Ony jsou různé prototypy, od pouhých mockupů, statických HTML stránek s návrhem UI/dialogů přes polofunkční aplikace (kde se třeba simuluje databáze statickými daty) až po kostru výsledné aplikace. Ale právě pro tyto účely vznikly rapid prototyping nástroje a ty většinou nejsou postaveny na silně typovaných jazycích, spíš na Pythonu apod.
Já plně chápu váš názor a někdy je do toho tlačen i vývojář stylem "hele takto přesně to chceme, takže je vlastně hotovo, jen to trošku přeleštit". Takže je asi nutný dávat natvrdo informace, že se jedná o mockup, throwaway prototyp atd. (https://en.wikipedia.org/wiki/Software_prototyping#Throwaway_prototyping)
Pokud můžu mluvit za sebe, tak jedna z nejhorších fází projektu je právě situace, kdy je k dispozici +- slepenec, který se může podobat výsledné aplikace a má se začít kódit výsledný kvalitní(!) produkt. Člověku je líto ten slepenec zahodit s tím, že se to postupně doupravuje.
„Takže je asi nutný dávat natvrdo informace, že se jedná o mockup, throwaway prototyp atd.“
Jenže moje zkušenost je ještě tak trochu jiná. Vedení samo neustále opakuje mantru „je to jen prototyp, nějak to co nejrychleji nabouchejte, pak to zahodíme“. A ze dne na den (po schválení prototypu) se ona mantra změní na „nemáme čas, doděláme to na tom, co máme“. Všechny protesty vývojářů jsou smeteny ze stolu slovy „však to funguje“.
„Pokud můžu mluvit za sebe, tak jedna z nejhorších fází projektu je právě situace, kdy je k dispozici +- slepenec, který se může podobat výsledné aplikace a má se začít kódit výsledný kvalitní(!) produkt. Člověku je líto ten slepenec zahodit s tím, že se to postupně doupravuje.“
Popravdě, za tuto fázi jsem se už dávno dostal po několika projektech, které byly udělány na prototypu. Ty zkušenosti se vryjí tak silně, že ne, už mi to není líto zahodit. Naopak, vítám možnost některé věci napsat jinak, když při prototypování experimentuji s architekturou a zjistím, co není tak úplně ideální.
Na druhou stranu jsem zároveň nabyl dojmu, že se z prototypu dá udělat dobrý výsledný produkt. Jenže to vyžaduje ochotu a odvahu se pouštět do těžkého refactorignu a zjistil jsem, že podobně jak vedení bývá rezistentní vůči zahazování prototypů, tak většina programátorů je úplně stejně rezistentní vůči tomuto typu úprav. (Ale uznávám, kdyby to bylo v Pythonu nebo Java Scriptu, tak budu do určité míry rezistit taky. Ale v takovém případě bych v první řadě rezistil vůči použití těchto jazyků na větší projekt.)
Ono je možné to brát i z opačného úhlu: dělat prototyp v něčem jiném je způsob, jak zaručit, že se z něj nestane ostrá verze. Tohle se samozřejmě, až na čestné výjimky, v korporátech nemá šanci prosadit: jediným cílem všeho je vždycky snížit náklady teď hned a problémy se budou řešit "když nastanou", i když to pak znamená náklady řádově vyšší.
„Ono je možné to brát i z opačného úhlu: dělat prototyp v něčem jiném je způsob, jak zaručit, že se z něj nestane ostrá verze.“
No, přesně tak jsem to myslel, takže se omlouvám, pokud to vyznělo jinak.
A moji poznámku, že z praxe znám jen jeden případ jsem mj. myslel i tak, že i v tom vidím past. Řeknu si „Python není na tento projekt dobrý, ale rychle se v něm píše, takže ten prototyp udělám v něm“ a pak riskuji, že mi backfirene a samotná ostrá verze nakonec bude celá v Pythonu, jakkoliv je nevhodný. Takže jedině použít něco fakt šíleného, jako je Haskell zmiňovaný Ondrou...
ony se ty rozdíly stírají. Dynamické jazyky přidávají možnost typových anotací a statické jazyky se postupně stávají uživatelsky přívětivější (typescript, Kotlin). Statické typy vnucované VŠUDE je podle mě přechodný trend. Třeba typescript je na ústupu. Nepřináší nic navíc oproti anotacím v komentářích, jen složitější ekosystém.
Jako letitý C++ař, navíc ještě ovlivněný Haskellem, bych se pod tohle podepsal. pointer->bool je ještě ok, ale třeba bool->int nebo int->unsigned jsou jenom na zlost.
Šablony na silně typované inty osobně dost používám. Nemotají se mi indexy, nedějou automatické konverze a zakázal jsem si takhle neinicializované proměnné. Není to úplně ideální, ale poměr odchycených chyb k dodatečnému opruzu mi zatím vychází dobře.