sobota 4. října 2014

Jak zpracovávat chyby?

V programu může běžně nastat nějaká chyba, kterou bychom měli zpracovat. Výjimky nejsou jediná možnost, jak to řešit. Co víc, výjimky nemusejí být vždy tou nejlepší možností.

Dost totiž záleží na stylu programování. Nicméně dnes se styly programování často mísí, takže to není tak jednoznačné. Většinou dnes uplatníme od každého přístupu něco.

Imperativní přístup

V imperativním kódu budou výjimky nejspíše správná cesta. Pokud volám funkci (proceduru), která má něco provést, ale nevrací žádný výsledek nebo mě její výsledek nemusí zajímat, je dost velké riziko, že zapomenu zkontrolovat výsledek. Dopady mohou být někdy fatální. Pokud se nepodaří změnit adresář, mohu vymazat třeba úplně jiná data. Pokud se nepodaří zkopírovat data, může dojít k jejich ztrátě. Pokud se nepodaří volání setuid, program může běžet dál s vyšším oprávněním, jako to bylo v případě rageagainstthecage. V takovýchto případech je lepší program nechat spadnout než dělat, že se nic špatného nestalo.

Bylo by fajn, kdyby se programátor již při kompilaci dozvěděl, že něco zapomněl ošetřit. V Javě jsou k tomuto účelu checked exceptions. Používají se v situacích, kdy si programátor nemůže být jist, že operace proběhne bez chyby. Typicky jde o I/O. Naopak třeba u dělení by bylo otravné pokaždé muset kontrolovat, jestli nedošlo k ArithmeticException, ale zase programátor má šanci různými způsoby zajistit, aby nedělil nulou. Uznávám, že okolo checked exceptions je jistá kontroverze, a že nejspíš kvůli tomu je nemá moc jazyků. Nalezení hranice mezi checked a unchecked mi kupodivu v praxi většinou (ne vždy) nepřišlo jako až takový problém, ale třeba podpora v lambda funkcích je docela peklo. Dobře se to projevuje v Javě 8. Zkuste schválně upravit kód urlStringList.map((url) -> new java.net.URL(url)) do funkční podoby.

Funkcionální přístup

Mám dvě zprávy, jednu špatnou a druhou dobrou.

Špatná zpráva je, že v čistě funkcionálních jazycích není chytání výjimek zrovna běžná záležitost. Například v Haskellu se snad nedají výjimky chytat mimo I/O monády. Důvodů pro to může být více, třeba určité narušení čistoty vzhledem k línému vyhodnocování. Je tedy celkem OK vyhodit výjimku třeba u dělení nulou, což mohl programátor snadno ošetřit různými způsoby. Na druhou stranu je méně vhodné házet výjimku třeba u neexistujícího klíče mapy.

Dobrá zpráva je, že funkcionální jazyky přicházejí s něčím v jistých ohledech lepším, co by mohlo nahradit checked exceptions. Pokud výraz nemění stav, určitě nás bude zajímat jeho návratová hodnota. Jinak je zbytečný. (Výjimkou může být snad jen sleep.) V návratové hodnotě bude tedy buď výsledek, nebo chyba. Když chce programátor číst hodnotu, musí zároveň ošetřit i chybu. Podstatné je, že by nemělo jít o uspořádanou dvojici (errorCode, value), protože tady je velmi snadné přečíst pouze value, i pokud došlo k chybě. Spíše by mělo jít o typ Either[ErrorType, ReturnValueType]. V případě úspěchu se vrátí Right(value), v případě chyby se vrátí Left(errorDescription).

Možná to vypadá strašně komplikovaně, ale není. Funkcionální jazyky mívají pattern matching, který to usnadní. Ukážu příklad. Dejme tomu, že budeme mít celočíselné dělení safeDivision, které skončí chybou nejen v případě dělení nulou, ale i v případě nepřesného výsledku. Tedy safeDivision(9, 3) vrátí Right(3), ale safeDivision(9, 2) vrátí Left(InaccurateResult) a safeDivision(9, 0) vrátí Left(DivisionByZero). Budeme psát funkci, která má prezentovat výsledek uživateli. Její tělo může vypadat třeba takto:

safeDivision(numerator, denominator) match {
 case Right(result) => s"$numerator/$denominator = $result"
 case Left(error) => "Can't divide"
}

Nebo můžeme vypsat i konkrétní chybu:

safeDivision(numerator, denominator) match {
 case Right(result) => s"$numerator/$denominator = $result"
 case Left(InaccurateResult) => "Can't divide accurately"
 case Left(DivisionByZero) => "Can't divide by zero"
}

Daly by se vymýšlet i složitější příklady, kdy bychom napsali nějaký výraz pro prvek JSONu (například json.a.b.c.d.as[String]) a na konci bychom zjistili buď hodnotu, nebo srozumitelnou chybovou hlášku (např. "a.b.c je null"). Toto by se přes výjimky dělalo obtížně.

Nabízí se otázka, kdy ve funkcionálním programování použít výjimky a kdy návratové hodnoty. Výhoda výjimek je, že nezaplevelují kód, pokud ta chyba nemůže nastat, například u foo/(1+x*x) nenastane dělení nulou (pokud je vyřešeno číselné přetečení). Jejich nevýhoda je, že se na jejich zpracování snadno zapomene a že se hůře zpracovávají. Někdy se osvědčilo nabídnout dvě funkce, kdy jedna je optimistická (předpokládá bezchybný průběh, jinak hodí výjimku) a druhá pesimistická (předpokládá, že může nastat chyba, a vrátí Either nebo něco podobného). To může být užitečné třeba u mapy (slovníku), kdy záleží na použití, co se více hodí.

Který použít?

Rozmýšlíte se, jestli použít funkcionální přístup, nebo imperativní? Nenechte se zmást jazykem. Máme imperativní jazyky s funkcionálními prvky (Ruby, Java, PHP), máme čistě funkcionální jazyky s I/O monádami (Haskell) a máme nečisté funkcionální jazyky (Scala, LISP). Hranice jsou někdy diskutabilní, záleží dost na kultuře. Co tedy s tím?

Pokud by chyba v dobře napsaném programu neměla nastat, pak budou nejspíš nejlepší výjimky. Nutit programátora ošetřovat chybu, která nemůže nastat, těžko povede k něčemu dobrému. V lepším případě ji sám konvertuje na výjimku, v horším případě ji nějak bude ignorovat.

Funkcionální přístup se dobře hodí u výrazů, které nemají žádný side effect. Tam těžko zapomenu na kontrolu návratové hodnoty. Zbývá pouze otázka, zda zvolený jazyk nabízí vhodné prostředky pro tento přístup.

Diskutabilní bude použít funkcionální přístup, pokud sice mám side effect, ale vracím nějakou zajímavou návratovou hodnotu.

Pokud je ale volání čistě o tom, abych udělal nějaký side effect (změna adresáře, setuid, ...), potom je dost riskantní se spoléhat na ověření návratové hodnoty. Jsme čistě imperativní, výjimka je tedy skoro jasná volba, pokud to jazyk umožňuje. Diskutovat lze možná o tom, jestli má jít o checked exception, nebo unchecked exception.

pondělí 24. února 2014

Nokia s Androidem pod Microsoftem? Ono to začíná dávat smysl.

Nejdřív Microsoft, nepřesně řečeno, „koupil Nokii“. Potom se objevily spekulace o Nokii s Androidem, které byly v Barceloně potvrzeny. A do toho se objevuje spekulace, že by měl Microsoft umožnit běh aplikací pro Android na Windows. Dává vám to smysl? Začínám tušit, co se chystá.

Tento článek je spekulace. Snažil jsem se ale fakta odlišit od domněnek.

Telefony s Androidem byly skutečně představeny

Jasný fakt je, že Nokia smartphony s Androidem skutečně představila. Jde o levnější smartphony, mají systém upravený do vzhledu Windows Phone a nemají Google Play. Uživatel s telefonem dostane prostor v úložišti OneDrive od Microsoftu. Dokonce v systému lze najít označení „Nokia X software platform 1.0.1“, jako by to ani nebyl Android. Samo o sobě některé věci, zejména absence Google Play, znějí jako šílenost, ale s ostatními událostmi to dohromady začne dávat smysl.

Tyto telefony nejspíš bude vyrábět Microsoft

Ještě šíleněji může na první pohled znít, že tyto telefony bude nejspíš vyrábět Microsoft. Microsoft totiž koupil mobilní divizi Nokie. (Nekoupil celou firmu Nokia – ta bude stále existovat a bude dělat mapy Here, bude mít Nokia Solutions and Networks a další.) Zdroj už přesně nevím, ale od převzetí mobilní divize (očekává se první čtvrtletí 2014) do zhruba konce roku 2015 nebude, tuším, Nokia podle dohody smět vyrábět vlastní telefony. Těžko tedy můžeme předpokládat, že tyto telefony bude dělat Nokia. Spíš to převezme Microsoft s celou divizí Devices & Services.

Teoreticky by Microsoftu snad nemělo nic bránit v zahození těchto telefonů. Hádám ale, že se tak nestane. Spíše to vypadá, jako by vývoj těchto telefonů začal na pokyn Microsoftu.

I když je bude vyrábět Microsoft, mohou ještě mít značku Nokia

Nenechte se zmást, i když Nokia jako taková nebude patřit Microsoftu a bude stále mít svoji původní značku, dohodla se s Microsoftem na tom, že v některých případech může použít její značku. Můžeme se hádat, jestli „current Nokia mobile phone products“ napsané 3. 9. 2013 zahrnuje i telefony představené v roce 2014. Tisková zpráva nicméně není smlouva a právníci nejspíš pro skutečnou dohodu udělali přesnější formulaci. Dávalo by smysl, kdyby Microsoft nemusel rebrandovat všechny předchozí telefony a značku Nokia vypustil až u těch nových.

Microsoft prý snad umožní běh aplikací pro Android na Windows

Objevují se spekulace, že Microsoft umožní na Windows spustit aplikace pro Android. Nejspíš ale pouze ty, které sám schválí ve Windows Store. Instalace APK ze souboru tak asi možná nebude, Google Play nečekejte vůbec. Myslím, že podpora aplikací pro Android na Windows sice bude, ale bude to s ní trošku vlažnější, než to na první pohled může vypadat.

Zaprvé, těžko tu bude 100% kompatibilita. Některé aplikace pro Android mohou být vázány nějakým způsobem na Linux a to se Microsoftu asi nebude chtít řešit. (To se mimochodem nechtělo řešit ani BlackBerry, které to s aplikacemi pro Android myslí asi o něco vážněji.) Jiné aplikace zase používají Google Play Services, které tu bez dohody s Googlem nebude. (A pokud chce Microsoft schvalovat aplikace a mít provize z prodeje, dohoda tu asi nevznikne.) Microsoft může místo Google Play Services nabídnout alternativu s podobným či stejným API, ale třeba podporu push notifikací bude muset vyřešit vývojář i na serveru. Opět tu můžeme vidět do jisté míry paralelu s BlackBerry OS 10, kde též řešili podporu aplikací pro Android.

Zadruhé, možná ani po „jailbreaku“ nepůjde instalovat vlastní APK. Microsoft totiž nemusí dát do Windows obecný runtime pro aplikace pro Android. Možná bude mít pouze nějakou on-line službu, která aplikace pro Android (s nějakými omezeními) konvertuje pro Windows Phone. K této službě se mohou vázat různá omezení, která i v případě odemčeného telefonu zabrání nebo aspoň významně ztíží instalaci cizí aplikace jako APK.

Na druhou stranu, možná bychom nemuseli čekat na Windows 9, jak některé zdroje tvrdí. Touto cestou může Microsoft nabídnout tyto aplikace i pro starší Windows. V extrémním případě by věškeré potřebné součásti byly přímo v té konvertované aplikaci.

Microsoft to nejspíš dělá zejména kvůli Windows Phone. Smysl to ale může mít i kvůli desktopovým Windows – pro ty je sice aplikací dost, ale asi málo z nich je přizpůsobených pro dotykové ovládání. Pokud budou mít vývojáři možnost se věnovat hlavní platformě (Android) a s minimem práce ty aplikace dát i na Windows Store, budou tak nejspíš činit mnohem ochotněji a Microsoft by mohl tak rychleji zaplnit nedostatek aplikací.

Z Nokia X software platform může být „Windows Phone Lite“

Pokud ale bude podpora aplikací pro Android na Windows Phone, začínají dávat smysl telefony s Androidem. Zvláště když jsou upraveny tak, aby to Android moc nepřipomínalo a bude mít jiný obchod s aplikacemi. Navíc s nimi dostane člověk 10GB v OneDrive od Microsoftu. Jde o lowendy, které nebudou příliš konkurovat Windows Phone. Zatím snad vše nasvědčuje tomu, že Windows Phone budou pro Microsoft hlavním operačním systémem a upravený Android bude pro lowendy. Očekávám, že nastane zhruba toto:

  • Pokud budu chtít aplikaci pro Android vystavit na obchodu Nokie (nebo Microsoftu?), bude muset splňovat stejná omezení jako pro Windows Marketplace. (Možná se najdou výjimky – například aplikace, které mají speciální verzi pro Windows Phone.)
  • Na Nokiích s Androidem nepůjde instalovat aplikace z neznámých zdrojů, ale pouze schválené aplikace z obchodu. Naproti tomu na běžných Androidech je instalace z neznámých zdrojů otázka jednoho zatržítka v nastavení.
  • Obchod Nokie časem splyne s Windows Marketplace.
  • Všechen software pro Nokia X software platform půjde spustit i na Windows Phone. Naopak to ale platit nemusí.

Teď by to všechno mohlo dávat smysl. Microsoft by skutečně dělal telefony s Androidem, ale měl by tam Windows Marketplace a vlastně by ty telefony až tak nekonkurovaly těm s Windows Phone. Android v podání Microsoftu by byl spíše Windows Phone Lite.

Nové smartphony s Windows Phone by mohly používat značku Lumia, kterou Microsoft dostane od Nokie. Nové smartphony s Androidem by spíše použivaly jinou značku. Možná Asha, možná ještě jinou.

Možná se dočkáme navigace Here pro Android

Navigaci Here bude mít Microsoft licencovanou, ale patřit bude stále Nokii. Pokud tyto nově představené telefony mají mít Nokia Here, znamená to jediné – Nokia tuto navigaci připravila i pro Android. Samozřejmě nevím, jestli půjde nainstalovat do běžných telefonů s Androidem ani jestli tak půjde učinit oficiálně. Možná se ale objeví i přímo v Google Play. když Nokia nepatří Microsoftu, zveřejnění navigace Here v Google Play by dávalo smysl.

Budou aplikace pro Android univerzální?

Aplikace pro Android již dnes umí spustit Jolla (podrobnosti neznám) a BlackBerry OS 10 (s jistými omezeními). Nejspíš to bude do jisté míry umět i Windows. Stane se to trendem?

Hádám, že u iOS se podpory aplikací pro Android jen tak nedočkáme, aspoň zatím. Na to jsou příliš mainstreamové. Možná bude ale situace jiná třeba u Ubuntu. Technicky to může být i jednodušší než u Windows.

Na druhou stranu se jednotlivé operační systémy od sebe více nebo méně liší i logikou ovládání. Pokud bude snaha dostat k sobě aplikace pro cizí systém, mohou si s sebou vzít i logiku ovládání. V jednodušších případech to mohou vyřešit upravené knihovny, jindy ale bude potřeba ruční práce programátora a případně i návrháře UI. Jenže se může také stát, že aplikace pro ten OS nebudou mít uživatelské rozhraní dostatečně přizpůsobené a ovládání „infikují“ zvyky z Androidu.