2 Stimmen

Verbesserung der Kohäsion und Kopplung von Klassen

Ich erhalte diesen Code und soll Vorschläge machen, wie der Zusammenhalt des Codes und die Kopplung der Klassen verbessert werden können. Aber ich dachte, dass diese Klassen recht gut entkoppelt sind, da es so aussieht, als würden sie Ereignisse nutzen. Und was den Zusammenhalt angeht, so sind alle init()-Aufrufe zusammen platziert, das scheint mir alles in Ordnung zu sein.

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) { ... }
    }
}

Gibt es noch Möglichkeiten, die Kohäsion und Kopplung der Klassen zu verbessern? Für mich sieht es gut aus, aber ich glaube, ich übersehe etwas.

Vielen Dank für alle Vorschläge zu diesem Thema.

1voto

TrueWill Punkte 24357

Beginnen Sie mit dem Schreiben von Unit-Tests (besser noch, machen Sie TDD ). Die Kopplung (und, in geringerem Maße, der Zusammenhalt oder dessen Fehlen) wird sofort deutlich.

Die Start-Methode der Klasse B hat zum Beispiel einen Parameter vom Typ A. In Ihrem Beispiel könnten Sie einfach A instanziieren, aber was wäre, wenn A andere Abhängigkeiten hätte? Vielleicht ist alles, was start braucht, eine Schnittstelle, die A implementiert (mit einer Aktualisierungsmethode).

Und was macht getNextEvent? Wenn es andere Abhängigkeiten verwendet, kann es sich als schwierig erweisen, B in ein Test-Harness aufzunehmen.

Tests können helfen, Ihren Entwurf zu validieren.

0voto

Garrett Hall Punkte 28608

Ohne mehr von Ihrem Code zu sehen, ist es schwierig zu sagen, wie entkoppelt Ihr Code ist. Ereignisse sind eine Möglichkeit, Code zu entkoppeln, können aber auch dazu führen, dass der Code schwerer zu verstehen und zu debuggen ist.

Beim Entwurf von Klassen bedeutet hohe Kohäsion, dass viele der Methoden wiederverwendet werden, und geringe Kopplung bedeutet, dass Sie nur einige wenige öffentliche Methoden offenlegen müssen.

Bei der Entwicklung von Paketen bedeutet hohe Kohäsion, dass viele der Klassen in einem Paket voneinander abhängen, und geringe Kopplung bedeutet, dass nur einige wenige Klassen öffentlich zugänglich sind oder über Schnittstellen mit anderen Klassen kommunizieren.

Die Vorteile einer hohen Kohäsion und einer geringen Kopplung sollten in weniger Schmerzen bestehen, insbesondere wenn es darum geht, auf Veränderungen zu reagieren. Wenn es die Schmerzen nicht verringert, sollten Sie nicht viel Zeit in die Optimierung investieren. Ich weiß, es hört sich an, als ob ich hier Plattitüden von mir gebe, aber Sie sollten Ihre eigenen Maßstäbe im Auge behalten, wenn Sie messen, ob hohe Kohäsion und niedrige Kopplung "gut genug" sind, anstatt sich auf die Meinung von Leuten zu verlassen, die nicht unbedingt das Problem verstehen, das Sie zu lösen versuchen.

0voto

Efox Punkte 637

Wenn der ursprüngliche Entwurf ist es, eine andere Funktionalität oder Klassen in der Zukunft zu übernehmen, mit einem Event-Handler, wie Sie sagten, es verwendet wurde, dann nur auf die Strategie Muster auf die Umsetzung und die Optimierung auf Klassen oder Schnittstellen konzentrieren.

0voto

Asaf Punkte 6166

Ein Vorschlag wäre, die Logik der Ereignisbehandlung von der Logik des Controllers (Klasse A) zu entkoppeln.

Sie hätten also 4 Arten von Klassen:

  • die Hauptklasse, die für den Betrieb des "Servers" verwendet wird (A)
  • der Thread, der auf Ereignisse wartet (B)
  • die Modellebene, die aktualisiert werden soll (C)
  • eine Ereignisbehandlerklasse, die eine bestimmte Operation für ein Ereignis unterstützt (D)

Sie könnte etwa so aussehen:

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
  }

}

Beachten Sie, dass in diesem neuen Entwurf die Geschäftslogik der Aktualisierung des Modells (C in Ihrem Beispiel) in eine externe Klasse statt in die Klasse "Runner" verlagert wurde. Dies ist etwas sauberer, da die Klasse Main nicht wissen muss, was Ereignisse sind und wie sie zu behandeln sind.

Ein weiterer Vorteil ist, dass Sie auf diese Weise problemlos komplexe Ereignisbehandlungen mit verketteten Ereignisbehandlungsroutinen oder mehreren seriellen Ereignisbehandlungsroutinen programmieren können. Es ist auch recht einfach, eine asynchrone Ereignisbehandlung zu implementieren, da B nur für den Aufruf der Handler zuständig ist und die Ereignistypen nicht verstehen muss. Dies wird manchmal auch als Veröffentlichen/Abonnieren und hält den Listener (B) und den Handler (Ihre update(e)-Methode) lose gekoppelt

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X