Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to document return value of function that calls another function

Tags:

Given the following example:

/**
 * An outer function
 * @param {number} age - The age to pass to outerFunction
 * @returns {#What goes here?#}
 */
function outerFunction(age){
    return addTen(age)
}

/**
 * Adds 10 to the age
 * @param {number} age - The age to add 10 to
 * @returns {number} - The age + 10
 */
function addTen(age){
    return 10 + age
}

the outerFunction returns another function's result.

I thought of several ways to document this:

  • @returns {number} - We know that addTen returns a number, but what if this changes? We will have to update both (or each time it is returned, which could be a lot), which isn't maintainable.

  • @returns {function} - I am not sure if this is available in JsDoc. I couldn't find it anywhere. This also doesn't feel like it gives much information.

  • @returns {any} or - @returns {*} - This isn't particularly helpful to anyone reading the doc.

None of these feel correct to me for the reasons stated.

I guess I want something like

@returns {addTen.return}

So that I am essentially saying "outerFunction returns whatever type addTen does".

Note: these are in the same place in this example, but could be contained in multiple files, so using this approach doesn't work, unless it's possible to do this across multiple files.

How do we write JsDoc comments to document that the function returns another function?

Does something similar to my suggestion exist?

like image 960
Matt Lishman Avatar asked May 10 '16 10:05

Matt Lishman


1 Answers

The caller of outerFunction will have certain expectations of what that function accepts as arguments and what it will return. The caller of outerFunction does not care what outerFunction does, only that its interface works as described. The caller of outerFunction does not know or care nor should they care that some function called addTen is involved in anything outerFunction does. In fact, someday you may rewrite the entire implementation of outerFunction to not call addTen anymore, but keep it behaving exactly the same way.

Treat every function individually as a black box. You're describing the interface of outerFunction, so describe what it does/is supposed to do. Don't describe it in terms of some other function which may or may not be related. If outerFunction is expected to return a number, describe it as such. If addTen also happens to return a number, well, what a coincidence.

I understand the impetus to want to implicitly tie the return value of one function to that of another, because that's how it's actually implemented, and you know... DRY and all... But in this case that's counter productive. It doesn't matter that you "repeat" the "same information" about the return type on two different functions; because you're not describing a connected thing. Both functions are independent black boxes with their own specific signature; that their implementation happens to be coupled is irrelevant for that, and may in fact change tomorrow. What is important is that the signature stays as described.

In fact, if addTen did change its return type (and implicitly so did outerFunction), that would be a big deal anyway that's not just going to blow over by implicitly updating some documentation. By changing the return type of any function, you're breaking a previously established contract, which will have a cascade of effects to every user of that function. Implicitly and automatically updating the return type of outerFunction is the least of your worries in such a scenario, as you might have to rewrite large swaths of code to conform to the new contract.

like image 81
deceze Avatar answered Sep 28 '22 02:09

deceze