Code Complete: Explicit and Implicit Function Parameters

In dynamic languages, there are two main approaches when choosing the input parameters for functions: the first is to use explicit, positional arguments, and the second is to pass a structure containing everything that the function expects. In real code, passing arguments implicitly and explicitly are equally common, and it’s not always clear which one should be chosen for a given function. That's what we're going to look at today.
Let's start with a simple example, a function that finds the highest integer among passed:
Explicit parameters make the code self-documenting: the function signature immediately indicates which arguments are expected, and the good names suggest their types. The apply
method makes it much easier to call the function if the parameters are stored in an array:
Now, let's talk about the drawbacks. First and foremost, the function is too argument-dependent. If you change the number of arguments, including adding and removing default parameters, you must then rewrite all function calls. This is especially true for high-level functions that handle a large amount of data:
When implicit arguments are used, the situation changes. Self-documentation level decreases dramatically. It's hard to sort out what can be passed to a function without first describing or examining its contents. The definition of such functions, on the other hand, rarely changes since the number of inputs is increased automatically:
Which option is preferable in a given situation? According to the previous, explicit arguments work best with simple and low-level functions, such as mathematical ones. As a result, all functions that work with strings or numbers in any language have explicit arguments. Almost every other built-in function and method is the same.
This also applies to users’ functions with a clear, rarely changing structure and a limited number of arguments.
Implicit arguments are a little more complicated. Here is when it’s better to use them:
-
When a function does not directly use a given input but instead passes it further down the call chain. At this point, explicit arguments will only get in the way because of the need to constantly edit them, although the function does not use them
-
When there is a lot of data, especially, if it can mutate frequently in the process. Or when many of these parameters are optional. That is exactly what the user example below is about. In such cases, data is frequently given as an object (an associative array), and it is more convenient to pass it all at once. In addition, this approach is commonly used for configurations:
-
Library functions that can work with arbitrary parameters and structures. A common situation is an ORM or a library for making requests to some system, for example, GitHub. In this case, the library developers simply cannot predict what and how the user will do, so they leave the specific content to those who will use the code:
In some languages, such as Python or Ruby, there are special named parameters. They are explicitly stated as positional parameters in the definition, making them self-documenting. However, they can be provided in any order by specifying the parameter name when called. This method does not replace the others, but it does simplify the code in some cases.
But not all situations can be decomposed so easily. If you're not sure what to do, start with explicit arguments and only then move to implicit ones if necessary. Common sense should be your main guideline.
Contents
Additional materials:
Kirill Mokevnin
3 years ago
pages.blog.posts.show.categories