Architettura per la libreria di messaggistica C ++

2

Ho una libreria, che invia e riceve una serie di messaggi binari e li analizza.

Finora ho usato l'ereditarietà per il mio design, cioè

class BaseMsg 
{
    // init msg from rx'd binary stream
    virtual bool fromBinary(std::vector<char> b) = 0;
    // write msg content to binary stream to tx
    virtual std::vector<char> toBinary() const = 0;

   MsgType type;
};

class MsgA : public BaseMsg 
{
    MsgA()
    {
        type = MsgType::A;
    }

    bool fromBinary(std::vector<char> b)
    {
        // parse binary stream here and init members
    }

    std::vector<char> toBinary() const
    {
        // encode members to binary stream here
    }
private:
    std::string freetext;
    // more members
};

class MsgB : public BaseMsg
{
    MsgB()
    {
        type = MsgType::B;
    }

    bool fromBinary(std::vector<char> b)
    {
        // parse binary stream here and init members
    }

    std::vector<char> toBinary() const
    {
        // encode members to binary stream here
    }
private:
    double latitude;
    double longitude;
    // more members
};

Inoltre ho una classe di messaggistica Messenger , che ha metodi per inviare e ricevere, cioè

bool sendMessage(std::unique_ptr<BaseMsg> msg)
{
    std::vector<char> bin = msg->toBinary();
    // send bin
}

std::unique_ptr<BaseMsg> receive(std::vector<char> receivedBinaryStream)
{
    if (/*check in binary stream, if msg is MsgA*/)
    {
        auto msg = std::make_unique<MsgA>();
       msg->fromBinary(receivedBinaryStream);
    return std::move(msg);
    }
if (/*check in binary stream, if msg is MsgB*/)
    {
        auto msg = std::make_unique<MsgB>();
       msg->fromBinary(receivedBinaryStream);
    return std::move(msg);
    }
}

Funziona abbastanza bene, ma quando uso la libreria finisco per lanciare molto dalla classe base a una sottoclasse specifica. Questo è specialmente dopo la ricezione di un messaggio e l'utilizzo del messaggio nella mia applicazione.

// 
auto msg = messenger.receive(binStream);

if (msg->type == MsgType::A)
{
    // cast to MsgA and continue processing
}
else if (msg->type == MsgType::B)
{
    // cast to MsgB and continue processing
}

Quindi la domanda è, se esiste un'architettura / design alternativo, che eviti i cast nell'ultimo esempio di codice.

La domanda non riguarda i dettagli dell'implementazione, ma se c'è un design migliore rispetto all'utilizzo dell'ereditarietà.

modifica

I messaggi hanno parametri diversi, ad es. MsgA fornisce testo libero, MsgB fornisce informazioni sulla posizione di un oggetto, ecc.

Pertanto, quando un messaggio viene utilizzato dall'applicazione, viene trasmesso alla sottoclasse per ottenere i parametri specifici del tipo.

    
posta Simon 09.11.2018 - 20:45
fonte

1 risposta

2

Innanzitutto, messaggi separati dai gestori .

Invece di avere MessageTypeA gestire la propria analisi da e verso binario; introdurre un intermediario MessageHandlerTypeA che fa questo. In questo modo puoi ridurre i messaggi stessi ai tipi di dati di Plain Ol 'o, per lo meno, semplici contenitori di dati, e puoi mantenere i gestori effettivi instanziati invece di crearli ogni volta.

Quindi nel tuo codice di ricezione del messaggio puoi registrarti per ogni tipo di messaggio che MessageHandler deve trasmettere ai dati binari. Questo è estendibile dall'esterno della libreria poiché è possibile esporre la funzione di registrazione per consentire l'interpretazione arbitraria di nuovi messaggi.

In secondo luogo, utilizza le callback per eseguire ulteriormente la gestione dei messaggi.

Invece del receive e quindi dell'approccio al processo che stai utilizzando, fai in modo che MessageHandler decodifichi il messaggio nel tipo message appropriato e quindi chiami qualsiasi codice che deve sapere su quel particolare messaggio. Il tuo codice chiamante, invece di interpretare il messaggio, registra semplicemente una richiamata con il gestore e quindi riceve una richiamata con il messaggio interpretato ogni volta che viene ricevuto quel messaggio.

    
risposta data 10.11.2018 - 15:36
fonte

Leggi altre domande sui tag