In quale livello deve essere localizzata la validazione?

9

Sto creando un'API di resto utilizzando Spring Boot e sto utilizzando la convalida dell'ibernazione per convalidare gli input delle richieste.

Ma ho bisogno anche di altri tipi di convalida, ad esempio quando è necessario verificare i dati di aggiornamento, se l'ID azienda non esiste Voglio lanciare un'eccezione personalizzata.

Questa convalida dovrebbe essere localizzata sul livello di servizio o sul livello del controllore?

Service Layer:

 public Company update(Company entity) {
    if (entity.getId() == null || repository.findOne(entity.getId()) == null) {
        throw new ResourceNotFoundException("can not update un existence data with id : " 
            + entity.getId());
    }
    return repository.saveAndFlush(entity);
}

Livello controller:

public HttpEntity<CompanyResource> update(@Valid @RequestBody Company companyRequest) {
    Company company = companyService.getById(companyRequest.getId());
    Precondition.checkDataFound(company, 
        "Can't not find data with id : " + companyRequest.getId());

    // TODO : extract ignore properties to constant

    BeanUtils.copyProperties(companyRequest, company, "createdBy", "createdDate",
            "updatedBy", "updatedDate", "version", "markForDelete");
    Company updatedCompany = companyService.update(company);
    CompanyResource companyResource = companyAssembler.toResource(updatedCompany);
    return new ResponseEntity<CompanyResource>(companyResource, HttpStatus.OK);
}
    
posta fdarmanto 02.02.2016 - 11:31
fonte

5 risposte

3

Sia il livello controller che il livello servizio espongono determinate interfacce. Le interfacce definiscono i contratti su come utilizzare l'interfaccia. Contratto generalmente indica quali argomenti (e quali tipi e valori) sono previsti, quali eccezioni possono essere generate, quali effetti collaterali vengono creati ecc.

Ora, la validazione è essenzialmente l'applicazione del contratto del metodo update () del controller e del metodo update () del livello di servizio. Entrambi hanno un contratto molto simile, quindi sarebbe naturale se anche la convalida (applicazione del contratto) fosse comune.

Un modo possibile per farlo è separare la validazione di questo contratto e farlo chiamare in entrambi gli strati. Questo di solito è più chiaro: ogni classe / metodo applica il proprio contratto, ma spesso non è pratico a causa delle prestazioni (accesso al database) o per altri motivi.

Un'altra possibilità è delegare questa convalida al livello di servizio definendo esplicitamente il comportamento in caso di convalida non riuscita nel contratto del livello di servizio. Il livello di servizio restituirà in genere qualche errore di convalida generico (o genererà un'eccezione) e il livello del controller vorrà reagire in un modo specifico all'errore - in questo caso restituiremo 400 richieste non valide per segnalare che la richiesta in entrata non era valida.

In questo progetto, c'è il rischio di un eccessivo accoppiamento tra la business logic nel livello di servizio (che dovrebbe essere piuttosto generico) e il controller (che gestisce la logica di integrazione).

Comunque, questa è una domanda abbastanza controversa e 100 persone risponderanno con 100 risposte. Questo è solo il mio punto di vista.

    
risposta data 02.02.2016 - 17:21
fonte
1

L'input dovrebbe essere controllato nel livello di servizio.

E "Impossibile trovare l'ID" è una condizione di errore logico. Quindi dovrebbe essere gettato dal livello del controller.

Di nuovo dipende dal tuo layering / design.
Che cosa dovrebbe fare un livello di servizio e cosa ci si aspetta dal livello del controller.

    
risposta data 02.02.2016 - 12:30
fonte
0

Nel nostro negozio Java, abbiamo intenzionalmente suddiviso la convalida del web widget su tre operazioni separate.

  1. Formattazione di base: i numeri devono essere numeri; le date devono essere date valide ecc. Di solito questa convalida viene fornita gratuitamente - il framework web lo farà per te quando leghi i contenuti del widget al modello.
  2. Convalida di un singolo widget - la data deve essere nel passato; un numero intero deve essere compreso tra 1 e 100; customerId deve esistere nel database ecc. Questo appartiene al livello controller nella maggior parte dei casi, ma potrebbe essere necessario il supporto dall'archivio dati.
  3. Convalida cross-widget: la data di check-out deve essere successiva alla data di check-in; la data di morte non può essere anteriore alla data di nascita, ecc. Questa è sicuramente la convalida delle regole aziendali. Tendiamo a inserirli anche nel livello controller, ma potresti volerlo spostare in un validatore aziendale in modo che possa essere riutilizzato.

Se il livello 1 fallisce, non verifichiamo 2 o 3. Analogamente, se 1 succede e 2 fallisce, non lo facciamo 3. Questo smette di generare messaggi spuri di errore.

Stai chiedendo dei valori in una chiamata REST piuttosto che nei contenuti del widget, ma si applicano gli stessi principi.

    
risposta data 04.04.2016 - 09:51
fonte
0

Le convalide di Hibernate sono controlli sull'integrità dei dati. Al fine di evitare RuntimeExceptions da bbdd. Sono praticamente le stesse convalide che devi controllare con Vincoli . Poiché solo il livello aziendale deve nutrire il livello di persistenza, puoi (o meno) fidarti della correttezza dei dati provenienti dal tuo livello aziendale

Non inserisco le convalide nei DAO. Mi aspetto dati validi dai livelli superiori. In caso di errore, delegato al bbdd la responsabilità di essere consapevole dei suoi contenuti.

Quindi vengono le convalide a livello aziendale. Tutte le convalide aziendali si sono incentrate sul mantenimento della coerenza dei dati, non sulla sua integrità .

Finalmente eseguo le convalide precedenti sul livello di controllo. Quelli relativi solo a tale livello.

Vedrai presto quali validazioni sono previste per essere implementate a livello aziendale. Il più comune: controllo ID. Questo può essere facilmente implementato in entrambi gli strati. Se si prevede di avere molti controllori o clienti che utilizzano il proprio livello aziendale, invece di ripetere la stessa convalida ovunque, sarà un candidato eccellente da inserire nel livello aziendale.

A volte i controllori hanno le proprie regole e condizioni che non saranno riprodotte in nessun'altra facciata. Quindi è un candidato da inserire in un controller di questo tipo.

Pensa a cosa stai convalidando e se desideri applicarlo a tutti, non importa cosa. O se si tratta di una convalida contestuale ("Im validare qualcosa che accade solo in un particolare controllo / vista facciata).

    
risposta data 03.04.2016 - 20:50
fonte
-1

L'ombra di avvio guidata da test è una luce su questo, dopotutto non c'è un controller e devi scegliere un'altra opzione. Ovviamente le regole di bussines dovrebbero essere in un unico posto, e questo è un altro vincolo nella tua decisssione.

    
risposta data 14.05.2016 - 17:19
fonte

Leggi altre domande sui tag