<!--
  canonical-url: https://www.avonture.be/fr/blog/linux-bash-too-many-function-parameters
  published:     2024-06-28
  This is a static plain-Markdown mirror generated at build time.
  Visit the canonical URL above for the fully rendered page, with images and interactive components.
-->

# Clean code - Linux Bash - Réduire au maximum le nombre de paramètres d'une fonction

> Appliquez le Clean Code à vos scripts Linux Bash. Découvrez comment éviter d'avoir trop de paramètres de fonction grâce à une solution simple et robuste : le tableau associatif.

---
![Clean code - Linux Bash - Réduire au maximum le nombre de paramètres d'une fonction](/img/v2/bash.webp)

**TL;DR**

Cet article applique à Bash le principe de clean code qui consiste à limiter le nombre de paramètres d'une fonction. En Bash, on ne peut pas passer un objet : on passe donc un seul tableau associatif (`declare -A arr=()`) à la fonction. L'appelant n'a plus à se soucier de l'ordre des arguments positionnels, et de nouveaux champs peuvent être ajoutés plus tard sans casser les appels existants.

Un des concepts du clean code est d'éviter d'avoir trop de paramètres de fonction (je dirais que quatre paramètres, c'est déjà trop).

Quand vous programmez dans un langage plus évolué que Linux Bash, il est facile de contourner le problème. Par exemple, en PHP, si je dois appeler une fonction et lui passer plusieurs paramètres, je vais créer un objet qui sera mon seul paramètre et cet objet aura alors plusieurs propriétés.

Ainsi, par exemple, si je dois passer des données comme un nom, un prénom, une date de naissance, un genre, etc., je vais créer un objet `person`, définir mes propriétés et voilà, je n'ai plus qu'un seul paramètre à passer à ma fonction. Dans la plupart des cas, c'est une très bonne solution.

Mais comment faire en Linux Bash ? Impossible de passer un objet... je vais donc lui passer un tableau associatif.

L'astuce, pour un script Bash, est de définir un tableau associatif (créé avec la commande `declare -A arr=()`) et de passer ce tableau en paramètre à la fonction.

Voici un exemple :

**curl.sh**

```bash
#!/usr/bin/env bash

# let script exit if an unused variable is used or if a command fails
set -o nounset
set -o errexit

function runCurl() {
    local -n arrCall=$1

    # The endpoint (the URL to request) is mandatory
    local -r endpoint="${arrCall["endpoint"]}"

    # The other properties are optional; initialize to an empty string or any other default values
    [[ ! -v arrCall[header] ]]  && local -r header=""    || local -r header="${arrCall["header"]}"
    [[ ! -v arrCall[method] ]]  && local -r method="GET" || local -r method="${arrCall["method"]}"
    [[ ! -v arrCall[payload] ]] && local -r payload=""   || local -r payload="${arrCall["payload"]}"
    [[ ! -v arrCall[proxy] ]]   && local -r proxy=""     || local -r proxy="${arrCall["proxy"]}"
    [[ ! -v arrCall[token] ]]   && local -r token=""     || local -r token="${arrCall["token"]}"

    # And now I can work with my multiple variables exactly as I would have done if I'd passed them all as parameters.
    #
    # Here is an example:

    cmd="curl -X ${method} ${endpoint} --no-progress-meter"

    [[ -n ${payload} ]] && cmd="${cmd} --data ${payload}"
    [[ -n ${header} ]]  && cmd="${cmd} --header ${header}"
    [[ -n ${token} ]]   && cmd="${cmd} ${token}"
    [[ -n ${proxy} ]]   && cmd="${cmd} --proxy ${proxy}"

    if ! json="$(eval "${cmd}")"; then
        echo "CURL has failed"
        exit 1
    fi

    echo "${json}"

    return 0
}

declare -A arr=(
   [endpoint]=https://jsonplaceholder.typicode.com/todos/5
   [token]="--header 'Authorization:Bearer ABCDEF'"
)

# As you know, when using variables you should use the syntax like ${variable}
# But, here below, no. We're passing our array and we should not use the `$`
runCurl arr
```

Un des gros avantages, c'est que vous n'avez plus à vous préoccuper de la position des arguments (ah oui, donc le premier paramètre c'est l'url, le deuxième la méthode HTTP, le troisième c'est, euh ? le proxy ? ah non, mince).

De nouveaux paramètres peuvent aussi être créés plus tard sans impacter les scripts existants.

Tout est beaucoup plus propre avec un tableau associatif, et plus robuste aussi.

Deux autres habitudes qui gardent une base de code Bash propre : [trier vos fonctions](/blog/linux-sort-functions-in-script) pour les retrouver facilement, et [les couvrir avec des tests unitaires bats](/blog/bats-unit-tests) pour qu'un refactoring comme celui-ci se fasse sans retenir votre souffle.
