Search code examples
performancefunctionparameterscoding-stylestandards

Should we pass a variable that can be acquired in O(1) into nested functions, or recall that function within every nested function?


The example below explains the question best. Which is standard: (A) or (B)?

A) Passing Variable in Each Nested Function:
def bar(X, y, n_rows, n_cols):
    # Do stuff....
    return stuff

def foo(X, y, n_rows, n_cols):
    stuff = bar(X, y, n_rows, n_cols)
    # Do stuff...
    return stuff
B) Recalling O(1) Function within each Nested Function:
def bar(X, y):
    n_rows = get_number_of_rows(X)  # X.shape[0]
    n_cols = get_number_of_cols(X)  # X.shape[1]
    # Do stuff....
    return stuff

def foo(X, y):
    n_rows = get_number_of_rows(X)  # X.shape[0]
    n_cols = get_number_of_cols(X)  # X.shape[1]
    stuff = bar(X, y)
    # Do stuff...
    return stuff

It seems kind of verbose to pass the number of rows and columns into nested functions, but on the other hand it seems inefficient to keep setting variables. I am not even too sure if the number of rows and columns can be acquired in constant time O(1). I wrote this in Python (using R in reality), but my goal was to frame this question generically enough that it could be applied to any language.

Helpful Links:
Are there guidelines on how many parameters a function should accept? (Suggests making this an object to avoid multiple parameters)

Questions:
  1. Which is better for readability?
  2. Which is better for performance?
  3. Should we code in a way that this situation never arrises?
  4. Could the answer for (1) and (2) be different for different languages?

P.S. Need a little help with the naming of this question – less verbose more generic.


Solution

  • I think that

    1. B is preferred because it avoids some problems with changing the number or names of parameters. Option A has a code smell data clumps, and B is his solution called preserve whole object.

      Also both approaches have a trump data smell. Which can be solved by making the OO re-design and making the passed variables members of the class. Or the introduction of a global or context variable (but this is quite rare)

    2. If there are no unwanted side effects or copying large objects by value, then performance can be neglected. And I would advise you to adhere to the following rule when developing: Don't do premature optimization.

    3. The word "never" does not apply in software design. It all depends on the context.

    4. I think so, and not only for different languages, but also on the problem being solved within the framework of one language, the tools used, libraries, frameworks, etc.