Correct handling of return data [closed]
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this questionI 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 functio开发者_开发知识库n 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?
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.
- null. But method
getCustomer()
should return Customer. If it returns String it should be probably calledgetCustomerName()
orgetCustomerId()
- empty list
- throw exception. Probably wrap it with application-layer exception.
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
Since it's your API, any approach is good as long as you are consistent and make sure that it is documented properly.
For 1 & 2: Just take note though, that returning nulls will force client code to keep on performing checks like the following:
result = yourAPICall();
if(result != null){
// do something
}
Which is why I prefer returning empty objects or collections
For 3: That will depend on your APIs design. But first, never throw low level exceptions up the call stack. You should wrap them in an custom exception class designed for your API so that your client code will only need to catch your API exceptions rather than a variety of lower level ones (SQLException, IOException etc...)
Second, you must decide if there is any benefit for the exception to be thrown in the first place. Throwing an exception allows client code the ability to customize how it wants to the handle problems encountered by its API dependencies. But throwing it also prohibits you as the API designer from designing internal contingencies that will allow your code to perhaps recover from the problem (makes your API less robust)
精彩评论