Come dovrei creare un'interfaccia combinata per due moduli logicamente indipendenti?

5

Ho difficoltà a trovare un buon modo per strutturare le interfacce per due moduli che sono logicamente indipendenti ma le cui implementazioni possono essere combinate ai fini delle prestazioni o dell'efficienza.

La mia situazione specifica è la sostituzione dei moduli di accodamento e registrazione separati in un'applicazione di instradamento dei messaggi con un'implementazione combinata supportata da database (chiamiamola DbQueueLog ). È abbastanza facile per DbQueueLog implementare entrambe le interfacce IQueue e ILogger in modo che i client dei vecchi moduli di accodamento e registrazione possano utilizzarlo senza problemi. La sfida è che l'implementazione più efficiente e performante di DbQueueLog comporta la combinazione dei metodi EnqueueMessage(Message m) e LogMessage(Message m, List<LogParams> p) in un metodo EnqueueAndLogMessage(Message m, List<LogParams> p) che riduce al minimo il numero di chiamate database cross-process e la quantità di dati scritti sul disco. Potrei creare una nuova interfaccia IQueueLog con questi nuovi metodi, ma non mi sento a mio agio con cosa significherebbe se una futura iterazione dell'applicazione tornasse a moduli di accodamento e registrazione separati.

Esistono approcci progettuali a questa situazione che mi permettano di costruire un'implementazione efficiente, performante DbQueueLog ora senza dover accoppiare in modo permanente i moduli di accodamento e registrazione dell'applicazione?

Modifica: l'applicazione è costruita su Windows utilizzando C # nel caso in cui vi siano tecniche specifiche della piattaforma che potrebbero essere disponibili.

    
posta Dan 23.09.2013 - 16:07
fonte

3 risposte

1

Sembra che EnqueueAndLogMessage sia un servizio piuttosto tipico. Il mio suggerimento è di esporre un'interfaccia a EnqueueAndLogMessage. Quindi, nella concreta implementazione del servizio, utilizzare due variabili di istanza per le proprie interfacce EnqueueMessage e LogMessage. Ciò ti consentirà di fornire un servizio che gestisce sia le funzionalità di registrazione e di registrazione, senza vincolarti all'implementazione di entrambi. Se non hai più bisogno del servizio combinato, è semplice come chiamare un servizio diverso.

pseudo-codice:

Interface EnqueueAndLogMessageService {
   public void queAndLogMessage(Message message);
}

Class EnqueueAndLogMessageServiceImpl {
   EnqueueMessage enqueueMessageSvc;
   LogMessage logMessageSvc;

   public void queAndLogMessage(Message message) {
      enqueueMessageSvc.queMessage(message);
      logMessageSvc.logMessage(message);
   }
}
    
risposta data 25.09.2013 - 02:38
fonte
1

Se sono moduli logicamente indipendenti che condividono in parte un'implementazione comune, dovresti non creare un'interfaccia combinata per loro, perché ti ti perseguiterà se mai decidere di utilizzare nuovamente implementazioni separate.

D'altra parte, hai menzionato che uno dei moduli è un modulo di registrazione.
Se tutte le chiamate a IQueue dovrebbero (idealmente) essere accompagnate da una corrispondente chiamata al logger, allora potresti decidere di attribuire tale responsabilità all'implementazione di IQueue . Una funzione può chiamare EnqueueMessage e ottenere quell'evento registrato allo stesso tempo, senza alcuno sforzo.

In questo modo, puoi ora utilizzare l'implementazione ottimizzata e, se hai mai bisogno di dividerli, puoi farlo senza influire sugli utenti di IQueue e il programma di registrazione.

Se l'interfaccia di registrazione prende parametri aggiuntivi per i quali non esiste un valore ragionevole e il valore non può essere dedotto dagli argomenti esistenti al metodo IQueue , allora dovrebbe essere chiaro che aggiungere la responsabilità dell'esecuzione della registrazione con l'implementazione IQueue potrebbe significare che devi modificare l'interfaccia di alcuni (o tutti) i metodi IQueue .

    
risposta data 23.09.2013 - 19:51
fonte
1

Vedo qui due casi che potrebbero essere applicabili alla situazione che richiede approcci diversi.

EnqueueMessage è un caso speciale di LogMessage

Non è completamente chiaro dal messaggio, ma sembra che tu voglia combinare EnqueueMessage e LogMessage in una singola funzione che EnqueueMessage è semplicemente un caso speciale (null "p") di LogMessage. In tal caso, anziché combinare le interfacce, le terrei separate e useremo la composizione a proprio vantaggio. In questo caso, ILogger sarebbe un membro della classe che implementa IQueue. Il metodo EnqueueMessage utilizza semplicemente l'istanza di ILogger e chiama il suo metodo LogMessage. Se in futuro l'implementazione di una classe IQueue dovesse cambiare, semplicemente non istanziare più un ILogger.

EnqueueMessage contiene funzionalità diverse da LogMessage

In questo caso, raccomanderei vivamente di essere classi separate e di non avere un'interfaccia combinata. Se hanno effettivamente funzionalità diverse, combinandole insieme si rompono l'incapsulamento e si crea un codice difficile da mantenere. Detto questo, devi bilanciare la manutenibilità con le prestazioni. Basta fare attenzione a non sopravvalutare il guadagno in termini di efficienza della combinazione dell'implementazione. Costruiscilo in entrambe le direzioni e misura la differenza in modo da poter prendere una decisione informata.

    
risposta data 25.09.2013 - 21:44
fonte

Leggi altre domande sui tag