On 10/02/2016 15:41, Emil Dotchevski wrote:
This sort of thing could be a good argument for "degrees of success", where eg. the above delete call returns success in both cases but can also indicate that the file was already missing and it did nothing. (Which is trivial in this case since it can be done with a simple bool return value, but you can probably imagine other cases where it might make sense to return both a T and a non-error status value of some kind.)
Assuming the correct postcondition for delete_file is "the file does not exist", and assuming that knowing if the file existed is either important or trivial for delete_file to detect, the correct interface of that function is:
//Postconditions: the specified file does not exist. //Returns: true if the file was actually deleted, false if it did not exist //Throws: delete_file_error bool delete_file( char const * name );
This is not "degrees of success", as the condition in which the file did not exist is not an error.
As I said, that was a trivial case. For a less trivial case, imagine a function that fills in a variable-size data structure, but can also indicate that some of it was truncated and supplying a larger buffer would get a more complete result. (Sort of like strncpy, but more complex.) Or a cursor enumeration function that wants to simultaneously return a pageful of data and how many records are left unreported, so these don't have to be checked separately, but the latter could be ignored in contexts where it's not interesting. Of course, these can be handled by making a larger return type T (perhaps as a tuple), but this implies they have equal weight, which is not necessarily the case. It's also brittle if a future version of the method wants to add more information. Having said that, I'm not entirely sure where I was going with this topic. I might be rambling a bit.