2009-09-17 10 views
6

Scrivo il codice principalmente per uso personale, ma sto considerando di rilasciare un'applicazione (simulazione scientifica/visualizzazione) che ho originariamente sviluppato per uso personale.Java Habits per il metodo principale

Una delle mie abitudini è utilizzare un metodo principale nelle classi per testare il funzionamento della classe in isolamento. Immagino che probabilmente sia in qualche modo cattivo (come sono senza dubbio varie altre abitudini derivanti dall'autodidatta e dall'ambiente di sviluppo scientifico). Tuttavia, non è mai stato un problema per l'auto-uso che ho notato.

Sareste tutti così gentili da confermare (o negare) che la proliferazione di rete è un problema per un'applicazione rilasciata alla comunità scientifica (la fonte sarebbe anche aperta), e se sì, perché?

EDIT: Per giocare con l'avvocato del diavolo (ok, il mio avvocato) rispetto ad alcune delle risposte offerte: una parte dell '"uso delle applicazioni" dovrebbe essere la modifica della fonte da parte dei non sviluppatori (lo scienziato tipico) su scala ridotta . So che sul lato ricevente, che avere i test per una classe costruita direttamente in quella classe sarebbe abbastanza semplice per me riconoscerlo e modificarlo di conseguenza (specialmente se ciò fosse coerente per le classi). Usare qualcosa come JUnit fornirebbe un'utilità simile, tenendo presente il pubblico?

DECISIONE ACCETTA: Penso che la risposta di KLE sia il miglior bilanciamento di esauriente e conciso, quindi l'ho scelto, ma penso che anche i commenti alla discussione in Bill siano molto utili. Inoltre non capisco perché la risposta di Johannes sia stata respinta - la prospettiva "come funziona questo pezzo" è molto importante per i codificatori della comunità scientifica - e mentre le altre risposte evidenziano vari motivi per cui i test unitari separati sono probabilmente più utili dei miei l'abitudine attuale, in realtà non si rivolgono a quell'uso, quindi la sua risposta è tutt'altro che "inutile". Grazie a tutti i rispondenti attuali (e futuri), ed ecco a desiderare che ci fosse un modo per combinare più risposte come risposta corretta!

+1

+1 bello esporre te stesso ;-) – KLE

+2

Sono d'accordo con KLE. È importante parlare di cattive abitudini in modo da poter scoprire * perché * sono cattive (e non solo seguire ciecamente il branco) o giustificare il motivo per cui potrebbero stare bene in un determinato insieme di circostanze. –

+2

@ Bill Bene messo.Non ho potuto assemblare le parole esatte, ma l'hai fatto. Probabilmente sei un madrelingua inglese, hai buone capacità di comunicazione e sicuramente ci hai pensato su **. _ _ Grazie e continua ... alcuni di noi stanno guardando e imparano da te ;-) – KLE

risposta

6

JUnit permette di avere le prove, proprio come i vostri rete, ma anche:

  • un principale è in genere solo un metodo, che si può ottenere vero e proprio grande; se estrarre piccoli metodi utilizzati solo per prova, c'è il rischio di utilizzare tale metodo nel codice normale
  • non ingombrare la classe stessa con i metodi di prova, sono in una classe diversa
  • permette ereditarietà il test delle classi (principale, come metodo statico, impossibile ereditare o riutilizzare); in genere, l'impostazione prima del test effettivo potrebbe essere piuttosto lunga e riutilizzarla naturalmente è ottima
  • un main non ha alcun risultato (esito positivo o negativo), solo un'uscita; è necessario controllo manualmente l'uscita per determinare il risultato, e possibilmente comprendete
  • permettere l'esecuzione di diverse prove (classe, pacchetto, progetto, tutti) in una volta, che è necessaria per l'analisi di regressione (o vi trascorrere il pomeriggio eseguendo uno per uno)
  • JUnit forniscono molte funzioni aggiuntive, fuori dalla scatola, come la marcatura alcuni test come ignorato, controllando che un test non sia troppo lungo, fornire diverse interfacce utente di lancio ecc
  • voi può riutilizzare alcuni test su ciascuna implementazione o sottoclasse (es. Sostituzione Liskov), che consente di testare molto senza mantenere molto codice di test.
12

Testare la classe con il suo metodo principale non è buona perché fornisce alla classe una responsabilità aggiuntiva (test stesso). I test dovrebbero andare in classi separate, preferibilmente usando una libreria di test come JUnit.

La proliferazione di alimentazione (mi piace questa frase che hai coniato) rende anche più confuso per uno sviluppatore trovare il punto di ingresso per l'applicazione quando si stanno avvicinando per la prima volta.

+5

+1: Tutti i 'public static void main' dovrebbero essere isolati in classi che non fanno quasi nient'altro. Tutta l'elaborazione "reale" dovrebbe essere altrove con API migliori di "main". Questi oggetti di elaborazione "reali" dovrebbero essere istanziati da 'main'. –

+0

diciamo che lo sviluppatore tipico non è in realtà uno sviluppatore e ha abitudini di codifica mondiale "reali" da zero a zero. Apprezzo che la tua risposta sia probabilmente perfettamente corretta per le persone effettivamente impiegate come sviluppatori (anche se ovviamente non ne ho idea), ma pensi che sia quella giusta per questo pubblico atipico? – Carl

+2

@Carl: lo sviluppatore tipico con un po 'di esperienza nel mondo reale probabilmente segue già questo consiglio, quindi il pubblico atipico è esattamente a chi è rivolto. –

2

È necessario utilizzare uno strumento di test come JUNIT per eseguire test sulle classi anziché inserire il codice di test nel codice di produzione.

Questo separa in modo pulito i test dal codice.

3

Non è terribile, ma non è consigliato per due motivi:

  1. Può consentire agli utenti di fare cose che non vuoi che facciano, o almeno dare loro l'idea che si può fare qualcosa di te' anzi non l'hanno fatto; e
  2. I metodi prolifici main() sono spesso un cattivo sostituto dei test unitari.

È (2) dovresti davvero concentrarti.

6

Prima di tutto, è bello che si stiano scrivendo dei test. Non mi piace molto l'approccio di avere un metodo principale in molte classi in un progetto. Vorrei sostenere lo spostamento del codice di test e l'utilizzo di un framework di test. Ciò mantiene il codice sorgente più pulito e, se si utilizza un metodo di denominazione coerente per le classi di test, è facile trovare anche i test associati.

0

Non c'è niente di sbagliato in questo approccio di per sé, ma c'è un grosso svantaggio: è necessario chiamare singolarmente ogni metodo main() per testare tutto il codice. Le probabilità sono che non lo farai. È solo troppo entusiasmo. Inoltre, quando si esegue questa operazione, è necessario sapere quali metodi main() sono veri punti di ingresso e quali sono test. Questo non è affatto ovvio.

Con JUnit e strumenti simili, è possibile contrassegnare il codice come "questo è un test". Ciò consente allo strumento di trovare automaticamente tutti i test nel progetto e di eseguirli tutti contemporaneamente. In questo modo, è molto più probabile che tu esegua tutti i test la maggior parte del tempo e che i bug vengano rilevati in anticipo.

0

Non vorrei utilizzare i metodi principali in tutte le classi anche a scopo di test. In primo luogo, seguire la regola della separazione delle preoccupazioni (l'utilizzo e il test sono preoccupazioni diverse) e perché abbiamo soluzioni eleganti per i test.

In secondo luogo, e che non è stato menzionato finora, se ogni classe ha un metodo principale, è piuttosto difficile trovare il punto di ingresso "reale" nell'applicazione. Se vedo una classe con un metodo principale, mi aspetto che questo mi permetta di "usare" la classe nel modo previsto. Non mi aspetto che questo possa iniziare un test (magari con effetti collaterali gravi).

Ah, solo un terzo aspetto che mi viene in mente: i metodi principali sono sempre pubblici, quindi l'utente della libreria è libero di utilizzare questi metodi in qualsiasi momento, anche durante l'esecuzione della propria applicazione. Questo può avere effetti collaterali terribili, specialmente negli ambienti multi-thread.

Problemi correlati