PRIMA E FORMENTE: Perdonami se la seguente domanda rientra nella categoria "off topic" di questo StackExchange, a causa della sua natura di sondaggio leggermente d'opinione. Questa non è la mia intenzione, sto semplicemente cercando consigli sulle buone pratiche in merito alla progettazione generale delle API.
Attualmente sto implementando un framework di sviluppo di applicazioni.
Nell'API framework ci sono client e servizi API. Un client è un oggetto creato dall'utente e un servizio API è un oggetto fornito dal framework. Ogni oggetto deve essere in grado di chiamare l'altro.
Ora al momento vedo due possibili modi per farlo quando riguarda il dominio del problema completo:
SOLUZIONE 1 : ogni oggetto client / servizio deve implementare un oggetto FunctionTable come variabile membro e contenere tutto il codice init richiesto come segue:
struct MyClient {
MyClient(ServiceProxy& service) {
functionTable.init(this, {"foo", "bar"});
service.registerClientContract(&functionTable);
}
void foo(int a, float b) {
}
void bar() {
}
struct FunctionTable<
MyClient,
decltype(&MyClient::foo),
decltype(&MyClient::bar)
> functionTable;
}
SOLUZIONE 1 PROBLEMA: Questo metodo porta a un sacco di codice della piastra caldaia lordo sia sul lato client che su quello API. Questo mi porta alla seconda soluzione.
SOLUZIONE 2 : Il client registra semplicemente le sue funzioni direttamente con il servizio e il servizio crea dinamicamente la tabella internamente sull'heap. Esempio:
struct MyClient {
MyClient(ServiceProxy& service) {
service.registerClientContract
(
MyClient
std::make_pair("foo", decltype(&MyClient::foo)),
std::make_pair("bar", decltype(&MyClient::bar))
);
}
}
SOLUZIONE 2 PROBLEMA : leggermente meno SOLID friendly?
THE QUESTION : la soluzione 1 potrebbe diventare un mal di testa per l'utente dell'API. Un progettista esperto di API si orienterebbe verso i vantaggi di incapsulamento della soluzione 2.
Grazie :)