Certainly not. If you are missing the code to specifically handle a null value, you hope you get a noisy explosion, not a runaway train in your program's logic. Fail-fast is a virtue.
This (anti-)pattern has a Wikipedia page, complete with Criticism section.
Incidentally, Objective-C does something like this out-of-the-box. Unlike Java, where invoking a method on null causes an exception to be thrown, or C++, where you just get good old undefined behaviour, Objective-C 'defaults' to doing nothing. This is described in the Wikipedia article. Strikes me as a very bad idea.
Well in terms of system stability I’ve usually found OS X and Obj-C GUIs to be much more stable than on any other platform. Objective C’s null handling could well be part of that. If so, what’s better for GUIs then?
As I said, explicit fail-fast behaviour is what you want. It's far better that a bug manifest noisily and immediately, than that it go unnoticed.
At the risk of just re-stating myself:
In Java, if you attempt to invoke a (non-static) method on a null reference, it throws a `NullPointerException`. This is exactly what you want: it's immediately obvious to the developer, and to a user. No further damage can occur as a result of the bug. (Ignoring broader questions of exception-handling, of course.)
Java pretty consistently adopts this philosophy of runtime checks everywhere, even on production builds. C#/.Net does the same. It's a valuable feature for software correctness.
(Java's choice of exception name is curious given that Java has references and not pointers, but still, they have the right idea.)
C++ is the opposite: if you invoke a non-static method (or 'member-function') on `null`, you get 'undefined behaviour'. Anything could happen. Hopefully the program will crash with something akin to a 'segfault', but maybe it will do something disastrous.
Unlike Java, the C++ philosophy is generally performance first, and it does few runtime checks for you. C++ has its reasons, but this approach is extremely unhelpful for software correctness; it can make both bug-detection, and bug-hunting, much harder.
(Incidentally, GCC and Clang feature a `-fsanitize=null` flag which gives you Java-style runtime checks, presumably with a moderate runtime performance cost. This isn't in the C++ standard, though.)
Objective-C is somewhere in the middle: you don't get undefined behaviour, but neither does the system tell you when you've got a null-dereference bug. It just silently carries on, and you're left assuming that your code is working fine.
There's nothing at all special about GUI code. Fail-fast is still what you want. There could be any number of technical or non-technical reasons you've found OS X GUI applications to be more stable. Null handling is just a tiny piece of the picture.
> Objective-C is somewhere in the middle: you don't get undefined behaviour, but neither does the system tell you when you've got a null-dereference bug. It just silently carries on, and you're left assuming that your code is working fine.
And the program often keeps running and generally working despite some potentially rare-null related bug occurs.
For a contrived example, imagine a user tries to paste a text field into a table and the text has an emoji in it. Let's further imagine the code doesn't handle full unicode properly, and the internal function handler returns a NULL, breaking the data model. In the die-on-null case the entire app often dies since the devs didn't think to add a try/catch around this case, thinking user strings from the UI object could never be null. Now the user has lost an entire table of data they've entered and don't know why for sure. The app just died when they pasted a bunch of data.
In the case of Obj-C with "ignore-null" behavior the data model would effectively ignore the field and likely result in an empty field. The user would still be able to save the rest of their data, with the curious exception of this field. They try pasting just that field and realize it has an emoji. Maybe they'd file a bug that emoji's don't work but they work around and enter a text smiley face. Of course many other things can/could happen like weird data corruption. But I've experienced very similar occurrences in apps and worked around them without data corruption.
Now as a developer, it's harder to find the reason as you don't have a nice log with "app crashed on NPE", but your users can still find a work around and often still find the app useable.
This scenario still requires defensive programming around sub-system interfaces to prevent said errors from reaching, say the internal embedded db, though that's already usually the case in a well designed code base.
> There's nothing at all special about GUI code. Fail-fast is still what you want. There could be any number of technical or non-technical reasons you've found OS X GUI applications to be more stable. Null handling is just a tiny piece of the picture.
For general systems code, I'd agree with you on null detection and fail-fast behavior. As a developer it's much better to know sooner when an error occurs. Granted null handling is just a small component of an overall system, it is an important component and NPE's are some of the most common errors and are most likely to cause an entire app to die due to unhandled/unexpected nulls.
However, from a simple analysis as an end-user of various GUI systems I prefer that some random probably unused feature silently fails or does weird stuff but that the main program keeps running, rather than an entire application (or worse the whole DE) fail due to an un-handled NPE.
And I disagree that there isn't anything unique about GUI code. It's a very different domain than systems / server applications. It should therefore utilize coding patterns which produce better results for that target domain.
I believe the point is that IF the problem with nil is that when it shows up you can't be sure whether it was on purpose (to indicate an "empty" value) or on accident (because an error in the code caused a variable to not get bound). By introducing a separate identifier (e.g. :id-unknown) to explicitly handle the empty-value case, it frees up nil to solely signify improperly bound variables.