19

People who write functions which return NULL should be moved to /dev/null.

Comments
  • 7
    but what if my function is called findByIdOrNull(string id)? :thinking:
  • 3
    @alexbrooklyn then I would fire you maybe? ;-)

    This function name means that I can supplied an id or NULL as a parameter, not that it does find something or returns null.
  • 3
    @UnmutableToday alright my example needed some more work, but are explicit mentions of null better? Or should an exception be the answer?
  • 3
    @alexbrooklyn exceptions are way better, they convey meaning. NULL has no meaning, you cannot recover because how would you decide what to do? With an exception you can recover the state, or at least fail gracefully.

    You might think NULL means False, or something failed - but in my specific example a validator returned NULL when the value was valid.

    This is insanity.
  • 1
    @UnmutableToday I completely agree with you on that one, I tried to convince some of my peers to use exceptions and not use implicit nulls as well and treat exceptional situations as exceptions :)
  • 2
    Blech, handling exceptions breaks the code apart. I'd rather have NULL returned when a resource I'm looking for isn't found, as in findById
  • 0
    @AlgoRythm you could just return an empty list, or an empty resource, look into the "null object" pattern. NULL does not mean "no result".
  • 3
    @UnmutableToday Pretty sure that null represents emptiness. It's even defined as (void*) 0; It's great because you can do checks like

    (Pseudo code)

    element = findById(2);
    if(element){
    bitch();
    }
  • 7
    I only write functions that raise an exception if they succeed, otherwise return NULL.
  • 0
    @AlgoRythm with for example the Null Object Pattern you do not need any checks, which mean less code, better to read code and less bugs. This is what you want, checks are workarounds.
  • 1
    @UnmutableToday how are null checks workarounds?

    NOP doesn't work as well for things like finding a specific value (Item by ID), can make debugging harder (Since empty objects are still objects) and often decreases performance by ALWAYS constructing an object, even in a situation where none exists.

    Plus, it goes against the already deeply rooted standards used in almost every programming language.

    So I don't subscribe to NOP.
  • 3
    @UnmutableToday Empty lists always keep me wondering: Is the resource really not available or did I query wrong?

    Codebases that default to empty lists tend to hide away bugs due to that. A missing null check at least breaks production and makes the bug visible.

    That being said: I either prefer:

    - strict exceptions explaining why nothing was found (can still be converted to empty lists to the end-user if you must) and log the issue
    - if the language allows: Option[Type] as that enforces the handling of both cases.
  • 0
    @AlgoRythm it works around the regular flow of the program, making it harder to understand.

    Why is debugging harder? NULL makes it harder, because you don't know if you got NULL because it should be returned, or because there was an problem in the type system for example. The NOP Object will tell you that the code ran like expected.

    You also do not need to construct new NOP objects, you need to create one and then you can point to it. In the worst case you use the Object Pool Pattern to make everything reusable. At the other hand the performance hit is negligible in most cases.

    It does not go against any rooted standards and even if, "We always did it that way." is no argument.
  • 0
    bool tryFindById (int of, out aThing)
  • 0
    @k0pernikus and NULL does not keep you wondering if your query was wrong, or even your code which messed up something and returned NULL instead of the proper list?

    It also does not hide any bugs at all, as long as you have unit tests which would immediately find these kinds of issues. Thats way better than breaking production don't you think?

    Exceptions in these cases are wrong, an empty list on a query is expected behaviour, not an exception.

    Option/Maybe types on the other hand are a solution.
  • 2
    @UnmutableToday NULL for not found (Nothing returned) Exception raised for improper query. It's a standard, and non-trivial part of programming.
  • 3
    @UnmutableToday Null also hides the reason of the emptyness (which is why, as stated above, I prefer exceptions).

    Unit tests only prevent the issue if you thought of all the edge cases to begin with. I don't dare to say that I manage that always. Something slips easily.

    Yet in contrast to an empty list, a missing null check might break the app. And yes, I consider crashing that a good thing! I don't see any value in not crashing or not showing error states to the end user. If something weird goes on, crash the app. (You can and still should still beautify that error to your end user, whoever that may be.)

    Why? Because I for one have wasted to many hours working around APIs that always return 200 OK and empty lists in cases of bad requests OR in cases when they were crashing internally. It is maddening as I could never tell the difference.

    The pain is real.
  • 0
    @k0pernikus if you have a test that is using a known working query and it returns an empty list, you know you broke it, that's not an edge case.

    I'm not at liberty to crash the APP our clients pay for. If there is an issue it needs to be handles in a way that allows the client to use any other feature. Thats what good software does. It is allowed to crash in the testing environment.

    I understand your pain, but a bad, broken API is not an argument
  • 1
    @AlgoRythm NULL does not mean that nothing was found, but that something has no value and no type, these are two different statements. You are confused about it like many others. This might be OK in some old languages, but in an OOP environment you should return objects, not holes in the universe.

    There is a reason the guy who invented NULL said it is a Billion Dollar Mistake:

    https://infoq.com/presentations/...

    Here is a good overview of all the issues:

    https://yegor256.com/2014/05/...

    You do you, but it's bad and one of the reasons so much software and source code is crappy.
  • 2
    Long live the Optional()!
  • 0
    I think it depends on the language and logic of the system. null means something. An error means something is wrong.
  • 0
    @Mbithy the purpose of NULL is to tell you that you read physical memory that has nothing saved in it. That can only be an issue in low level programming where you have such access.

    @Codex404 it means as much as an empty page in a book.
Add Comment