2013-03-03 13 views
12

Sto creando un'applicazione Web seguendo lo schema MVC.Devo convalidare i parametri nel costruttore?

In Java effettivo l'autore menziona di convalidare i parametri nel costruttore della classe durante la creazione di un nuovo oggetto.

Tuttavia, non sto creando alcune API che verranno utilizzate da terze parti. Le mie classi accettano solo parametri dai campi di input di un modulo che vengono convalidati prima di essere inviati al server.

Quindi in questo caso dovrei creare le mie lezioni come l'autore fa riferimento a Effective java o è inutile?

+0

Dove hai letto nel libro che l'autore menziona per convalidare i parametri nel costruttore per favore? – Kwadz

risposta

9

Non è così chiaro come leggere un libro e implementare ciò che dice. Devi pensare e applicare la conoscenza alla tua situazione specifica.

in realtà dipende da come si inizializza le variabili nella classe e li utilizzano a destra dopo la costruzione oggetto:

Alcune indicazioni:

  • Se le variabili stanno per essere utilizzati da alcuni metodi nella classe o l'oggetto verrà riutilizzato subito dopo le costruzioni (che nella maggior parte dei casi lo faranno), dovresti verificare che i valori richiesti non siano vuoti o nulli, per evitare di ottenere brutte eccezioni.

  • La seconda volta per convalidare i parametri di input è quando ci si aspetta che i valori corretti siano impostati su variabili interne specifiche. Se si richiede che un parametro sia vincolato a un intervallo di valori specifico, è importante convalidarlo.

Esempio:

Dire che abbiamo un tetto salariale nell'oggetto:

int salary = 0; 
int salaryCap = 1000; 

Durante la creazione, è possibile convalidare il passato in quantità stipendio:

public Employee(int salary) { 
if(salary >= this.salaryCap) 
    this.salary = salary; 
} 
  • La relazione di classe determina anche se si desidera convalidare th e valori o no. Se i parametri verranno passati alla catena di ereditarietà, ad esempio, impiegherei del tempo per convalidarli, specialmente se influenzeranno lo stato di altri oggetti nella catena di ereditarietà.

Esempio:

Ogni volta che ho a chiamare il costruttore super, sono tentato di convalidato l'ingresso:

public Employee(int salary) { 
super(salary); //validate salary against known constraints 
} 
  • Dove sono le variabili provenienti da?Se non ti fidi della fonte (come i parametri sql, ecc.), Allora dovresti convalidarli e possibilmente disinfettare l'input prima di eseguire un ulteriore codice. Questo impedisce attacchi di sicurezza.

  • Sono sempre stanco di eseguire la convalida e il controllo dei parametri nel costruttore. Preferisco avere getter e setter per convalidare l'input. In questo modo, se qualcosa accade durante la creazione dell'oggetto, almeno ho la garanzia di un oggetto semi-lavorante rispetto a un oggetto completo incoerente il cui stato non può essere facilmente determinato. Ovviamente ciò dipende dal contesto, se i vincoli sono rigidi, è possibile interrompere la creazione dell'oggetto e richiedere al client (utente, oggetto chiamante, ecc.) Parametri di input validi.

Il vantaggio che l'uso di getter/setter permette me è che l'oggetto è in realtà costruito passo dopo passo chiamando sull'interfaccia esterna l'oggetto dà, diversa da vincolare la convalida durante la creazione, che quando si verifica un'eccezione, rende l'oggetto inutilizzabile/instabile.

Così, invece di questo:

public Employee(int salary) { 
if(salary >= this.salaryCap) 
    this.salary = salary; 
} 

preferisco questo:

public class Employee { 
public void setSalary(int salary) { 
    if(salary >= this.salaryCap) 
     this.salary = salary; 
} 
} 

Quest'ultimo mi dà la possibilità di modo pulito uscire con un'eccezione valida per il chiamante, che non alteri la creazione di oggetti (Non mi piace lanciare eccezioni nel costruttore).

In poche parole, le variabili hanno vincoli? In caso affermativo, convalidare tali vincoli prima di impostarli sulle proprietà dei dati interni.

+10

In realtà non si dovrebbe nemmeno finire di costruire un oggetto quando i parametri in entrata non sono validi. Dovresti lanciare un [IllegalArgumentException] (http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/IllegalArgumentException.html) e non creare un oggetto con invarianti di classi rotte. Se il tuo chiamante ti sta dando dei parametri sbagliati, allora dovrebbero essere quelli con il contesto corretto per gestirli che probabilmente includerà la raccolta di nuovi input dall'utente e il tentativo di ritentare l'istanza dopo di ciò. – Jazzepi

-4

Sembra che tu stia convalidando campi che sono già stati precedentemente convalidati. In tal caso, è solo una perdita di tempo (sia la scrittura sia in fase di esecuzione). Se il tuo modulo (javascript sul lato client) non ha convalidato i campi, allora avrebbe senso. Altrimenti puoi saltarlo.

+4

Affidarsi alla convalida * clientside * è una delle peggiori cose che puoi fare. – PeeHaa

+0

Sì, è vero. Ecco perché li convalida anche sul server. –

+0

Se stai deducendo i punti dovresti spiegare perché, e non solo "è molto cattivo". Nello scenario che l'autore sta sottoscrivendo, non sembra che le convalide siano "complesse" (cioè, questa email esiste già nel db?). Né sembra una API diversa dal fatto che il web stia accedendo al server. Quindi, perché sarebbe "cattivo" convalidare solo il lato client? – ShinySpiderdude

1

A prima vista non è necessario convalidare i parametri poiché la convalida è stata eseguita prima. Ma dovresti prendere in considerazione che la tua classe verrà utilizzata in altre circostanze, non puoi essere sicuro che ogni volta che l'input del tuo costruttore è valido.

1

Suggerirei di convalidare i dati nel dominio e restituire un'eccezione (personalizzata) quando i campi non sono compilati correttamente. In questo modo sarai in grado di implementare un'interfaccia utente diversa senza dover ripetere l'intera procedura di convalida, è meglio separarla il più possibile.

Problemi correlati