This Is My FAVORITE Error Handling Class

preview_player
Показать описание
In this video I'll show you my FAVORITE Error Handling Class!

💻 Let me be your mentor and become an industry-ready Android developer in 10 weeks:

⭐ Courses with real-life practices
⭐ Save countless hours of time
⭐ 100% money back guarantee for 30 days
⭐ Become a professional Android developer now:

🎁 Get my FREE 4.5h course "The Best Practice Guide to Android Architecture":

Read our weekly Android blog:

Join my Discord server:

Get the source code for this video on GitHub:
Рекомендации по теме
Комментарии
Автор

I agree that using a custom Result with a sealed hierarchy of errors is the way to go. However, I think you should have included the extension functions that really make this class useful. Things like ifSuccess, ifError, getOr, getOrNull, recover, map, and, andAlso, orElse, etc. Michael Bull’s Result class, Arrow’s Either, and Rust’s Result have many more examples for functions that make “railway oriented programming” possible with function chaining.

mve
Автор

Absolutely! The advantage of using a sealed interface instead of strings is huge.👍

skarloti
Автор

The idiomatic Kotlin implementation of the classic Result pattern — a wonderful thing to know! Oh, and also — awesome usage of "when subject capture" at 12:10 — I didn't know we could do "when val"!!

ArthurKhazbs
Автор

I do this by writing custom Either<Left, Right> sealed class left being error and right being the data we don't need the entire arrow library just few of those extensions like fold makes it lot easier. As always good tutorial 👏

baranidharanmurali
Автор

Thank you thank you thank you! I saw a very similar video yesterday from Stevdza-San and I pointed out the same concerns you had about localisation and separation of concerns. I was about to write my first Medium article on this but then your video came out with more or less the same solution. Awesome video Philip!

pelealexandru
Автор

Mapping 4xx or 5xx errors from retrofit's (or ktor's) exceptions to your own enums may seem redundant to some, but this is the only way to isolate your presentation layer from the actual networking library used by the data layer. Which in turn makes it easy to switch networking libraries if the need arises, e.g. you start using Kotlin Multiplatform (which retrofit does not support).
Great video, as usual!

gekylafas
Автор

I had good luck two days ago and I was looking for a solution to this problem and a way to deal with different types of errors, but the matter was terrible, and it happened that today you are posting a video on this topic and delving into it in depth. Thank you.

زيد_اليماني
Автор

Furthermore you could map the status code of network request to your enums so that you avoid doing too many "when" . ... Great video btw

JPilsonSumbo
Автор

I have two questions:
1. Why on this code (7:40) we use "out" keyword for each generic?
2. Why in Success class we use "<out D, out E: RootError>" instead of writing "data class Success<out D>(val data: D) : Result<D, Nothing>"?

looee
Автор

If you have a use case class that throws its own domain level errors that also communicates with a repository, how would you encapsulate both DataError as well as the usecase's errors? I can see these types of scenarios happening where the usecase returns errors of type Error supertype only. It would be preferable to know the exact subset of errors it could be without looking at the usecase code. Any ideas?

lukesmoljak
Автор

Very nice Improvement, Oh boy, much to learn, much to re-factor!

CryptoCodeZone
Автор

How do you recommend dealing with "Loading" state? It seems closely related. Solutions often include all-in-one (Success|Error|Loading) or creating a second class that is used in the Presentation layer that includes Loading.

ubersticks
Автор

instead of passing message: String from your old sample you could just pass in enum class there :D and its gonna be the same but less boilerplate

jimpauloovejera
Автор

What you really need is only the data and catching exceptions on the presentation layer. For general errors just use an error handler which translates the error into an action or a message. That's it.

RonnyBeeeeee
Автор

I see wrapped errors a lot and it makes processing the successful path require a flatMap. I prefer to throw errors and have the root coroutine catch and handle the error. This leads to much cleaner data, domain layers since they do not need to handle errors and only the coroutine in the ViewModel is concerned with errors.

robchr
Автор

I'd recommend that the Succes result not take an E type (it doesn't care about the error) and have it use Nothing as it's error type for implementing the interface. Same thing goes for the D type on the Error implementation.

nsshurtz
Автор

Interesting approach which looks clean, but is there actually a need to introduce another domain layer for errors? You can just use regular kotlin Result<T> class (which also can return non-nullable data), and throw a different instances of custom Throwable classes for different error cases (or even introduce a custom base sealed interface for domain layer throwables), then just catch throwable in a ViewModel and map a different throwables to the resource strings and show different messages? And in my opinion when some domain logic functions throw exceptions makes code more readable and does not need some custom mapping when using it with mapping/flat-mapping with coroutines or rx.

shifthackz
Автор

Philipp has so good and solid approaches that I implement them also in iOS.

leunamvon
Автор

what about the "class Loading<T>(data: T? = null): Ressource<T>(data)" you had in your Ressource class before ? Would you still have a similar mechanism in the Result interface or do you manage it in an another way ?

Ayor
Автор

Thanks for philipp, i've learn a useful and efficient way to write error class, and do error handling. It would be easier to write out logic codes ✌😁

hoeric