Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct handling of return data [closed]

I have a question related to correct handling of returns of the DAO library I'm writing for one project. This library probably is going to be used by another people, and I want to do it correctly. How I should deal with return statements of the functions of my DAO?

Example 1 I have function to getCustomer which should return String. In case a query doesn't return any result should I return null, an empty string or throw some kind of exception?

Example 2 I have a function, getCutomerList, which returns a value of type ArrayList<String>. In case a query doesn't return any result should I return null, an empty ArrayList or throw some exception?

Example 3 Some SQL exception was detected, what should I do, throw exception or do try..catch of the block where it can occur?

What is the "good" practice or "best" practice to apply in my case?

like image 710
Serhiy Avatar asked Feb 07 '11 14:02

Serhiy


3 Answers

It seems your library is doing database-like calls. If that is the case, then I would do exactly what is implemented by the JPA 2 specification.

What I mean by that is, look at the find() method in JPA API and return exactly what they are doing there.

    /**
     * Find by primary key.
     * @param entityClass
     * @param primaryKey
     * @return the found entity instance or null
     *    if the entity does not exist
     * @throws IllegalStateException if this EntityManager has been closed.
     * @throws IllegalArgumentException if the first argument does
     *    not denote an entity type or the second
     *    argument is not a valid type for that
     *    entity's primary key
     */
    public <T> T find(Class<T> entityClass, Object primaryKey);

You see here in find, which I think is similar to your getCustomer() method, it will return null if none is found, and only throwing IllegalArgumentException if the argument is invalid.

If the find() method is not close to what you want with getCustomer() you should implement the same behavior as getSingleResult():

    /**
     * Execute a SELECT query that returns a single result.
     * @return the result
     * @throws EntityNotFoundException if there is no result
     * @throws NonUniqueResultException if more than one result
     * @throws IllegalStateException if called for a Java 
     *    Persistence query language UPDATE or DELETE statement
     */
    public Object getSingleResult();

Which will throw EntityNotFoundException if no result is found, NonUniqueResultException if multiple instances are found or IllegalStateException if the SQL is wrong.

You have to decide which behavior is most suitable for you.

The same goes for getResultList():

/**
 * Execute a SELECT query and return the query results
 * as a List.
 * @return a list of the results
 * @throws IllegalStateException if called for a Java 
 *    Persistence query language UPDATE or DELETE statement
 */   
public List getResultList();

getResultList() will return null if none is found and only throwing exception if the SQL is illegal.

By following this behaviour, you are being consistent, and your users will get a feeling of knowing how the library is.


An alternate behavior is to return an empty collection instead of null. This is how Google Guava have implemented their API, and which is really the preferred why. However, I like consistency, and still think you should implement the library as close to the standard as possible.


Resources

Joshua Bloch made a video explaining how to design a good API and why it matters.

like image 164
Shervin Asgari Avatar answered Nov 15 '22 23:11

Shervin Asgari


  1. null. But method getCustomer() should return Customer. If it returns String it should be probably called getCustomerName() or getCustomerId()
  2. empty list
  3. throw exception. Probably wrap it with application-layer exception.
like image 33
AlexR Avatar answered Nov 15 '22 22:11

AlexR


Example 1: Since nothing is retrieved, null should be returned. Alternatively, Null-Object pattern can be a choice.

Example 2: Prefer empty ArrayList to null. See "Effective Java" Item 43: Return empty arrays or collections, not nulls

Example 3: Translate the SQLException to higher Exception and throw it. See "Effective Java" Item 61: Throw exceptions appropriate to the abstract

like image 22
卢声远 Shengyuan Lu Avatar answered Nov 15 '22 23:11

卢声远 Shengyuan Lu