Sto scrivendo un programma client-server con la seguente idea (analogia per il mio vero programma). Ci sono molti tipi di forme. Il client rappresenta le forme all'utente che può accodare le operazioni (come la traduzione, la rotazione ...) su di esse. Il client invia al server id
e tipo di operazione. Il server esegue l'operazione e invia i nuovi dati di forma al client.
Nel mio attuale design ho le classi che dettaglio di seguito.
La classe Shape
si trova solo sul server, le sue sottoclassi contengono algoritmi per eseguire le operazioni per ogni forma (fingere che ruotare un triangolo e un quadrato sia molto diverso). Non voglio né ho bisogno che siano accessibili al cliente.
abstract class Shape {
ShapeData data; // see below
int[] plane; // some non-static parameter used by the server
abstract void rotate();
abstract void translate();
abstract void rescale();
// ... 10 more
}
Anche le sottoclassi siedono solo sul server
class Square extends Shape {
void rotate() { /* using ShapeData data and int[] plane ...*/ }
void translate() { /* " */ };
void rescale() { /* " */ };
}
class Circle extends Shape {
// same structure as square
}
// many more shapes
ShapeData
è una classe che contiene i dati di una forma (stessa struttura dati per tutte le forme). È la classe che viene trasferita dal server al client da cui il client può, ad esempio, disegnare la forma. La classe viene anche utilizzata dal server per eseguire i calcoli come visto sopra.
abstract class ShapeData implements Serializeable {
int id; // after manipulating the shape represented by this class, the
// client send this id back to the server
int edgesNum;
int width;
int height;
// ...
// setters and getters
}
Comprendo che separare dati e comportamenti non è un approccio OO, ma considero questa classe come un DTO ( riferimento )-classi-senza-metodi chiamare.
Ottenere i dati di forma dalla forma è semplice poiché è "composto" in esso, il problema è il contrario. Il server conserva un List<ShapeData>
che recupero da id
, ma non esiste un modo ovvio per ottenere Shape
su cui applicare la trasformazione. Questo mi ha portato a pensare che il design sia pessimo.
In questo momento tengo un Map<ShapeData, Shape>
per recuperare Shape
. Un altro modo è quello di aggiungere un campo id
a Shape
con lo stesso valore di ShapeData
e mantenere un List<Shape>
da cui recupero anche per id
.
Il design è brutto o ci sono solo alcune modifiche che posso fare per farlo funzionare "correttamente"?