Domanda

Mi viene dato questo set di codice e devo suggerire modi per migliorare la coesione e l'accoppiamento del codice delle classi. Ma ho pensato che queste classi fossero abbastanza ben accoppiate dal momento che sembra che stiano facendo uso di eventi. E in termini di coesione, tutte le chiamate init () sono messe insieme, tutto mi sembra abbastanza bene.

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

Esistono ancora modi per migliorare la coesione e l'accoppiamento delle classi? Mi sembra a posto ma penso che mi manchi qualcosa.

Grazie per eventuali suggerimenti su questo.

È stato utile?

Soluzione

Un suggerimento sarebbe quello di disaccoppiarsi la logica di gestione degli eventi dalla logica del controller (Classe A).

Quindi avresti 4 tipi di classi:

  • La classe principale utilizzata per l'esecuzione del "server" (a)
  • il thread che ascolta gli eventi (B)
  • il livello modello che verrà aggiornato (C)
  • Una classe di gestori di eventi che supporterà alcune operazioni su un evento (D)

Potrebbe assomigliare a questo:

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
  }

}

Si noti che in questo nuovo design la logica aziendale dell'aggiornamento del modello (C nel tuo esempio) è passata a una classe esterna rispetto alla classe "Runner". Questo è un po 'più pulito in quanto la classe principale non ha bisogno di conoscere quali eventi sono e come gestirli.

Un altro vantaggio è che l'utilizzo di questo puoi facilmente codificare la gestione degli eventi complessi utilizzando gestori di eventi incatenati o più gestori di eventi seriali. È anche abbastanza semplice implementare la gestione degli eventi asincrona poiché B è responsabile solo di chiamare i gestori e non è necessario comprendere i tipi di eventi. Questo a volte viene definito come Pubblica/iscriviti e mantiene l'ascoltatore (b) e il gestore (il tuo metodo di aggiornamento (e)) accoppiato vagamente

Altri suggerimenti

Inizia a scrivere test unitari (meglio ancora, fai TDD). L'accoppiamento (e, in misura minore, la coesione o la sua mancanza) diventerà immediatamente evidente.

Ad esempio, il metodo di avvio della Classe B ha un parametro di tipo A. Nel tuo esempio potresti semplicemente istanziare A, ma cosa succede se A avesse altre dipendenze? Forse tutte le esigenze di avvio sono un'interfaccia che un implementa (con un metodo di aggiornamento).

E cosa fa getNextevent? Se utilizza altre dipendenze, ottenere B in un imbracatura di prova può rivelarsi difficile.

I test possono aiutare a convalidare il tuo design.

Senza vedere più del tuo codice è difficile dire quanto sia disaccoppiato il tuo codice. Gli eventi sono un modo per disaccoppiarsi, ma possono anche rendere il codice più difficile da capire e eseguire il debug.

Durante la progettazione di lezioni, ad alta collaborazione significa che molti dei metodi si riutilizzano a vicenda e il basso accoppiamento significa che devi solo esporre alcuni metodi pubblici.

Durante la progettazione di pacchetti, ad alta coezione significa che molte delle classi in un pacchetto dipendono l'una dall'altra e il basso accoppiamento significa che solo pochi sono ambito pubblico o un messaggio con altre classi attraverso interfacce.

I benefici dell'alta coezione, a basso contenuto di acquisizione dovrebbero essere meno dolore, specialmente quando si tratta di rispondere al cambiamento. Se non riduce il dolore, non passare molto tempo a ottimizzarlo. So che sembra che io stia lanciando banalità qui, ma dovresti tenere a mente la tua metrica quando misurano se ad alta collaborazione e bassa accoppiamento è "abbastanza buono" piuttosto che fare affidamento sulle opinioni delle persone che non comprendono necessariamente il Problema che stai cercando di risolvere.

Se il design originale è quello di incorporare un'altra funzionalità o classi in futuro, usando un gestore di eventi, come hai detto, è stato utilizzato, quindi concentrati sul modello di strategia sull'implementazione e sull'ottimizzazione su classi o interfacce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top