2014-05-14 20 views
5

Sto sviluppando un framework che ha una classe chiamata StableClass. Questa classe è "stabile": gli utenti possono contare sul proprio codice su questa classe. Le versioni future del framework avranno questa classe e saranno retrocompatibili.Come taggare un metodo/API come sperimentale?

Quello che voglio è aggiungere un metodo in questa classe, ma voglio dire agli utenti che questo particolare nuovo metodo è sperimentale e potrebbe cambiare in futuro.

esempio:

class StableClass 
{ 
public: 
    void stableMethod1(); 
    void stableMethod2(); 
    void stableMethod3(); 
    void unstableMethod(); // How to tag this method as experimental ? 
}; 

Gli utenti devono conoscere il unstableMethod() è sperimentale. Che l'API potrebbe cambiare in futuro (o meno).

Possibili opzioni:

  • aggiungere la parola experimental come suffisso o un prefisso del nome. ad esempio: unstableMethod_experimental()
  • log alla console ogni volta che il metodo viene richiamato
  • tag come deprecato, ma l'avvertimento dice che è sperimentale

Qualsiasi altra opzione?

Mi piacerebbe avere l'attributo experimental e che il compilatore sollevi un avviso in fase di compilazione (come l'attributo deprecated), ma per quanto ne so, tale attributo non esiste.

[UPDATE]:

voglio rilasciare una versione stabile del quadro, con un paio di API nella categoria sperimentale. A volte ci vuole tempo per trovare il nome corretto, o i parametri corretti o la funzionalità corretta per un particolare metodo, o implementarlo per tutte le piattaforme supportate.

Voglio dire ai miei utenti che "questa è la nuova versione stabile del framework. Abbiamo anche aggiunto questa nuova funzionalità ma è sperimentale poiché presenta le seguenti limitazioni: ...".

Quindi, ho questo requisito in cui le versioni stabili potrebbero avere funzionalità sperimentali. Anche se potrebbe sembrare una contraddizione, è un requisito per me.

+0

Non nel linguaggio standard. Un compilatore è libero di implementarlo come estensione, ma in ogni caso, consiglierei di scriverlo nei documenti e non di manipolare il nome della funzione o altri attributi non standard. – DevSolar

+0

Forse: Una singola funzione sperimentale rende l'intera libreria sperimentale (un ramo sperimentale nel controllo di revisione) –

+0

Sembra che dovrebbe essere una cosa di documentazione, non una cosa di codice ... – twalberg

risposta

2

Penso che tu sia sulla strada giusta. Il CSS fa qualcosa di simile con i prefissi specifici del fornitore.Per esempio:

.my-css-class { 
    /* Border-radius for CSS3 compliant browsers */ 
    border-radius: 2px; 

    /* Border-radius for browsers where CSS3 border-radius support 
    * is experimental, or non-standard */ 
    -webkit-border-radius: 2px; 
    -moz-border-radius: 2px; 
    -o-border-radius: 2px; 
}; 

Poiché il metodo è sperimentale, è ragionevole supporre che il metodo può cambiare in modo significativo tra oggi e il momento in cui sei felice con l'API, e questo viene fornito con alcuni rischi. Gli utenti della tua versione "sperimentale" dell'API potrebbero dover implementare gli hack attorno all'API per fare ciò che vogliono e, auspicabilmente, ti segnaleranno i loro problemi e ti permetteranno di soddisfare meglio le loro esigenze.

Con il tempo il metodo è finalizzato, hack degli utenti potrebbero non essere più necessaria, e peggio, di introdurre bug in loro codice, quindi è auspicabile imporre agli utenti di API per rivalutare il loro codice, e fare sicuro che il loro codice sia corretto prima di utilizzare l'ultima versione della tua API.

Ci sono una moltitudine di modi si potrebbe fare questo con grazia, un paio mi viene in mente:

Rinominare il metodo

Mentre la vostra API è sperimentale, si può chiamare il metodo di qualcosa di simile:

void EXPERIMENTAL_MyMethod(); 

Successivamente, è possibile rimuovere il prefisso EXPERIMENTAL_. Quando gli utenti scelgono di aggiornare il proprio codice all'API più recente, riceveranno un errore del compilatore che gli dirà che il metodo sperimentale non è più disponibile. Questo li costringerà a passare attraverso il proprio codice e rimuovere tutti gli hack che sono stati richiesti quando si utilizza la versione sperimentale. Per lo meno, tutto quello che dovranno fare è trovare/sostituire EXPERIMENTAL_MyMethod() con MyMethod().

PRO:

  • semplice, facile da lavorare.
  • Ovvio per vedere cosa è sperimentale e cosa no.
  • Greppable. Gli utenti possono facilmente trovare le chiamate di funzione EXPERIMENTAL_ nel proprio codice.

CONTRO:

  • Rende metodi sperimentali disponibili nelle classi stabili.
  • Pollutes completamento automatico IDE con metodi instabili che l'utente potrebbe non voler utilizzare.

Creare una classe wrapper

Ti piace questa:

namespace MyApi 
{ 
    namespace Experimental 
    { 
     class StableClass; 
    } 

    class StableClass 
    { 
    public: 
     void stableMethod1(); 
     void stableMethod2(); 
     void stableMethod3(); 

     friend class Experimental::StableClass; 
    };  

    namespace Experimental 
    { 
     class StableClass : public MyApi::StableClass 
     { 
     public: 
      void unstableMethod(); 
     }; 
    } 

utilizzando lo spazio "sperimentale", come questo ...

MyApi::Experimental::StableClass myStableClassInstance; 

... invece di questo ...

MyApi::StableClass myStableClassInstance; 

... affermi esplicitamente che chiunque usi le versioni dello spazio dei nomi Experimental delle classi è soggetto ai capricci dello sviluppatore.Una volta completata la versione stabile del metodo, aggiungilo alla versione non sperimentale della classe e rimuovi dalla versione sperimentale. Gli utenti dell'istanza Experimental::MyClass riceveranno quindi un errore del compilatore. La tua documentazione può quindi spiegare cosa è cambiato.

PRO:

  • Nizza a guardare, fa una chiara distinzione tra l'API stabile e instabile.
  • Rende esplicito ciò in cui si trova l'utente quando utilizza lo spazio dei nomi Experimental.
  • Forza agli utenti di rivalutare l'utilizzo dell'API sperimentale in caso di interruzione delle modifiche.

CONTRO:

  • richiede un lavoro da mantenere.
  • I wrapper e gli spazi dei nomi aggiuntivi potrebbero inquinare l'API.
  • using namespace Experimental; * brivido *
+0

Questa risposta si adatta molto bene al nostro framework, dal momento che stiamo già utilizzando lo spazio dei nomi 'experimental' per le classi. – ricardoquesada

+0

Sebbene non abbia ancora provato questa soluzione, sembra che non funzioni con le sottoclassi. Se l'utente ha già una sottoclasse di 'StableClass', e se vuole usare la nuova funzione sperimentale, avrà invece bisogno di sottoclasse da' experimental :: StableClass'. Sebbene non sembri un problema importante, preferirei forzare gli utenti a modificare il codice esistente per poter utilizzare la nuova funzione sperimentale. – ricardoquesada

0

Come indicato in alcuni dei commenti, questo deve essere gestito al di fuori della fonte stessa. O tramite documentazione o come succursale nel sistema di controllo di revisione. Quando si rilascia la versione finale stabile della libreria, non si vuole che le persone passino attraverso e cambino tutti i nomi nel loro codice, cosa che succederebbe con un suffisso _experimental.

L'aggiunta di messaggi di avviso del compilatore potrebbe essere corretta, ma è anche possibile irritare le persone che vengono eseguite con l'opzione "Gestisci avvisi come errori".

+2

* "Quando si rilascia la versione finale stabile della libreria, non si vuole che le persone passino attraverso e cambino tutti i nomi nel loro codice, cosa che succederebbe con un suffisso _experimentale." * Potrebbe essere effettivamente ciò che è migliore. Il CSS, per esempio, fa questo con i prefissi dei fornitori (ad esempio '-moz-border-radius') perché indica una proprietà che potrebbe modificare il suo comportamento prima del rilascio. Analogamente, l'aggiunta di un prefisso o suffisso "_esperimentale" costringerà l'utente dell'API a rivalutare il proprio codice ed eventualmente a rimuovere eventuali hack una volta completata l'implementazione finale dell'API. –

+0

@KarlNicoll Buona analogia. Python ha il 'from __future__' che in realtà non è la stessa cosa, ma simile a – ricardoquesada

6
#ifdef EXPERIMENTAL 
    void unstableMethod(); // How to tag this method as experimental ? 
#endif 

Nascondere metodi inaffidabili sotto definisce appropriati costringerà gli utenti a modificare i loro progetti/obiettivi impostazione preprocessore in modo da essere consapevoli di ciò che hanno a che fare con.

+1

Upvote. Assicurati che il valore predefinito sia quello di nascondere i metodi, quindi gli utenti devono pensare a ciò che chiedono. – ssube

+0

Ciò potrebbe causare problemi con il linker, suggerirei di utilizzare 'EXPERIMENTAL' per passare da pubblico a privato. Buona idea però. –

+0

Sì, questa è un'opzione valida. Ma il problema con questo approccio è che abiliterà tutte le funzionalità sperimentali e un utente potrebbe utilizzare una funzionalità sperimentale senza sapere che è sperimentale. es.: l'utente definisce 'SPERIMENTALE' perché vuole usare la caratteristica A, ma abilita anche la funzione B. L'utente può utilizzare la funzione B (es. completamento automatico IDE) senza sapere che è sperimentale. – ricardoquesada

Problemi correlati