2013-11-26 9 views
6

Quali strategie ci sono per le funzioni di deprecazione quando il tipo di ritorno deve cambiare? Ad esempio, ho:Come deprecare la funzione quando cambia il tipo di ritorno C++

BadObject foo(int); // Old function: BadObject is being removed. 
Object foo(int); // New function. 

Object e BadObject sono molto diversi internamente e scambiando i loro tipi restituiti spezzerò codice per gli attuali utilizzatori di mia libreria. Sto cercando di evitarlo.

Posso contrassegnare BadObject foo(int) deprecated e dare agli utenti il ​​tempo di modificare il codice interessato.
Tuttavia, I can't overload foo based on return-type. foo ha un nome molto buono, e non ha bisogno di prendere parametri extra. Come posso aggiungere la nuova funzione alla mia libreria mantenendo la versione precedente, almeno per un po '?

Qual è la strategia per deprecare la vecchia funzione senza interrompere troppo il codice dipendente, fornendo agli utenti il ​​tempo di migrare alla nuova versione? Idealmente manterrei il nome della funzione e l'elenco dei parametri attuali, perché è chiamato abbastanza bene ora. Sembra che questo sia un problema ragionevolmente comune: qual è un modo decente per risolverlo?

+0

Bene, se gli utenti usavano l'auto ovunque, invece di digitare manualmente il tipo restituito, tutto funzionava automaticamente :). – ScarletAmaranth

+0

Questo non ti aiuta ora, ma gli spazi dei nomi inline C++ 11 sono perfetti per questo. Dichiarate 'pippo' in' namespace inline v0', quando è richiesta una modifica dichiarate 'foo'' in' namespace inline v1' (e rimuovete 'inline' da' v0'). – mythagel

risposta

4

Sebbene la soluzione sia obbliga a modificare i nomi delle funzioni, ma sarà un compromesso tra i vecchi utenti e quelli nuovi.

Così - Rinominare il vecchio foo in deprecatedFoo e il vostro nuovo foo in foo2 (o tutto quello che vuoi). Poi, nel file di intestazione di includere con la libreria, si può semplicemente:

#define deprecatedFoo foo 

e all'interno della funzione stessa do:

#warning ("This function is deprecated. Use 'foo2' or change the #define in LINE in file HEADER.") 

Gli utenti delle vecchie versioni non dovranno cambiare il loro codice e verrà emesso un avviso e i nuovi utenti probabilmente ascolteranno e modificheranno il #define per utilizzare il nuovo foo.

Nella prossima versione sarà sufficiente eliminare il vecchio foo e lo define.

+1

Intendevi che '# define' nell'altro modo? Allo stesso modo, gli utenti della nuova funzione otterranno lo stesso numero di avvisi degli utenti della vecchia funzione. – aschepler

+0

Gli utenti della nuova versione dovrebbero ricevere l'avviso, in modo che possano (se lo desiderano) cambiare. Se hai fatto il '# define' in modo opposto, il codice non sarebbe compatibile con le versioni precedenti. Ma penso che sia una scelta che l'OP dovrà fare, e non siamo noi a discuterne. –

0

Penso che un esempio classico sia Boost's Spirit.

Dal loro FAQ:

Mentre l'introduzione di Spirito V2 abbiamo ristrutturato la struttura delle directory in per ospitare due versioni allo stesso tempo. Tutti Spirit.Classic ora vive nella directory

boost/spirito/home/classic

in cui le directory di cui sopra contengono le intestazioni di inoltro alla nuova posizione che consente di mantenere la compatibilità delle applicazioni. Le intestazioni di inoltro emettono un avviso (a partire da Boost V1.38) che dice allo all'utente di modificare i percorsi di inclusione. Si prega di attendere presto le directory /intestazioni di inoltro.

Questo spiega la necessità per la directory

boost/spirito/include

che contiene l'inoltro intestazioni pure. Ma questa volta le intestazioni non andranno via. Incoraggiamo gli scrittori di applicazioni ad utilizzare solo gli include contenuti in questa directory. Questo ci consente di ristrutturare le directory sottostanti, se necessario, senza preoccupare la compatibilità dell'applicazione . Si prega di utilizzare questi file solo nella vostra applicazione. Se è risulta che manca un file di inoltro, si prega di segnalare questo come un bug.

È possibile semplificare la migrazione mantenendo le versioni nuove e vecchie in directory separate e utilizzando le intestazioni di inoltro per mantenere la compatibilità. Gli utenti saranno infine costretti a utilizzare le nuove intestazioni.

SDL 2.0 ha un approccio diverso. Non forniscono un livello di compatibilità ma piuttosto una guida alla migrazione che accompagna gli utenti attraverso i cambiamenti più drammatici. In questo caso, puoi aiutare gli utenti a capire come devono ristrutturare il loro codice.

0

Cosa fare se si desidera ereditare la classe Object da BadObject (che manterrà temporaneamente)? Quindi il vecchio codice utente non lo saprà, quindi non si romperà a condizione che la nuova funzione "pippo" restituisca ancora correttamente gli oggetti.

Problemi correlati