Click here to Skip to main content
13,149,756 members (82,070 online)
Click here to Skip to main content
Add your own
alternative version

Stats

34.3K views
228 downloads
16 bookmarked
Posted 17 Sep 2014

Is it Really Better to 'Return an Empty List Instead of null'? - Part 3

, 8 Jan 2015
Rate this:
Please Sign up or sign in to vote.
Part III: Empty Lists in Real Life

Table of Contents

Home

Part III: Empty Lists in Real Life

Introduction

In the previous installment, we saw why it is better to return null instead of an empty list if a function is called with 'no data' to return. For example, the following Java function ...

public static List<ICustomerOrder> getOrdersByCustomer ( String customerID )

... should return null (and not an empty list) if no orders exist for a given customer. As we saw, this reduces the risk of bad outcomes due to a bug and has other advantages.

In this part of the article series, we will look at how we use lists in real life.

When thinking about how to design or implement a piece of software, I find it often useful and illuminating to consider how things work in real life.

So, what can we say about empty lists in real life?

Do they exist?

Do they occur frequently?

Do real life examples confirm our conclusion from the previous installment?

Let's see.

Alice's Shopping List

Imagine the following story of Alice and Bob:

Alice: "Bob, could you please go to the groceries and buy some food?"

Bob: "Yes, of course!"

Alice gives Bob a shopping list.

Bob drives to the groceries. He looks at the list and sees that it is ... empty.

Alice's shopping list

Alice's shopping list

Bob drives back home and gives Alice an empty box.

Bob: "Here is the food you asked me to buy."

Alice: "Thank you darling."

What we perceive as ridiculous, stupid or funny in real life has happened (and will happen) billions of times in the world of software execution. It happens every time (in avoid-null environments) a function returns an empty list (instead of null) to denote 'no data'.

One might argue that handling an empty list in software doesn't consume considerable time and resources - in contrast to Bob who spent time and used his car. It is true that the time and resources needed to handle an empty list is negligible in many cases. Nevertheless, there is a time and space penalty, and the consequences can be dreadful. Just imagine a worst case scenario of a network connection that must be established and data that has to be exchanged between computers to handle an empty list. And then, once in a while, there might be a network connection failure which leads to a total system crash because the operation 'do nothing' could not be executed. This would be similar to Bob having a car engine breakdown (or something worse happening) when he drives to the groceries to 'buy nothing'.

On the other hand, as we saw in the previous installment, null is always cheap in terms of time and space.

Bob's Postage Stamps

Here is another real-life example:

Bob collects postage stamps.

Alice doesn't collect postage stamps.

Bob has a box labelled 'Postage stamps' containing his stamps.

Does this mean that Alice has an empty postage-stamps-box because she doesn't collect postage stamps?

No, of course not! She simply doesn't have a box for stamps.

Just imagine everybody in the world had an empty box for everything he/she doesn't collect. Weird!

So, what should getPostageStamps in the following Java interface return if a person doesn't collect stamps? An empty list or null?

interface IPerson {

   public String getName();
   // ... more attributes

   public List<IPostageStamp> getPostageStamps();
}

Returning an empty list is like Alice having an empty box.

Returning null is like Alice having no box at all.

[Note]Note

In languages that support the Optional/Maybe pattern, an alternative solution would be to always return a non-null Optional or Maybe object. The basic idea of the Optional/Maybe pattern is this:

Instead of providing a non-null value or null, always provide a non-null container object that either contains a value or doesn't contain a value.

Please refer to my previous article Why We Should Love 'null' (chapter 'The Optional/Maybe Pattern') for a discussion of this solution.

Is this pattern popular in real life? I don't think so. Just imagine an application of this pattern in our example. Alice doesn't collect stamps. Therefore she has a box that contains ... nothing. Bob collects postage stamps. So, he has a box that contains a box that contains postage stamps.

Customers in Luxembourg

Suppose we have the following method to get a list of customers by city:

public static List<ICustomer> getCustomersByCity ( String city ) {
   // code to retrieve customers from database and return the result
}

What should this method return if there are no customers in the database for a given city?

If we read through the many forums that discuss this kind of question, we can see that we typically get the following three different answers, sorted by popularity (the first one being the most popular one):

  1. The method should return an empty list
  2. The method should return null
  3. The method should throw an exception

Another important question is this: How should this method behave in case of a resource error such as a database connection error at runtime? Again, depending on who you ask, you'll get different answers.

To find the correct answers, let us think about how such a case would be handled in real life.

Imagine:

Big boss to assistant: "I need a list of all our customers in Luxembourg. Could you do that for me please?"

The assistant obliges. His or her task is to launch a query in the company's ERP software in order to print out a list of customers in Luxembourg.

There are three possible outcomes:

  1. The company has customers in Luxembourg:

    The assistant prints out the list and hands it over to the boss.
  2. The company doesn't have customers in Luxembourg:

    The assistant tells his or her boss: "We don't have customers in Luxembourg".

    Important: Under normal conditions, the assistant wouldn't give an empty, white piece of paper to the boss to signal the fact that there are no customers, would he?

  3. The assistant can't execute the query because of a technical problem (for example: he forgot his password (because he changed it in the morning (but forgot to write it down on a post-it that is kept at a secret place (i.e. stuck on the front of his desktop monitor)))):

    The assistant tells his boss "Sorry, I couldn't print the list because ...".

Now the correct answers to our software design questions become pretty much obvious, don't they?

  1. No need to discuss the first case. If there are customers in Luxembourg, then getCustomersByCity returns a non-empty list.

  2. If we model the real world, then we obviously return null in case 2 (no customers in Luxembourg). Returning an empty list would be like the assistant handing over an empty piece of paper to his boss. Nobody would do this in real life - it wouldn't make sense, at least not under 'normal' conditions.

    And there is no need to do it in software, unless we have a very good reason to do so.

    For example, imagine that the boss really needs a piece of paper, even if there are no customers. He/she wants a document like this one ...

    ... as a 'proof' to be filed somewhere.

    If we want to model this, we might be tempted to actually return an empty list. But a better solution would be to return a non-null object implementing the following Java interface:

    interface ICustomerByCityReport {
    
       public String getCity();
    
       public Date getDateOfReport();
    
       public List<ICustomer> getCustomers();
    }

    In case of no customers for a given city, the method would return a non-null ICustomerByCityReport object with getCustomers() returning null.

  3. Case 3 (i.e. the operation couldn't be executed because of a technical problem) is less obvious. Should we simply return null? No! Because that would be like the assistant telling his boss: "There are no customers in Luxembourg.". Obviously, the information "There are no customers in Luxembourg." is semantically very different from "I couldn't print the list because of a technical problem. I can't tell you if we have customers in Luxembourg or not". This is an important distinction for the boss, and only he/she can decide what to do. The same is true for client code that calls getCustomersByCity. The information "there was a technical problem" must be forwarded to the client and it is the client's role to decide what to do.

    How to do this depends on the programming language we use.

    In languages that support an exception mechanism (C#, Java, etc.), we would throw an exception if the data cannot be retrieved from the database (e.g. connection to database could not be established).

    In other languages (e.g. languages that support multiple output arguments or tuples) we might return two values - the first one being the result and the second one being the error. The following return states are then possible:

    • The operation succeeded and results were found: result holds a (non-empty) list and error is null

    • The operation succeeded but no results were found: result and error are null

    • The operation could not be executed: result is null and error contains an object describing the error

Empty Lists in Real Life

If we look around us in the physical world, we can quickly see that empty lists are very rare in real life. Most often, we either have a non-empty list or we have no list at all. For example, you might have a to-do list. If you have one, it is probably (like mine) not empty.

However, it is obvious, but also interesting to note that empty lists occur each time we start to create a non-empty list.

Imagine Alice jotting down a shopping list for Bob:

  1. She takes a piece of paper which is empty - an empty list.
  2. She writes down all the items to buy. At the end, the list is non-empty. Moreover, during the writing process, the list is mutable - items are added (and some might be removed or modified).
  3. Once the list has been created, it becomes immutable - the list doesn't change anymore.

This is how we typically proceed in real life. And this reflects exactly how we should proceed in software. Here is a trivial example in Java:

public static List<String> getShoppingList() {

   // 1. create a mutable empty list
   List<String> result = new ArrayList<String>();

   // 2. populate the list      
   result.add ( "Almonds" ); 
   result.add ( "Coconut oil" );
   result.add ( "Avocado" );
   result.add ( "Blueberries" );

   // 3. return an immutable, non-empty list
   return Collections.unmodifiableList ( result );
}

Conclusion

Immutable empty lists are very rare in real life. Normally, we either have a non-empty list or there is no list at all.

The corollary is that we shouldn't use immutable empty lists in our software applications, unless there is an exceptional case. This matches our conclusion from the previous installment and confirms that it is generally better to return null instead of an empty list.

In the next installment, we will look at real-world source code examples. We will have a look at typical cases that happen frequently in practice. And we will see how to treat exceptional situations, such as invalid input argument values and resource errors.

Links to Related Articles

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

Share

About the Author

ChristianNeumanns
Software Developer PPL
Thailand Thailand
I am a passionate programmer still dreaming of 'number of bugs: 0'

http://www.practical-programming.org

You may also be interested in...

Comments and Discussions

 
GeneralNull lists are not empty lists. Pin
brianmfear9-Feb-17 5:02
memberbrianmfear9-Feb-17 5:02 
GeneralMy vote of 2 Pin
Erik Funkenbusch26-Jan-15 6:06
memberErik Funkenbusch26-Jan-15 6:06 
GeneralRe: My vote of 2 Pin
ChristianNeumanns27-Jan-15 21:26
memberChristianNeumanns27-Jan-15 21:26 
GeneralRe: My vote of 2 Pin
Erik Funkenbusch28-Jan-15 6:07
memberErik Funkenbusch28-Jan-15 6:07 
GeneralRe: My vote of 2 Pin
Erik Funkenbusch7-Feb-15 14:45
memberErik Funkenbusch7-Feb-15 14:45 
General[My vote of 1] Bad advice - wrong solution for the problem. Pin
mrcellux25-Jan-15 9:03
membermrcellux25-Jan-15 9:03 
GeneralRe: [My vote of 1] Bad advice - wrong solution for the problem. Pin
ChristianNeumanns27-Jan-15 21:13
memberChristianNeumanns27-Jan-15 21:13 
GeneralRe: [My vote of 1] Bad advice - wrong solution for the problem. Pin
mrcellux28-Jan-15 1:08
membermrcellux28-Jan-15 1:08 
QuestionThis is absurd.. Pin
Member 104333329-Jan-15 15:14
memberMember 104333329-Jan-15 15:14 
AnswerRe: This is absurd.. Pin
ChristianNeumanns9-Jan-15 21:20
memberChristianNeumanns9-Jan-15 21:20 
GeneralRe: This is absurd.. Pin
Timothy R10-Jan-15 5:56
memberTimothy R10-Jan-15 5:56 
GeneralMy vote of 1 Pin
Malte Klena9-Jan-15 7:04
memberMalte Klena9-Jan-15 7:04 
GeneralRe: My vote of 1 Pin
ChristianNeumanns9-Jan-15 21:07
memberChristianNeumanns9-Jan-15 21:07 
QuestionShopping List Poor Example Pin
DevKnightlie9-Jan-15 3:24
memberDevKnightlie9-Jan-15 3:24 
AnswerRe: Shopping List Poor Example Pin
ChristianNeumanns9-Jan-15 21:00
memberChristianNeumanns9-Jan-15 21:00 
GeneralMy vote of 3 Pin
DeltaEngine9-Jan-15 1:54
professionalDeltaEngine9-Jan-15 1:54 
GeneralRe: My vote of 3 Pin
ChristianNeumanns9-Jan-15 20:53
memberChristianNeumanns9-Jan-15 20:53 
SuggestionNo links to 4th article Pin
Ricky Rick6-Jan-15 10:57
memberRicky Rick6-Jan-15 10:57 
GeneralMy vote of 2 Pin
Elrond19-Nov-14 6:34
memberElrond19-Nov-14 6:34 
GeneralRe: My vote of 2 Pin
ChristianNeumanns18-Dec-14 20:43
memberChristianNeumanns18-Dec-14 20:43 
GeneralMy vote of 2 Pin
wout de zeeuw13-Nov-14 3:54
memberwout de zeeuw13-Nov-14 3:54 
QuestionIt's not really about lists. Pin
wout de zeeuw13-Nov-14 3:39
memberwout de zeeuw13-Nov-14 3:39 
GeneralRe: It's not really about lists. Pin
PIEBALDconsult13-Nov-14 3:46
protectorPIEBALDconsult13-Nov-14 3:46 
AnswerRe: It's not really about lists. Pin
ChristianNeumanns16-Nov-14 17:44
memberChristianNeumanns16-Nov-14 17:44 
QuestionBad advice based on wrong interpretation of examples Pin
icokk89-Nov-14 4:39
membericokk89-Nov-14 4:39 
AnswerRe: Bad advice based on wrong interpretation of examples Pin
ChristianNeumanns9-Nov-14 21:22
memberChristianNeumanns9-Nov-14 21:22 
GeneralRe: rethink your arguments Pin
Ricky Rick3-Jan-15 11:38
memberRicky Rick3-Jan-15 11:38 
GeneralRe: rethink your arguments Pin
ChristianNeumanns4-Jan-15 18:08
memberChristianNeumanns4-Jan-15 18:08 
GeneralPrinciple Pin
Alexandru Lungu22-Sep-14 5:17
memberAlexandru Lungu22-Sep-14 5:17 
GeneralRe: Principle Pin
ChristianNeumanns22-Sep-14 23:56
memberChristianNeumanns22-Sep-14 23:56 
GeneralRe: Principle Pin
mrcellux23-Jan-15 12:12
membermrcellux23-Jan-15 12:12 
GeneralRe: Principle Pin
Alexandru Lungu24-Jan-15 9:32
professionalAlexandru Lungu24-Jan-15 9:32 
GeneralRe: Principle Pin
mrcellux24-Jan-15 9:58
membermrcellux24-Jan-15 9:58 
GeneralRe: Principle Pin
Alexandru Lungu25-Jan-15 2:17
professionalAlexandru Lungu25-Jan-15 2:17 
GeneralRe: Principle Pin
mrcellux25-Jan-15 5:01
membermrcellux25-Jan-15 5:01 
GeneralRe: Principle Pin
Alexandru Lungu26-Jan-15 3:24
professionalAlexandru Lungu26-Jan-15 3:24 
GeneralRe: Principle Pin
mrcellux31-Jan-15 9:10
membermrcellux31-Jan-15 9:10 
QuestionClose, but not quite. Pin
Alexander Wieser19-Sep-14 14:24
memberAlexander Wieser19-Sep-14 14:24 
AnswerRe: Close, but not quite. Pin
ChristianNeumanns21-Sep-14 18:05
memberChristianNeumanns21-Sep-14 18:05 
GeneralRe: Close, but not quite. Pin
Alexander Wieser22-Sep-14 7:12
memberAlexander Wieser22-Sep-14 7:12 
GeneralRe: Close, but not quite. Pin
ChristianNeumanns23-Sep-14 0:20
memberChristianNeumanns23-Sep-14 0:20 
GeneralRe: get or getDeliveryDate is a bad example here Pin
Ricky Rick4-Jan-15 11:03
memberRicky Rick4-Jan-15 11:03 
AnswerRe: Close, but not quite. Pin
wout de zeeuw13-Nov-14 4:02
memberwout de zeeuw13-Nov-14 4:02 
GeneralMy vote of 1 Pin
Jorge Lalinde18-Sep-14 21:50
memberJorge Lalinde18-Sep-14 21:50 
GeneralRe: My vote of 1 Pin
ChristianNeumanns19-Sep-14 0:44
memberChristianNeumanns19-Sep-14 0:44 
GeneralRe: My vote of 1 Pin
Sinisa Hajnal14-Oct-14 20:32
memberSinisa Hajnal14-Oct-14 20:32 
GeneralRe: My vote of 1 Pin
Jorge Lalinde30-Oct-14 2:22
memberJorge Lalinde30-Oct-14 2:22 
GeneralRe: My vote of 1 Pin
den2k8830-Oct-14 1:50
memberden2k8830-Oct-14 1:50 
GeneralRe: My vote of 1 Pin
Jorge Lalinde30-Oct-14 2:10
memberJorge Lalinde30-Oct-14 2:10 
GeneralMy vote of 2 Pin
merlin98118-Sep-14 15:26
membermerlin98118-Sep-14 15:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170924.2 | Last Updated 8 Jan 2015
Article Copyright 2014 by ChristianNeumanns
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid