Se nel pistolotto contro (l’uso come verità rivelata che si fa di) Agile, oltre ad annoiarvi, ho attirato le vostre antipatie e accuse di essere demodée (avete ragione) e agèe (vi sbagliate), sento che tirando in ballo il pattern MVC non potrò che risultarvi blasfemo, con relativi inquisizione e rogo. E andiamo allegramente a morire da filosofo, come disse il filosofo che andò a morire allegramente.
Nel tentativo di partire da una piattaforma comune, premetto:
- nessuno mette in discussione i concetti e la metodologia OO, al contrario
- nessuno mette in discussione che sia necessario separare il software che gestisce ciò che è view, da quello che gestisce ciò che è controller, da quello che gestisce ciò che proviene dalla base dati, e rendere questi tre aspetti modulari e agganciabili mediante interfacce, possibilmente chiare.
Ma, come si evince dal fatto che nell’ultimo punto non viene citato il model, è solo ed esattamente questo che metto in discussione. E in questo caso, non l’uso che se ne fa: a volte ho paura che il concetto sia sbagliato. Almeno allo stato attuale delle tecnologie disponibili e nella stragrande maggioranza dei progetti informatici che quotidianamente affrontiamo e in cui viene adottato.
Prima del modello MVC erano a disposizione altri schemi di riferimento, tra loro quantomeno simili; avendo io partecipato, molti anni fa, a un corso di aggiornamento in cui veniva presentato il modello three-tiers (DB/BR/UI), quello è il mio imprinting, ma siamo tutti d’accordo che non è l’unico e non il primo. E’ solo una metafora, una simbologia, uno strumento per capirsi, tutto qui. D’altro canto, le case produttrici che hanno bisogno di difendere i propri brevetti e i divulgatori che hanno bisogno di vendere le proprie idee, hanno purtroppo interesse a reinventare ogni volta l’acqua, calda tiepida e spesso anche fredda, battezzando questi concetti con terminologia fantasiosamente sempre nuova. Ma della stessa minestra stiamo parlando.
Per capirci, e a costo di risultare pedante, con DB/BR/UI si fa riferimento a database/business-rules/user-interface, dove risulta ovvia l’analogia con l’MVC.
Analogia, con una grossa differenza: DB non ha logica a bordo, cioè si preoccupa esclusivamente di reperire un dato e metterlo a disposizione dell’applicazione, magari tipizzandolo (l’idea è quello dei recordset), ma niente più di questo. Con questo modello, se volete relazionare gli anni di vostra nonna con la cilindrata di un motoscafo siete liberissimi di farlo, posto che l’output dell’elaborazione sia di vostro interesse.
Al di la’ del fatto che non esiste una definizione univoca di model, e già questo è campanello d’allarme, in generale si può dire che, spingendo al massimo l’acceleratore dell’OO, qualche mattacchione non si è limitato a trasformare il recordset in un POJO, operazione legittima e forse in certi casi obbligatoria, soprattutto in JAVA, ma non strettamente OO; ha detto: aggiungiamo logica a DB, spostiamo così una parte di ciò che è BR (la manipolazione/restituzione applicativa dei dati) all’interno di DB; a BR resta solo la gestione del flusso operativo (routing, dispatching, risposta a eventi, ecc.). Avremo così un disegno più OO e la logica che è contenuta nel model può così essere riutilizzata nell’applicazione successiva che fa uso dello stesso model.
L’idea sulla carta è ottima, ma da qui è nato il disastro di tutte le applicazioni che ho visto costruite secondo questo paradigma. I sintomi tipici sono:
- lentezza nello sviluppo
- per ovviare alla lentezza dello sviluppo uso smodato di “fil di ferro” per tenere legate insieme le cose “purchè vada che stiamo perdendo un sacco di soldi”, e mai più risistemate a dovere
- lentezza nell’esecuzione
- salti mortali per riuscire ad effettuare operazioni non previste dall’architettura di base (tipicamente: aggiornamenti massivi)
- incapacità, in applicazioni anche non troppo complesse, di definire un chiaro diagramma di flusso degli eventi in cui si capisca chi fa cosa: una spaghettata di frecce che si intersecano vanno dal model al controller alla view secondo criteri che, dopo l’ottava freccia, nessuno è più in grado di decifrare. Se non hai partecipato dall’inizio al progetto, non capirai mai più come è il quadro di insieme
- nessun vantaggio (nessuno!) rispetto ad applicazioni sviluppate senza utilizzo del model.
Ho visto applicazioni la cui landing-page, dovendo essere riassuntiva (la tipica dashboard), effettuava qualcosa come 400 (quattrocento!) accessi alla base dati! Idratazioni incontrollate, caricamenti di relazioni di relazioni di relazioni non necessarie, generazioni di oggetti a nastro… Ogni pagina: 5/10 secondi. E allora ulteriori superfetazioni: cache, caricamento in RAM di interi DB o quasi, cubi OLE, Pentaho e chi più ne ha…
Ora, lo ammetto, in questo scenario c’è molto dell’incapacità tutta italiana di pianificare e di arrivare sempre all’ultimo secondo con l’acqua alla gola a dover improvvisare una interrogazione di matematica avendo sfogliato il libro sull’autobus prima di entrare in classe. C’è la particolare tendenza del committente italiano all’ “abito di sartoria” rispetto alla commessa industriale, che cambia i requisiti con facilità disarmante. C’è questo. Ma non solo questo. Ho provato ad analizzarne le cause e, allo stato, sono giunto a questa conclusione: gli oggetti applicativi hanno poco senso. E, allo scadere del primo quinto del ventunesimo secolo, il loro scopo prefissato non è raggiungibile.
Provo a spiegare.
La metodologia OO prevede che un’applicazione sia composta dalle relazioni esistenti tra gli oggetti che la compongono. In particolare, possiamo individuare due macro-tipi di oggetti:
- tecnologici o trasversali (database, tabelle, moduli, menu, messaggi, code, eventi, log, ecc.)
- applicativi o longitudinali (utenti, conti correnti, carrelli, ordini, pagamenti, pazienti, cani, ecc.)
Ci si potrebbe immaginare quindi, e hanno quindi immaginato, una sorta di griglia in cui a seconda di come disponi gli oggetti trasversali e longitudinali e li metti in relazione salta fuori una applicazione. Ma mentre una tabella è sempre una tabella e un menu un menu e si riesce, idealmente, a definirli una volta per tutte, per gli oggetti applicativi non è così. Se per un essere umano, pur se afflitto da laurea in informatica, il cane è sempre un cane, i programmi non vedono così la realtà: il cane dell’anagrafe canina è un oggetto diverso dal cane della farmacia, il quale è un oggetto ancora diverso nel sito di e-commerce di alimenti per animali, diverso per l’assicurazione, ecc. . Hanno proprietà diverse. Metodi diversi. E soprattutto hanno relazioni con altri oggetti applicativi diverse.
Quindi creare un unico oggetto applicativo riutilizzabile, al netto delle problematiche sistemistiche che si porta dietro (DBMS a cui è agganciato, collation, ecc., per non parlare di una eventuale UI che è, con ogni evidenza, impossibile da riciclare), significa portarsi dietro metodi e proprietà a volte tra loro in clamorosa contraddizione e anche tutte le relazioni che potrebbe avere con tutti gli altri oggetti applicativi con cui potrebbe entrare in relazione.
Volete la dimostrazione che gli oggetti applicativi multiapplicazione non possono, allo stato, esistere? Eccola: non li vendono.
Quindi, se non è possibile definire oggetti applicativi riutilizzabili, che senso ha, all’interno di una singola applicazione, creare un’ulteriore indirezione, ossia spostare la logica applicativa dentro l’oggetto model anzichè mantenerla dentro l’applicazione? Perchè la logica del calcolo degli interessi devo implementarla nel model e poi richiamarla una sola volta in un controller che fa solo da passacarte? Se ho problemi di DRY, semplicemente implementerò un metodo dell’applicazione, oppure un oggetto destinato a fare questo tipo di elaborazioni. Perchè il risultato di una vista complessa che coinvolge più oggetti applicativi, cosa assai di frequente utilizzata in un’applicazione, deve essere implementato all’interno del model in cui perde ogni significato, e spesso coerenza, e non nel suo contesto di utilizzo, ossia l’applicazione/controller?
E’ questo dovere agire su due sottosistemi che devo poi mantenere armoniosamente collegati, laddove potrei ottenere il medesimo risultato intervenendo su uno solo perchè l’altro non esiste, che rende tutto così lento, farraginoso, e da un certo punto in poi ingovernabile: il programmatore, per sciatteria e ignoranza, non implementa più i singoli efficienti metodi nel model e si affida alla idratazione automatica degli ORM, fino a quando scopre che per sostenere il sito delle marmellate della mamma ci vorrebbe la potenza di calcolo di un mainframe. E via così per tutti gli esempi che vi possono venire in mente.
Obietterete: certi risultati disastrosi sono frutto di cattiva pianificazione e programmazione. Vero. Ma a parità di qualità del lavoro, rimane che in uno dei due sistemi ho lavorato di più e il risultato rimane più “sparpagliato”, meno sotto controllo e meno facilmente manutenibile.
Come già sottolineato e come chiunque di noi ha sperimentato, gli oggetti applicativi non vivono di vita propria: vivono della relazione con gli altri oggetti applicativi; e queste relazioni il committente ce le sposta 100 volte all’interno del progetto. Il committente italiano, per la sua particolare abitudine alla sartoria su misura, 1000 volte. Se ognuna di queste 1000 volte abbiamo voglia e lucidità (e tempo) di analizzare bene dove e come implementare un metodo che coinvolge la manipolazione o la restituzione di 4 diversi model per dar seguito alle linee guida che il gruppo di lavoro si è date, allora, nello scenario migliore possibile, pareggiamo la chiarezza e la governabilità di un’applicazione che non usa il model. In tutti gli altri casi, in cui trattiamo la fragilità, l’evanescenza, di un oggetto applicativo con la faciloneria a cui la realtà ci costringe, it’s spaghetti-code.
Può darsi che in certe realtà big-enterprise e big-data (very big) il pattern MVC abbia un senso, ossia sia, nel lungo periodo, conveniente. Però lo vedo applicato a tappeto su qualsiasi framework e su qualsiasi progetto, anche al di sotto della soglia “big” (che è, indicativamente, un progetto JAVA da 2 anni di lavoro di 4 persone, ossia sopra i 400mila euro, escludendo i progetti da 40mila venduti per 400mila). Ci sono altri modi per tenere ordinato il codice.
Usare acriticamente gli strumenti destinati ai grattacieli per costruire villette a schiera… è da problem-solver?