Come progettare un sistema che consente estensioni multiple parallele dello stesso "componente"?

6

Come giocatore, ho riscontrato i seguenti problemi relativi alla creazione e all'utilizzo di "estensioni" (alias mod) per i giochi:

1) Whenever the game is updated, all the mods break.

2) Most mods don't work with each other, so the player "has to choose"

3) If you ever de-install a mod, your "saved games" almost always become unusable.

Voglio progettare un gioco in Scala / Java che NON mostri questi problemi. Ho bisogno di aiuto con il punto 2. Voglio scriverlo in modo tale che sia massimamente estensibile. Il mio problema è che non riesco a inchiodare correttamente come dovrei fare questo, e dal momento che l'intero progetto risiede in cima all'architettura componente / servizio / plugin, che non posso andare avanti fino a quando non ho risolto questo problema.

Le qualità di design che voglio raggiungere sono:

1) For any "service", there should be a single object (at any given time) that implements it. Since it is a cycle-based simulation, I can safely "swap implementation" between the cycles.

2) It should be possible for a "third party" to create a "bundle" which either modifies or more likely extends the functionality of a "service", and "bind" it into the existing application at runtime, without recompilation.

3) It should be possible to load and unload those bundles at runtime, because they will be used in a long-running server.

4) Developing extensions should be easily possible, even for a "junior" programmer, without requiring extensive knowledge of some complex framework.

5) It should be possible for several bundles to extend/modify the same service at the same time, as long as they follow a certain set of rules preventing most conflicts.

Prima stavo progettando di usare OSGi, ma non riesco davvero a vedere come farlo funzionare. La soluzione OSGi consiste nel consentire a molti bundle di registrare lo stesso servizio e utilizzare un "filtro" per sceglierne uno nel codice client. Rendendo il codice consapevole che in un dato momento, ci possono essere diversi oggetti che implementano diverse varianti dello stesso servizio, e che tali istanze possono andare e venire, renderebbero tutto troppo complicato e fragile.

Il mio piano era di registrare ogni servizio come un "handle" generico, che l'utente del servizio può utilizzare per ottenere l'istanza e il cast reali su ciò che vogliono. Il contenuto dell'handle potrebbe cambiare nel tempo, ma l'oggetto handle stesso sarebbe valido per la durata del programma, ignorando quindi l'interrogazione costante del registro, con il filtro associato.

Penso che OSGi possa risolvere da 2 a 5, ma solo usando più istanze dello stesso servizio, che è in contraddizione con 1. Penso che 1 si possa ottenere usando la composizione, o fondendo tutte le diverse implementazioni di un servizio in un singolo oggetto tramite manipolazione del codice byte. Uno sguardo a Javaassist mi ha mostrato che "ridimensionare" una classe non sembra troppo difficile, se tutti estendono la stessa classe base e prendono gli stessi parametri del costruttore. La composizione, d'altra parte, sembra mettere molto più lavoro nelle mani degli sviluppatori di estensioni di terze parti, che è in contraddizione con 4, e generalmente è una soluzione goffa al meglio.

Se implemento la strategia di manipolazione del codice byte, allora sostanzialmente devo fare quasi tutto io stesso e perdere la maggior parte dei benefici di OSGi. Inoltre, non riesco a creare il servizio di fusione fintanto che non sono stati attivati tutti i pacchetti , quindi non possono registrare un'istanza di servizio "reale" al momento dell'attivazione, che è ciò che OSGi tratta (?). So già da OSGi quando è "finito"?

L'unico modo per raggiungere questi obiettivi è creare un mio framework di componenti, o posso ancora farlo usando OSGi o qualche altro sistema? Reinventare la ruota a quel livello sembra un'idea stupida (e che richiede tempo), ma non riesco a vedere come risolvere questi problemi con OSGi. Forse un altro framework di servizio / plugin può farlo? O utilizzando una strategia di progettazione ben definita specifica?

UPDATE: Sarà un modello Client-Server Internet (Cluster) in esecuzione su OpenGL. Io sono per lo più "quadro privo di ostacoli", cioè posso scegliere qualunque cosa si adatta alle mie esigenze, ma voglio attenermi alla JVM. OSGi è un tentativo di standardizzare "componenti" (chiamati bundle) per JVM.

    
posta Sebastien Diot 12.09.2011 - 16:54
fonte

3 risposte

2

Java Swing gestisce questo problema usando i gestori di azioni. Ogni componente si registra utilizzando uno o più gestori di azioni. Quando si verifica un'azione particolare, ogni componente registrato ottiene l'opportunità di eseguire del codice in risposta all'azione.

Un'idea simile è un sistema di messaggistica. Un componente si registra per ricevere messaggi. Il componente è responsabile di rispondere a qualsiasi messaggio che sceglie.

Entrambe queste idee si basano sul componente che ha accesso al resto della base di codice. Non sono sicuro di come rendere al meglio pubblico tutti i campi e le istanze del gioco. Suppongo che un insieme ben definito di interfacce di programmatori di giochi sia il modo migliore.

    
risposta data 12.09.2011 - 17:58
fonte
2

Concettualmente, vuoi gestire Programmazione dei componenti , in cui una sezione di codice, magari sostituita con un'altra, o una nuova sezione di codice simile potrebbe essere aggiunta, rimossa o aggiornata in fase di runtime .

link

Ho letto diversi modi per farlo, a seconda del linguaggio di programmazione e del quadro di programmazione che stai utilizzando. Ignoro come farlo con "Java Framework" o "Scala Framework".

(Ho fatto qualcosa di simile con C / C ++ e Object Pascal (Delphi) e "Shared Libraries" sulla rete Windowze)

Il tuo gioco o applicazione si troverà in una rete, in internet o in una app desktop indipendente. ?

È destinato a essere eseguito su una pagina Web (javascript), un controllo flash o un'interfaccia desktop come Swing o SWT?

La tecnologia per implementare un'applicazione "component driven", è molto diversa da una "piattaforma" o da un ambiente, da un altro.

Dal lato del linguaggio di programmazione, la maggior parte di questi "pacchetti" o "componenti", sono oggetti che condividono la stessa classe o implementano la stessa interfaccia.

    
risposta data 12.09.2011 - 17:40
fonte
0

Il vecchio gioco Dark Forces 2: Jedi Knight non aveva questo problema. In sostanza, tutte le risorse di gioco sono state archiviate in un luogo. Potresti aggiungere risorse addizionali e usarle (a patto che non stessero sovrascrivendo le risorse ... ad esempio sostituendo le skin) e tutto ciò era onnicomprensivo. Devi solo fare riferimento a fasi / risorse personalizzate con un nome univoco. È solo una progettazione appropriata e include il nome del pacchetto come parte dell'ID risorsa.

Se ho una comprensione grossolana errata della tua domanda, fammelo sapere, ma penso che questo sia un approccio valido a ciò che stai affrontando.

    
risposta data 12.09.2011 - 20:55
fonte

Leggi altre domande sui tag