|
|
|
|
|
by MaxBarraclough
2021 days ago
|
|
I agree the article might have been more explicit there. If I'm understanding correctly, it's all about possibility of this statement throwing an exception, as for example the cool.ico file might not be found or might be corrupt: icon.Icon = new Icon(GetType(), "cool.ico");
I think the point is that the 'bad' version can make the icon visible in the UI and then throw an exception. The 'not bad' version has a more transactional flavour: if the aforementioned statement throws, then, because of the better ordering, the 'not bad' version doesn't make the unfinished icon object visible, it just bails out with the exception having made no change to the UI, and the unfinished NotifyIcon instance gets garbage-collected.I presume that the real-world code included some extra machinery to hook it up to the existing UI objects, omitted for brevity in the example. It's a bit confusing as it looks rather like it's just building up and returning a NotifyIcon instance for the caller to make use of, but I think the icon.Visible = true; is meant to represent truly making the icon visible in the UI. |
|
As presented, this is hardly an argument that explicit error passing code is better at detecting bad code than exception based code. His other article, https://devblogs.microsoft.com/oldnewthing/20040422-00/?p=39..., is making the point a bit more clearly.
The point itself is half-sound. While it is true that with exception based code, it is hard to distinguish which statements may fail, the real issue is about correctly releasing resources. Assume that every statement can fail, and use some form RAII to manage resource cleanup. The exact content of RAII is hard to glean in both explicit error code and exception based code, as it depends on how the specific third party API acquires/releases resources. Though APIs can be organized to essentially force the use of RAII, even if popular but ancient APIs like POSIX file system are not designed that way.
The real language design issue is that Java/C# mechanism for running cleanup code 'try {} finally {}' a. fails to pass through a handle to the resource that needs cleanup and b. is not scoping the lifetime of the resource that needs cleanup. Furthermore, the standard API makes no effort to provide RAII constructs for correctly managing resource lifetimes. Those language ecosystems actively steer people towards writing bad code. Exceptions may be fine, but the lack of language supported RAII is definitely poor language design. For better language design, exception based Python offers 'with' mechanism and error code based Golang offers 'defer'.
https://www.python.org/dev/peps/pep-0343
https://golang.org/ref/spec#Defer_statements