9
votes

PHP bonnes pratiques - méthodes avec trop de paramètres

J'ai fait une classe et une méthode juste pour rechercher des choses sur mon site Web. Il a trop de paramètres, les paramètres de recherche. Mon contrôleur saisit les données des formulaires, puis passe au modèle.

public function search($name, $age, $foo, ... $bar, $lorem) {


7 commentaires

Passez un seul tableau contenant chaque paramètre en tant qu'élément de tableau.


@Marcb: Pourquoi ne postez-vous pas cela comme une réponse?


Habituellement, il s'agit d'un indicateur que la méthode est trop complexe / puissante. Vous devriez casser la fonctionnalité.


Il n'y a pas de balle d'argent pour cela. C'est très spécifique sur la méthode. Un tableau est une possibilité, mais pas toujours approprié. Pourquoi ne postez-vous pas la méthode en totalité, ou du moins la signature et décrivez (en détail) quels paramètres individuels font et quelle est la méthode bien sûr! Modifier : "Comment?" En développant votre question afin que nous puissions aider;)


@thom je vous recommande de lire "Refactoring", il peut répondre à de nombreuses questions sur la manière de rendre la méthode plus simple. J'ai posté ci-dessous une des techniques, Google pour voir des exemples.


Ah, je ne peux pas descendre un commentaire. Seulement uppote - c'est faux. Donc, Marc B, -1 pour votre commentaire.


Votre édition ne me clarifie pas vraiment beaucoup pour moi, j'avais espéré une explication plus détaillée, également du vrai code et de la signature de méthode réelle , non seulement allongé par ... < / code>


6 Réponses :


0
votes

Faites-le pour que cela accepte un tableau comme paramètre avec de nombreuses paires de noms de nom. Ensuite, vous pouvez utiliser extraire ($ paramysarray) pour effectuer tous les noms dans la matrice en tant que variables $.


0 commentaires

2
votes

Vous pouvez emballer les choses dans une clé => Array basé sur la valeur

Exemple: P>

$object = new Object();
SearchClass->search($object)

public function search(Object $object){
     // Do junk here
}


8 commentaires

Vous pouvez toujours transmettre des arguments à une méthode ... Avoir une matrice ne permet pas de l'utiliser "de manière incorrecte".


Celui-ci est ok pour les paramètres facultatifs, mais à mon avis, il ne convient pas aux paramètres requis, car vous devez vérifier le corps de la méthode pour voir quelles étaient les clés requises. En outre, cela fait du corps plus longtemps, car vous devez vérifier si le paramètre donné a été passé ou non (et pour fournir les valeurs par défaut)


@ Phant0M Si vous avez un ensemble défini de paramètres requis dans une fonction, vous savez qu'il nécessite ces paramètres. En utilisant un tableau, vous pouvez transmettre un nombre incorrect de paramètres que la fonction peut nécessiter de fonctionner correctement. Comme je l'ai dit, vous devrez créer une méthode de validation desdits paramètres requis afin que vous puissiez jeter une exception si elles sont incorrectes. Par conséquent, il est plus facile d'abuser. Surtout si un client utilise le code et n'est pas familier avec celui-ci.


@Darhazer je suis d'accord. Cela crée un code approximatif et probablement des problèmes de débogage à l'avenir. Les paramètres requis doivent être transmis séparément.


Ce n'est pas seulement mauvais parce que vous ne savez pas quels arguments sont facultatifs et qui ne sont pas. C'est mauvais parce que vous devez garder en mémoire tous les noms et types de données de champs de ce tableau (!), et parce que l'IDE ne sera pas en mesure de vous donner des suggestions de selfomomplete.


@Trevor: True, mais PHP ne délivrera qu'un avertissement, alors que l'accès à une matrice via un indice non défini déclenchera un avis, je suppose, mais l'appel va réussir dans les deux cas.


Oui, mais comme indiqué par @OZ_, il convient beaucoup plus aux arguments facultatifs.


@Trevor, transmission de paramètres C'est toujours une mauvaise pratique.



1
votes

2 commentaires

Déjà -2 (et le mien +1). @Darhazer, votre réponse n'est que celle qui est correcte, mais peut-être, vous pouvez écrire quelque chose de plus de 3 mots dans un lien? :)


@OZ_, lorsque les paramètres sont $ FOO, $ BAR et $ LOREM est difficile à expliquer comment les refroidir;) Vous savez - la question contient la moitié de la réponse ou la réponse est de la même qualité que la question. Quoi qu'il en soit, merci pour les critiques, je conviens que certaines explications seraient utiles afin de motiver le lecteur à en savoir plus sur ce refactoring :)



2
votes

J'utiliserais la comparaison la plus proche de Objets de valeur , où vous passez un Objet em> contenant tous les paramètres nécessaires comme propriétés à la fonction.

<?php
class FilterVO {
    public $id;
    public $name;
    // etc ...
}

class SomeCollection {
    public function FilterResults(FilterVO $prefs) {
        // got all the goodies in here
    }
}
?>


3 commentaires

Au lieu de check $ Prefs, vous pouvez faire quelque chose comme: Filtre de fonction publiqueRésultats (Filtervo $ Prefs) ... merci.


C'est bon lorsque l'auteur de la question corrige les réponses :)


Hehe, donner et prendre! : D merci!



16
votes

darhazer strong> et Zanathel strong> a déjà donné de bonnes réponses, et je veux juste vous montrer une chose: Setteurs avec interface fluide. Seulement lorsque tous les paramètres sont facultatifs.

$query = new SearchQuery($required_argument);
$query->setAge($optional)->setLorem($optional);

$finder->search($query);


0 commentaires

6
votes

J'aime utiliser des tableaux pour des fonctions pouvant / avoir de nombreux paramètres. Ce type d'approche permet une expansion quasi infinie des paramètres et est plus simple et meilleure que d'utiliser quelque chose comme func_get_args () code>.

class SearchQuery
{
    public function __construct(array $options = null)
    {
        if (!is_array($options)) {
            return;
        }

        if (array_key_exists('name', $options)) {
            $this->setName($options['name']);
        }
        if (array_key_exists('age', $options)) {
            $this->setAge($options['age']);
        }
    }

    public function setName($name)
    {
        if (!is_string($name)) {
            throw InvalidArgumentException('$name must be a string');
        }

        $this->_name = $name;

        return $this;
    }

    public function setAge($age)
    {
        if (!is_numeric($age) || $age <= 0) {
            throw new InvalidArgumentException('$age must be a positive integer');
        }

        $this->_age = $age;

        return $this;
    }
}

// then you can use dependency injection in your main search class

class SearchService
{
    public function search(SearchQuery $query)
    {
        // search
    }
}


0 commentaires