Estendere un'API esistente: Utilizzare argomento di default o funzione wrapper?
-
06-09-2019 - |
Domanda
Ho un metodo esistente (o una funzione in generale), che ho bisogno di crescere funzionalità aggiuntive, ma io non voglio rompere qualsiasi uso del metodo in altre parti del codice. Esempio:
int foo::bar(int x)
{
// a whole lot of code here
return 2 * x + 4;
}
è ampiamente utilizzato nella base di codice. Ora ho bisogno di fare il 4 in un parametro, ma qualsiasi codice che già chiama foo :: barra dovrebbe continuare a ricevere quello che si aspetta. Devo estendere e rinominare il vecchio metodo e avvolgerlo in uno nuovo come
int foo::extended_bar(int x, int y)
{
// ...
return 2 * x + y;
}
int foo::bar(int x)
{
return extended_bar(x,4);
}
o dovrei dichiarare un argomento di default nel file di intestazione come
int bar(int x, int y=4);
e solo di estendere la funzione
int foo::bar(int x, int y)
{
// ...
return 2 * x + y;
}
Quali sono i vantaggi e gli svantaggi di ciascuna variante?
Soluzione
Io di solito uso un funzione wrapper (via sovraccarico maggior parte del tempo), invece di parametri di default.
Il motivo è che ci sono due livelli di compatibilità all'indietro :
-
Avere a livello di sorgente retrocompatibilità significa che si deve ricompilare il codice chiamante, senza modifiche, in quanto le nuove firme di funzione sono compatibili con quelli vecchi. Questo livello può essere ottenuto con entrambi; valori di default e gli involucri / sovraccarico.
-
Un livello più forte è binary-livello compatibilità all'indietro, che funziona anche senza ricompilazione, ad esempio quando non si ha accesso al codice chiamante. Immaginate si distribuisce la funzione in forma binaria, come in una DLL, ecc In tal caso, le firme hanno l'essere esattamente lo stesso per farlo funzionare, che non è il caso per i valori di default - si romperà questo livello di compatibilità .
Un altro vantaggio di funzioni wrapper è - se l'applicazione dispone la registrazione di qualsiasi tipo - si può scaricare un avvertimento nella vecchia funzione che diventerà obsoleta nelle versioni future e che si consiglia di utilizzare il nuovo
Altri suggerimenti
Il più io uso C ++, meno mi piace parametri di funzione di default. Non riesco a individuare alcun motivo specifico per la mia antipatia, ma trovo che se li uso, ho quasi sempre finiscono per rimuoverli in seguito. Quindi il mio voto (soggettiva) va per la nuova funzione denominata -. Il nome potrebbe ovviamente essere uguale a quella del vecchio
Personalmente credo che i comportamenti impliciti sono (uno dei) le radici di tutti i mali.
Tutto ciò che offusca per un manutentore o chiamante l'identità del bersaglio essere invocato dovrebbe avere una forte giustificazione, soprattutto se fa parte di un importante API.
Quindi, direi con forza contro l'opzione con l'operazione predefinita.
Inoltre, credo che se una certa funzione può essere richiamata con un numero diverso di parametri, allora c'è qualcosa di intrinsecamente diverso entrambe le versioni della funzione o che stanno facendo troppo. La distinzione dovrebbe probabilmente essere nel nome, e dovrebbe probabilmente essere più significativo di "_extended"