Question

J'ai reçu cet ensemble de code et j'ai besoin de suggérer des moyens d'améliorer la cohésion du code et le couplage des classes.Mais j'ai pensé que ces classes sont assez bien découplées car il semble qu'elles utilisent des événements.Et en termes de cohésion, tous les appels init () sont placés ensemble, tout me semble très bien.

public class A
{
    private C t;
    private B g;
    public static void main(String args[]) {
        // Creates t and g.
        t = new C();
        t.init();
        g = new B();
        g.init();
        g.start(this);
    }
    pubic void update (Event e)
    {
        // Performs updating of t based on event
    }
}

public class C
{
    public C() { ... }
    public void init() { ... }
}

public class B
{
    public B() { ... }

    public void init() { ... }

    public void start(A s) {
        e = getNextEvent();
        while (e. type != Quit)
            if (e.type == updateB)
                update(e) ;
            else
                s.update(e) ;
        e = getNextEvent();
    }

    public void update(Event e) { ... }
    }
}

Y a-t-il encore des moyens d'améliorer la cohésion et le couplage des classes?Cela me semble correct mais je pense que je manque quelque chose.

Merci pour vos suggestions à ce sujet.

Était-ce utile?

La solution

Une suggestion serait de découpler la logique de gestion des événements de la logique du contrôleur (classe A).

Vous auriez donc 4 types de classes:

  • la classe principale utilisée pour exécuter le "serveur" (A)
  • le fil à l'écoute des événements (B)
  • le calque du modèle qui sera mis à jour (C)
  • une classe de gestionnaire d'événements qui prendra en charge certaines opérations sur un événement (D)

Cela pourrait ressembler à quelque chose comme ceci:

public class Main {
  private Model m;
  private EventListener listener;

  ... main() {
    m = new Model();
    listener = new EventListener();

    EventHandler eventHandler = new MyEventHandler();

    // set the event handler
    listener.setEventHandler(eventHandler);

    listener.start(m);
}

public class Model {
  // nothing to see here
}

public class EventListener() {

  private EventHandler handler = new DefaultEventHandler();

  public void start(final Model m) {
    // startup
    while (event.type != Event.Quit) {
      // get event
      handler.handleEvent(event, m);
    }
    // shutdown
  }

  public void setEventHandler(EventHandler eh) { this.handler = eh }
}

public class MyEventHandler implements EventHandler {

  public void handleEvent(Event e, Model m) {
    // update the model
  }

}

Notez que dans cette nouvelle conception, la logique métier de la mise à jour du modèle (C dans votre exemple) a été déplacée vers une classe externe par opposition à la classe "Runner". c'est un peu plus propre car la classe Main n'a pas besoin de savoir ce que sont les événements et comment les gérer.

Un autre avantage est qu'en utilisant cela, vous pouvez facilement coder une gestion d'événements complexes à l'aide de gestionnaires d'événements chaînés ou de plusieurs gestionnaires d'événements série. Il est également assez simple d'implémenter la gestion des événements asynchrones car B est uniquement chargé d'appeler les gestionnaires et n'a pas besoin de comprendre les types d'événements. Ceci est parfois appelé Publier / S'abonner et garde l'auditeur (B) et le gestionnaire (votre méthode update (e)) faiblement couplée

Autres conseils

Commencez à écrire des tests unitaires (mieux encore, faites TDD ).Le couplage (et, dans une moindre mesure, sa cohésion ou son absence) deviendra immédiatement évident.

Par exemple, la méthode de démarrage de la classe B a un paramètre de type A. Dans votre exemple, vous pouvez simplement instancier A, mais que faire si A avait d'autres dépendances?Peut-être que tous les besoins de démarrage sont une interface implémentée par A (avec une méthode de mise à jour).

Et que fait getNextEvent?S'il utilise d'autres dépendances, obtenir B dans un faisceau de test peut s'avérer difficile.

Les tests peuvent aider à valider votre conception.

Sans voir plus de votre code, il est difficile de dire à quel point votre code est découplé. Les événements sont un moyen de découpler le code, mais peuvent également rendre le code plus difficile à comprendre et à déboguer.

Lors de la conception de classes, une cohésion élevée signifie que de nombreuses méthodes se réutilisent les unes les autres, et un faible couplage signifie que vous n'avez besoin que d'exposer quelques méthodes publiques.

Lors de la conception de packages, une cohésion élevée signifie que de nombreuses classes d'un package dépendent les unes des autres, et un faible couplage signifie que seules quelques-unes sont de portée publique ou envoient des messages avec d'autres classes via des interfaces.

Les avantages d'une cohésion élevée et d'un couplage faible devraient être moins pénibles, en particulier lorsqu'il s'agit de réagir au changement. Si cela ne réduit pas la douleur, ne passez pas beaucoup de temps à l'optimiser. Je sais que cela donne l'impression que je jette des platitudes ici, mais vous devez garder votre propre métrique à l'esprit lorsque vous mesurez si le couplage à haute cohésion et faible est `` assez bon '' plutôt que de vous fier aux opinions de personnes qui ne comprennent pas nécessairement le problème que vous essayez de résoudre.

Si la conception originale est d'intégrer une autre fonctionnalité ou des classes dans le futur, en utilisant un gestionnaire d'événements, comme vous l'avez dit, il a été utilisé, alors concentrez-vous simplement sur le modèle de stratégie sur l'implémentation et l'optimisation sur les classes ou les interfaces.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top