Proper Error Handling in Flutter & Dart (#1 - Principles)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
as much as we would all like to close our eyes and pretend that errors don't exist we still have to deal with exceptions on a daily basis modern languages including dart support exception throwing and catching however if you've developed apps for some time you may have become frustrated with this special flow of errors in the program so is there a way to return errors just like you return regular values while keeping the code maintainable in this two-part series you're going to learn how to deal with errors properly and in the first part which is this one you're going to learn the best practices of classic error handling using try catch blocks because there are many things which can go wrong even with classic exceptions and then in the second part we will introduce powerful concepts from functional programming that will make handling errors even more streamlined this is something you might have seen in my clean architecture for flutter tutorial series but over here in these two-part series we are going to expand on that even further hello welcome to SoCo drew where you are getting prepared for real app development so that you will get freelance clients or a job and be confident about the apps you built so subscribe and hit the bell to join us on our quest for becoming sought-after developers and also if you want to meet up with the flutter community including me and people from Google in January 2020 which is just around the corner in Warsaw Poland check out flutter Europe da death or also there is a link in the video description there is no better way to learn error handling than on a semi real app and that's precisely what we are going to be building in this tutorial two-part series actually you already have the app prepared for you as the starter project which you can get from the link in the video description but first let me show you what this app entails it's a very simple concept you just press this button and it's going to load this post from a fake API and this post simply has I be user ID title and body and it's gotten from the fake API as the JSON string as you can see over here and then we of course parse it into some sort of model class we convert it from map using JSON decode just as usual and then we have a possibility to throw errors from the fake HTTP client by simply uncommenting these lines so we can either throw a socket exception an HTTP exception or we can return an invalid JSON which will of course trigger a format exception when we try to parse this invalid JSON and of course we also have some sort of a UI which displays what you have just seen so we are currently doing that inside a state full widget with a future builder which simple displays a circular progress indicator and then it displays either the error message or a post or the press the button text and toward the end of this first part we are going to migrate to a more mature state management solution using provider I just want to show you how to handle errors when you don't use any sort of a state management like this when you have just a future builder inside the stateful widget and the concepts which we set out for proper error handling in the first half of this tutorial will very much translate also to provider or mob X or block or whatever else of a state management solution you want to use with some very minor changes so if you want to get this starter project and also learn from the written tutorial check out the link from the video description where you can find all of the code to this video links to occasional libraries and overall go through this lesson at your own pace as we've already seen errors can be thrown from the fake HTTP client currently we return a proper JSON so we are good however when we short-circuit the execution this method by simply throwing a socket exception for example so we uncomment this line and now we're going to go to the app and get post it just says press the button but the error is not present anywhere right and we should definitely have an error displayed because we are checking if the future snapshot has error we want to display the error string but currently it seems that because we are just outputting press the button style text it means that there is no error present in the snapshot so why is that well that's because currently we are handling errors in the worst possible way and honestly if you handle errors like this it is much better to let them propagate throughout the app and crash the app in the end because what we are doing currently is that we just catch any kind of an error from the post service which simply calls the HTTP clients method which throws that exception and whenever we catch any kind of an error which is printed out to the console so yes we are catching an error and the app will not crash as you can see it prints out socket exception no internet three times because we've pressed the button three times but the problem is that printing out to the console will not make the user aware of the error there is nothing present in the UI which talks about the error so the user will probably think that we have just a buggy app which does not do anything because the user will have no clue that some sort of an error occurred but you might think we are using a future builder and ask the good flutter developer knows future builder catches errors itself after all it has this field has error which you can check for and then you can get the error from the future builders snapshot itself so actually we do not need to catch exceptions from the post service right we can just let them propagate freely to the UI and the UI will take care of them itself so let's try bad fuzzy also this comment and let's remove the catch and let's say that right so what we can do now we are still throwing a socket exception so let's just again press the button and we get a crash of the app suppose it crash however do not worry if you get something like this because that's just probably a bug in vs code because actually this exception has been caught by the widgets library more precisely by the Future Builder so we can just nicely continue with the execution of this program and so that we do not get any further suppose it fake app crashes we can go to the debug tab and down here we want to uncheck on call exceptions so once you have that unchecked you are not going to get these fake positives although you are not going to get any positive positives either so we'll just keep this in mind if this uncalled exceptions is unchecked that just buck with fierce code but either way whether we have the bug or not if we now open up the emulator we can see that we have a socket exception message present right over here and we can also change it to HTTP exception so let's just try all of the exceptions nice and also if we have an invalid JSON format it's going to bring out the format exception but you know the issue with this simpler approach is that we do now want to display these low-level error messages to the user because what is this talking about like we have an invalid JSON gotten from the supposed server which we are faking currently so the user really does not even have to know about some characters which are returned from the server we should really format this to say something like internal error or bad response or something like that because this is just scary to the regular user and it doesn't tell him anything which is useful and also another very much huge issue is that currently we basically again have some sort of a blanket catch statement even though we have not written it ourselves we are still catching every kind of an exception which is thrown in the future builder then output in it as the text widget the issue with catching every single possible exception which is thrown and that's also sort of an issue of using a future builder is there what if there is some sort of an unrecoverable error upon which it's just much better to crash the app you know you have these fatal errors all the time at least on Windows or on some apps like fatal error the app crashes you cannot continue something like that can happen I don't know maybe you are building and banking app and when there is some problem with the transaction it's probably just better to crash the app than to let the improper transaction go through and do some monetary harm to some people right so just to recap what do we want to do well we want to customize error messages and also make sure that we catch only these particular types of exceptions and nothing more just to be safe so what can we do about this well we can of course reintroduce the try catch block so let me just write try we're going to grab this code and move it upwards and then inside catch we're going to write something well sort of kind of we of course do not want to catch everything instead what we want to do is that we want to utilize darts weird syntax because in other languages you may be used to something like catch socket exception II and so on but over here in dart it's a bit different so instead of doing catch socket exception II if you want to catch only a socket exception you are instead going to say on socket exception and then you can either catch E or you don't have to so we actually do not want to get the error so we can just leave off this catch part and with that we are now catching only a socket exception and we want to do the same thing all of the other exceptions which can be thrown from the fake httpclient so we also want to catch HTP exception and also a format exception okay so now we are catching them but we are not doing anything with these three particular exceptions so we want to do something but we mustn't let ourselves slip into just printing out some messages because then we are going to arrive in the same situation as we were at the beginning of this tutorial although it's a better situation because we still let other non called exceptions propagate but still we are going to be only printing so something like no internet connection and also a neutral face all right or maybe this one and we can do that for all of the other exceptions as well so for HTTP exception we're going to print couldn't find the post and for format exception we would print something like bad response format but this is no cool because still when we now run the app you know what's going to happen of course nothing will be propagated to the UI so we want to get post and again the error message will be just printed to the console bad response format right but we won't get that error message displayed to the user in the UI so of course what we can do is early throw an exception we could do that we could just wreath row for example the socket exception and with three throw if we now output the socket exception and run the app again so we press the button we have just gotten rid of the awesome message saying no internet connection and instead we are again printing some socket exception which does not tell a lot to the user although the latter part of the message tells him something but still we want to print this nice message with an emoji so the solution to throwing an exception only on particular exceptions when they are caught and also customizing the error message is to not tree throw of course but instead we want to create our own custom exception type which will be used solely for the purpose of getting the exceptions from outer boundary layers for example as this post service because post service communicates with an HTTP client so it's an outer layer of our app and that exception will be responsible for just getting these messages to our layers of our app so the trick is to create a single half wide failure class and let's just create it right below the post service there will be a class failure and it will have final string message and we want to have this message in the constructor populated and then we also want to override to string where we will just return an arrow function so expression bodied method message because we are in dart this class failure does not need to extend exception because in dart you can throw any sort of an object it doesn't need to be an exception and we are going to utilize that feature of dart to our advantage and also if you want to translate these error messages you probably do not just want to pass around strings like that instead you would probably have something like final int code and you would pass around just these integer codes and then translate to a proper message to a proper language in the UI player but we are building only an example app so we are good to go with messages directly and now what we want to do is simply instead of printing we're going to throw a failure and that's it so we want to replace every print with throw failure and now what's going to happen is that if we now hit the button no socket exception will throw no internet connection failure so we have a nice message and also we can try it out with all the other exceptions so HTTP exception will get us couldn't find the post and the last one will show us bad response format and of course just to test out if even the proper path the happy path of the code works we're going to test it if no errors occur we should get the post displayed nicely and we do which is the good thing this is how you can handle errors using stateful widget which is very simple state management solution but it still works for simple apps however if you have something more elaborate a bigger project you probably just probably do not want to use the stateful widget for your state management and that way you also probably aren't going to use a future builder which sort of handles exception caching itself and printing out errors from a future builder is very simple you do not need to do any additional setup so because of that I also want to show you how to handle exceptions properly when you use a more elaborate state management solution and the simplest one to show here is provider however these techniques will work more or less with minor modifications also for mob x-block redux whatever else you want to use we're going to use a simple change notifier with a provider and also if you want to learn how to handle errors properly solely in block and also learn clean architecture along the way check out my tutorial course from the cart in the corner which is going to teach you is that all using the block library actually there are not a lot of changes we have to make to our code at least not to this one which hand those errors and throws failures in order for it to work with change notifier so let's just first create a brand new file post change notifier and also because this is definitely not a tutorial about change notifier i do not want to bore you to death by watching me type out along as notifier so i will just paste the code which is present in the written tutorial so go over there and get it yourself if you want to follow along alright so here we go and what we have inside the change notifier is a notifier state which of course can be initial loading and load it initial state will of course display the if we restart the app it will display this message press the button this is the initial state then we have a loading state which will display this circular progress indicator and then we are gonna have also a loaded state which will display either this nice post or an error message of course we depend on both surveys because we want to get the data from somewhere and inside that post service remember that we are still handling all of the exceptions and changing them up to be failures with proper error messages so that's still taking place in the post service and basically we then just have three glorified fields in the change notifier glorified because we have one private field then we have one public get only property and then private setter we could also go with a property setter but I feel that setter methods are more manageable I just like them better but you can use getters and setters properties just as well so whenever we set a property we notify listeners so that we can update the UI and that's basically it there is nothing more to that we have a state field post field and failure field so we also want to store the failure at least with this first approach because in the second part which is coming up next you are going to learn how to handle errors even better using some concepts from functional gramming which are pretty powerful but for now we still store the failure as a separate field so there are some specificities which stem out from this decision but we're going to run with that for now as I said in the second part we are going to change this and then we also have just one method which is void and public get one post and over here as soon as it's called we set the state to loading so that we display this nice loading indicator and then we have a try-catch block and we catch only failures so whenever a failure happens we are going to actually also catch the instance of the failure and we are going to call set failure otherwise we are going to call set post with the pose which is gotten from the post service and then we again set state to be loaded so that we can update the UI and some of you might get heart attacks if you see this code because you are going to say Matt this is so uh knocked my eyes what you are doing like you are calling notify listeners from set state and also from set pose set failure you're going to have unnecessary builds rebuilds of the UI well just chill out this is just a simple project but yes you could optimize it by even removing the notify listeners from set pose and set failure because after all you are always calling set state which notifies listeners as well but let's just leave it as dead I'm not going to change this code just for you purists out there and again notice that we are catching only failures in the post change notifier or you would also do the same thing in the block or in a mob X store or in a reducer wherever else and we still leave out the actual error management and converting the feature specific errors to add wise failures to the post service this does not change even when you introduce some sort of a middle layer in a way of a proper state management solution you still want to handle the particular types of exceptions and convert them to failures as soon as possible in the outer layers of the app because I hope you agree that post-service is an outer layer because it communicates with httpclient however our post change notifier is a more inner layer because it does not really depend on some classes which we do not own granted we do own our HTTP client but that's only because it's fake if you are using a proper HTTP client a live one you are not going to be able to change its code as easily so really catch particular types of exceptions as soon as you can and then convert them to add wide failures that's because you want to follow the single responsibility principle and since our post service has the responsibility to communicate with HTTP client I think that main responsibility entails also the responsibility to handle errors coming from the HTTP client and also of course from the from JSON conversion of a post even if you do not want to follow a single responsibility this approach of handling exceptions close to their source will still be beneficial to you because you have much less chance of forgetting to handle a particular type of exception when you handle it close to its source because if you have multiple services and have changed notifier it's very very easy to forget about some type of an exception which you would want to catch all right so moving on we have the notifier setup so now what's left for us to do is to modify the UI so currently we have a future builder and a state fall widget which depends on post service itself and also it stores the future of the post we can remove all of these dependencies because we have them over in the post change notifier and also let me just show you that the starter project already comes with the provider dependency so if you want to follow along just be sure to use the same provider version which is currently three-point 2.0 in a short while 4.0 0.0 version will come out but we'll change a few things so just make sure that you are using three-point 2.0 just to follow along of course before using provider we have to provide the change notifier down to our home widget so we're going to just wrap it with a new widget which will be a change notifier provider note the file provider it's child is home of course and also we want to have a create method which will simply instantiate our post change notifier currently we are still using the future builder in our widget we're gonna leave this in here just for now and above it we are going to create a consumer consumer of post change notifier and it needs to have a builder of course let me just put a comma and B end and inside this builder we want to have a function granting us only the notifier we are not interested in the build context nor the child so two underscores and inside this method we're going to do basically the same thing as we are doing in the future builder it's only going to be working with the change notifier and again because this is not a tutorial about change notifier i am just going to paste the code over from the written tutorial so what do we have here well it's basically the same thing as we have in the future builder because if the state is initial we return style tex press the button if we are loading we output circular progress indicator and if we are neither loading or we are not initial that means the state is loaded and here we have to check if the failure is not no in which case if it's not null we have an error so we want to print out the failure converted to string otherwise there is no error so we can print out the post which we have gotten from the fake HTTP API and with that we can now remove the your builder and also in the race button we are no longer just going to set the state and call posters directly instead we are going to grab a provider and with that we want to get an instance of power change notifiers so post change modifier and arned we want to call get one post and with this if we now check out the app as it's running it's still going to work and just test it out once more we are going to for example uncomment this HTTP exception and we should get a nice error message print out and we surely do so the code we have written in this first part is good enough however we can make it a lot better by introducing a few practices from functional programming but first if you want to go through this tutorial at your own pace once again because there may be a lot to process and also if you want to get all of the code check out the written tutorial available from the link in the video description with that said we have some issues currently which are present in the code for example we currently have only one failure here but what if I will change notifier will do more than just get a single post what if we have some error data field over here as well well we also have to have multiple failure fields or we are just going to throw everything into one failure field no matter where that failure is coming from and also what about this if statement in main dot dart where we are checking if failure is not know currently we are relying on good practices and conventions so that we have to remember to check if failure is not know but wouldn't it be better to be forced to handle failures no matter if we remember to handle them or not we are going to be forced to do that through the support of the dart compiler whenever you can rely on a compiler you should rely on that and not on your own memory because your memory is unreliable but the compiler is reliable because compiler has rules and if you do not follow them you can be sure that the compiler will give you a hard time about it and all of these problems stem from one thing which is that the flow of errors is currently different from the flow of the success data because we are just throwing exceptions all over the place and then we have to catch them and even though we have streamlined the process with a failure which is app wide and use forgetting the exceptions across to the change notifier still the flow of exceptions is throw and catch and the flow of regular data is just nice return values from a function so in the next part you are going to learn how to also return errors together bundled with the data and we are going to use functional programming concepts such as either task we're going to map over the function to catch the either type to hold only failures and overall you are going to learn a lot in regards to functional programming and also in regards to proper error handling and if you have watched my tutorial and if you have watched my clean architecture test-driven development tutorial series this error handling will be even better than what we have over there so definitely stay tuned for that no matter if you've seen that series or not and if you are serious about becoming a great flutter developer who can build real apps for clients or add a job go to flutter that education and link is also in the description to get the top curated flutter news and resources aimed at improving your app development career over there you can also subscribe to my mailing list to get the best flat resources delivered weekly right into your inbox so if you do not want to miss that next part and also more tutorials like this be sure to subscribe to this channel and also join the notifications squad by hitting the Bell button to make sure you grow your flutter skills because here on reso coder I am determined to provide you with the best tutorials and resources so that you will become a sought-after flatter of developer and if this video helped you with understanding how to handle errors properly and how to get them over to a change notifier or a block or a ma big store give this video a like and also share with our developers who will surely benefit from this - leave a comment if you have anything to say and see you in the next [Music]
Info
Channel: Reso Coder
Views: 30,990
Rating: undefined out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, flutter, flutter tutorial, flutter exception handling, flutter exceptions, flutter error handling, flutter error, dart error handling, darts errors, dart exceptions
Id: NoZde-wYGA4
Channel Id: undefined
Length: 31min 29sec (1889 seconds)
Published: Wed Dec 11 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.