1. 3

  2. 4

    I am firmly in the camp who thinks ?. accessors are the path to ruin. My java experience was long ago and not very good, but we quickly found ourselves in the situation where everything and anything could be null, and therefore half the code base was null checks, which in turn just returned null or did nothing or whatever was “sensible”. Holy hell, that became a mess later. You’d click a button and nothing would happen. null pointer somewhere in the jungle. Which pointer? Literally any or all if them. The whole thing was held together by so much string it turned into a ball of string. Hard to break, but not very useful.

    1. 1

      I agree. The article suggests some better approaches.

    2. 2

      Not really applicable to Java, but the best explanation I’ve seen of the underlying issues at play with this problem is on Jane Street’s blog: https://blogs.janestreet.com/making-something-out-of-nothing-or-why-none-is-better-than-nan-and-null/

      1. 1

        The underlying problem is due to predominately calling methods to obtain values, which violates encapsulation. This is also known as tight coupling. A much more robust solution to avoid the null pointer problem is to loosely couple the classes through well-defined interfaces using a mechanism called self-encapsulation. Consider:

        In the tight coupling example above, each time the Blue Agent requests data from the Green Agent a null value could be returned, which must be checked. Regardless of the checking mechanism (assertions, conditionals, annotations, catching exceptions), the entire approach is incorrect.

        Instead, the Blue Agent should query the Green Agent to determine the correct course for subsequent actions based on a boolean result, thereby maintaining encapsulation. Such loose coupling offers critical benefits. First, it eliminates null checks, as null cannot be returned. Second, it permits extending the class without imposing changes on client classes; e.g., if the Green Agent were to require middle names, the Blue Agent code should not have to change.

        The tight coupling anti-pattern is everywhere. In my mind, the most prominent example is file handling, such as:

        String extension = FileUtils.getExtension( file );
        if( "JPG".equalsIgnoreCase( extension ) ) { ... handle JPEG file ... }
        if( "PNG".equalsIgnoreCase( extension ) ) { ... handle PNG file ... }

        Beyond terrible, this is abysmal code and all the null-checking in the world–automated or otherwise–won’t improve it. First, it uses a “utility” class, which isn’t a true class (see Bertrand Meyer’s book). Second, the series of if statements would be better as a dictionary (mapping values to methods). Third, it isn’t extensible. There are more issues, but the jist should be clear.

        A flexible approach avoids the problem’s crux entirely: stop breaking encapsulation. I’ve drafted a presentation on this subject that includes source code examples.


        Constructive critiques are most welcome.

        1. 6

          The practice you are criticizing has nothing to do with null pointers, it also doesn’t cause the other problem that you say it does (which is unrelated to null pointers), and your style of argument is profoundly unconvincing.

          You’re arguing (maybe unintentionally?) for eliminating methods with return values, which is to say, all methods should be “commands” in Meyer’s sense. Meyer certainly doesn’t argue for eliminating queries (methods with return values), just separating them from commands. CPS-transforming buggy code doesn’t remove nulls; it just transforms them from return values to arguments. I’m not convinced that CPS-transforming tightly-coupled code makes it loosely-coupled, either.

          Meyer’s Eiffel, which allows methods to have return values, is in fact free of null-pointer problems. So are ML and Haskell. In Haskell, in fact, functions that don’t have return values are useless, because there are no side effects. ML and Haskell don’t have encapsulation at all, but they still don’t have null pointer problems.

          As for Blue Agent, I am deeply unconvinced by examples that rely on analogies to real-world objects:

          I propose a new rule for discussions of object-oriented programming:

          Anyone who brings up examples of Dog, Bike, Car, Person, or other real-world objects, unless they are talking about writing a clone of The Sims or something, is immediately shot.

          I feel that this new policy will improve the quality of the discourse enormously.

          If you want to find out if your ideas have merit, try them on some real code. Then you can show the “before” and “after” versions of the code, and show how the “after” version has some virtue that the “before” version lacks; for example, that some possible enhancement can be carried out by a local code change instead of a global one, or by adding code instead of changing it. Also, if you want to convince people who didn’t go to your talk, post an actual prose explanation of your argument, not just the bullet points, pull-quotes, and code samples in your slides. That way, people will be able to understand what you’re saying, instead of having to imagine it.

          You may find it useful to use a more succinct language than Java for your code samples. Python or JS are much better at this.

          Metaphors and similes are fine for helping people intuitively grasp your way of thinking. The problem is that they work equally well for learning ways of thinking that work and learning ways of thinking that don’t work. They are useful when you are trying to persuade someone who already trusts you to see things your way, but they do not help to persuade people to trust you or that you know what you are talking about.

          I hope that is sufficiently constructive: I have given you specific step-by-step instructions for how to improve your presentation of your ideas, as well as, I think, identified some problems that you will have to address. I regret that you will probably have to do substantial background reading to understand what I have written above.

          (And I don’t actually want to shoot you.)

        2. 1

          Any thoughts on using the null object pattern?

          1. 1

            Supposedly C# is adding this feature in 6.0:

            See #7 here: http://damieng.com/blog/2013/12/09/probable-c-6-0-features-illustrated

            Also, here is a way to use generics and lamdas to achieve something similar in existing C#: