Question

In many languages, it is common for a function to have multiple return values (as a tuple), such as:

def foo():
    return "Hello, World!", 0

I often do this when a computationally expensive (or an often called) function calculates multiple values. For example, a function that walks through an automaton to find the state for the longest prefix of a word contained in the automaton as well as the length of the prefix. A clean way of doing this would be to write two functions get_longest_prefix(word) and get_state(prefix), but it saves quite some computation to return both in one run.

The question is, what is the general approach, (or python convention), for naming such functions. Something like get_longest_prefix_and_len mostly results in too lengthy names.

Was it helpful?

Solution

A function is named for its purpose

The question's premise, i.e. what a function's name should reflect, isn't quite right. From your comment on candied_orange's answer:

What I am not satisfied with when using a [function] name such as those you suggested is that they are not descriptive of the [data type] being returned.

Function names should not describe their return value, at least not inherently. A function should describe what the function's purpose is.

If a function inherently needed to be named after what it returns, every function (that returns something) would need to be called returnFoo, returnBar, ... Clearly, this isn't all that useful if it were the primary naming rule.

There are cases where a function has no real purpose other than returning a value which is already trivially available, at which point it can be useful to name the function after the value it returns. But it's not a blanket rule that should be blindly applied.

When a function does something and then returns the subsequent result, the primary purpose is doing something, and returning the result is just a secondary consideration (since it'd be pointless to not return your achieved result, in most cases).

Think of it this way: if you want to return multiple values, you could approach this two different ways:

  • Wrap all needed return values in a DTO class and return an instance of that class
  • Return multiple values (for languages that support it).

In either case, the method does the exact same thing. The only thing that changes is the returned type(s). Following your logic, these methods should have different names, since they're returning different types.

That doesn't make sense. The function has the exact same purpose in either case, so its name should be unchanged.

The only valid justification for picking different function names is related to overload conflicts, i.e. in case you want to implement both methods and they have the same signature.
But this is not related to the question on what you should name a function when there is no overload conflict.


A function's purpose (and thus name) is contextual

In a question that solely focuses on naming decisions, you've not really focused on the most important information: context.

a function that walks through an automaton to find the state for the longest prefix of a word contained in the automaton as well as the length of the prefix

Notice your usage of "prefix" in describing both values. This strongly indicates that your multiple return values are all prefix-related information. This leads us to understand the purpose of your function: it finds a prefix and returns information on it.

a function that walks through an automaton to find the state for the longest prefix of a word contained in the automaton as well as the length of the prefix

The primary purpose of the function is to find the longest prefix. Returning data related to that prefix is a secondary consideration.

The name of the function should reflect its primary purpose:

def findLongestPrefix():
    return "Hello, World!", 0

Note: There may be a contextual name (e.g. "prefix details", "prefix information", ...) which is already defined/understood in your domain and reflects the information that you're trying to return here. If that is the case, such a contextual name would be better than the "prefix" name I chose to use here. You have more contextual awareness than me, so adapt my suggestion accordingly.

Note: I'm not sure which language you're using (python?) and what it's casing conventions are. Adjust the casing as appropriate.


Documenting the returned values

my concern for being indicative of the data structure remains, especially for dynamically typed languages such as python

I'm aware that this probably isn't applicable to Python, but C# specifically added named tuples to ensure that developers could give each value an appropriate name which describes each individual returned value. There is a clear benefit to labeling return values (when there is more than one).

Python doesn't allow for it (AFAIK), so you're going to have to live with that. This is a design consequence of the language you chose to use.

But as much as I agree that lack of clear typing can lead to issues like these in dynamically typed languages, I disagree that you should therefore foist this return type information in the method name itself.

While not impossible, it doesn't really fix the issue. You still don't get the benefits of strong typing, the function name still needs to be read and understood by humans, and if a human needs to look it up anyway (and gets no compiler validation), then proper function documentation trumps function naming. Don't try to inject documentation in the function name.

Instead of forcing a terse bit of information in the function name, instead you should clearly document this function and what it returns.

Whether documentation comments suffice or you instead use an external documentation tool is up to you and what your company prefers to use.

a name such as get_longest_prefix_data is at least indicative that the returned type is not just a string or a state, but a structured value, so it is not misleading at all, and encourages the developer to check to documentation

If you're a developer working in a language where there is no strongly typed return value, you'd have by default check a function (or its return type) to ensure that you know what to expect it to return.

There shouldn't be a need to name functions specifically so you can remind developers to look up documentation on things they aren't yet familiar with.

OTHER TIPS

Why did you bundle the return values together in the first place? Choose a name that makes that clear.

"walked through an automaton" inspires a name like getWalkedData()

If you're tuple stays focused on the prefix getPrefixData()

You absolutely do not need a name that describes each element in the tuple. You need to remind people what the tuple is about so they don't have to keep looking inside.

... a function that walks through an automaton to find the state for the longest prefix of a word contained in the automaton as well as the length of the prefix

Or you could just write a class PrefixAutomaton that contains both the logic and the data and initializes itself appropriately.

That's not to say you must use OO for these cases - free functions may be fine. But grouping several data values with some invariants and related behaviour is the sort of situation classes were invented for.

Licensed under: CC-BY-SA with attribution
scroll top