After coding AS3 for about 2 years now, I’ve come to 1 conclusion: I’m sick and tired of testing for null. It seems to be the most common if then statement I write in all of my code. I’ve been doing some pure ActionScript work in the past few months, and I have to so say, the more ActionScript only, as opposed to Flex projects using MXML, code I write has more of these checks. It’s nice how MXML handles all the deferred instantiation stuff for you. I certainly have more appreciation for it. Same with Flash CS3 and automatically declaring stage instances.
The second reason, however, is exceptions. I’ve never had to use exceptions until now. Half the reason is 90% of all exceptions in Flex are bugs that you can fix in your code. When doing API work, it’s the opposite. I cannot control what gets passed into my code when I plug libraries into some other project. I have the benefit of drinking my own kool-aid; we’re using the very API’s we create. There came a point last week where I realized that some of the exceptions weren’t my fault. Meaning, I could go to a court of law, represent myself, and still win with utter confidence. When developers use an API, you cannot control what they put into it. While you can expose some strongly typed public methods, and hope for the best, but ultimately they’re going to pass something in there that is null, NaN, or just plain wrong.
For debugging, it’s easy; you can use default values when you don’t have time to correct the one who is using the API if you are coding both yourself. You can’t do that, though, in production. When creating video players for work, if I have 2 million customers having SWF’s on their desktop trying to hit our internal development server that cannot be reached without VPN… that’s a bad thing.
Running into that scenario, I started trying to handle some of the exceptions myself. I started to get some deeply nested try/catch blocks. The code started to look really nasty (maybe ’cause I’m not used to it). However, I started feeling really confident that if something didn’t work, I can could capture it in one place, and create an error screen for it. After awhile, this spiraled out of control. Suddenly, I was catching just about every method. In short, it’s bs; I shouldn’t have to code like that. Clearly I was in uncharted territory that the C++ and Java crowd had already figured out.
Whilst the bird was cooking, I went digging on Google and found 2 good articles (Best Practices for Exception Handling, Exceptions in Java: Nothing Exceptional About Them). I told her majesty I wouldn’t work over the holidays; I don’t count learning exception handling as working. The one on Sun’s site I didn’t agree with. Furthermore, while the articles are years old, and appear to disquiet controversy, it sounds like the same arguments Flash Developers have of code on frames vs. no code on frames. Both are valid, 1 is a purist angle, the other a pragmatic angle. Doing my best with just 3 hours worth of research, it seems that Java has checked and unchecked exceptions; in the Flash Player world meaning those that show the debugger popup window in the debug player, and those that do not. I’ve yet to see an exception not show a debug window. I had 1 nestled deeply in a View not do it once, but I think that was a bug in the beta Flex 3 bits I’m using. So… it doesn’t sound like ActionScript has an unchecked exception equivalent.
That said, if you read Sun’s article explaining the reasoning behind unchecked exceptions, they justify it by saying there are just some errors you either can’t reasonably recover from, and there are too many exceptions to possibly catch. If you did, you’re code would become too verbose and un-readable.
I call busllshit. First off, YOU MUST recover. If you’re a GUI developer like me, you know that you can’t show user’s a cryptic error screen, or worse, nothing. Heck, if you’ve ever used Windows and got some useless error screen with no information on how to proceed, all it did was make you frustrated with no clue on how to solve your problem… nor even a clue as to what the problem even is. Unfortunately, this is a problem in the Flash Player as well; there is no way to catch all exceptions assuming you put a big-ole try catch on _root for example. Even though exceptions can act like events for asynchronous exceptions (aka, Error’s that have an Event equivalent are dispatched when something goes wrong, and you ‘catch’ them like you do events via addEventLsitener ). You can’t do that, but that’s what a lot of us want for Enterprise apps, or those apps that CANNOT have errors thrown under any circumstance in production code. I’d still argue, however, that most of the relevant ones you can catch and handle. There is a caveat to this I’ll mention later.
Secondly, after reading the 2 other articles, you are not pre-disposed to write bad code proportional to the amount of exceptions thrown. This is a fallacy Java’s designers apparently thought would happen… maybe they didn’t want to have their uber-sexy OOP language look like Eiffel, no clue. Bottom line is, there are good ways to throw and handle exceptions in Java, C++, and ActionScript.
After reading the articles, one mentioned the anti-pattern of deeply nested try / catch blocks. I’d only be doing exception handling for 2 days, and already I used an anti-pattern… sweet, I suck! In doing so, I clearly recognize the key point in one of the articles; exceptions can break encapsulation. The consumer of the API had to know too much about the API to use it; meaning, it had to know what could go wrong with it and handle it. Shouldn’t an API handle it’s own problems or at least lessen the amount of code I have to write? Isn’t that the point of an API? When I started seeing my code checking for IOError’s on URLLoader, which my code shouldn’t even know a URLLoader is being used, I clearly saw the break in encapsulation. It’s a bad feeling to not know if you are doing something correctly. It’s great, however, to know you are clearly doing something utterly wrong. That means there is a RIGHT way to do it. Google search FTW!
Java has this thing called throws; it’s a keyword that goes on the end of a function in Java, and forces the method that calls it to use a try catch block just in case the method does throw an error. It’s nice because it’s a compiler thing, so the code won’t even compile unless you use the method correctly. This is problematic in ActionScript for 2 reasons. First, ActionScript doesn’t block so you can’t do a try / catch on an asynchronous method. Secondly, there is no “throws” equivalent for events; since Error’s are treated as events and dispatched the same way, you cannot force someone to use an addEventListener in ActionScript. Even if you could, you cannot control how they do so. For example, if you used a weak listener to an addEventListener, and there were no hard references to it, so Garbage Collection ate it, the exception wouldn’t be “caught” by an event listener. Technically you made the compiler happy, but you failed to catch said exception/event.
The point here is in Java this is part of the language, the contract that goes along with strong-typing. While interfaces are a programming by contract methodology, so to are throws in Java. It seems to me this is not a strong point of ActionScript (at least the parts ofECMA 4 it’s implanted; haven’t read where ECMA 4 is going), nor are there any best practices yet since the API creation field for ActionScript has just now started on a major up-swing (don’t believe Zoho, they’re full of it, there are a lot of great AS3 libraries. Do a google search).
To Sun’s credit, in reading the 2 articles, I didn’t realize one particular scenario, and that is if your API is put into a GUI you don’t have control over. It’s really easy for me to think, “Sure, if there is an error, I’ll just have my designer create an error screen for it, or have some Information Architect / Interaction Designer document which exceptions do what in the interface”. That’s all well and good if you are the one both creating and consuming the API. For some of our customers, that is a set of glorious, and wrong, assumptions. First off, they shouldn’t have to know about our API too much to use it. For all the crap I give f’ing DoubleClick , their API is brain-dead simple to use. They still suck that they don’t support AS3, though. Second, I cannot control customers’ GUI; if they choose not to show an error screen because something didn’t load properly, who’s fault is that… mine or theirs? It’s mine if I didn’t provide an easy, simplified way of letting them know when something went wrong. Only then is it theirs. Third, error handling is yet ANOTHER thing to do. Thus, it takes time. A lot of Flash work sometimes is under insane deadlines; just because I have reasonable deadlines with reasonable management and competent developers does not mean that our customers will be as lucky. I need to work extra hard to make sure I make their job as easy as possible. Aka, a good API.
In short, what I gleaned is:
- Don’t ignore exceptions. Find out why your code is breaking and fix it. For those situations which you can’t control, handle it, clean up your mess, and dispatch/throw an error.
- Don’t over architect your Error’s. Some internal error’s are perfectly named; use them instead of your own. The RangeError is a good example. If you try to access item 10 of an array that only has 9 items, you don’t need to abstract that further, nor shield an API user from it. It’s a simple error that comes from using array’s.
- Going along with point #1, if you have a ton of errors that could potentially happen, consolidate them so users of your API only get 1 error (or is few as possible). You do this by extending Error and then throwing / dispatching it. If they really want to know the root cause, store the original error as a class member.
Again, if you are creating a Flex app, you probably don’t have to worry about this too much. I’d argue most exceptions are something you did, in your code. A lot of us Flash Developers have the perception of exceptions as being “errors in your code”. Our attitude typically is, “If there is a bug in your code… fix it.” This perception breaks down when you start creating API’s for others that you cannot control how they use it. That, or just the user’s internet connection goes down and an IOError is thrown. You can’t fix the interwebs connection using Flash.
I’m sure how to resolve Joel’s angle. While I wasn’t much of a coder back then, handling “error codes” in Director’s Multiuser Server was a royal pain in the neck, so not sure how to code to what he’s suggesting. Painting by numbers is fun… coding by them is not.
7 Replies to “Your Mom is null throws Exception OT OT OT … or Learning Exception Handling in ActionScript”
I’ve also been struggling with this dilemma lately. So, do your methods still check for null and NaN when they accept parameters with no default values? If they do, what do you do when you do get a null or NaN? Do you return an error code, throw an exception, do nothing, etc? And do you do this for each and every method or only those that are public?
For now, throw an exception if I canâ€™t recover. For some methods, itâ€™s ok if you pass a null value. However, for UUIDâ€™s, for example, the represent a massive amount of data that I need from the serverâ€¦ no UUID, no data.
Rather than returning false, or trying the call anyway (knowing itâ€™s going to fail), I clean up the mess (remove event listeners from the URLLoader, delete it) and then throw an exception. The exception for typical messages is just an error:
For some of the API stuff Iâ€™m doing, however, I feel like, based on what I read from the Java articles, encapsulate it into a custom event. I do the same as the above for the custom error:
For internal things, like bad data, errors returned from the database because itâ€™s down, or just no internet connection, Iâ€™ll capture all 3 and put into a generic error:
That way, people using the API only have to do:
This includes asyncronous ones:
The generic ones help in debugging.
However, key thing to note, if I know that a simple operation will fail, say passing NaN to an addChild method, I wouldnâ€™t catch that myself. The crackhead who passed the NaN should either inspect his/her own data, and/or try/catch for RangeErrorâ€™s. The downside is, unlike Java, he has no clue heâ€™ll even GET a RangeError because there is no â€œthrowsâ€ like thing in Java. Part of me wants to encapsulate those as well; store the root cause in my custom error, and just throw an APIError.
The other part of me doesnâ€™t want to allow bad data in, and then hide the true cause 1 level away. If you are passing in NaNâ€™s, thatâ€™s the API userâ€™s fault. Iâ€™m leaning more towards the custom exception, though, because I feel I can write better error messages than what the defaults imply. So, instead of:
In the API, itâ€™d instead attempt to find a valid depth, and then throw:
The root cause is in there, and they can print out the stack trace if they so choose. Furthermore, the error gives more context.
:: shrugs :: Iâ€™m new at this, no hard and fast opinons yet.
Hey Jesse, interesting post. Checked exceptions is still something that people aren’t sure about in Java. The fact that C# chose not to have them brought a lot of discussion a few years ago. There’s a lot of good articles on this: see http://www.mindview.net/Etc/Discussions/CheckedExceptions
The strangest thing to me with exceptions is something small, which is that binding swallows a few exception (see BindingUtil). That’s caught me a few times.
After reading that, I’m inclined to:
– try/catch to capture all errors inside my class(es)
– never use throw again. Instead, dispatch an error event that abstracts all errors into one event.
– have that error event include the reason why something broke
If you code ActionScript, you understand events. Events are optional, just like RuntimeExceptions (unchecked exceptions) in Java. So… seems good enough for me! Heck, even HTTPService does this via the fault event. No exceptions there… good enough for Flex, good enough for me.
One solution for the future might be the “nullable types” proposal for ES4. (http://wiki.ecmascript.org/doku.php?id=proposals:nullability). Not much help today of course…
Comments are closed.