Come contrassegnare una classe come in fase di sviluppo in Java


12

Sto lavorando a un progetto di internato, ma devo partire prima di poter finire tutto.

Ho 1 classe che non è abbastanza stabile per l'uso in produzione. Voglio contrassegnare / contrassegnare questa classe in modo che altre persone non la utilizzino accidentalmente durante la produzione. Ho già inserito l'avviso in Javadoc, ma non sembra abbastanza. Qualche errore o avviso del compilatore sarebbe migliore.

Il codice è organizzato in questo modo:

[Package] | company.foo.bar.myproject
          |-- Class1.java
          |-- Class2.java
          |-- Class3.java <--(not stable)

Se esistesse un'unica classe factory che chiama tali classi in metodi pubblici, avrei potuto impostare il metodo su class3as private. Tuttavia l'API NON è esposta in questo modo. Gli utenti useranno direttamente quella classe, ad esempio new Class1();, ma non riesco a rendere privata una classe di livello superiore. Qual è la migliore pratica per affrontare questa situazione?


1
Cosa intendi con "L'API non è esposta attraverso i metodi?" Questa classe è destinata all'uso tramite l'API Reflection?
Tom G

5
Un errore del compilatore? Perché non lanciare un'eccezione nel costruttore?
Mchl

Dispiace per la confusione. Ho modificato il mio post.
Wei Shi,


1
Non puoi rendere privata la classe, ma puoi renderne privato il costruttore.
Peter Taylor,

Risposte:


15

Perché non semplicemente controllare tutte le classi instabili in un ramo diverso sul sistema di controllo della versione?


2
Mi sembra che questo "nasconderebbe" il codice. Che cosa succede se il codice fa quasi quello che gli altri hanno bisogno di fare con alcune piccole modifiche. Se lo metti in un ramo, potrebbero non vederlo mai e implementerebbero di nuovo tutto.
c_maker,

3
@c_maker: far sapere agli altri che esiste il ramo e che cosa contiene dovrebbe far parte di ciò che viene trasmesso quando se ne va.
Blrfl

2
@Birlf Se è preoccupato che gli altri non vedano la spiegazione in JavaDoc del codice che stanno usando, dubito che andranno a cercare l'altra documentazione che produce.
KeithB,

La mia preoccupazione è che la funzionalità sia ancora in evoluzione, ma lo scrum master ha scelto di metterla da parte per qualsiasi motivo (moratoria che blocca i test E2E, nel nostro caso). Se non ci uniamo a Master, potrebbe esserci un sacco di lavoro di fusione lungo la strada. Abbiamo appena reso privato il ctor e annotato la classe @Experimental, come in Spark
Joey Baruch,


4

Non conosco tale avviso del compilatore.

Nella tua situazione probabilmente @Deprecateduserei l' annotazione. Cancellerà le chiamate di metodo, quindi sarà ovvio per gli altri che qualcosa è successo. Quando guarderanno cosa succede, vedranno i tuoi commenti su 'non pronto per la produzione' e andranno AHA.


2
le chiamate al metodo vengono cancellate solo se l'IDE lo supporta.
FrustratedWithFormsDesigner

5
È vero, ma la maggior parte delle persone probabilmente utilizzerà uno di quegli IDE che lo supportano.
c_maker,

3

Io non credo che ci sia un modo standard di marcatura codice come WIP, Incompleteo qualcosa del genere.

È possibile creare una nuova eccezione denominata ClassUnstableExceptione quindi sollevarla nel Class3costruttore con un messaggio che spiega come non dovrebbero usarla. Questo è male, perché li avverte solo in fase di esecuzione.

Potresti anche provare a rendere la classe incompatibile in qualche modo, quindi aggiungere una nota alla sezione di codice che fa scattare il compilatore in modo che se qualcuno va a sistemare il codice, si spera che vedrà una spiegazione del perché non dovrebbero usare quella classe . Questo potrebbe non funzionare se usano uno strumento semiautomatico di "risoluzione di questo problema" di alcuni IDE. Anche questo è negativo perché potrebbe rompere le build.

Potresti creare un'annotazione denominata WIP(dal momento che il più vicino a cui riesco a pensare è Deprecatedma non significa davvero la stessa cosa) e usarla per annotare la classe. Questo sarebbe probabilmente un po 'più di lavoro, e cosa sosterrebbe l'annotazione?

Infine, potresti semplicemente inserirlo nei commenti, ma funzionerà solo se le persone li leggono davvero .

MODIFICARE:

Ciò può essere rilevante: come causare intenzionalmente un messaggio di avviso del compilatore java personalizzato?


genera un'eccezione che fa eclissare lamentarsi del codice non raggiungibile. Qualche soluzione?
Wei Shi,

@Usavich: Non sono sicuro da quando non ho visto il codice, ma forse questo potrebbe anche aiutare a impedire ai futuri sviluppatori di utilizzare il codice?
FrustratedWithFormsDesigner

@Usavich: dai un'occhiata al link che ho aggiunto in EDIT nel mio post, è una domanda simile in cui l'OP ha voluto aggiungere un avviso del compilatore personalizzato. Potrebbe aiutarti ad aggiungere un'annotazione personalizzata "UnstableCode".
FrustratedWithFormsDesigner

3

Perché è lì in primo luogo?

Hai controllato il codice instabile nella linea principale? Perché?

Il codice instabile non dovrebbe essere registrato in trunk / main / master o qualunque sia il nome del trunk principale. Questo è considerato uno sviluppo ad alto rischio e dovrebbe invece essere stato sequestrato nel suo ramo su cui hai lavorato piuttosto che controllato in principale.

Incoraggerei fortemente voi (e il vostro responsabile del team) a leggere le strategie di ramificazione avanzate di SCM . In particolare, presta attenzione al ruolo di sviluppo e a ciò che dice su quello che è considerato uno sviluppo ad alto rischio:

In generale, considerare l'utilizzo di filiali separate per ciascun progetto ad alto rischio. I progetti ad alto rischio sono caratterizzati da grandi dimensioni, un gran numero di persone, argomenti non familiari, argomenti altamente tecnici, tempi molto stretti, date di consegna incerte, requisiti incompleti o volatili e team di progetto distribuiti geograficamente. Allo stesso modo, prendere in considerazione la designazione di un singolo ramo per lo sviluppo a basso rischio in ogni versione. Diverse fonti tra cui [WING98] raccomandano di utilizzare la linea principale per questo scopo. Considera i fattori discussi sopra per la linea principale prima di impegnarti in questo corso d'azione. Lo sviluppo a basso rischio può avere una politica diversa dalla linea principale anche se ci sono più membri di una famiglia di prodotti che coordinano attraverso la linea principale.

Consentire alle persone di controllare il codice instabile (o non utilizzato) nella linea principale significa confondere gli sforzi di sviluppo futuri nel tentativo di mantenere questo codice. Ogni ramo e clone del rappresentante da ora fino alla fine dei tempi conterrà questo fino a quando qualcuno dice "il suo codice morto" e lo elimina.

Ci sono alcuni che dicono "beh, se si trova in un ramo viene dimenticato" e mentre ciò può essere vero, aver dimenticato il codice morto (e instabile) nella linea principale è molte volte peggiore in quanto confonde tutto lo sviluppo futuro fino a quando non viene rimosso - e allora è ancora più dimenticato. Una branca ben definita di "/ fooProject / filiali / WeisBigIdea" (o equivalente) è visibile e più facile da lavorare in futuro, specialmente se funziona in qualche modo.

@Deprecated

La prima cosa è l' @Deprecatedannotazione. Questo va oltre il javadoc e sputa gli avvisi del compilatore. javacfornisce un -deprecationflag che è descritto come:

Mostra una descrizione di ogni utilizzo o sostituzione di un membro o di una classe deprecati. Senza -deprecation, javacmostra un riepilogo dei file di origine che utilizzano o sovrascrivono membri o classi deprecati. -deprecation è una scorciatoia per -Xlint:deprecation.

Come notato, questo va oltre le avvertenze standard del compilatore.

In molti IDE, metodi e valori obsoleti sono mostrati con un barrato:

foo.bar();

E produrrebbe output come:

$ javac -Xlint:all Foo.java Bar.java
Bar.java:2: warning: [deprecation] Foo in unnamed package has been deprecated
interface Bar extends Foo { }
                      ^

A seconda della struttura della build, è possibile che gli avvisi interrompano la build. Questo sarebbe solo rompere la build se una delle classi è stato utilizzato (non se è semplicemente compilato).

@CustomAnnotation

Ci sono molti approcci a questo. Ad esempio, l' annotazione Lightweight javac @Warning che fornisce un processore di annotazione che emette un avviso in fase di compilazione quando viene utilizzato qualcosa con tale annotazione ( un tutorial di netbeans su processori di annotazione personalizzati in modo da poter avere un'idea di ciò che sta accadendo dietro scene).

Oracle descrive persino un esempio dell'utilizzo di annotazioni personalizzate per @Unfinishedun'annotazione in Come sfruttare al massimo i metadati di Java, Parte 2: Annotazioni personalizzate .

Con AnnotationProcessor , è possibile eseguire codice arbitrario in fase di compilazione. Sta davvero a te decidere cosa vuoi che faccia. Avvertire, interrompere la build quando viene utilizzato qualcosa. Esistono numerosi tutorial sul Web per sapere come scrivere questo tipo di codice. Se si desidera generare un errore quando viene compilato (questo sarà fastidioso e porterà alla sua eliminazione) o se viene utilizzato (un po 'più complesso da scrivere).

Si noti che tutto ciò implica la modifica delle build per utilizzare effettivamente il processore di annotazione.


2

È possibile introdurre l' elaborazione delle annotazioni in fase di compilazione, ma ciò impone a tutti i membri del team di adattare il processo di compilazione.

Tuttavia, trovo un po 'confuso l'intero processo. Un'API instabile deve essere chiaramente separata creando un ramo nel sistema di controllo della versione. Se deve davvero essere nel resto della base di codice, è stato documentato come instabile e tuttavia viene utilizzato, il problema non è realmente tecnico ma si trova all'interno dell'organizzazione e della comunicazione. Sì, potresti introdurre verifiche tecniche (come l'elaborazione delle annotazioni) ma ciò non risolverebbe il problema: spostalo semplicemente su un altro livello.

Quindi la mia raccomandazione è: se non riesci a separare la base di codice inserendola in rami diversi, parla con le persone e spiega loro perché non devono usare l'API.


0

Potresti spostare tutte le classi incomplete in un subpackage chiamato qualcosa di ovvio come "NOTCOMPLETE"? È un po 'un trucco ma potrebbe essere abbastanza visibile.

(Se non sono tutti nello stesso pacchetto, è possibile ricreare la struttura del pacchetto sottostante).


0

Non so che ci sia davvero un buon modo per farlo nel codice. Fai un passo indietro:

Crea due copie dell'intero progetto, una con la classe e una senza. Contrassegna la versione senza la classe come base di codice stabile, pronta per la versione di produzione e la versione con la classe come sviluppo per una versione futura. Documenta ciò che deve accadere prima che questa classe possa essere considerata di qualità di produzione.

Idealmente, dovresti farlo usando i rami nella tua scelta di controllo del codice sorgente. Potrebbe essere necessario imbrogliare un po ', dal momento che sembra che non stiate usando una tale strategia di ramificazione. Rimuovere con attenzione la nuova classe, verificare una versione senza di essa ed eseguire alcuni test di regressione. Quando sei soddisfatto è stabile, puoi taggare quella revisione, creare un ramo di sviluppo dal tag e quindi aggiungere nuovamente la classe nel ramo di sviluppo.


0

Opterei per rendere astratta la classe e commentare in modo appropriato - in questo modo, il codice è ancora lì per riferimento, ma buona fortuna a chiunque cerchi di istanziarlo :)


-1

Che ne dici di fare una dipendenza che il compilatore non può risolvere? Aggiungi solo:

import this.is.not.done.yet.do.not.use.it;

verso l'alto. Gli utenti non saranno in grado di compilare con esso.

Se vuoi testare la classe, crea semplicemente un pacchetto / classe con quel nome (o usane uno più semplice come "sperimentale.danger") e puoi testare il nuovo codice.


1
La compilazione fallirà anche se non la utilizzo ... cattiva idea ...
Silviu Burcea,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.