3 votes

Est-ce une mauvaise pratique d'utiliser des tableaux comme paramètres pour renvoyer plusieurs valeurs ?

Il m'arrive parfois (en fait, souvent) d'utiliser un tableau à un élément pour renvoyer plusieurs valeurs à partir d'une méthode. Quelque chose comme ceci :

public static int foo(int param1, int param2[], String param3[])
{
    // method body
    ....
    // set return values
    param2[0] = <some value>;
    param3[0] = <some value>;

    return <some value>;
}

S'agit-il d'une mauvaise pratique ? (Il semble que oui, car certains de mes amis m'ont dit qu'ils ne savaient pas ce qu'ils faisaient pendant deux secondes !) Mais la raison pour laquelle j'ai utilisé cette méthode est qu'elle se rapproche le plus de ce que l'on appelle le pass-by-reference en C++. Et cette pratique n'a pas été découragée en C++ , donc ...

Mais s'il s'agit vraiment d'une mauvaise façon de faire, une idée sur la façon de réécrire cela proprement ?

Remerciements

6voto

jahroy Points 10072

Créez un objet contenant les données que vous souhaitez renvoyer.

Vous pouvez ensuite renvoyer une instance de cet objet.

class FooData {
    private int someInt;
    private int anotherInt;
    private String someString;

    public FooData(int a, int b, String c) {
        someInt = a;
        anotherInt = b;
        someString = c;
    }
}

public FooData foo() {
    // do stuff
    FooData fd = new FooData(blah, blahh, blahhh);
    return fd;
}

5voto

Mirko Klemm Points 829

Bien que je sois d'accord avec l'opinion générale selon laquelle l'utilisation de tableaux à cette fin est une mauvaise pratique, j'aimerais ajouter quelques éléments. Êtes-vous sûr que le "passage par référence" est vraiment ce dont vous avez besoin en premier lieu ? Beaucoup ont dit que votre code est de mauvais style, mais laissez-moi vous dire pourquoi, selon moi. Le "passage par référence" est principalement un synonyme de "programmation par effet de bord", une chose que l'on veut toujours éviter. Cela rend le code beaucoup plus difficile à déboguer et à comprendre, et dans un environnement multithread, les mauvais effets de cette attitude peuvent vraiment vous frapper de plein fouet. Pour écrire un code évolutif et sûr pour les threads en Java, vous devez faire en sorte que les objets soient en "lecture seule" autant que possible, c'est-à-dire qu'idéalement, vous créez un objet et l'initialisez en même temps, puis vous l'utilisez avec cet état non modifiable tout au long de votre application. Les modifications logiques de l'état peuvent presque toujours être considérées comme une "création" d'un nouvel état, c'est-à-dire la création d'une nouvelle instance initialisée à un état alors nécessaire. De nombreux langages de script modernes ne permettent de travailler que de cette manière, ce qui rend les choses beaucoup plus faciles à comprendre. Contrairement au C++, Java est beaucoup plus efficace dans l'allocation et la libération d'objets à courte durée de vie, il n'y a donc rien de mal à ce que d'autres ont suggéré ici : Créer une instance d'une classe spéciale pour contenir le résultat de la fonction, dans le seul but de renvoyer le résultat. Même si vous faites cela dans une boucle, la JVM sera suffisamment intelligente pour gérer cela efficacement. Java n'alloue la mémoire du système d'exploitation que par très gros morceaux lorsque c'est nécessaire, et gère la création et la libération des objets en interne, sans les frais généraux qu'impliquent des langages tels que C/C++. Le "Pass by reference" n'est pas d'une grande utilité en Java.

EDIT : Je vous suggère de faire une recherche sur ce forum ou sur le net avec les termes "effet secondaire", "programmation fonctionnelle" ou "immutabilité". Cela ouvrira très probablement une nouvelle perspective à votre question.

4voto

rgettman Points 74908

Je pense que c'est une mauvaise pratique de "renvoyer" des valeurs en utilisant des tableaux à un élément qui sont des paramètres de votre méthode.

Voici une autre question sur le SO sur ce sujet. En bref, c'est très mauvais pour la lisibilité.

Il existe une solution simple : Enveloppez toutes les valeurs que vous souhaitez renvoyer dans une classe que vous définissez spécifiquement à cette fin, et renvoyez une instance de cette classe.

return new ValueHolder(someValue1, someValue2, someValue3);

3voto

Cody A. Ray Points 1516

Ce n'est pas très idiomatique en java. Il existe généralement de meilleures approches de la conception de logiciels.

Ce que vous faites réellement avec le "tableau à un élément", c'est créer un objet mutable (puisque String est immuable, tout comme les primitives telles que int) et le passer par référence. La modification de cet objet mutable est appelée "effet de bord" de la méthode. En général, il convient de minimiser la mutabilité ( Poste 15 de la Java en vigueur ) et vos méthodes devraient être exemptes d'effets secondaires. Il existe plusieurs approches.

1. Diviser la méthode en deux (ou trois) méthodes qui prennent toutes les mêmes paramètres :

public static int foo1(int param1)
{
    // method body
    ....
    return <some value>;
}

De même, vous pouvez avoir

public static int foo2(int param1) { ... }

y

public static String foo3(int param1) { ... } .

2. Renvoyer un objet composite.

public Container {
    private final int originalReturn;
    private final int param2;
    private final String param3;

    public Container(int originalReturn, int param2, String param3) {
        this.originalReturn = originalReturn;
        this.param2 = param2;
        this.param3 = param3;
    }

    // getters
}

public static Container foo(int param1, int param2[], String param3[])
{
    // method body
    ....
    // set return values
    return new Container(<some value>, <some value>, <some value>);
}

2voto

thatidiotguy Points 3213

Il s'agit en effet d'une mauvaise pratique si les valeurs ne sont pas liées. Cela indique généralement que vous pouvez diviser cette fonction en deux, chacune renvoyant l'une des valeurs.

EDITAR:

Je suppose que vous renvoyez les deux valeurs calculées dans la méthode dans un tableau. N'est-ce pas le cas ?

par exemple

public int[] getStatistics(int[] nums)
{
    //code

    int[] returns = new int[2];
    returns[0] = mean;
    returns[1] = mode;

    return returns;
}

La fonction ci-dessus pourrait être divisée en getMean() y getMode() .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X