Perché è considerata una buona pratica impacchettare il codice del programma e il codice dell'interfaccia grafica in diverse classi?


15

Quindi il mio insegnante mi dice che è molto importante non incapsulare il codice del programma e il codice dell'interfaccia grafica nelle stesse classi, ma per mantenerli completamente indipendenti. Al momento sto scrivendo un gioco per iPhone con una griglia al suo interno. per me ha molto più senso creare sia la griglia grafica che il codice tecnico nella stessa classe "Grid". L'altro programmatore non si accorgerà di questo? È davvero molto importante mantenere l'interfaccia grafica e il codice indipendenti. Quali problemi sorgeranno se non lo faccio?

Grazie!

EDIT: grazie ragazzi! Andrebbe bene per me scrivere prima il progetto e poi copiare il codice per formare la separazione dei problemi di progettazione. So che questo potrebbe completamente vanificare lo scopo, ma proprio come pratica ... Quindi la prossima volta che posso applicare questo modello di progettazione dall'inizio?

Risposte:


17

Il concetto a cui si riferisce il tuo insegnante è qualcosa chiamato Separazione delle preoccupazioni.

Per illustrarlo nel tuo contesto, se completi il ​​tuo programma e decidi di portarlo su Android; dovrai riscrivere molto più codice che se avessi tenuto separata la logica della griglia.

Un controllo dell'interfaccia dovrebbe occuparsi solo di disegnare ciò che viene detto, la logica della griglia dovrebbe riguardare solo ciò che è nella griglia, non come disegnarlo.

Questo aiuta ?


Grazie mi ha aiutato. Il fatto è che è molto più facile per me visualizzare il mio prodotto finale quando incapsulo entrambi in una classe. È questo un motivo valido per me stesso di non seguire la "separazione delle preoccupazioni"? O è assolutamente necessario e non potrei definirmi un vero programmatore: p?

Un effetto positivo di questa separazione è che non devi riscrivere la logica del tuo gioco, se scegli di sostituire la tua interfaccia, ad esempio

@ John - Scrivi un documento di specifica se devi visualizzare il tuo design. Se riesci a descriverlo, puoi iniziare a separare il codice dell'interfaccia grafica dalla logica del gioco stesso.
Ramhound,

3
Inoltre semplifica il test del codice di rete. Testare le GUI è doloroso (a causa di possibili problemi di confusione degli ambienti), quindi ottenere che la GUI sia un sottile livello "ovviamente corretto" rispetto a qualcosa che è testabile è una grande vittoria. (Ancora una volta, questa è separazione delle preoccupazioni.)
Donal Fellows

1
@Giovanni: alcuni di noi imparano meglio facendo. Supponendo che questo progetto non sia così grande, prova a scriverlo come una singola classe e fallo funzionare su iPhone. Ora portalo su Android, tenendo traccia dei tuoi "punti deboli". Infine, riscrivilo come suggerito da Russ C. Penso che vedrai perché la separazione tra logica e presentazione è la strada da percorrere.
Peter Rowell,

4

Per semplificare la modifica del codice . E se domani non volessi usare una griglia ma un elenco? Quando la tua GUI è separata dalla tua logica è facile da fare.

Inoltre scriverai codice più riutilizzabile . Se la tua GUI non contiene il tuo codice tecnico, puoi anche riutilizzarlo. Crea una griglia di fantasia con tutte le opzioni una volta e puoi usarla in altri progetti. Mischiare la tua GUI e il codice tecnico ti impedirà di farlo.

Ti dà anche il codice che è più facile da leggere. Se la tua griglia fa solo la funzionalità della GUI, è più facile capire o cambiare il tuo codice.


3

L'approccio generale della programmazione orientata agli oggetti per una separazione delle preoccupazioni , in cui il codice è separato in attività logiche. Inizialmente, questo può sembrare più lavoro. Ma man mano che il tuo progetto cresce, diventa più facile tenere traccia e gestire il tuo codice.

Per tale motivo, sarebbe probabilmente meglio separare il codice responsabile della visualizzazione di una griglia e del codice che si occupa dei dati che possono essere visualizzati in quella griglia.



0

Per basarti sulle altre risposte e darti un esempio, dovresti in qualche modo permetterti di iniettare la tua logica / i tuoi dati nella tua griglia o viceversa.

Il controllo della griglia può esporre un Rendermetodo o un DataBindmetodo.

class GridControl
{
    public Render(GridData data) { ... }
}

o

class GridControl
{
    public DataBind(GridData data) { ... }
}

Quindi l'unità logica può prendere GridControl e associarvi un oggetto dati o chiamare manualmente il rendering con l'oggetto dati ogni volta che cambia qualcosa.

GridLogic dovrebbe anche avere un riferimento a GridControl in modo che possa essere associato a qualsiasi input / evento.

L'idea alla base dell'associazione dei dati è che il controllo della griglia controlla i dati per eventuali modifiche e si esegue il rendering di se stessi, poiché esponendo una funzione di rendering significa che l'unità logica esegue nuovamente il rendering manuale del controllo.

In ogni caso, suddividere la logica e la griglia in questo modo ti consente di cambiare più facilmente l'una dell'altra senza rompere nulla. Puoi anche scrivere un nuovo controllo come a ListControlper mostrare i tuoi dati come elenco anziché come griglia senza dover riscrivere tutta la tua logica.


0

Consiglio vivamente di dare un'occhiata all'architettura MVC .

È un perfezionamento del concetto che hai citato (separazione del codice del programma e dell'interfaccia grafica). MVC sta per Model-View-Controller. Qui il modello è i dati, View è il codice dell'interfaccia grafica e COntroller è il codice che elabora i dati.

In questo modo hai creato tre parti del tuo programma. Ogni parte può essere sostituita senza richiedere modifiche nelle altre due parti.


0

Dipende dai tipi di cambiamenti futuri che puoi aspettarti che si verifichino. Ciò che si desidera ridurre al minimo è il numero di modifiche manuali al codice necessarie per implementare correttamente ogni singola modifica funzionale.

Dove vince MVC è se le modifiche sono limitate alla parte V o "Visualizza".

Nella mia esperienza, è molto più probabile che i cambiamenti interessano tutte e tre le parti, quindi è meglio se sono non separati. Per mostrare ciò che intendo, ho usato a lungo una tecnica che ho sviluppato chiamato Dynamic Dialogs , in cui un nuovo requisito, come "consentire all'utente di modificare il nome, e quando completo do XYZ" è inserito nel codice sorgente come un singolo blocco di testo:

if(deTextEdit(&sName)){
  // do XYZ
}

invece di più modifiche separate, per specificare che esiste il campo di modifica, per creare un identificatore univoco per esso, per associarlo alla variabile del modello e collegarlo al gestore di eventi lost-focus.

Se vai a quel link vedrai un esempio più complesso.

Fondamentalmente l'idea è quella di trasformare il codice in una lingua specifica del dominio, in modo da ridurre al minimo il numero di modifiche per raggiungere lo scopo. La ragione per cui vuoi farlo non è solo quella di ridurre lo sforzo, ma anche di ridurre la possibilità di introdurre bug, dimenticando o codificando erroneamente una o più modifiche. Riduce anche le dimensioni del codice sorgente di circa un ordine di grandezza.

Non è gratuito Introduce una curva di apprendimento una tantum per il programmatore.


0

L'interfaccia grafica dipende dal sistema, mentre il core del gioco è un algoritmo totalmente indipendente dal sistema su cui gira. Mantenere i due appart faciliterà la manutenzione, il test e il debug del programma perché le modifiche in un sottosistema non influiscono sul modo in cui l'altro funziona. Anche se non ti interessa la portabilità, scommetto che ti preoccupi della robustezza e della manutenibilità del tuo programma.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.