It is also important to return values in an elegant manner.

Try to return a result at the end if the method is more than just a few lines.

The following example is a poorly structured method with many return points throughout. It is not strictly invalid, but it will become harder to maintain if more return code functionality is added.  For example, imagine if you wanted to log the value being returned:

public MobileRenderingProfile getRenderingProfile(String userAgent)  
{
    if (userAgent == null)
    {
        logger.debug("Returning null");
        return null;
    }
    String deviceId = getDeviceID(userAgent);
    if (deviceId == null)
    {
        logger.debug("Returning null");
        return null;
    }
    if (profileList.containsKey(deviceId))
    {
        logger.debug("Returning " + profileList.get(deviceId));
        return profileList.get(deviceId);
    }
    else
    {
        logger.debug("Returning " + addProfile(userAgent));
        return addProfile(userAgent);
    }
}

The code would be better structured as follows:

public MobileRenderingProfile getRenderingProfile(String userAgent)  
{
    MobileRenderingProfile profile = null;
    if (userAgent != null)
    {
        String deviceId = getDeviceID(userAgent);
        if (deviceId != null)
        {
            profile = profileList.get(deviceId);
            if (profile == null)
            {
                profile = addProfile(userAgent);
            }
        }
    }
    logger.debug("Returning " + profile);
    return profile;
}

Exception 1

For more complex methods, it isn't always convenient to return a single result at the end of a method without more complex logic, such as inside multi-layer loops.  In this case it is appropriate to allow early returns, stopping processing the method at any place.  Of course if  it can be done neatly, return at the end of the method only, but sometimes it adds too much irrelevant code to the loop to “manage” the single return point.

And another exception to the rule:

Exception 2

Another way of writing methods is to have code at the beginning that validates all the parameters that were passed in, returning an error immediately.  Once the parameters have been verified for correctness, the real work for which the method was designed can begin, its purpose not obscured by validation code or excessive nesting.  In method structures like this, it is acceptable to return early before the real processing begins, but within the processing section don't return early if it can be avoided.

Tip: Never throw an exception to pass data back from a method. Exceptions were not designed to carry a payload of data (other than the error itself)  and using them in a different manner will create an immediately maintenance problem.  Instead place values in a return data structure or change one of the passed-in data structures.  Convention is that the last parameter in the method call will contain return values if there are any.  See the [exception.message] rule for more information.

For passing more than one value back that is not an error code or a boolean success/fail flag, use the last parameter in the method, as in the following example:

public ModelAndView handleRequest(HttpServletRequest request,
                                  HttpServletResponse response)  
    throws Exception
{
    :
    streamImageToResponse(filename, response.getOutputStream());
    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
    :
}
blog comments powered by Disqus