2009-07-21 10 views
2

J'ai franchi le pas et utilisé Guice pour mon dernier projet. Les impressions globales sont bonnes, mais j'ai rencontré un problème que je n'arrive pas à comprendre. Contexte: C'est une application Java6 qui accepte les commandes sur un réseau, analyse ces commandes et les utilise ensuite pour modifier certaines structures de données internes. C'est un simulateur pour certains matériels fabriqués par notre société. Les modifications apportées aux structures de données internes correspondent à l'effet que les commandes ont sur le matériel réel, de sorte que les requêtes ultérieures des structures de données doivent refléter l'état matériel en fonction des commandes précédemment exécutées.Aller à Guice créer des objets à partir d'objets de données stupides

Le problème que j'ai rencontré est que les objets de commande doivent accéder à ces structures de données internes. Ces structures sont créées par Guice car elles varient en fonction de l'instance réelle du matériel émulé. Les objets de commande ne sont pas créés par Guice parce qu'ils sont essentiellement des objets stupides: ils acceptent une chaîne de texte, l'analysent et invoquent une méthode sur la structure de données. La seule façon de faire en sorte que tout cela fonctionne est de faire en sorte que ces objets de commande soient créés par Guice et transmis dans les structures de données par injection. Il se sent vraiment maladroit et bloque totalement le constructeur des objets de données.

Qu'est-ce que j'ai manqué ici?

Répondre

1

L'injection de dépendances fonctionne mieux pour les services de câblage. Il peut être utilisé pour injecter des objets de valeur, mais cela peut être un peu gênant, surtout si ces objets sont mutables. Cela dit, vous pouvez utiliser les méthodes Providers et @Provides pour lier vous-même les objets que vous créez.

+0

Si vos objets de valeur varient en fonction du matériel émulé, vous pouvez écrire une fabrique pour les créer et demander à Guice d'injecter l'usine dans le code qui en a besoin. En d'autres termes, une façon d'éviter d'injecter des objets de valeur est de créer un service qui produit les objets de valeur. – NamshubWriter

0

En supposant que répondre à une commande n'est pas si différent de répondre à une requête http, je pense que vous allez dans le bon sens.

Un modèle couramment utilisé dans les applications http consiste à intégrer la logique de l'application dans des objets à durée de vie courte qui ont à la fois les paramètres de la requête et certains backends injectés. Ensuite, vous instanciez un tel objet et appelez une méthode simple et sans paramètre qui fait toute la magie.

Peut-être que les oscilloscopes pourraient vous inspirer en quelque sorte? Regardez into documentation et some code examples pour lire les détails techniques. Dans le code, ça ressemble moins à ça. Voici comment cela pourrait fonctionner pour votre cas:

class MyRobot { 
    Scope myScope; 
    Injector i;  

    public void doCommand(Command c) { 
     myScope.seed(Key.get(Command.class), 
     i.getInstance(Handler.class).doSomething(); 
    } 
} 


class Handler { 
    private final Command c; 
    @Inject 
    public Handler(Command c, Hardware h) { 
    this.c = c; 
    } 

    public boolean doSomething() { 
    h.doCommand(c); 
    // or c.modifyState(h) if you want c to access internals of h 
    } 
} 

Certaines personnes désapprouvent cette solution, mais j'ai vu ceci dans le code en se basant essentiellement sur Guice dans le passé au moins deux projets différents. Accordez que vous injectiez un peu d'objets de valeur dans les constructeurs, mais si vous ne les considérez pas comme des objets de valeur mais plutôt comme des paramètres de la classe qui modifient son comportement, tout cela a du sens. C'est un peu gênant et certaines personnes désapprouvent d'injecter des objets de valeur de cette façon, mais je l'ai vu dans le passé dans des projets qui dépendaient fortement de Guice pendant un moment et ça a bien fonctionné.