La situazione
Sto sviluppando un'applicazione desktop JavaFX che può essere descritta in tre parti:
- I dati
- La GUI
- Il processo
La GUI è un mezzo per vedere e modificare i dati e il processo è, beh, un processo che richiede che i dati eseguano il proprio lavoro. Pensa alla GUI come a un pezzo supplementare che consente all'utente di personalizzare il processo.
Data la natura, i dati devono essere scrivibili per la memorizzazione e leggibili dalla GUI. Naturalmente, sto tentando di
Il problema
Diciamo che ho una "Persona" di classe con membri per Nome ed Età. Per poter associare questo oggetto a una vista, deve contenere oggetti Property che rappresentano i dati. Questo renderà la classe intrinsecamente non serializzabile (nel senso che avrò bisogno di serializzarlo con un codice extra). Anche questo tipo blandisce la classe, che sembra una violazione di Separation of Concerns.
Per risolvere questo problema, ho trovato una guida abbastanza standard su StackOverflow. link
La migliore risposta in quella pagina che suggerisce l'uso di DataModels, che sono fondamentalmente versioni osservabili dei tuoi modelli. Inoltre, possono avere metodi "salva" e "carica" per la serializzazione.
Questa sembra una soluzione migliore, per le applicazioni puramente basate sui dati. La mia situazione è diversa, tuttavia, anche se la mia applicazione è basata sui dati, è anche molto funzionale (esegue azioni sullo sfondo).
Se utilizzo i DataModels tradizionali, dovrò assicurarmi che i DataModels possano essere convertiti in modelli non osservabili, o assicurarsi che abbiano metodi per restituire tutti i dati in oggetti non osservabili (come le primitive). Il modulo funzionale del codice non dovrebbe avere bisogno di riconoscere e gestire le proprietà osservabili.
A titolo di confronto, mi piace molto il modo in cui C # ha proprietà intrinsecamente osservabili e si adatta molto bene a WPF. L'approccio di C # mi consente di utilizzare i dati in entrambi i modi senza la necessità di conversioni da e verso osservabili (ci sono eccezioni, ovviamente!).
La domanda
Come faccio a decidere tra queste opzioni?
- Rendere i miei modelli osservabili dalle viste E serializzabili pur continuando a funzionare come modelli base con getter e setter primitivi.
- Creazione di una fase intermedia di DataModels, che sono oggetti osservabili che rappresentano i modelli e si collegano alle viste. Questi oggetti dovrebbero essere in grado di accettare i modelli come dipendenza e in seguito essere riconvertiti nei modelli (dopo essere stati modificati dalla GUI).
La prima opzione è meno codice. Tutto ciò che richiede è un membro di proprietà temporaneo per ogni membro primitivo, nonché 2 metodi per serializzare e deserializzare. Tuttavia, sembra una diretta violazione di Separation of Concerns.
La seconda opzione è più codice, ma separa completamente i dati grezzi e la GUI attraverso un middleman (DataModels). Richiede una classe completamente nuova per ogni oggetto che ho bisogno di visualizzare in una vista, con metodi per la conversione da e verso detto oggetto! Tuttavia, sembra ..... "corretto".
Sto limitando la portata della domanda tra queste opzioni, per adattarsi meglio a StackExchange. Tuttavia, sono aperto a qualsiasi nuova prospettiva!
Ecco alcuni esempi di codice
Ecco un esempio con datamodels
class Person implements Serializable
{
private String name;
public String getName(){...}
public void setName(){...}
}
class ObservablePerson //DataModel
{
private StringProperty name;
public ObservablePerson(Person person)
{
name = new SimpleStringProperty(person.getName());
}
public StringProperty nameProperty()
{
return name;
}
public Person toPerson()
{
...
}
}
Ecco un esempio senza datamodels:
class Person implements Serializable
{
private transient StringProperty name;
public String getName(){ return name.getValue();}
public void setName(String name){ this.name = new SimpleStringProperty(name); }
public StringProperty nameProperty()
{
return name;
}
//
public void serialize()
{
//pseudocode
write(name.getValue());
}
public void deserialize()
{
//pseudocode
name = new SimpleStringProperty(readString());
}
}
Lo scopo principale dell'applicazione è funzionale in natura. Esegue azioni in background. È uno strumento di automazione. Pertanto, i dati (e la GUI) sono complementari alla sua funzione. La GUI è uno strumento di personalizzazione, non una funzionalità di base.