Kung ikaw ay sumubok na sa mundo ng KotlinAlam mo na ang pamamahala ng mga pagkabigo sa isang asynchronous na kapaligiran ay maaaring maging isang tunay na sakit ng ulo. Wala nang mas nakakadismaya pa kaysa sa makitang nag-crash ang iyong application dahil sa isang exception na hindi mo alam kung saan ito nanggaling, lalo na kapag nagtatrabaho sa mga coroutine na tumatakbo sa mga pangalawang thread at wala silang iniiwang malinaw na bakas ng kanilang pagkakamali.
Para maiwasan ang isang hindi magandang karanasan ng gumagamit, mahalagang magpatupad ng isang matibay na lambat pangkaligtasan. Hindi lamang ito tungkol sa pag-aayos ng mga bagay-bagay, kundi tungkol sa pag-unawa kung paano napupunta ang exception mula sa anak patungo sa magulang at kung paano natin ito mahahadlangan bago pa man ito... magdulot ng nakamamatay na aksidente sa sistema, gamit ang mga katutubong kagamitang iniaalok sa atin ng wika.
Pag-unawa sa CoroutineExceptionHandler
Ang isang mahalagang punto ay ang handler na ito ay nagpapaputok lamang kapag mga hindi nahuli na eksepsiyonKung ang error ay naayos na gamit ang isang internal try-catch block, hindi na mapapansin ng global mechanism. Bukod pa rito, sa mga normal na hierarchy, itinatalaga ng mga child system ang error sa parent, na siya namang nagpapasa nito hanggang sa root, kung saan tuluyang nareresolba ang error. CoroutineExceptionHandler naka-install sa konteksto Pumalit upang iproseso ang problema.
Pagpapalaganap: paglulunsad vs. async
Hindi lahat ng tagapagtayo ng mga tiwaling gawain ay kumikilos nang pare-pareho sa harap ng sakuna. launch Tinatrato nito ang mga eksepsiyon bilang mga hindi nahuli na error, katulad ng kung paano ang Thread.uncaughtExceptionHandler ng Java. Sa kabilang banda, async isinasama ang eksepsiyon sa loob ng bagay Deferred nagreresulta, kaya ang error ay mangyayari lamang kapag sinubukan nating isagawa ang paraan ng await().
Nangangahulugan ito na kung gagamitin mo ang async, Ang CoroutineExceptionHandler Wala itong magiging epekto, dahil ang responsibilidad sa pamamahala ng pagkabigo ay ganap na nakasalalay sa developer sa oras ng ubusin ang resulta ng operasyonSa kabaligtaran, kasama ang launchKung walang malinaw na landas ng pagpapalaganap patungo sa isang magulang na humahawak sa error, ang pandaigdigang tagapangasiwa ang magiging huling linya ng depensa.
Ang Papel ng Superbisor at Superbisor
Sa karaniwang nakabalangkas na concurrency, kung ang isang bata ay mabigo, awtomatiko nitong kinakansela ang magulang nito at lahat ng mga kapatid nito. Minsan ito ay labis. Upang maiwasan ang domino effect na ito, maaari tayong gumamit ng SupervisorJob o isang supervisorScopeSa mga sitwasyong ito, ang pagkansela ay lumalaganap lamang pababa; ibig sabihin, Ang pagkabigo ng isang anak ay walang epekto sa ama ni sa iba pang mga prosesong kapatid.
Kapag nagtatrabaho sa ilalim ng superbisyon, ang mga coroutine na direktang inilulunsad sa loob ng saklaw ay gumagamit ng CoroutineExceptionHandler sa parehong paraan tulad ng mga root coroutine. Ito ay mainam para sa mga bahagi ng UI kung saan gusto nating mabigo ang isang pangalawang gawain nang hindi naaapektuhan ang sistema. Nawawala ang buong visual na bahagi mula sa screen ng gumagamit.
Mga modernong alternatibo: runCatching at Result
Kung gusto mong maiwasan ang pagiging magulo ng mga nested try-catch block, iniaalok sa atin ng Kotlin ang mga sumusunod: runCatching at ang klase ResultAng pamamaraang ito ay mas praktikal at elegante, dahil isinasama nito ang resulta sa isang bagay na maaaring maging matagumpay o mabigo. Sa ganitong paraan, binabago natin ang pamamahala ng error sa isang nahuhulaang daloy ng datos at madaling iugnay.
Salamat sa mga tampok tulad ng map, flatMap y recoverMaaari nating iproseso ang tugon mula sa isang API o isang database at magpasya kung ano ang gagawin sa error sa susunod na bahagi ng code. Ito ay isang mahusay na estratehiya para sa pagpapanatili ng malinis na lohika sa negosyo at hiwalay sa paghawak ng mga teknikal na eksepsiyon, na nagpapahintulot sa code na maging mas madaling basahin at mapanatili sa pangmatagalan.
Paghahambing sa ibang mga kapaligiran tulad ng Spring Boot o Express
Bagama't pinag-uusapan natin ang Kotlin, interesanteng tandaan na karaniwan ang pilosopiya ng pagsentro ng mga error. Halimbawa, sa Spring Boot, ginagamit ito @RestControllerAdvice para makuha ang mga eksepsiyon ng domain at gawing pare-parehong mga tugon ng JSON ang mga ito gamit ang mga sentralisadong error code sa EnumsGayundin, ang Express sa Node.js ay gumagamit ng error middleware kung saan ang failure ay ipinapasa sa function. next().
Ang malaking pagkakaiba ay sa mga coroutine ng Kotlin, ang paghawak ay mahigpit na nakadepende sa konteksto ng pagpapatupad at ang puno ng mga TrabahoHabang sa isang web server, ang error ay karaniwang umaabot pataas sa HTTP call stack, sa Kotlin, dapat tayong maging maingat kung tayo ay nasa isang GlobalScope o sa isang pinangangasiwaang saklaw upang maiwasan ang isang eksepsiyon na maligaw sa kawalan o hilahin pababa ang buong aplikasyon.
Mga pangwakas na pagsasaalang-alang sa daloy ng error
Upang maipatupad ang isang matatag na sistema, ang mainam na pamamaraan ay pagsamahin ang paggamit ng mga try-catch block para sa mga mababawi na error, runCatching para sa mga daloy ng paggana at isang CoroutineExceptionHandler bilang pangwakas na lambat pangkaligtasan. Mahalagang tandaan na ang Hindi pinapansin ang CancellationException Sa disenyo, ito ang built-in na tool ng Kotlin para sa pagpapahinto ng mga proseso nang hindi ito itinuturing na isang error. Sa pamamagitan ng pagsasama ng mga layer na ito, gagawin nating matatag ang application, na maiiwasan ang anumang hindi inaasahang teknikal na isyu na magreresulta sa hindi inaasahang pag-shutdown at tinitiyak na ang bawat pagkabigo ay maayos na natutugunan. rehistrado at mahusay na pinamamahalaan. Ibahagi ang impormasyong ito upang mas maraming tao ang matuto tungkol sa paksang ito.