Newsgroup: it.comp.lang.c++
Titolo: Architettura Documento/Vista

Ciao a tutti,
programmo da un po' con le MFC ma non ho ancora ben chiaro cosa si
intenda per architettura documento/vista. O meglio ho capito che si
tratta di una tecnica di astrazione dei dati per facilitarne la
gestione ma non ho ben chiaro quando e' necessaria e come si usa.
Qualcuno potrebbe illuminarmi magari con un breve esempio ?
Grazie.

...
    [snip]

E` un design pattern ben noto (in effetti, una semplificazione di
quello, piu` completo, detto Model-View-Controller).  Il concetto
fondamentale e` quello di separare 2/3 responsabilita` distinte:
    -- mantenere un complesso insieme di dati ("documento" o
        "modello" che dir si voglia);
    -- presentare una qualche 'visione' di quei dati all'utente ("vista");
    -- ottenere richieste di modificare quei dati ("controller").
Nell'architettura document/view, la "view" svolge in realta` la
2a _e_ la 3a di queste 3 responsabilita`; in model/view/controller,
abbiamo 3 classi separate, una per ciascuna responsabilita`.
Restiamo sulla document/view, piu` semplice.  A pensarci,
dovrebbe essere chiaro che di modi di "presentare" (far
vedere all'utente) lo stesso identico insieme di dati ce ne
possono essere tanti -- magari, uno testuale, uno tabellare,
svariate forme grafiche, e, perche` no, qualche forma sonora.
Non e` certo ragionevole che la responsabilita` di gestire
tutte queste "presentazioni" debba essere intruppata
assieme a quella di gestire i dati stessi (salvarli e/o
recuperarli da file, database, o altra forma di persistenza,
garantirne l'integrita` semantica secondo gli opportuni
vincoli, decidere quali parti sono memorizzate e in che
forma, quali calcolate con o senza caching e di che
durata, e cosi` via -- tutte funzioni che con la presentazione
dei dati all'utente poco hanno a che spartire).
Chiedi un breve esempio.  OK, facciamone uno molto
semplice, che non c'entra nulla con l'MFC e tutto con
la pattern document/view.
Dobbiamo progettare un sistema per gestire "testi".
Un "testo" puo` essere visto come una sequenza di
caratteri, ovvero di righe; puo` essere memorizzato
in vari modi (file, stream, database, ecc ecc); le
tipiche operazioni che interessera` eseguire saranno
ricerca di stringhe, sostituzioni, inserimenti e
cancellazioni di blocchi, ecc ecc.
D'altronde, e del tutto indipendentemente da come
il "testo" sia _gestito_, puo` essere _presentato_
all'utente in modi svariati.  Un sintetizzatore vocale
puo` leggergliene una parte; una finestra di testo
(console, o form appositamente progettato) puo`
mostrargliene i glifi, in vari font, con varie opzioni
di formattazione; una stampante puo` fornirgli una
"hard copy"; e cosi` via.  In alcuni di questi casi,
l'utente avra` diversi modi per richiedere le varie
operazioni suddette (responsabilita` che scegliamo
di aggregare a quella di presentazione; se invece
la separassimo, avremmo M-V-C invece di D/V).
Dovrebbe dunque essere chiaro come ci convenga
separare le due responsabilita`:
    -- gestire il documento-testo, e
    -- presentare il documento-testo all'utente.
Come al solito per le design patterns, le cose si
gestiscono al meglio con un paio di classi astratte,
tipo (schizzo abborracciato di un progetto):
class TextView;
class TextDocument {
    std::list<TextView*> activeLists;
public:
    void RegisterView(TextView *pView);
    void RemoveView(TextView *pView);
    int numLines() const = 0;
    string fetchLine(int lineNumber) const = 0;
    int findText(string text, int startLine) const = 0;
    // ecc, ecc
};
class TextView {
    TextDocument *theDocument;
public:
    TextView(TextDocument *pDocument);
    void showLines(int startLine, int numLines) const = 0;
    // ecc, ecc
};
Avremo poi delle classi concrete che implementano
varie policy relative ai documenti, ed ereditano da
TextDocument; altre, che implementano varie viste
sui documenti, ed ereditano da TextView; e uno schema
complessivo che aggancia e sgancia documenti e
viste, ecc ecc, secondo necessita` e richieste.
L'alternativa "becera", di mischiare le responsabilita`
di gestire e quelle di presentare i dati nella stessa
classe, dovrebbe, spero, risultare a questo punto
clamorosamente e chiaramente inferiore.
L'inferiorita` puo` non essere cosi` manifesta per una
applicazione "piccola piccola", dove puo` sembrare
solo una scocciatura quella di avere i dati e la loro
presentazione in classi separate... ma "applicazioni
piccole crescono", si sa!, e quindi e` meglio avere sin
dall'inizio un'architettura piu` solida e "scalabile" -- o
almeno, si tratta di una scelta difendibile.
Un po' piu` chiaro ora...?
Alex