In MVC, chi è responsabile della gestione degli osservatori?

4

(Sto scrivendo una grande GUI MATLAB che fa un uso significativo di MVC, quindi il mio esempio è scritto in MATLAB, tuttavia, credo che questa domanda sia indipendente dalla lingua. Per favore correggimi se sbaglio.)

Ho una classe Model che è ovviamente il modello per la mia applicazione MVC. Supponiamo di avere il seguente:

classdef Model < handle
    properties
        objectA
        objectB
        objectC
    end
end

objectA , objectB e objectC sono tutti oggetti che possono essere osservati:

classdef objectA < handle
    events
        ObjectAEvent
    end
    methods
        function raise(this)
            this.notify('ObjectAEvent', someEventData);
        end
     end
end

ecc.

Ora dì che voglio che il mio View risponda alle modifiche al mio Model . In particolare, voglio che View risponda all'evento ObjectAEvent . Ci sono due modi per farlo:

  1. Consenti a View di iscriversi direttamente all'evento ObjectAEvent . Abbiamo ora accoppiato il View all'interno del Model , che a mio avviso viola la legge di Demeter. Sono abbastanza sicuro che questo viola anche il concetto di MVC per definizione.

  2. Lascia che Model "inoltra" l'evento a View , come segue.

    classdef Model < handle
        properties
            objectA
            objectB
            objectC
    
            listeners
        end
        events
            eventFromObjectA
            ...
        end
        methods
            function this = Model
                this.listeners(1) = addlistener(this.objectA, 'ObjectAEvent', @(src, eventdata) this.notify('eventFromObjectA', eventdata);
                ...
            end
        end
    end
    

    Ora View osserva direttamente Model , ma Model deve passare gli eventi e i dati associati a View . Suppongo che questo sia un po 'il punto di MVC, ma ora c'è un accoppiamento tra ogni object_ e Model direttamente. Suppongo che Model debba sapere della sua object_ s, ma questo sembra ancora ... goffo.

Quale approccio è più corretto? Ci sono altre alternative più pulite di queste?

(Le risposte possono avere degli esempi in qualsiasi linguaggio OOP, sono più familiare a MATLAB.)

    
posta Dang Khoa 01.05.2015 - 01:49
fonte

1 risposta

3
  1. Let the View directly subscribe to the ObjectAEvent event. We've now coupled the View into the internals of the Model, which I believe violates the Law of Demeter. I'm pretty sure this also violates the concept of MVC by definition.

MVC non riguarda il disaccoppiamento totale . Si tratta di evitare l'accoppiamento con elementi instabili. Per quanto riguarda Law of Demeter, dovresti mostrare perché pensi che lo stia violando. Non è un principio duro e veloce, nonostante il suo nome abbia la parola "Legge" in esso. È quasi impossibile non violarlo a un certo punto.

Le classi tendono ad essere meno stabili rispetto alle classi del modello, poiché le viste fanno parte dell'interfaccia utente. Gli utenti tendono a volere nuovi modi per visualizzare le informazioni (è difficile ottenere le viste correttamente la prima volta), ecc. E.g. quante volte è cambiata la GUI per Microsoft Word, tuttavia il modello di un documento (pensate a paragrafi, parole, caratteri, caratteri, stili, ecc.) non è cambiato molto?

In MVC, le viste possono essere direttamente accoppiate alle classi del modello, perché le classi del modello tendono ad essere più stabili. MVC considera questa ipotesi come una scelta progettuale. Se le classi del modello cambiano (può succedere), allora tutte le scommesse sono disattivate per quelle modifiche che sono isolate al modello. Probabilmente dovrai modificare anche le visualizzazioni.

Le classi modello devono comunicare con le viste, ma MVC vuole evitare l'accoppiamento diretto. Abbiamo aggirato questo problema mascherando le visualizzazioni come "Osservatori". L'API Observer è molto stabile, anche se le viste che lo implementano non lo sono. Quindi, per quanto comprendo MVC, è corretto avere un accoppiamento nel modo in cui lo hai descritto al punto # 1.

Usiamo un oggetto reale anziché ObjectA, diciamo engineTemperature . La vista che mostra la temperatura sicuramente saprebbe cosa sta visualizzando. Potrebbe aggiungere le unità "gradi C" poiché la vista sa che il valore è una temperatura. Potrebbe utilizzare il colore rosso se la temperatura supera un valore superiore. È normale che le viste siano direttamente accoppiate agli elementi del modello che visualizzano.

L'altro modo, tuttavia, è diverso. engineTemperature non dovrebbe sapere come viene visualizzato, quali colori vengono utilizzati, chi lo visualizza ecc., poiché tale conoscenza lo renderebbe strettamente accoppiato alle viste e perderebbe la sua stabilità. Qualsiasi cambiamento nella vista potrebbe "rompere" l'oggetto temperatura. Quindi, con MVC e Observer, engineTemperature (come Subject nel pattern Observer) sa solo che ha Observers, che supportano tutti l'API Observer.

Dai un'occhiata al link per maggiori informazioni su MVC e su altri design dell'interfaccia utente.

    
risposta data 06.05.2015 - 13:55
fonte

Leggi altre domande sui tag