Je lis le livre "Learning TypeScript" de Remo Jansen. Dans une section, l'auteur décrit comment créer un cadre MVC de preuve de concept très simple, y compris comment créer la Model
classe et dit ce qui suit:
Un modèle doit être fourni avec l'URL du service Web qu'il consomme. Nous allons utiliser un décorateur de classe nommé ModelSettings pour définir l'URL du service à consommer. Nous pourrions injecter l'URL du service via son constructeur, mais il est considéré comme une mauvaise pratique d'injecter des données (par opposition à un comportement) via un constructeur de classe .
Je ne comprends pas cette dernière phrase. En particulier, je ne comprends pas ce que signifie "injecter des données". Il me semble que dans presque toutes les introductions aux classes JavaScript utilisant des exemples simplifiés, des données sont introduites ("injectées"?) Dans le constructeur via ses paramètres. Par exemple:
class Person {
constructor(name) {
this.name = name;
}
}
Je pense certainement à des name
données, pas à un comportement, et elles sont universellement incluses dans ce type d'exemple comme paramètre constructeur, et il n'est jamais fait mention que c'est une mauvaise pratique. Je suppose donc que je comprends mal quelque chose dans la citation ci-dessus, soit ce que l'on entend par "données" ou par "injecter" ou autre chose.
Vos réponses pourraient inclure des explications sur quand, où, comment et pourquoi utiliser des décorateurs en JavaScript / TypeScript, car je soupçonne fortement que le concept est intimement lié à la compréhension que je recherche. Cependant, plus important encore, je veux comprendre plus généralement ce que l'on entend par injection de données via un constructeur de classe et pourquoi c'est mauvais.
Pour donner plus de contexte à la citation ci-dessus, voici la situation: une Model
classe est créée qui, dans cet exemple, sera utilisée pour créer des modèles de bourse, un pour NASDAQ et un pour NYSE. Chaque modèle nécessite le chemin du service Web ou du fichier de données statiques qui fournira les données brutes. Le livre indique qu'un décorateur doit être utilisé pour ces informations, plutôt qu'un paramètre constructeur, conduisant à ce qui suit:
@ModelSettings("./data/nasdaq.json")
class NasdaqModel extends Model implements IModel {
constructor(metiator : IMediator) {
super(metiator);
}
...
}
Je ne comprends tout simplement pas pourquoi je devrais ajouter l'URL du service via le décorateur plutôt que simplement comme paramètre pour le constructeur, par exemple
constructor(metiator : IMediator, serviceUrl : string) {...
la source
Réponses:
Je donnerai à l'auteur le bénéfice du doute et c'est peut-être la façon dont les choses sont pour Typescript, mais sinon dans d'autres environnements, c'est une affirmation totalement infondée qui ne devrait pas être prise au sérieux.
Du haut de ma tête, je peux penser à une variété de situations où le passage de données via le constructeur est bon, certains qui sont neutres, mais aucun où c'est mauvais.
Si une classe particulière dépend d'une donnée particulière pour être dans un état valide et s'exécuter correctement, il est parfaitement logique d'exiger ces données dans le constructeur. Une classe représentant un port série pourrait prendre le nom du port, un objet fichier pourrait nécessiter le nom de fichier, un canevas de dessin nécessitant sa résolution, etc. doit être surveillé et vérifié. Sinon, vous ne pouvez vérifier qu'à l'instanciation de l'objet et supposer ensuite son fonctionnement pour la plupart. Les auteurs affirment que cette situation bénéfique est impossible.
De plus, la décision d'interdire le passage de données dans un constructeur rend également pratiquement tous les objets immuables impossibles. Les objets immuables ont une variété d'avantages dans de nombreuses situations, et tous ces éléments seraient rejetés avec la politique de l'auteur.
Même si vous voulez des objets modifiables, quelle est cette mauvaise pratique:
en faveur de:
L'auteur pense-t-il vraiment que la première est une mauvaise pratique et que je devrais toujours choisir l'option 2? Je pense que c'est un discours fou.
Donc, puisque je n'ai pas le livre, et que je ne le lirais pas de toute façon, même si je le faisais, je verrais cette déclaration et à peu près n'importe quelle déclaration générale à ce stade avec beaucoup de suspicion.
la source
Je pense que cela dépend du contexte du type de modèle qui est discuté ici. Je n'ai pas le livre de Remo, mais je suppose que le modèle est une sorte de modèle de service, qui doit récupérer les données d'un service Web distant. Si tel est le cas, étant un modèle de service Web, il est préférable de passer toutes les données requises comme arguments dans les méthodes du service Web, ce qui rend le service sans état.
Le service sans état présente plusieurs avantages, par exemple, toute personne lisant un appel de méthode de service n'a pas besoin de rechercher lors de la construction du service pour connaître les détails du service appelé. Tous les détails sont affichés dans les arguments utilisés dans l'appel de méthode (à l'exception de l'URL distante).
la source
Je devine.
Si j'entends «injecter du comportement, pas des données», je penserais, au lieu de faire ceci:
(Désolé pour l'exemple en pseudocode):
Pour faire ça:
De cette façon, vous pouvez toujours changer le comportement du bruit, le rendre aléatoire, dépendant d'une variable interne ...
Je pense que tout tourne autour de la règle «favoriser le composite par rapport à l'héritage» Ce qui est une excellente règle, je dois dire.
Cela NE SIGNIFIE PAS que vous ne pouvez pas «injecter» le nom à l'objet «Personne», évidemment, car ce nom est purement des données commerciales. Mais dans l'exemple que vous donnez, le service Web, l'URL est quelque chose que vous avez besoin de générer quelque chose d'une certaine manière qui relie un service. C'est en quelque sorte un comportement: si vous injectez l'URL, vous injectez les «données» nécessaires pour créer un «comportement», dans ce cas, il est préférable de rendre le comportement à l'extérieur et de l'injecter prêt à être utilisé: injectez plutôt une injection d'URL une connexion utilisable ou un constructeur de connexion utilisable.
la source