2010-05-09 4 views
9

Ecco un esempio di un metodo di utilità:Metodo di utilità: passare un file o una stringa?

public static Long getFileSize(String fileString) { 

    File file = new File(fileString); 

    if (file == null || !file.isFile()) 
     return null; 

    return file.length(); 
} 

E 'una buona pratica per passare una stringa piuttosto che un file a un metodo come questo? In generale, quale ragionamento dovrebbe essere applicato quando si realizzano metodi di utilità di questo stile?

+3

Se stanno facendo un 'File' per primo, non penso che si preoccuperebbero di fare' getFileSize (file) 'quando potrebbero semplicemente fare' file.length() '. Inoltre, 'file' non può essere effettivamente' null' in quella situazione; i costruttori non hanno la possibilità di restituire un oggetto nullo, dovrebbe essere un metodo factory come 'File makeFile (String filename)' –

risposta

3

Questa è la mia soluzione preferita:

public static Long getFileSize(String path) { 
    return getFileSize(new File(path)); 
} 

public static Long getFileSize(File file) { 
    return (!file.isFile()) ? -1L : file.length(); 
} 

Nota che sta tornando -1L piuttosto che 0L, per consentire al chiamante di distinguere tra un file vuoto, e un "file" la cui lunghezza non può essere determinato per qualche ragione. Lo file.length() restituirà zero in alcuni casi in cui non si dispone di un file di lunghezza zero; per esempio.

  • quando il file non esiste
  • quando il file è una directory
  • quando il file è un file speciale (file esempio dispositivo, tubi, ecc) e il sistema operativo non può determinare la sua lunghezza.

Gli accordi di chiamata file.isFile() con questi casi. Tuttavia, è discutibile se il (i) metodo (i) deve restituire -1L o generare un'eccezione. La risposta a questo dibattito si attiva se i casi -1L sono "normali" o "eccezionali" e che possono essere determinati solo in riferimento ai contesti in cui è progettato il metodo,

0

L'unica cosa che conta è come userete questo metodo. In altre parole, se l'applicazione funziona con oggetti File, è possibile passarli e rimuovere alcune operazioni non necessarie. Se si opera con percorsi di file, il parametro stringa potrebbe essere più conveniente.

Ma alla fine, nessuna scelta è sbagliata: nessuno dei due farà peggiorare la tua applicazione.

1

Penso che ciò dipenderà da ciò che hai a disposizione nel momento in cui chiamerai questo metodo. Se si ha il nome del file (String), ma nessun file, sembra poco che il chiamante crei il file dal nome del file.

Il mio approccio a questo quando non sono sicuro è quello di creare due metodi, uno per String, uno per File. Quindi avere la stringa uno crea il file e chiama il file uno.

public static long getFileSize (final String fileString) { 
    return getFileSIze (new File (fileString)); 
} 

public static long getFileSize (File file) { 
    if (file == null || !file.isFile()) return null; 
    return file.length(); 
} 
1

Dipende dall'utilità attesa dal lato client. Nel caso in cui il lato client abbia già un oggetto file e desideri recuperare il file, lo sviluppatore lato client è costretto ad estrarre il percorso del file e passarlo al metodo di utilità. Per evitarlo, fornirei metodi sovraccaricati 1) con File 2) Stringa di percorso file

Inoltre, nel caso in cui il file non sia disponibile, vorrei generare un'eccezione che restituire null.

+0

Qui c'è un vantaggio zero nel sovraccaricare, usare nomi distinti a meno che non ci sia qualche giustificazione. http://stackoverflow.com/questions/248222/method-overloading-can-you-overuse-it – leonbloy

+0

@leonbloy - Quale consideri la giustificazione? Ad esempio, nella domanda che hai collegato, la risposta accettata suggerisce esplicitamente sovraccarichi per, tra le altre cose, nomefile come stringa e File. – CPerkins

+0

@CPerkins: vedi la mia risposta a binil e la citazione di Joshua Bloch. L'overloading del metodo (con lo stesso numero di parametri) è la radice di molti mali specialmente quando: i tipi alternativi sono una sottoclasse di un altro o usati nei setter (o in metodi generali che alcuni framework cercheranno in runtime attraverso il reflection). Sono d'accordo che questi fattori aggravanti non si applicano qui, ma comunque, sono conservatore su questo, e non sono d'accordo con questo consigliato. – leonbloy

1

La mia raccomandazione sarebbe di avere entrambi:

public static Long getFileSize(String path) { 
    return getFileSize(new File(path)); 
} 

public static Long getFileSize(File file) { 
    return (file == null || !file.isFile()) ? 0L : file.length(); 
} 

e consentire agli utenti di scegliere in base al tipo di oggetto che stanno utilizzando per rappresentare i percorsi del file system. Come ha detto @Nikita, nessuna scelta è sbagliata.

+2

Ti darei +1 ... se non fosse per il test 'file == null'. Quel caso è un errore di progettazione nel metodo originale ... dovrebbe solo lasciare che si verifichi un NPE.) Inoltre dovresti restituire -1L invece di 0L per "non un file" per distinguere il caso di un file con zero byte. –

+1

@Stephen Sì, sono d'accordo con tutto ..tranne per la parte +1. :-) –

+0

Sovraccarico del metodo è frequentemente abusato, e questo è un esempio. Non c'è nulla da guadagnare (tranne qualche dolore futuro) chiamando i due metodi in questo caso lo stesso. Leggi qui http://stackoverflow.com/questions/248222/method-overloading-can-you-overuse-it – leonbloy

1

A mio parere, tale funzione è utile solo con un parametro stringa. Che cosa fa?

  • Crea un oggetto file.
  • Verifica che possa essere creato.
  • Controlla che si tratta di un file di
  • restituisce la lunghezza

Se si passò un file, la prima cosa che non è necessario, i prossimi due dovrebbero probabilmente essere assunti, e la lunghezza è un membro di file funzione. Se si passa questo un file, questa funzione diventa troppo banale scrivere :)

(Inoltre, penso che il ritorno nulli da una funzione che restituisce un tempo è strano)

Se si dispone già di un oggetto File, l'uso :

length = file.isFile() ? file.length() : -1; 

Se le offerte di codice con i file al posto dei nomi di file si potrebbe risparmiare un po 'di file si apre se si riutilizza i puntatori di file. In tal caso, potrebbe indurti a utilizzarli sull'approccio del nome file.

+0

Quel codice non apre i file! Crea un "fancy String wrapper" (l'oggetto 'File') e lo usa per cercare il file nel file system (in' isFile() 'e' length() '). Poiché la ricerca è nativa, non vedo se si possa risparmiare tempo o risorse riutilizzando l'oggetto 'File'. –

+0

@Christian Semrau: Non ho molta familiarità con java, grazie per averlo indicato. Apparentemente File() non effettua una chiamata di sistema. Ma isFile e length producono entrambe chiamate di sistema (giusto?). Se stai lavorando con oggetti file altrove, è possibile che tu sappia già se isFile è stato chiamato ... probabilmente non vuoi che tutto il tuo codice controlli isFile() e gestisca le directory in modo diverso. (risposta fissa) – Stephen

1

Ci sono un numero di considerazioni:

  1. metodi Utility esistono per ridurre la quantità di codice di piastra caldaia ripetitivo nella vostra applicazione, rendendo quindi il codice più leggibile e riducendo il numero di potenziali bug. È logico provvedere ai più comuni schemi di utilizzo, ad esempio se la maggior parte delle volte si dispone di una stringa che descrive un file, passare la stringa. La maggior parte del beneficio deriva dall'avere un metodo di utilità in primo luogo, non ottenendo la firma ottimale che è al 100% a prova di futuro.

  2. Passare un file anziché una stringa fornisce una digitazione più forte, vale a dire che più di voi il codice può essere controllato in fase di compilazione salvaguardando gli errori di battitura. Fai in modo che il compilatore lavori per te, sfrutta i vantaggi di una digitazione forte.

  3. Passare un file significa che è possibile passare qualsiasi tipo di oggetto File, possibilmente un oggetto file in memoria su misura senza dover cambiare il metodo di utilità per gestire il descrittore di file personalizzato.

  4. Passare una stringa può essere d'aiuto quando devi gestire molto con i percorsi dei file OS e vuoi solo controllare la dimensione con un numero minimo di linee.

  5. Alla fine è possibile avere diversi metodi di utilità sovraccaricati a un costo molto basso. Questo scenario è esattamente la ragione dell'esistenza dell'overload dei metodi come funzionalità del linguaggio. Guarda cosa funziona naturalmente nella tua base di codice. Il codice è malleabile e questa non è una delle decisioni progettuali con cui dovresti vivere per sempre, a meno che tu non stia costruendo un'API da utilizzare per altre persone.

  6. Si potrebbe anche voler cambiare il nome ad essere un po 'più descrittivo, per esempio

    • lungo sizeFromFile (File f) e
    • lungo sizeFromFileName (String name)

    utilizzando la convenzione originariamente suggested by Joel Spolsky.

2

mi piacerebbe andare con un file. Mi sembra corretto un po 'di OOP: più typesafe (Le stringhe sono così "generali" in Java ...) e semanticamente espressive: se hai a che fare con i file, allora passa un oggetto File.

Ricordiamo che in Java un file oggetto non rappresenta in realtà un filein sé (il suo contenuto), ma piuttosto il suo percorso: "An abstract representation of file and directory pathnames" (che può essere anche il percorso di un file inesistente) e questo è quasi esattamente quello che ti serve qui.

Questo può essere solo un limite in alcuni casi: se il "file" è in realtà una sorta di pseudo-file o risorsa, ad esempio all'interno di un file jar. Un'alternativa che ho trovato utile è un URI, che (concettualmente) include un file come caso speciale, ma anche altre risorse.

E se decidi di rimanere con le due alternative (String o File), non consiglio assolutamente di nominare i metodi allo stesso modo. Method overloading can be a pain, usalo solo quando ti dà un beneficio tangibile.

1

Metodo Il sovraccarico è la migliore pratica in questi casi.