2010-10-28 12 views
3

Ceci est une question sur l'injection de dépendance. Lors de la construction d'un objet service, nous transmettons des collaborateurs via le constructeur dans la phase de construction. L'objet de service implémenterait une interface, qui serait appelée pendant la phase d'exécution.Que passer par constructeur et que passer via interface?

Parfois, est-il difficile de savoir si un objet particulier doit être passé via le constructeur ou faire partie de l'interface implémentée par la classe de service?

Existe-t-il des règles pour choisir une option plutôt qu'une autre? La question est la plus difficile lorsque vous savez que l'interface ne sera appelée qu'une seule fois dans le scénario pour lequel vous codez.

Répondre

5

J'aime à penser comme ceci:

  • arguments du constructeur sont les détails de mise en œuvre
    • Ils sont étendus à toutes les opérations
    • Ils ne changent pas en réponse à une opération (invariant)
    • L'interface peut être comprise sans les
    • Ce sont des valeurs de configuration qui reflètent les coutures d'une application
  • arguments de méthode sont contextuelles
    • Ils sont étendus à une opération individuelle
    • Ils sont des valeurs exécution qui reflètent les données d'une application de flux

Beaucoup de l'art est en cadrage le problème correctement. Par exemple, nous pourrions nous dire "J'ai besoin de créer une nouvelle ligne dans la table utilisateur". De ce point de vue, l'une de ces signatures semble bien:

void Insert(User user); 

void Insert(User user, IDbConnection dbConnection); 

Cependant, nous pouvons briser notre définition de tâche:

Intention: Créer un nouvel utilisateur

détail de mise en œuvre: A l'utilisateur est une ligne dans une table

À la place, encadrons la tâche comme suit: «J'ai besoin de créer un utilisateur». Cela nous donne un moyen d'évaluer les deux signatures ci-dessus, en favorisant celle qui correspond à notre intention:

void Insert(User user); 

Analyse de l'intention d'une opération et la portée applicable de ses données donne généralement des résultats solides.

2

Une règle de base que j'utilise souvent est de savoir si la classe peut fonctionner sans la valeur transmise, en équilibre avec la complexité du constructeur. Si la classe ne peut pas fonctionner correctement sans l'argument, il est généralement bon de le placer dans le constructeur. D'un autre côté, si la classe est conçue pour faire quelque chose qui nécessite un travail supplémentaire, comme accepter des connexions sur un socket, ce travail devrait normalement être retardé à une fonction ultérieure.