1

Is this right?

Example code:

void foo(E param){

    if(param == null){
        // do this
    }else{
        // do that
    }
//...
}

First of all I read some posts where people where discussing about allowing variables to be null adds complexity to the software Best explanation for languages without null so I would like to make and effort and forget about this to try to answer this question.

The thought (My thought)

As a beginner my thought might be wrong but i Would like you to help me clear this up.

I think checking if a variable is null is correct depending on the context in which that variable is, let me explain with an example:

Bad use:

Our project have the Command pattern implemented and we have a set of instructions. Then we write in the console an instruction and we have to interpret it. We have an Interpreter Class which tries to parse that so if the interpreter cant find the appropiate instruction it returns null.

Code example:

public class Interpreter {

    public static final String LINE_SEPARATOR = System.getProperty("line.separator");
    private static final List<Instruction> listInstructions = loadInstructions();


    /**
     * Generates a new instruction according to the user input
     * @param line - A string with the user input
     * @return The instruction read from the given line. If the instruction is not correct, then it returns null.
     */
    public static Instruction generateInstruction(String line) throws WrongInstructionFormatException
    {
        Instruction instru = null;
        Iterator<Instruction> it = listInstructions.iterator();
        int i = 0;
        while(it.hasNext() && i <9 && instru == null)
        {
            try
            {
                instru = it.next().parse(line);
            }
            catch(WrongInstructionFormatException e)
            {

            }
            finally
            {
                i++;
            }
        }
        return instru;
     }
//...




public class MainClass
{
    /**
     * MainFunction
     */
        public void mainFuction()
        {

            Instruction instru;
            while(true)
            {
                instru = Interpreter.generateInstruction(orden);
                if(instru == null) <------
                    // Error.
                else
                    instru.execute();

            }

        }
  }

Well in this case I think we are implementing this wrong because the interpreter must not return null but an exception because in my opinion a variable in this context could never be null. I hope I'm being clear, if it is not then I would like to clarify later with your comments

Correct use: (EDITED)

The main class of our project has a set of attributes from which both can be instantiated or not. Depending on whether we have instantiated one, both or neither there will be a set of functions to perform one, two or no action.

public class MainClass extends Observable
{
    private A a;
    private B b; // This attribute allows you to start making a log in a txt file
    private C c; // This attribute allows you to start making a log in a DB

    public MainClass(A a){ //....}
    public MainClass(A a, B b) { // .....}
    public MainClass(A a, C c) { // .....}
    public MainClass(A a, B b, C c){ //.....}


    public void log(String update)
    {
        if(this.b != null) <-----
            // Save the update in the txt file
        if(this.c != null) <-----
            // Save the update in a db row
    }
}

Well, why is this right? I think is right because the attributes may have null value and not as in the previous case.


With this begins the discussion and I would like it to help other people if they had the same doubt.

Community
  • 1
  • 1
Jesus
  • 1,116
  • 3
  • 10
  • 17
  • 4
    If it could be null then check if its null. Exceptions vs nulls is a matter of opinion and style when the situation is recoverable – Richard Tingle Sep 24 '13 at 14:42
  • What's striking about your examples is that your first one is quite concrete, and you conclude that it would be better to throw an exception, whereas your second is rather vague, and you do not come to that conclusion. It would be interesting to work out your second example in more detail, and see if you still think that. – Tom Anderson Sep 24 '13 at 14:43
  • 1
    There are two cases for **not** checking an incoming reference argument for null: (1) You have complete control of all callers, and have ensured the actual argument is never null, or (2) there is nothing you could do about a null more helpful than throwing a NullPointerException from wherever the reference is first used as a pointer. – Patricia Shanahan Sep 24 '13 at 14:45
  • also, if you do: `if (null != someVar)` and/or `if ("".equals(someVar))` you can avoid a `NPE` – SnakeDoc Sep 24 '13 at 14:45
  • Okey im going to work in the second example right now. – Jesus Sep 24 '13 at 14:45
  • @SnakeDoc: `if (null != someVar)` is no different to `if (someVar != null)`. Neither will throw a NullPointerException. – Tom Anderson Sep 24 '13 at 14:48
  • @TomAnderson my mistake, use it for checking empty strings to avoid the NPE, thanks for the correction. – SnakeDoc Sep 24 '13 at 14:49

3 Answers3

3

The advice about nulls isn't not to check for them, but not to generate or allow them. Obviously, if you have nulls in your program, you will need to check for them.

In your second example, the way to follow the advice would be to find a way to implement your class so that it doesn't have nullable fields. Why does the class have optional attributes? What does it do with these attributes? Is there a way to structure the class (perhaps by breaking it into multiple classes) so that it does not have optional attributes?

In the second example, you are using the nullity of attributes in if tests. A standard thing to do in object-oriented design is to replace conditionals with polymorphism. Could you try that?

EDIT: Okay, here's how i'd solve the second case using polymorphism. I have removed the field a because it's not relevant in this case.

public class MainClass extends Observable {
    private final Collection<? extends LogDestination> logDestinations;

    public MainClass() {
        logDestinations = Collections.emptySet();
    }

    public MainClass(B b) {
        logDestinations = Collections.singleton(new TextFileLog(b));
    }

    public MainClass(C c) {
        logDestinations = Collections.singleton(new DatabaseLog(c));
    }

    public MainClass(B b, C c) {
        logDestinations = Arrays.asList(new TextFileLog(b), new DatabaseLog(c));
    }

    public void log(String update) {
        for (LogDestination logDestination : logDestinations) {
            logDestination.log(update);
        }
    }
}

interface LogDestination {
    public void log(String update);
}

class TextFileLog implements LogDestination {
    private final B b;

    public TextFileLog(B b) {
        this.b = b;
    }

    @Override
    public void log(String update) {
        // Save the update in the txt file
    }
}

class DatabaseLog implements LogDestination {
    private final C c;

    public DatabaseLog(C c) {
        this.c = c;
    }

    @Override
    public void log(String update) {
        // Save the update in a db row
    }
}

In abstract terms, what this is doing is pushing the only alternatives in the logic all the way up into the constructors, in the form of the choice of which LogDestinations to create. Once they're created, they can be treated completely uniformly, with polymorphism dispatching the general invocation to the specific method. Because there are different constructors for the different ways of setting up the object, there is no need for any conditional logic at all.

Tom Anderson
  • 46,189
  • 17
  • 92
  • 133
  • I have doubts , imagine that my main class attributes are for save the software logs. I can save or not save the information in the db or text file or neither. How should I implement this with polymorphism? Actually I would implement it as in the second example, What is your advice? – Jesus Sep 24 '13 at 15:26
  • So in this example, what are the attributes? A log file name and a database URL or something? – Tom Anderson Sep 24 '13 at 16:07
  • The attributes are references to clases which do the job, calling X methods. – Jesus Sep 24 '13 at 17:22
  • Apologies for the delay, but i have got round to showing how to do this. – Tom Anderson Sep 28 '13 at 20:44
  • No problem, thanks for this, I've done something similar to solve other problems but didn't see how to apply here – Jesus Sep 29 '13 at 20:06
2

When it's a situation that is expected and/or recoverable, throwing an Exception vs returning null is almost entirely a question of style. The arguments you've laid out are good ones for a distinction, and if they make sense to you, then I say go for it.

That's not to say you should use Exceptions as a go-to flow-control tool, of course, but in situations like the one you're describing it sounds perfectly reasonable.

Henry Keiter
  • 16,863
  • 7
  • 51
  • 80
  • It's more than style. Throwing an exception has performance implications. It's better to avoid it in anticipated situations. – pamphlet Sep 24 '13 at 14:49
  • @pamphlet Unless you're using Exceptions as flow-control tools inside a loop or something, the performance implications ought to be negligible. I can't picture a non-contrived example where the performance difference is particularly meaningful. Besides, Java has Checked Exceptions precisely for "anticipated situations"--hence my claim that this is largely a matter of style rather than cut-and-dry correctness. – Henry Keiter Sep 24 '13 at 14:57
  • I would argue that exceptions are for "exceptional situations". There are many performance critical applications that need to process 10k or 100k transactions per second (financial, medical imaging, online gaming, smart metering, etc.). If any significant percentage of these were throwing transactions, I believe the impact would be significant. I'm really just arguing for conventions that scale well. – pamphlet Sep 24 '13 at 15:15
1

I have a program that has over 2000 classes. Assuming around 20 functions per class, that's 40,000 functions. A lot of them have only a few lines of code each (example: get/set functions). If each function checked for null arguments, etc, that's a lot of code devoted just to validation (a similar argument can be made for a lot of exceptions being handled). Also, if I were to check just for nulls, I might as well do full validation to ensure the (javadoc) contract is fulfilled. For example, iterating over a list of objects that is passed to the function, checking for nulls, range issues, etc. Note there will be performance issues with that approach.

Instead, I prefer to have an agreed upon policy that applies to the entire project that no functions are allowed to have null for arguments, or a return value that is null, unless specified in its javadoc (design by contract). It's the caller's responsibility to obey the (javadoc) contract and do any validation checks before calling my function. However, I would consider validation checks for constructors that take more than one argument (to ensure incomplete objects are not created), and a few functions that are overly complex on how they process the input arguments. Note the immediate caller of my function doesn't have to do the validation checks just before calling my function. Instead, at least one of the other functions somewhere along the call chain will need to do it. Note: I see on-line there is a lot of debate on the proper way to handle all this.

user2810910
  • 279
  • 1
  • 2