È sempre ottimale conservare l'incapsulamento in MVC?

3

Ho appena terminato un progetto in cui ho creato una simulazione visiva del ciclo di vita di un'istruzione ARM in un processore a ciclo singolo. Ho usato il pattern MVC in questo progetto e ho incontrato un bivio del design quando ho pensato a come avrei gestito una parte specifica dei dati passati tra il modello e la vista.

Nel mio diagramma nella vista, ho una serie di linee tracciate sui percorsi dati del processore, che evidenzierò in base al passo nel ciclo di vita ARM di cui sto parlando (ad esempio, se l'attuale step fa riferimento a due sorgenti passate all'ALU, le linee corrispondenti a quelle due sorgenti si accenderanno). Per ogni passo c'è una spiegazione testuale di ciò che sta accadendo, così come una serie di linee che vengono evidenziate.

Ecco un gif della vista in azione:

Èsemplicepassareidatitestualitrailmodelloelavistasenzaviolarel'incapsulamento,tuttavianonerosicurodicomegestireidatigrafici(lelinee).HolavoratoconunprogettosimileprimainuncorsochehoseguitoperOOP,ecièstatodettodiignorarelaviolazionedell'incapsulamentoinquestaistanza:quellocheabbiamofattoèstatocreareuninsiemedistatichesonostatipassatidallavistaalmodello,aggiornatoerinviatoallavista.

Misembrachequestasoluzionepotrebbeesseredannosainunasituazionerealeacausadiproblemidilarghezzadibandatrailservereilclient(passandooggettididatirelativamentegrandiavantieindietroperqualsiasicambiamentodistatonellavista).Inoltre,seavessiusatoquestasoluzione,avreiancheviolatountitolarebasedelpatternMVC,mantenendolavistaeilmodellocompletamenteseparati.Selavistadovessepassareisuoioggettilineaalmodello,ilmodellosaprebbeesattamentecomesonostatiimplementatiidati.

Perilmioprogettohodecisodiattenermiallepratichediprogrammazioneaccettateepreservarel'incapsulamentofacendoinmodocheleclassiconcretenelmodelloinviinooggettistringaalcontrollercherappresentaundeterminatoinsiemedilinee.Ilcontrollertradurrebbequestastringainuninsiemepre-inizializzatodisegmentidilineaeliattiverebbe(disattiverebbeancheisegmentidilineanonmenzionati).Questasoluzione,tuttavia,misembracomplicataenonsembraessereingradodiscalaremoltobeneperchéilcontrollerdovrebbecreareunnuovosetdilineeemapparloaqualsiasinuovastringapossibileinviatadalmodello.

Eccounosnippetdelmiocodicecontroller:

privateMap<String,HashSet<Line>>lineSet;publicvoidinitController(){//groupsoflineobjectsinitialized...HashSet<Line>ctrlIn=newHashSet<>();//asetoflinesthatwillbemappedtoastringctrlIn.add(instrH);ctrlIn.add(cond);ctrlIn.add(op);ctrlIn.add(funct);ctrlIn.add(rd);ctrlIn.add(instrV1);lineSets.put("CtrlIn", ctrlIn);//maps the string expected from the model to the set of lines in the view

    ...
}

public void updateLines(ArrayList<String> s){//called by the model to update states of line objects
  activateLines(s);
 }

//helper function for handling lines, called by the updateLines function above
 public void activateLines(ArrayList<String> s){
   for(Line l: currLine)//currline is the current set of displayed line objects
       l.setVisible(false);
   for(String set : s){
     HashSet<Line> c = lineSet.get(set);
     for(Line l : c){
       currLine.add(l);
       l.setVisible(true);
     }
   }
 }

Ecco un codice dalle mie classi di implementazione nel modello:

//'step' is a ArrayList<String> that contains the set of steps in order for the instruction
step.add("Step 1: Step description here...");

//creates an ArrayList<String> object to hold all strings representing lines that should be displayed in the view (translated by the controller)
ArrayList<String> step1 = new ArrayList<>();
step1.add("CtrlIn");
//more strings added to 'step1'...

lines.add(step1);//an array of strings is added to an outer array, corresponding to step 1

Un indice tiene traccia del passo corrente e restituisce due pezzi di dati al controllore: la descrizione del passo dall'oggetto% array% arraylist, e un array di oggetti stringa (corrispondente a un insieme di oggetti linea nel view) dall'oggetto% array% arraylist. Il controller visualizza i dati testuali in una casella di testo, quindi utilizza step per restituire l'insieme di oggetti linea mappati alla stringa restituita dal modello e attiva tutte le linee nel set.

Violare l'incapsulamento qui sembra che potrebbe funzionare meglio per il mio caso perché scalerebbe meglio. Né il controllore né le classi concrete del mio modello avrebbero dovuto fare molto lavoro pesante se fossero entrambi a bordo di ciò che stava accadendo nella vista. Potevo iniettare riferimenti degli oggetti linea nella vista alle classi concrete del mio modello. Quando la vista richiede un cambiamento di stato (passaggio successivo), il modello può semplicemente passare il set di righe da visualizzare - il controllore potrebbe saltare la traduzione della risposta dal modello e aggiornare semplicemente lo stato delle linee nella vista.

Mi sono sbagliato a optare per preservare l'incapsulamento nel mio progetto, o si potrebbe fare un'eccezione per gestire i dati in alternativa, ad esempio nel modo in cui ho descritto sopra? In definitiva, qual è il modo più corretto per gestire i dati degli oggetti di linea in questa situazione, in conformità con le pratiche di programmazione accettate?

Ho provato a limitare la quantità di codice non elaborato per risparmiare spazio: fammi sapere se esiste un codice pertinente relativo alla domanda che dovrei includere.

Grazie per qualsiasi consiglio.

    
posta Nick Borisenko 22.01.2017 - 22:59
fonte

1 risposta

5

Mi piace il design attuale.

It seems to me that this solution could be detrimental in a real-life situation due to arising bandwidth issues between the server and the client (passing relatively large data objects back and forth for any change of state in the view).

Meh, non preoccuparti dei problemi di prestazioni finché non sono problemi reali. Piuttosto, scrivi codice leggibile che rende le prestazioni di tweaking quando è necessario in un secondo momento più facile.

if I used this solution I would also be violating a basic tenant of the MVC pattern - keeping the view and the model entirely separate. If the view were to pass its line objects to the model, the model would know exactly how it's data was being implemented.

Il modello non dovrebbe conoscere i dettagli della vista. Cosa significa esattamente è più facile da capire se immagini di avere due punti di vista. Una vista come quella che hai, tutta grafica e cosa no, e una seconda visione che dice basta solo digitare quali linee sono illuminate. Avere due punti di vista completamente diversi per gestirlo dovrebbe chiarire a cosa non interessa il modello. Il modello dovrebbe essere in grado di estrarre i dati che possono essere utilizzati e nulla che nessuno dei due può utilizzare. Il modello non dovrebbe sapere quali sono le corde xey delle linee. Dovrebbe solo sapere quali linee sono illuminate. Non è un gran numero di dati in movimento.

Posso persino immaginare una terza vista fatta di controlli della GUI come caselle di controllo che vengono spuntate quando la linea che rappresentano è illuminata. L'aggiunta di queste viste non dovrebbe causare il contatto con una singola riga di codice modello.

Se la tua domanda è semplice, "posso ignorare tutto questo?", quindi sicuro. Vai avanti. Per favore, non chiamarlo MVC.

    
risposta data 23.01.2017 - 08:11
fonte

Leggi altre domande sui tag