|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
[C# 2.0] Refactor su UI
Ciao a tutti
![]() Ho un oggetto di tipo ToolStrip che viene caricato a runtime sui vari forms con il seguente codice: Codice:
ActionMenu m = new ActionMenu(); this.controls.Add(m); Ora, nel codice che riguarda il toolstrip, scrissi questi metodi: Codice:
public void MenuOnLoad() { menu.Items[1].Enabled = true; menu.Items[3].Enabled = false; menu.Items[7].Enabled = false; menu.Items[13].Enabled = true; } public void MenuOnNewClicked() { menu.Items[1].Enabled = false; menu.Items[3].Enabled = true; menu.Items[7].Enabled = true; menu.Items[13].Enabled = false; } ![]() In pratica, questi metodi fanno in modo che quando viene premuto ad esempio il pulsante 'Nuovo', quest'ultimo si disabilita e vengono abilitati i pulsanti di 'Salva' e 'Annulla' (sempre restando in tema di esempio). Le cose sono simili per gli altri 'stati' del menu. Per quanto rudimentale e magari stupida come cosa, riesco ad utilizzare il menu agevolmente. La domanda che vi pongo sperando di trarne nuovi spunti di apprendimento è quindi del tipo 'come fareste voi' ![]() Grazie mille ![]() RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
una prima bozza:
Codice:
private void SetButtonState(ToolStripButton btn, bool enabled) { btn.Enabled = enabled; }
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
![]() |
![]() |
![]() |
#3 |
Member
Iscritto dal: Dec 2005
Città: Provincia di Vicenza
Messaggi: 174
|
Ciao,
nei miei progetti se devo abilitare/disabilitare dei pulsanti del ToolStrip mi registro sull'evento Application.Idle. Poi nella funzione in base a variabili, stati, etc. attivo o disattivo i pulsanti. ![]() |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Prova a studiare il pattern
MVC oppure MVP oppure MVVM. Troverai la riposta che viene data al tuo problema per la gestione logica delle GUI.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Quote:
Devo dire però che, per quanto appreso fino ad ora, non sono semplici da implementare per una persona sola (almeno per me). In generale, io sono passato dal classico approccio di tipo "faccio tutto nel form", alla separazione (in parte) dei vari aspetti; Ovvero: creo una libreria dove rappresento le varie entità nel modo più semplice possibile, tipo: Codice:
public class Articolo { private int articoloId; private string descrizione; public int ArticoloId { get; set; } //etc... } Codice:
namespace BusinessObject { public class BOArticolo : Entity.Articolo { private IList articoli; public IList GetAll() { factory = new Factory(); articoli = factory.GetAll<Articolo>(); return articoli; } //seguono i vari GetById(), Add(), etc.. } } ![]() Ora, tornando al discorso UI, sto facendo qualche prova di apprendimento con quei patterns, ma sono ancora lontano dal poterci cavar fuori qualcosa di produttivo. Ho messo un attimo da parte il discorso del toolstrip, creandomi un progettino del tipo windows control library e, dopo qualche sforbiciata al codice, riesco ad utilizzarlo agevolmente. Una delle domande che invece vorrei sollevare adesso (in ambito windows form) è: in presenza di molti oggetti di input (textbox, combobox) etc.. immaginando due scenari: Codice:
1) Salvataggio dopo validazione Oggetto o = new Oggetto(); o.Descrizione = txtDescrizione.Text; o.Data = userData.Value; o.Totale = int.Parse(txtTotale.Text); //etc... //o anche: Oggetto o = new Oggetto(); o.GetValori(txtDescrizione.Text, userData.Value, int.Parse(txtTotale.Text), etc...) factory.Add(o); Codice:
2) Dopo aver ottenuto l'oggetto che mi interessa, devo presentarlo a video: Oggetto o = factory.GetById(1); txtDescrizione.Text = o.Descrizione; userData.Value = o.Data; txtTotale.Text = o.Totale.ToString(); //etc.. Ci sono altri modi per fare queste operazioni? Se in un programma devo presentare 50 entità diverse, per ciascuna UI di riferimento dovrò fare un lavoro del genere? Grazie mille ![]() RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
|
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Con l'MVC un'azione su una interfaccia si ripercuote sul modello tramite il controller, ma qui è tutto puramente relativo alla GUI (o vediamo la GUI come il Modello e la View contemporaneamente). Inoltre la sostanza non cambierebbe perchè la struttura del codice verrebbe semplicemente spostata dalla GUI al controller. Alla fine si tratta di gestire una sequenza di stati ben determinati. |
|
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Quote:
In sostanza, mi/vi chiedevo se c'è modo di creare una sorta di persistenza quando il testo o un valore contenuto in uno dei controlli presenti (textbox, checkbox etc..) cambia .
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
E' sempre MVP op MVC o MVVM, ovvero il pattern piu' usato in questi casi.
E' testabile, divisibile tra persone diverse, facilmente serializzabile/deserializzabile, la cui logica e' facilmente riusabile anche se si decide di cambiare tutta la gui, che resta solo lo strato di presentazione.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
E poi anche con un semplice applicativo n-tier puoi cambiare tutta la GUI senza intaccare il resto del programma. |
|
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
Allora, ho fatto un piccolo passetto in avanti in merito alla serializzazione.
Attualmente ho scelto la via dell'oggetto: XmlSerializer. Sono riuscito quindi a serializzare il mio oggetto in un file Xml. C'è ancora un passaggio che mi sfugge però: spero di spiegarmi con un esempio: Codice:
Oggetto o = new Oggetto(); o.Valore = txt1.Text; o.Data = datePicker.Value; o.AltroValore = txtAltro.Text; Serialize s = new Serialize(); s.Serializza(o); 1) Quando il form viene caricato, ovviamente tutti gli oggetti presenti hanno un valore nullo (riferendomi ai vari textbox, combo et similia) ; devo serializzarlo nel momento del load del form oppure dopo aver popolato i vari oggetti per l'input? 2) normalmente, quando salvo i dati dell'input utente in un database, svuoto il form . Come funziona il meccanismo con il quale la serializzazione dovrebbe aiutarmi a gestire in modo automatico il fatto che se richiamo un oggetto, o ne creo uno nuovo, non debba starmi a scrivere chilometri di: oggetto.x = textBox.Text etcetera ? Grazie mille ![]() RaouL.
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Sep 2004
Messaggi: 3967
|
un momento ... ...
![]() forse ho capito. In pratica, una volta che ho serializzato l'oggetto con il relativo metodo, in sostanza io non andrò più ad intervenire settando di volta in volta i valori dei suoi campi: Cioè: Codice:
private void Serializza() { Oggetto bla = new Oggetto(); bla.BlaBla = txt1.Text; bla.AsdAsd = txt2.Text; serializza(bla); }
__________________
Dai wafer di silicio nasce: LoHacker... il primo biscotto Geek ![]() |
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
E la modularita' offerta da MVC (e derivati) e' tale per cui si cambia la GUI, mettendonde un'altra, e anche al logica relativa alla abilitazione/disabilitazione resta salva. E testabile, che e' un requisito di ordine ancora superiore alla riusabilita'.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 19-11-2009 alle 22:08. |
|
![]() |
![]() |
![]() |
#13 | |||
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Mi potresti fare un esempio di utilizzo di MVC dove la View (intesa come GUI) è a sua volta un MVC? Quote:
La logica di attivazione/disattivazione dipende anche dagli oggetti grafici che utilizzi. Se cambio gli oggetti grafici cambia completamente il codice e molto probabilmente anche la logica che riguarda la gestione della GUI. Ad esempio potrei scambiare a livello grafico un click su un pulsante con segnalazione diretta sul Controller con la combinazione pulsante + visualizzazione di un dropdown prima non visibile + selezione elemento dalla dropdown appena visualizzata, sulla selezione eseguo quello che prima veniva eseguito sul solo click del pulsante. Quindi se prima magari dopo il click su un pulsante dovevo disabilitare altri pulsanti ora magari devo disabilitare elementi della dropdown oppure non renderli visibili o magari la nuova organizzazione grafica mi consente proprio di non disabilitarli. Cambia completamente la GUI, ma l'azione finale e i dati necessari alla sua esecuzione rimangono gli stessi. Oppure modifichi il Controller in conseguenza di ogni modifica della View? E' il Controller a dover dire cosa e come deve essere visualizzato sul View? Direi proprio di no, altrimenti il Controller sarebbe tarato su una View perdendo di generalità, quindi cambiando la View saresti costretto a riscrivere anche il Controller. Assurdo. Ovvero nell'ottica del pattern MVC scrivo un'altra View, alternativa alla precedente, ma non vedo come il pattern possa aiutarmi a scrivere questa nuova View. Quote:
Se prima dovevo testare che un pulsante fosse effettivamente disabilitato, ora devo verificare che un valore specifico del checkbox non sia selezionato oppure che non sia proprio presente nella lista. Cambia proprio la logica della GUI. Come mi aiuta l'MVC? |
|||
![]() |
![]() |
![]() |
#14 | ||||||
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Si puo' modellare un controllo complesso con MVC, a sua volta utilizzato una o piu' volte all'interno di un'altra Vista. Ma il concetto e' che hai sempre uno strato di uno o piu' controller da una parte, e uno strato di uno o piu' viste (anche i controlli complessi sono viste) dall'altra. Quote:
Tutta e solo la logica deve stare nel controller. La vista e' solo la presentazione del controller. Niente della vista deve essere la sorgente di informzione, ma tutto deve essere demandato (Binding e NotifyPropertyChanged) al controller. Es: Una checkbox tipicamente sorgente di informazione bool, dovra' andare a scrivere/leggere il proprio contenuto in un opportuno bool del controller, mediante binding. Nient'altro deve essere legato al bool esposto dalla checkbox. Nessun legame/iterazione deve essere permesso nel codebehind della vista, tra i vari controlli della vista. Tutti devono andare a leggere/scrivere i propri dati sul controlo, mediante binding. Di fatto sull'evoluzione del MVC chiamata MVVM, il codebehind della vista in pratica non esiste. E' vuoto. E i binding sono descritti in XAML, quindi di codice sulla vista proprio potrebbe non essercene. L'utilita' sta nel fatto che Modello e Controller possono essere istanziati e funzionare senza bisogno della vista. Che e' proprio lo scopo per poter raggiungere la testabilita' completa di tutta la logica degli Unit tests, che non possono istanziare finestre per vari motivi. - Ad esempio perche' il processo di test non e' un STA thread, e quindi non puo' aprire finestre. - Se crei un STA Thread apposito per creare finestre, allora avrai un'applicazione eseguibile agnostica della quale non potrai andare a leggere/scrivere gli stati del controller, e i test sono una pena (vedi test per GUI sotto) - Anche in questo caso tutto potrebbe andare male, dato che tipicamente la macchina di test e' una macchina sulla quale girano solo servizi, eventualmente neppure loggata, con il risultato che i test di GUI falliscono perche' non possono essere aperte finestre da nessuno. Quote:
Non se cambia la logica. Certo che se cambia la logica in MVC dovra' cambiare sia il controller che la vista... Quello che cambia e' come viene presentato il contesto della vista, che e' parte del controller. Certo che serve uno stato in piu' perche' si e' aggiunto un pulsante in piu', significa che probabilmente o non si era fatta bene l'analisi oppure, poiche' l'abilitazione/disabilitazione ha un significato logico (l'utente puo'/non puo' fare un'operazione), e' proprio questo il caso in cui occorre mutare in primis il controller perche' c'e' uno stato in piu', e poi la presentazione di questo nuovo stato sulla vista. Ma il percorso logico non e' il viceversa. Non e' perche' cambio la vista che allora devo cambiare il controller. Quote:
Quote:
Quote:
Ma per testare la GUI occorrera' semplicemente testare i Bindings. Questo lo si fa tipicamente mediante utility come QTP, che simulano processi tipo "Apro la finestra, cerco il controllo di nome pippo, ci muovo il mouse sopra, clicco, asserto che succeda questo e quest'altro" Ma poiche' non e' necessario testare la GUI ma solo i bindings, il compito di QTP (o simili) e' piu' semplice di quando lo si usa per testare un'applicazione intera. Ed e' anche fattibile, dato che altrimenti ti ritroveresti con un misto di UnitTest + IntegrationTest difficilmente distrivcabile. Nel senso che se testi un'applicazione completa vecchio stile, ti ritroverai l'applicazione con attaccati i servizi esterni, che magari non sono attivi o testabili. Insomma una pena inestricabile. Se invece hai adottato MVC potrai testare la GUI con i soli binding, appositamente gettati su una Mock di input/output, che sara' da dove QTP andra' a scrivere o pescare i dati da confrontare per i test. Senza bisogno di scomodare la logica o addirittura i servizi. Certo che parlarne cosi', senza avere un esempio sottomano, e' abbastanza difficile. Ma per curiosita', l'hai mai adottato o anche solo studiato?
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 21-11-2009 alle 00:16. |
||||||
![]() |
![]() |
![]() |
#15 | ||||||||||||||||||
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Metti che hai una serie di pulsanti, ne clicchi uno e ne disabiliti altri, poi cambi e metti un checkbox + dropdown, dove puoi decidere se togliere proprio gli elementi che prima disabilitavi. Il controller comanderà le 2 View con lo stesso evento, ma le 2 View avranno il loro codice per la gestione di quello stato, che ovviamente dipende da cosa devono visualizzare e come lo devono visualizzare. Quote:
Il controller potrà ritornare alla View uno stato del Model, ma poi quali controlli abilitare visualizzare o altro è pura logica della View. O no? Quote:
Sempre che non sia una view di semplice visualizzazione dati. Quote:
Che fai cambi il controller per adattarsi alla modifica della View? Quote:
Deve essere il controller a specificarlo esattamente? E se il controller impone checked=false, ma l'oggetto grafico non ha la proprietà checked? Il controller mi dirà bool=false, sarà la View a farci quello che deve. Quote:
Ovvero se modifichi la presentazione dei dati, da una visualizzazione statica (tutte le informazioni visibili con stati abilitato/disabilitato) ad informazioni visualizzate dinamicamente (controlli che vengono visualizzati o meno a seconda dello stato) devi cambiare il controller per adattarsi alla mutata View? Quote:
E poi parli di XAML, ma XAML è parte della View perchè non può essere sempre e comunque visto come codice? E' xml piuttosto che C# ma la sostanza non cambia. Se sono in una WebApp me ne faccio di poco di XAML e scrivo il codice della View nella pagina aspx o ascx che sia. E anche in Asp.Net MVC vado a modificare il codice inline nella pagina. Quote:
Personalmente non avevo interpretato così l'MVC, avevo sempre inteso che la View dovesse comunque occuparsi della gestione della visualizzazione dei dati, comandando o essendo comandata dal controller per la modifica del model, ma mai che il controller dovesse conoscere cosa viene visualizzato e come. Quote:
Altrimenti secondo questa visione sarebbe impossibile effettuare test su interfacce web, e invece si fanno eccome, lo stesso vale per le interfacce tradizionali. Quote:
*che poi cambiare tecnologia di visualizzazione comporta lo stravolgimento dell'interfaccia quindi secondo quello che dicevi prima devo cambiare il controller perchè è lui a dovermi esplicitare direttamente abilita/disabilita piuttosto che visualizza/non visualizzare. Se passo da una webapp tradizionale ad una ajax è la view a stabilire cosa è in un ajaxpanel piuttosto che no, hai voglia al controller a dire cambia lo stato di un oggetto che non sta nell'ajax panel, lo stato di quell'oggetto non verrà visualizzato e magari questo è il comportamento voluto per la View. Quote:
Quote:
Quindi il controller viene ad essere tarato sulla specifica visualizzazione. Quote:
se in una pulsantiera ad un click disabilito alcuni pulsanti, poi ne clicco un'altro e cambio di conseguenza gli stati dei pulsanti, io potrei decidere che invece di far vedere tutti i pulsanti, magari li visualizzo come una specie di wizard, dove la prima selezione mi determina un cammino di visualizzazione specifico, in cui faccio apparire solo i comadi ammessi in altra forma rispetto ai predenti pulsanti. Per me è solo un refactoring della GUI, sinceramente non vedo l'esigenza di cambiare il controller. Quote:
Quote:
Quote:
Ma i mock ti servono in ogni caso anche nell'MVC, dopo tutto il model potrà provenire da qualche fonte dati esterna no? Come carichi il model? O con i test di integrazione o con i mock. Mi è capitato più volte di dover inserire unit test su applicativi convenzionali, se l'applicativo segue un minimo di ordine è fattibilissimo. Decisamente da rinunciarci per programmi con "funzioni" di migliaia di righe, con codice replicato decine di volte. Spesso nasce l'esigenza anche di testare l'intero applicativo perchè magari la fonte dati viene modificata anche in altri contesti all'insaputa del programma, quindi è necessario sapere anche quando il programma smette di funzionare per influssi esterni, i semplici unit test in questo caso non aiutano, il programma risulterebbe sempre funzionante, quando nella realtà non lo è. Quote:
Quote:
Ovviamente se la logica è puramente di presentazione io la scrivo nella View, non mi sogno minimamente di modificare il Controller per gestire nel dettaglio gli stati della View, che comporterebbe avere un Controller per ogni View. Potrei anche aver interpretato male il pattern, se così fosse preferirei il tradizionale n-tier dove quello che riguarda la visualizzazione rimane confinato nella GUI e tutta la logica nel business, che non deve preoccuparsi di come vengono visualizzati i dati. |
||||||||||||||||||
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
SAi che non ho capito il tuo scopo in questa discussione?
Stai chiededno informazioni perche' vorresti capire meglio (Anche se dici che l'hai usato, da alcune domande o considerazioni che hai posto ho forti dubbi) oppure vorresti dire il tuo punto di vista? E' uno dei pattern piu' complessi, ed e' il piu' usato in ambito GUI. Chi lo vuole usare lo usi, chi non lo vuole usare non lo usi. Quando mi venono poste problematiche come quelle di partenza, per me e' naturale risolvere i problemi con il baglio di conoscenze che ho acquisito. Modi di fare GUI ne ho fatti provati e usati decine. Da GUI fatte con i piedi di programmi stile anni 70 a GUI avanzatissime come quelle che sto usando proprio in questo periodo. E da quanto ho appreso finora MVC (MVVM nello specifico) e' il piu' efficiente se si devono ottenere diversi requisiti. I soliti di riusabilita', modularita', divisione di compiti tra chi disegna la logica e chi disegna la GUI, etc. Ma senza esempi pratici e' inutile andare avanti.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 21-11-2009 alle 12:38. |
![]() |
![]() |
![]() |
#17 | ||||
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Ovvero se è corretto il tuo punto di vista io non ho capito niente dell'MVC. Per questo sto cercando di capire. Ovvero ogni funzionalità della View deve essere mappata 1:1 sul Controller? Se è così ogni Controller è strettamente legato alla View, altrimenti la View può avere una sua logica di funzionamento che non è sotto diretto controllo del Controller (quello che sostengo io, visto che è quello che mi capita di continuo nel refactoring di GUI mantenendo intatto tutto il resto). Quote:
Quote:
Quote:
Come il controller comanda direttamente i singoli elementi grafici? Secondo me non è il suo compito, secondo te invece è il controller a stabilire esattamente le proprietà di ogni singolo elemento grafico. |
||||
![]() |
![]() |
![]() |
#18 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Comunque, Il concetto principale del MVC e' quello di Binding, ovvero un "amenicolo" che crea un legame: - ad una via tra controller e vista (Forward binding o one way) - ad una via tra vista e controller (Backward Binding) - a due vie (Two ways) In presenza di un binding forward, ogni volta che cambia la proprieta' nel controller, allora cambiera' automaticamente la proprieta' reltaiva nella vista. (Tipicamente per segnalare al mondo esterno uno stato o una informazione del controller) in un binding backward, ogni volta che cambio la proprieta' del contrllo, allora cambiera' automaticamente anche la proprieta' relativa del controller (Tipicamente per dare gli input in pasto al controller) Un binding a 2 vie fa invece ambo le cose (Tipicamente per quando c'e' una proprieta' che puo' essere precaricata con qualche valore da qualche servizio, ma che puo' pero' poi anche essere cambiata dall'utente) Ad ogni vista e' associata, in ogni istante, un controller. Il controller e' di un certo tipo specifico, ma questo tipo non e' importante per la vista. La vista sa che c'e' un "oggetto" che espone determinate caratteristiche. A seconda che si scelga un MVC implementato mediante interfaccia oppure mediante WeakType, allora la vista si trovera' un'istanza di una interfaccia, oppure semplciemente un object. MVVM e' WeakType. Per quanto riguarda la vista, il controller e' un semplice "object", che avra' alcune determinate proprieta', accedute internamente dai binding di WPF mediate reflection immagino. Nel primo caso il binding con questo oggetto verra' fatto esattamente, nel secondo caso avverra' solo per nome, p.es. con una prorieta' del controller chiamata "CanChangeTown" La vista non deve avere nessuna logica. Potra' avere all'interno di se' solitamente i binding e nient'altro. Compito dei binding e' quello di spostare gli input fatti sull vista, verso il contoller, e viceversa. Certo, ci sono elementi grafici che fanno parte solo strato di presentazione, e quindi della sola vista, ad esempio: - Quando capita un errore, voglio segnalare sulla vista che c'e' questo errore. Il controller espone una stringa "Error". Non appena questa stringa e' diversa da null, allora la vista deve presentare quest'errore come meglio crede. (E poi tipicamente la presenza di un valore in questa stringa pilota anche altre proprieta' esposte, quelle relativa agli stati, ma non necessariamente) Potrai effettuare il binding di questa stringa direttamente sulla proprieta' Text di una label, perche' il grafico ha deciso che e' meglio cosi'. E qui non avrai bisogno di alcun codice aggiuntivo. Oppure potrai presentare questa stringa nel titolo della finestra. E qui non avrai bisogno di alcun codice aggiuntivo, effettuerai il binding sulla proprieta' Text della vista Oppure potrai presentare questa stringa su un controllone custom che accetta appunto una stringa, e che ciclera' le lettere una ad una presentandole su una porzione di schermo, renderizzando ciascun carattere a mano, diesgnandolo proprio con linee in grande (Drawline). Qui avremo quindi un timer interno, che si occupera' della presentazione, magari un pezzo di codice per disegnare il carattere, etc. E qui avrai pacchi di codice aggiuntivo relativo alla vista, ma il concetto e' che tutto questo nuovo "Controllone" dovra' poter essere pilotato e "acceso" semplicemente con una stringa. Ovvero cio' che si vuole segnalare all'utente. "Potresti" avere questo pacco di codice aggiuntivo. Ma tipicamente non l'avrai (vedi fine) Qualunque cosa tu scelga comunque potresti avere del codice attivo nella vista, ma che non deve utilizzare come input nient'altro che questa stringa, ed eventualmente altre proprieta' che il controller espone. Ma le abilitazioni/disabilitazioni di controlli di una vista sono tipicamente e quasi sempre tutte informazioni decise a priori, da colore che hanno studiato la logica. Io ad esempio NON voglio a priori che l'utente possa cambiare il numero di soldi richiesti su un bancomat tra quando li ha digitati, il bancomat ha controllato e quando l'utente magari clicca OK. Ci sara' un controllo relativo server-side, ma nel disegno della GUI io non voglio neppure permettere all'utente di farlo, e quest'informazione la presentero' a livello di controller. Il controller avra' qundi una proprieta' public bool CanChangeMoneyField che verra' bindata con Forward Binding dalla vista verso la proprieta' che piu' le aggrada (Magari la IsEnabled di una textbox) Il controller cambiera' il valore di questa proprieta' a suo piacimento, durante l'esecuzione. In questo modo io potro' testare in 2 momenti diversi Un primo momento sara' il test della logica. Ovvero crereo' l'istanza del controller, con le mock dei servizi creo le istanze dei modelli, passo di volta in volta i modelli al controller, piloto le proprieta' del controller che sarebbero in realta' pilotate dai binding della vista (Ad usempio il PIN messo dall'utente del bancomat) e vado a controllare che le propireta' output del controller siano transite negli stati corretti (ad esempio il CanChangeMoney vada a false quando ci si aspetta) Non ho creato istanze di vista. Poi testero' la vista. Per come e' costruita devo testare solo i Binding. Per testare i binding daro' in pasto alla vista una versione semplificata del controller, con stesse anolghe proprieta' del controller originale, ma Fake. Simulero' ad esempio gli input nelle textbox, e andro' a vedere che la proprieta' relativa bindata sul controller abbia assunto io valore corretto. Simulero' un click del mouse su un pulsante, e andro' a vedere che il comando relativo del controller finto sia stato eseguito. Non ho usato il controller vero, e il tool di test grafico (come dicevo ad esempio QTP) avra' un compito quasi banale. Scrivo un testo nella textbox, guardo l'output di 1 o proprieta' del fake controller. Clicco un pulsante, e vado a vedere cosa e' capitato sul controller (Se si implementa il Command pattern e' addirittura standard e banale) Niente mock, niente servizi, niente logica. Solo i binding. Cambio il CanChangeMoneyField del controller Fake, e andro' a vedere se la textbox dei soldi si e' effettivamente disabilitata. Nell'esempio di cui prima con quel controllone, se quel controllone e' un oggetto davvero complesso, si puo' pensare di modellare anche lui con MVC (Questo chiedevi all'inizio?) Ovvero a sua volta esso avra' una vista di presentazione e un controller con appunto almeno una proprieta' stringa, magari chiamata "InputString". Poi il controller di questo controllone esporra' altre proprieta' come "QualcosaDaPresentare", dove di volta in volta verra' piazzata ll'informazione sufficiente per renderizzare la singola lettera che di volta in volta capitera' a schermo, quinid magari una lista di punti-linee, colori, etc. Ma di nuovo la vista relativa sara' stupida. E potremo testare questo controllone di nuovo con i due momenti. Cambio la vista da WPF a WebApp? Cabmio il modo di rappresentare l'errore da "Mettilo sul titolo" a "Usa il nuovissimo controllone che disegna un carattere alla volta"? Fa lo stesso. La vista cambia di sicuro, ma la logica del controller e' salva.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 21-11-2009 alle 14:27. |
|
![]() |
![]() |
![]() |
#19 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Imho una buona spiegazione del paradigma M-V-VM è in questo video:
http://blog.lab49.com/archives/2650 Anche se è *lievemente* lunghetto.. ![]() cmq sostanzialmente concordo con gugoxx nella sua altrettanto lunga spiegazione. ![]()
__________________
![]() |
![]() |
![]() |
![]() |
#20 | ||||||||
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Quote:
Io dico di no. Mi sembrano tutte logiche della View che non hanno influenza sul model o il controller. Quote:
Quote:
Anche perchè devi anche testare cosa succede se il tuo Controller non risponde quello che ti aspetti. Se clicchi e ottieni una eccezione? Quote:
Quote:
Quote:
Quote:
Puoi sempre mettere un altro pattern MVC sopra quello esistente in modo che il Model di questo nuovo componente sia il Controller precedente, ma il problema si sposta logicamente verso il livello superiore: deve il nuovo Controller essere a conoscenza di Sessioni o ViewState oppure la loro esistenza rimane confinata nella View? Se cambio dall'uno all'altro agisco solo sulla nuova View o mi modifico anche il nuovo Controller? Ultima modifica di tomminno : 21-11-2009 alle 20:47. |
||||||||
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 17:16.