Let's step back and use a different example which computes the arithmetic mean of an array of values.
If the input array is empty (or null), can you reasonably fulfill the caller's request? No. What are your options? Well, you could:
- present/return/throw an error. using your codebase's convention for that class of error.
- document that a value such as zero will be returned
- document that a designated invalid value will be returned (e.g. NaN)
- document that a magic value will be returned (e.g. a min or max for the type or some hopefully-indicative value)
- declare the result is unspecified
- declare the action is undefined
I say give them the error if they have given you invalid input and the request cannot be completed. I mean a hard error from day one so they understand your program's requirements. After all, your function is not in a position to respond. If the operation could fail (e.g. copy a file), then your API should give them an error they can deal with.
So that can define how your library handles malformed requests and requests which may fail.
It's very important for your code to be consistent in how it handles these classes of errors.
The next category is to decide how your library handles nonsense requests. Getting back to an example similar to yours -- let's use a function which determines whether a file exists at a path:
bool FileExistsAtPath(String). If the client passes an empty string, how do you handle this scenario? How about an empty or null array passed to
void SaveDocuments(Array<Document>)? Decide for your library/codebase, and be consistent. I happen to consider these cases errors, and forbid clients from making nonsense requests by flagging them as errors (via an assertion). Some people will strongly resist that idea/action. I find this error detection very helpful. It is very good for locating issues in programs -- with good locality to the offending program. Programs are much clearer and correct (consider evolution of your codebase), and don't burn cycles within functions which do nothing. Code's smaller/cleaner this way, and the checks are generally pushed out to the locations where the issue may be introduced.