in reply to Re: return from subfunction
in thread return from subfunction

Depends. This code is in my "Common.pm" module which I keep common subroutines I write. So anything under the sun I suppose.

If it helps answer your question, the subroutine takes in a folder and a file. It returns various statuses depending on if the folder is writeable, readable, the combined path is used, not used... you get the idea.

Replies are listed 'Best First'.
Re^3: return from subfunction
by BrowserUk (Patriarch) on Apr 07, 2011 at 19:07 UTC
    It returns various statuses depending on if the folder is writeable, readable, the combined path is used, not used... you get the idea.

    So the negative failure values mean readable or writable etc? What does the successful string represent?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      The successful string is the full path with the folder and the file name provided combined. The negative values, as you said, provide states when the combined path is not useable. Some states are: folder provided doesn't exist, folder isn't writable, folder isn't readable, filename in the folder already exists, and whatever else I thought up of (pretty sure that's it though. I wasn't that inventive).

      I appreciate you getting to know my code, however, I suspect the answer you are about to provide may be specific to this scenario. While that would be appreciated and taken into consideration, I would also like an answer to the question in the general sense as well. Any help, tip, or lesson is appreciated frankly.
        however, I suspect the answer you are about to provide may be specific to this scenario.

        In general, my answer is: Don't return error codes. Either: return undef or an empty string for failure; or better: just die or Carp::croak().

        My reasoning comes back to my first question. What are you going to do with the error codes?

        There are essentially only 3 things you can do with exceptional circumstances .

        1. Abort the program.

          If there is nothing that you can do to recover, and so must die, there is no point in converting the error conditions into error codes within the routine, only to have the calling code (at every place the routine is called!) have to convert those error codes back to meaningful error messages in order to report them. (Whether to the terminal or log.)

        2. Abandon the operation.

          That is, the program continues to run, but this particular operation is abandoned and the program returns to some previous known-good state.

          For the most part, the caller doesn't need to know what went wrong, only that something went wrong. A simple boolean return (undef or '') indicates this just as well and more easily. But even this complicates the calling code more than catching an exception.

          In addition, the immediate calling code can choose to ignore the possibility of exceptions and push the resposibility of hadnling them to its caller when that makes sense.

        3. Attempt recovery.

          Under some, usually very limited circumstances, recovery may be possible. An example might be an interactive program (CLI or GUI or WUI (web user interface), where the subroutine is validating user input.

          Again, the exception model simplifies the calling code, because you can return the error text from the the die to inform the user of the problem, rather than having to convert the error code back to a meaningful message at every call site.

        The error code return model made some sense in C and similar languages when exception handling wasn't available. But it imposes clumsy, verbose error handling code at every call site that detracts and distracts from the normal (non-exceptional) flow of operations. It also tends to get "overlooked" when the pressure is on, and is a bitch to debug when it does bite.

        The exception handling model (used properly):

        • moves the exception handling out of the main flow of the code.
        • whilst ensuring that when exceptions occur, if they haven;t been handled, they become hard failures with trace back to the exact site of the problem. Rather than allowing unhandled error conditions to migrate silently through the code-base until some (often seemingly unrelated) hard error occurs.

        By writing your subroutines to die (or better Carp::croak()), when given garbage input, you both simplify the calling code and ensure that exceptional circumstances are either dealt with by the caller, or at least some meaningful error message is reported when the occur and are not handled.

        Basically, error codes are just an level of indirection that serves no good purpose.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.