mercoledì 10 settembre 2014

MVC non sempre

Dopo un lungo periodo di inattività, dovuto ai miei impegni lavorativi, oggi mi sono imbattuto in un articolo un po' datato, ma ancora attuale, che ha attirato la mia attenzione e che mi ha generato qualche riflessione.
L'articolo in questione si trova su: http://www.javaworld.com/article/2076459/core-javauilding-user-interfaces-for-object-orient/core-java/building-user-interfaces-for-object-oriented-systems--part-1.html

In effetti, MVC apparentemente è in contrasto con l'approccio Object Oriented puro. Ma credo che sia il caso di approcciare il problema senza troppi aut aut, invece dovremmo considerare il sistema nel suo complesso per capire.

Riutilizzare il codice è il motivo principale che ha portato alla OOP. Nel caso dei componenti grafici (widget) per l'interfaccia utente, avere oggetti che non sanno nulla del dato da rappresentare è cosa ottima, nonché in pratica assolutamente necessaria. Anche avere degli oggetti nel modello che comunicano le modifiche tramite eventi è cosa buona per riutilizzare e separare il codice.

Fino a questo punto sembra che MVC sia sempre la cosa giusta, tuttavia nella pratica di tutti i giorni si assiste a un suo uso, dovuto soprattutto al massiccio impiego degli strumenti di sviluppo rapido (RAD), che ne stravolge il senso.

Se ci sono, per esempio, diversi punti nell'interfaccia utente che riguardano una certa proprietà di un oggetto, per esempio il nome di una persona, la quale si ritrova in diverse maschere o report, il giorno nel quale si decida di fare una modifica per aggiungere il titolo (sig. dott. sig.ra ecc) lo si dovrà fare in tutti i punti del codice della gui. Questo è assurdo rispetto ai principi della OOP, che vuole facilitare il riutilizzo!

I RAD sono strumenti nati per fare prototipi, non per fare codice di produzione, purtroppo l'elevato costo iniziale dello sviluppo ha promosso i RAD anche dove sarebbe stato meglio che non fossero utilizzati. L'uso scriteriato di MVC porta a dovere modificare il codice in più punti, a meno che non si creino degli oggetti lato View che si conoscano in qualche modo il dato, oppure oggetti fintamente generici, ma che in pratica si useranno solo per quel dati,  ma si viene a perdere la separazione reale tra modello e view.

La soluzione? Usare MVC solo quando e dove serve, cioè all'interno degli oggetti wrapper, in modo che gli oggetti sappiano come rappresentarsi e magari come salvarsi !

Agli occhi di molti fedeli dei manuali di pattern, questo può sembrare un'eresia, ma non lo è.
Avere un'oggetto, anzi, avere un'interfaccia che propone i metodi per rappresentare un oggetto o per salvarlo, è proprio cioè che la OOP all'inizio si prefiggeva di fare!
I dettagli su come questo accada sono nascosti (incapsulati) dentro all'implementazione e questo deve essere trasparente a chi chiama (passa messaggi) a tali oggetti.

Per evitare che l'oggetto in questione diventi enorme e impossibile da mantenere, nessuno ci impedisce di ricorrere a delle strutture a plugin affinché l'oggetto implementante chiami altri oggetti per produrre diverse interfacce utente (Swing, HTML, Android ecc...) o per salvarsi su database con dialetti diversi.

Per esempio un campo "nome" che si mappa su un JTextEdit potrebbe internamente instanziare un JTextEdit e collegarsi ai suoi eventi. In questo modo non è più necessario per il programmatore o per l'IDE realizzare tale legame per ogni volta che questo oggetto è usato.
Se si desidera creare una web application, il campo "nome" potrebbe generare il codice html con tanto di controllo client - side!
Con un file di configurazione si potrebbe definire quali plugin i nostri oggetti dovrebbero caricare, per  generare le due GUI così diverse.
Se definiamo un metodo "disegna" nell'interfaccia del nostro oggetto, potremmo passare un generico oggetto "Contenitore" che sarà un JPanel o un body html.

Si potrebbe obbiettare che in questo modo la definizione dell'interfaccia diventa difficile, tuttavia mi viene in mente l'esempio dei css nel mondo html, dove il posizionamento, il colore, i bordi ecc sono definiti all'esterno. Credo che anche in questo caso tali regole grafiche per le interfacce potrebbero trovarsi all'esterno dell'oggetto e che magari potrebbero essere generate scrivendo del codice, così come scrivendo i css direttamente.

In questo modo la logica del programma non vede il controller e non vede i dettagli della gui e può veramente riutilizzare gli oggetti, incapsulando i dettagli. Questo è compatibile con un RAD? Direi di no, ma sono certo che i tempi di sviluppo, soprattutto per quanto riguarda la manutenzione, si abbatterebbero in questo modo.
Il discorso cambia nel caso di fast prototyping, dove i RAD rimangono secondo me strumenti molto efficaci.