Come rispondo ai messaggi di rete in arrivo in modo da ottenere un accoppiamento lento?

3

Sto lavorando a un tipo di protocollo client-server in questo momento in Ruby. Ho avuto un problema in cui non sono del tutto sicuro su come procedere. Attualmente, ho una classe, Remote che indica una connessione remota (da utilizzare tramite EventMachine). Quando Remote riceve un messaggio (cioè, pacchetto di rete), lo invia a MessageDecoder , che restituisce il messaggio decodificato in un hash, in questo modo (pseudo-codice in anticipo)

{ source = <the_remote_connection>,
  message_code = 1, // An operation code that indicates how to respond to this message
  payload = {
    packet_specific_key = packet_specific_value // provided by the decoder
  }
}

Quindi, quando ritorno da MessageDecoder , Remote lo spedisce alla sua ConnectionListener , che deve decidere come distribuire quel messaggio attraverso l'applicazione. Ecco il problema: ogni messaggio potrebbe richiedere un diverso ambito di variabili. Ad esempio, uno potrebbe richiedere l'istanza di un oggetto World di cui ConnectionListener non è a conoscenza (e, giustamente, non dovrebbe - il codice di rete non dovrebbe essere accoppiato al resto del programma)

Quindi la mia domanda è: come posso implementare un sistema liberamente accoppiato per distribuire la ricezione di messaggi ignoranti dalla rete da una connessione remota nella mia applicazione che in qualche modo conserva magicamente gli ambiti?

MODIFICA: per commenti, esempio.

Supponiamo di avere un oggetto World . Il World conosce le entità al suo interno: rocce, alberi, si ottiene l'idea generale. Quindi, arriva un comando dal Remote che dice :DestroyRock - che dovrebbe invocare World#destroy_rock . Il World non dovrebbe sapere dove viene il comando a :DestroyRock . Dovrebbe solo sapere che World#destroy_rock è stato invocato su di esso.

Il problema è che ho bisogno di trovare un intermediario tra ConnectionListener e World#destroy_rock . ConnectionListener sicuramente non dovrebbe conoscere l'oggetto World , perché se lo è, significa che ora ho accoppiato il mio codice network al mio gameplay logica .. funziona. È piuttosto brutto.

    
posta Dan Pantry 10.03.2014 - 15:33
fonte

1 risposta

0

Il ConnectionListener deve conoscere l' World istanza , perché ha bisogno di passarlo al comando. Il ConnectionListener è già un intermediario, aggiungendo un altro intermediario non risolverà nulla. Dovrebbe, tuttavia, conoscerlo solo tramite l'interfaccia . ICommandable o qualcosa del genere. Ciò fornirebbe un metodo per passare il messaggio e restituire una risposta appropriata, possibilmente anche per fornire una risposta / messaggio asincrona al client e probabilmente un filtro che i messaggi dovrebbero gestire da questo oggetto.

Più nel codice di inizializzazione creerai l'istanza World e l'istanza ConnectionListener e registrerai il mondo con il listener. Qualcosa come:

listener.addCommandable(world);

probabilmente il filtro ha più senso qui che all'interno dell'oggetto, quindi forse

listener.addCommandable(':DestroyRock', world);

(o con un elenco di comandi o qualcosa del genere).

Potrei anche avere senso implementare l'interfaccia non nell'oggetto World stesso, ma in un adattatore, quindi l'oggetto World non ha bisogno di conoscere il formato del comando dalla rete. Soprattutto se ci sono altri modi per inviarlo comandi come una versione stand-alone che ha sia l'interfaccia utente che il motore in un unico processo e non usa la rete.

Ovviamente, dato che Ruby è tipizzato dinamicamente, una "interfaccia" è solo un insieme documentato di metodi.

    
risposta data 10.03.2014 - 16:51
fonte

Leggi altre domande sui tag