Saturday 19 October 2013

Reading

This morning I did a test to see how my fisheye would work with the new Nikon G to Canon adapter I bought a while back. I had already done a test a week or two ago, but that was just on a ball head, and mainly to check the optimum focus position and correct position of the aperture lever for f/11. Today I wanted to make sure that both sides of the image were equally sharp, by taking overlapping shots on my pano head, which is what I use the fisheye for.

The annoying thing was, that after I took the photos, I realised the focus wasn't optimal. Strangely the focus position needed to be nearer to infinity for optimum results today than it did when I tested it a couple of weeks ago. I guess I'll have to do another test in another couple of weeks to confirm which position is correct.

Anyway, there didn't seem to be any issues with one side of the lens being more blurry than the other, so that's good. The resulting pano stitched nicely without any errors (that I noticed) as well. So it looks like I should be able to get back to taking panos when I want.

I started reading Sitepoint's PHP Master book, which thankfully seems to be a lot better than their useless OO PHP learnable course. I did think there were a couple of things they could have explained better. For example, they state that objects are always passed by reference, which is not exactly true. On that point I think they should have included a link to PHP Manual: Objects and References, which contains a more thorough explanation of how it works.

Similarly, they have a note that using clone only creates a shallow copy. They could easily have added a link to a page with information on how to create a deep clone. Or even added a bit in the book, it would only need to be a few lines. But they are only minor niggles and I am very happy with the book so far. It has taught me some things I didn't know (or have completely forgotten), such as the __sleep and __wakeup magic methods, called when serializing and unserializing an object.

After that I started looking into the info on using exceptions to control flow (the Sitepoint book talks a bit about the Exception class). I had previously started a thread on Sitepoint (related to JS rather than PHP) where another poster had stated that you shouldn't throw in javascript, and most definitely shouldn't throw in an object constructor.

Well, I have read a bit about the arguments for and against using exceptions to control flow (generally rather for a specific language), and it didn't seem to me like there was a particularly strong argument against it. (Though those against it did seem to have strong opinions about it). I had read a good article on why you should use exceptions for flow control, though I couldn't find it today.

I found this article Exceptions are Bad™, where the author suggests you just return a value / object that equates to the error, rather than throwing an error. I had also read elsewhere a suggestion for JS that was something like that your function should return an object like

{"error","value":"Everything OK"}

Then you'd check in your calling function to see if error was not empty on the return object and deal with it, or otherwise use the value.

There are two comments on that article that really make sense to me, and back up the use of Exceptions for flow control. This comment by Divye:

Okay. This might seem ugly, but while rapidly developing a system where everything seems to be breaking all the time, the Either approach is terrible. I would much rather have the fail fast semantics of Exceptions than keep hoping and praying that I have caught all the errors passed through the return values – especially when code is changing rapidly.
My personal experience has been that putting in exceptions all over the code for anything not being as expected ensures that the program works as intended in the default cases and any unhandled cases get identified real quick. You can then take the decision on whether to let the program crash on that case or whether the case is worthy enough of graceful handling and that handling can be put in at any level of abstraction in the code due to the bubbling nature of exceptions. This is very sadly not the case for return value based checking that you’re advocating.

And this comment by Cedric:

There are several reasons that make Either/Option/Maybe a worse solution:
- Once you go down that path, you have to change all your return types to being an Option, which leads to some pretty horrendous API’s.
- Now you have infected all your return values with error codes, which is exactly what HRESULT and other similar atrocities from the 80′s taught us was bad in the first place. There are excellent reasons why errors should use an alternative path in your code.
- You also completely ignored the non local benefit of exceptions. Sometimes, an error happens deep in your code and only a caller three stack frames up is able to handle it. How are you going to handle this, by bubbling up the Exceptional Option all the way back up? If you do that, you are basically doing manually what the exception mechanism is doing for you for free.
I think the commenter called d-range nailed it: you are essentially saying that “handling exceptions badly is bad”. The solution to this is not to replace exceptions but to handle them well, which has been documented to death in a lot of places (e.g. Effective Java).

In my opinion, I can't see what the issue is with throwing exceptions when a parameter for a function that you expect to be supplied is not supplied. Or similarly, throwing an exception if a parameter is not of a type you expect. Where I probably wouldn't throw an exception is when dealing with user data. For example, if a user fills out a form, it is not really 'exceptional' that they might miss out a piece of needed data. But for internal stuff I generally expect data being passed to it to have already been checked for validity, and so if it is not valid, then throw an exception. It makes it easy to see when something is wrong, what is wrong, and where.

Since the thread on Sitepoint I had started was about Javascript, I looked a bit more into what javascript does. It all seems a bit messy to me really. You can create a Date object with an invalid string, it will instantiate a Date object, but the toString method will give 'Invalid Date'.

If you create a new Event(), you will get a TypeError: Not enough arguments. So it seems that it is valid to throw an exception in a constructor. However, if you pass a non-string value as the parameter, the Event object will be created, but with a string value of whatever was passed, e.g.

new Event(undefined) //gives an Event object with a "type" property of "undefined"
new Event({}) //gives an Event object with a "type" property of "[object Object]"
new Event({"toString": function(){return 'Not a type of event';}}) //gives an Event object with a "type" property of "Not a type of event"

Since undefined has no toString method, I can't understand why it would be accepted as a valid parameter. In my thoughts really the Event constructor should be throwing an Exception for anything that isn't a string (even if it does have a toString method).

Looking into it a bit more, I found that for asynchronous events in javascript, you have an onerror handler. I played around for a bit with this, at first using the ErrorEvent, which I assumed was a special type of event triggered when an error occurred. But after no success and looking it up, I found that actually ErrorEvent is specific to webworkers. You just use a standard Event with a type of "error" for a normal error event.

So, if I do

window.onerror=function(e){console.log('An error occurred');}
window.dispatchEvent(new Event("error",{"message":"fake error"}))

I then get the message

An error occurred

However, I am not sure how many things in JS trigger an error normally. From my (brief) testing it seems most things either generate an exception or allow invalid parameters, e.g. document.getElementById(undefined) just returns null, no error event. I think that AJAX requests, IndexedDB requests, and image loading requests all do trigger an error event when something goes wrong though.

Anyway, so I haven't really figured out what the best practice (or at least 'makes most sense to me' practice) is for both generating and handling errors in javascript. I'll probably try and look into a bit more tomorrow.

No comments: