2010-05-07 2 views
3

J'écris un peu d'ORM homebrew (intérêt académique). J'essaie d'adhérer au concept TDD en tant qu'exercice de formation, et dans le cadre de cet exercice, j'écris de la documentation pour l'API au fur et à mesure que je développe la classe. Exemple de cas - Je travaille sur une classe classique de mappeur de type "getCollection". Je veux qu'il soit capable de récupérer des collections d'actifs X (disons des billets de blog) pour un utilisateur spécifique, et aussi des collections basées sur un tableau arbitraire de valeurs numériques. Donc - vous pourriez avoir une méthode comme une de cesPHP OOP: Méthode unique par type d'argument?

$User = $UserMapper->load(1); 
$ArticleCollection = $ArticleMapper->getCollection(range(10,20)); 
$ArticleCollection = $ArticleMapper->getCollection($User); 
$ArticleCollection = $ArticleMapper->getCollection($User->getId()); 

, par écrit la documentation relative à la méthode getCollection - Je veux déclarer la variable @param dans le DocBlock. Est-il préférable d'avoir une méthode unique pour chaque type d'argument, ou est-il acceptable d'avoir une méthode qui délègue à la méthode/classe interne correcte en fonction du type d'argument?

Répondre

6

Il est acceptable d'avoir une méthode qui délègue à la bonne méthode interne. Vous pouvez documenter comme ceci:

@param Array|User|Integer $argName optional explanation 

mais là encore, il n'y a pas que vous empêchant d'avoir une méthode chaque

public function getCollectionByRange(array $range) 
public function getCollectionByUser(User $user) 
public function getCollectionByUserId($id) 

En outre, vous pouvez utiliser le magic __call method de prétendre les méthodes ci-dessus existent et puis capturez les appels de méthode et déléguez-les à vos méthodes internes (ZF does that f.i. for finding dependant database rows). Vous documenteriez ces méthodes avec l'annotation @method dans Class DocBlock. Mais gardez à l'esprit que les méthodes magiques sont toujours plus lentes que d'avoir et/ou d'appeler les méthodes appropriées directement. Utilisez ce qui vous semble le plus logique pour votre application et votre utilisation.

1

Il semble comme si vous voulez faire une surcharge de fonction, mais PHP (même PHP5) ne fait pas de surcharge comme vous le feriez, disons Java. Le Overloading section dans le manuel PHP n'est pas function overloading:

Note: l'interprétation de PHP « surcharge » est différent de la plupart des langages orientés objet . Surcharge offre traditionnellement la possibilité de avoir plusieurs méthodes avec le même nom mais des quantités différentes et types d'arguments.

Vous pourriez dire ceci:

class ArticleMapper { 
    public function getCollection($param) { 
     if (is_array($param)) { $this->getCollectionByArray($param); } 
     if (is_int($param)) { $this->getCollectionByInt($param); } 
     if (is_a($param, 'User')) { $this->getCollectionByUser($param); } 
    } 
    private function getCollectionByArray(array $param) { ... } 
    private function getCollectionByInt($param) { ... } 
    private function getCollectionByUser(User $param) { ... } 
} 

Cela semble être la bonne façon de le faire à mes yeux.

+0

merci, J'apprécie la réponse, et très proche de ma mise en œuvre initiale. Ce que je suis curieux de savoir est, d'un point de vue des meilleures pratiques de la POO, est-il préférable d'utiliser une méthode unique en ce qui concerne les responsabilités? – sunwukung

+0

Ah, bon point: http://php.net/manual/fr/language.oop5.typehinting.php Je vais supprimer cet intendant errant de ma réponse. – artlung

1

Vous pouvez obtenir quelque chose comme method overloading en vérifiant le type du paramètre passé à l'exécution (PHP ne supporte pas ce concept connu d'autres langues comme l'ADA, Java, C# ou C++ par exemple):

[...] 
/** 
* @param User|array|integer $user 
* @return array 
*/ 
public function getCollection($user) { 
    // perhaps a switch-case would be better here 
    if ($user instanceof User) { 
     // do what has to be done if you passed in a User object 
    } else if (is_int($user) { 
     // do what has to be done if you passed in a user id 
    } else if (is_array($user)) { 
     // do what has to be done if you passed in an array of user ids 
    } 
} 
[...] 
+0

merci pour votre réponse - cependant, je suis moins intéressé par le comment, plutôt dans le pourquoi (ou ce qui est considéré comme "meilleure pratique") – sunwukung

+0

"Utilisez ce que vous pensez que le plus logique pour votre application et votre utilisation." - Gordon a ajouté cela il y a 26 minutes je pense. Il n'y a pas de meilleure approche, je pense, comme la plupart du temps: ça dépend. Personnellement, j'opterais pour l'approche de méthode unique, car elle maintient l'API dégagée. –