RFC: estensione del modello di progettazione MVC

2

Utilizzo da anni il pattern MVC nelle mie applicazioni (con separazione completa del controller dalle sue viste).

Dovendo implementare diverse centinaia di visualizzazioni per rappresentare un po 'più di 100 modelli per un potenziale contratto, questa volta vorrei ridurre i tempi di sviluppo delle mie attività di interfaccia utente e aggiungere alcune funzionalità aggiuntive (visualizzare le decorazioni, ecc.) .

Sono curioso di scoprire se qualcuno ha utilizzato o addirittura implementato un progetto come quello che spiegherò in seguito e, in tal caso, quali erano i tuoi pro e contro.

Senza entrare troppo nei dettagli, mi limiterò a elaborare un esempio di API con cui mi sono divertito nella testa per alcuni giorni insieme ad alcune spiegazioni un po 'più avanti, quindi ecco qui:

Model m = dao.getInstance(ID);  // ie: possibly fetch it from a database

VTextField text = new VTextField();  // simply 'extends' the Swing components

text.setModel(m);

Decorator deco = DecoratorFactory.getInstance();  // specific to a customer

text.setDecorator(deco);

Controller c = ControllerFactory.getInstance(m);

text.setController(c);

Validator v = ValidatorFactory.getInstance(m);  // get the current validator

c.setValidator(v, "validateText");

Quindi nell'esempio sopra, l'idea è che avrò la stessa applicazione per diversi client. Anche se ognuno ha accettato l'usabilità generale, ognuno vuole il proprio marchio L & F ad esso, alcuni basati su regole di business (ad esempio: un campo di testo ha errori, lo sfondo del campo di testo dovrebbe essere in giallo con caratteri rossi ... un altro vuoi il testo in nero e lo sfondo giallo con un bordo rosso).

Quello che stavo pensando è che in ogni evento (su focus, loss focus, tasto digitato, ecc.), il componente invocherà il controller. A sua volta, il controllore (attraverso la riflessione) invocerebbe il validatore. Se la convalida passa, il controllore aggiorna semplicemente il modello. Se la convalida fallisce, il controllore non aggiorna il modello.

Il controller manterrebbe uno stato di tutto questo (visualizzazione, modifica, modifica con errori, ecc.) e delegherebbe al decoratore che regolerebbe la L & F di ciascun componente in base alle richieste del cliente.

Ciò eviterebbe una tonnellata di blocchi "if / else" direttamente in un singolo controller. Il controller, il validatore e il decoratore conoscono l'istanza concreta da caricare in base a quale client esegue l'applicazione. In questo modo, posso separare la logica per ogni client e riutilizzarla quando è un comportamento condiviso.

Il decoratore non si limita ai metodi paintXXX (), ma chiama semplicemente 'setBackground (c)', 'setBorder (b)' e tutti questi metodi setter sono già disponibili nei componenti Swing. Il motivo per cui estendo ogni componente è semplicemente quello di aggiungere i metodi "setModel (m)" e "setController (c)" insieme a qualsiasi logica di framework di cui ho bisogno. Quando il componente è in modalità 'vista', di solito non dipinge il bordo e lo sfondo e tutte le cose (sembra più una pagina web tradizionale). Quando è in modalità 'modifica', sembra più simile a un componente Swing.

Quando progetto le interfacce utente dell'applicazione, di solito rimango a pochi componenti principali (JTextField, JTextArea, JPanel, ecc.). Quindi non sarebbe troppo lavoro da quella parte.

Non ho ancora iniziato a implementare nessuna di queste cose, quindi se conosci le librerie esistenti che eseguono qualcosa di simile, ti preghiamo di indicarle.

I miei unici veri problemi in questo momento sono come gestire casi in cui i componenti dipendono l'uno dall'altro. Ad esempio, due campi di testo con un valore int. Se un campo è dispari allora anche l'altro deve essere dispari e se uno è pari, l'altro deve essere pari. Quando si verifica la convalida, il validatore avrebbe bisogno del valore dell'altro campo di testo per validare correttamente ... quindi non ho ancora risolto questa parte.

    
posta Jeach 22.10.2011 - 19:59
fonte

3 risposte

1

Forse il modello di design Model View ViewModel (MVVM) , un'estensione di MVC, è adatto a te. Permette di separare le preoccupazioni in modo tale che i progettisti dell'interfaccia utente possano concentrarsi sul loro lavoro senza occuparsi della logica di business, ovvero possono concentrarsi sui vari L & F, come desiderato.

Tali framework (ad esempio Microsoft WPF e Silverlight) sono molto potenti ed espressivi. ViewModel è un'astrazione della vista con associazione di dati tra la vista e il modello. Sono sicuro che puoi attuare le tue idee con questi concetti ed evitare problemi seri.

Per ottenere una panoramica di questi framework e la potenza di MVVM, suggerisco questo podcast di Hanssminminutes su MVVM .

    
risposta data 23.10.2011 - 13:36
fonte
1

Questa è un'interfaccia utente desktop, giusto?

Questo potrebbe essere troppo lontano per te, ma secoli fa ho inventato (per necessità) un modo diverso di programmare le UI. L'ho implementato quando ne avevo bisogno nelle lingue C, Lisp, C ++, Visual Basic e C #. Nelle recenti incarnazioni l'ho chiamato dialoghi dinamici e si risparmia un ordine di grandezza del volume di codice su MVC e altri pattern basati su eventi.

L'idea di base è che ho bisogno di un dominio specifico per lingua (DSL) per programmare l'interfaccia utente. Ad esempio, in Windows esiste un linguaggio del compilatore di risorse (RC) utilizzato per descrivere i dialoghi. È un buon DSL, ma il problema è che è troppo "statico". Vive al di fuori del linguaggio di programmazione principale (MPL) e non ha accesso a tutte le variabili e alla struttura di controllo nella MPL. Di conseguenza, deve essere circondato da un sacco di codice MPL per gestire gli eventi, spostare i dati dentro e fuori i controlli, mostrare e nascondere i controlli, o renderli in grigio, ecc. Tutto ciò gonfia il volume del codice e rende difficile la modifica, come aggiungere un controllo richiede diversi passaggi di codifica in luoghi diversi. Gli strumenti possono aiutare con questo, ma la rimozione di un controllo richiede anche diversi passaggi di codifica che non ti aiutano. Inoltre, se vuoi che qualsiasi contenuto dinamico, come interi gruppi di controlli appaiano o scompaiano dinamicamente, o un numero variabile di essi, può essere fatto ma è relativamente complicato da programmare.

In questo DSL, scrivo una funzione (con funzioni secondarie che chiama) in MPL per paint l'interfaccia utente in un dato momento. Quindi quella funzione viene eseguita sotto una struttura di controllo chiamata esecuzione differenziale che trasforma la funzione in una anche per l'aggiornamento incrementale, oltre a cancellare, dell'interfaccia utente. Quindi non devo scrivere codice per apportare modifiche dinamiche all'interfaccia utente. Non devo scrivere codice per spostare i dati dentro e fuori i controlli. Questo è tutto sepolto nel livello di implementazione della finestra di dialogo dinamica. Non devo scrivere gestori di eventi separati o inventare nomi per i controlli. Il codice di gestione degli eventi è incorporato direttamente nel codice che dipinge l'interfaccia utente. Se ho bisogno che il codice di gestione degli eventi sia separato dal codice della vernice, è abbastanza semplice da renderlo una funzione separata, ma non è necessario.

È un modello / paradigma diverso (qualsiasi cosa tu voglia chiamare). Se voglio mantenere una responsabilità separata per aspetto, modello, attività, posso, ma molto spesso non ne ho bisogno. Fa risparmiare circa un ordine di grandezza dello sforzo di codifica (e bug), e "funziona".

Quindi non so se ti è utile, ma se vuoi andare oltre MVC, capisco completamente.

    
risposta data 22.11.2011 - 15:01
fonte
0

Non sono davvero così sicuro di quale sia la tua domanda, ma se è un "Sono sulla buona strada?", allora mi sembrerebbe di sì, sì. Lo schema di chiamate e costruzioni assomiglia molto ai pattern di bean creati in un'applicazione Spring, e Spring è ben noto per promuovere molte buone pratiche e modelli sensibili (eccetto che Spring ti permette di fare molto di più automaticamente cablaggio insieme).

L'unica cosa di cui bisogna fare attenzione è creare motori "do-anything" iper-generalizzati in cui tutto è guidato da regole di business semantico espresse in XML memorizzate in un database complesso ricercato utilizzando un bus di servizio aziendale configurato da ... Bene, ottieni l'immagine Ho visto una serie di progetti che hanno cercato di permettere alle persone di avere applicazioni guidate da descrizioni non create dai programmatori ma invece da qualche business unit, e non hanno mai funzionato molto bene (a meno che non si sia un gigantesco tre) lettera società di servizi globali che desidera avere quantità ancora maggiori di lock-in per i clienti [*] ). Quindi non aver paura di scrivere codice per clienti specifici; invece, pensa in termini di refactoring parti comuni quando trovi che diversi client hanno bisogno della stessa cosa.

[* Ci sono un bel po 'di queste aziende, davvero. Ho lavorato con diversi, e le loro attitudini sono quasi totalmente intercambiabili. ]

    
risposta data 23.10.2011 - 13:26
fonte

Leggi altre domande sui tag