Questa domanda deriva dal problema più concreto chiesto qui
Il problema che vorrei discutere qui sembra essere un modello molto comune nell'ingegneria del software. Molte applicazioni utilizzano l'architettura a due livelli: il livello aziendale e uno strato dell'interfaccia utente. Vorrei sapere qual è il modo OOP più pulito di mappare gli oggetti di business ai loro relatori UI (o alle visualizzazioni, se preferisci). Userò Java per illustrare le mie difficoltà.
Supponiamo di avere una struttura grafica in cui il livello aziendale contiene forme come Circle
, Rectangle
ecc. Tutte sono derivate da un'interfaccia comune Shape
. Nell'interfaccia utente abbiamo CirclePresenter
, RectanglePresenter
ecc. Tutti derivati da ShapePresenter
. La domanda è come mappare un'istanza di Shape
a un'istanza di ShapePresenter
. Vorrei che il sistema fosse estensibile in modo che gli utenti del framework possano aggiungere le proprie forme e relatori senza la necessità di ricompilare.
Ho visto e posso anche immaginare diversi approcci, ma tutti mi sembrano come hack che distruggono la bellezza del buon OOP:
Metodo 1: utilizzo dei visitatori
Se abbiamo un visitatore come questo
interface ShapeVisitor<T> {
public T visitCircle(Circle circle);
public T visitRectangle(Rectangle rect);
}
possiamo usarlo per creare fabbriche di presentatori come questa:
class Factory implements ShapeVisitor<ShapePresenter> {
public ShapePresenter visitCircle(Circle circle) {
return new CirclePresenter(circle);
}
...
}
Questo modello non consente di estendere il framework poiché è necessario aggiungere nuovi metodi al visitatore ogni volta che viene aggiunta una nuova forma. Non sono stato in grado di presentare personalmente un'implementazione dei visitatori estensibile, quindi questo approccio mi è sembrato inutile. Tuttavia, qui è un tentativo di creare un visitatore riflessivo, che afferma di risolvere questo problema esatto. Se questo non è l'hack hacking di tutti gli hack di Java, allora non so cosa sia ...
Approccio 2: Ispirato da Eclipse
Gli schemi di diagrammi di Eclipse come GEF e GMF affrontano questo esatto problema di forme e presentatori. GMF, si basa sulla generazione di codice in cui è necessario specificare le forme e i presentatori in una lingua diversa e quindi il generatore sputa classi Java con tonnellate di controlli instanceof. Questa soluzione non mi sembra molto pulita, per non parlare del fatto che il generatore limita la tua espressività. GEF, d'altra parte, tiene traccia della mappatura di shape- > presenter utilizzando HashMaps. Quando aggiungi un nuovo presentatore, devi aggiungere una voce al registro centrale che è gestita da qualche oggetto dio incapsulabile come PresentationLayer
.
L'approccio GEF ha più senso per me, ma non ne sono ancora soddisfatto dato che aggiunge troppi codici di gestione al framework. Sembra che il 20% del codice si concentri sul problema in questione, definendo e disegnando forme, mentre l'altro 80% è in grado di garantire l'estensibilità. Quindi in questo caso la maggior parte del codice è composta da classi trascendentali come AbstractFactoryExtensionPoint
, CompositeAdapterServiceLocator
o GenericDecoratorRegistry
. Ho solo voluto ingenuamente disegnare rettangoli e cerchi in modo estensibile e ho finito con un gruppo di AbstractAdaptableCompositeRegistryServiceLocator
s che nessuno può capire senza leggere la documentazione di centinaia di pagine.
Qualche idea?