Strumento / Motivo per regola aziendale anziché convalida

0

Sto cercando Fluent Validation per il mio modello di dominio ricco: link

Diciamo che ho una classe chiamata: Cliente. Il cliente deve avere un cognome Posso fare questo:

RuleFor(customer => customer.Surname).NotEmpty();

Posso fare qualcosa di simile per assicurarmi che abbiano più di una certa età, ecc. Ora diciamo che voglio offrire offerte a un cliente che ha un'età compresa tra 18 e 25. È qualcosa che dovrei fare usando il Fluent API? Se no, allora c'è un altro strumento / modello che dovrei usare?

Tutto ciò che devo fare è restituire un messaggio se la persona è compresa tra quelle età, ovvero hai diritto alle seguenti offerte: x, yez ". Si noti che questo è per un cliente piuttosto che per una collezione di clienti .

È normale testare le regole del dominio utilizzando l'API Fluent? Ad esempio, se l'utente è tra 18-25, quindi mostrare loro questa offerta (stringa); se sono 25-40, mostra loro questa offerta ecc. Questi non sono errori di validazione, cioè è perfettamente ragionevole che qualcuno abbia 25 anni o 40 anni ecc.

    
posta w0051977 26.06.2017 - 11:40
fonte

3 risposte

0

Creo una classe ValidationProvider che consente di ottenere i tuoi validatori su richiesta, dato qualsiasi stato di dominio.

come:

public class UserValidatorProvider
{
    public static IValidator GetValidator(User user)
    {
        if(user.Age > 40){
            return validator1;//you'd probably use the fluent api here
        }else{
            return validator2;//or maybe encapsulate that fluent in a ctor of a class like new UserOver40Validator()
        }
    }
}

Cioè, un Dominio ha uno Stato (come, l'utente ha più di 40), dato uno Stato seleziona un Validatore.

Dovresti scambiare i validatori in fase di runtime.

Per quanto riguarda dove collocarli nei livelli, si avranno diverse procedure di convalida per ogni caso d'uso a tutti i livelli necessari. Ovvero, feedback dell'interfaccia utente, regole aziendali, convalida del dominio, ma solo dove necessario.

Penso sia così semplice!

    
risposta data 22.05.2018 - 20:57
fonte
0

I requisiti che hai mostrato sembrano le convalide più vicine all'interfaccia utente, che è perfettamente valida, ed è qualcosa che di solito faccio.

Cioè:

  • Utilizza FluentValidation in qualsiasi interfaccia utente che stai utilizzando, per un rapido feedback all'utente (e come lo chiamo, per "interrompere" chiamate non necessarie al servizio / codice dominio dell'applicazione)
  • Dopo queste convalide e controlli iniziali sto anche convalidando il comando che arriva dall'interfaccia utente
  • E le convalide finali sono nella mia classe radice aggregata per applicare tutte le regole di business e gli invarianti del modello di dominio

Sì, questa è la duplicazione del codice e viola il principio DRY, MA è inteso. Perché queste (e altre) convalide stanno avvenendo in più punti.

Per rispondere al tuo commento: sì, tali convalide e le regole aziendali devono essere prima di tutto nel modello di dominio. Applico sempre un approccio capovolto. Dopo aver mappato i vincoli di un dato insieme di operazioni su un modello, dovresti sempre iniziare a implementare il "dentro" che è la tua entità / AR, quindi dirigersi verso "fuori" l'interfaccia utente.

Inoltre scrivi nel commento:

If the user happens to be 40 years old, then they can still login and get a different set of offers.

Sembra che una restrizione chiuda l'interfaccia utente, dal momento che la maggior parte dei domini con cui ho lavorato non aveva una definizione di "accesso o accesso" nel loro vocalbury comune, quindi penso che sia una responsabilità a livello di applicazione piuttosto che dominio.

    
risposta data 26.06.2017 - 11:47
fonte
0

Lo implementerei utilizzando criteri che un'entità può soddisfare o meno. Non ho familiarità con C #, quindi questo è solo uno schema approssimativo:

// declare your crietria as delegates - in Java this would be Predicate<T>
delegate boolean isEligibleForOfferXYZ(Customer c) {
    return c.age >= 18 && c.age <= 25;
}

Puoi quindi usare quella cosa in vari contesti. Nella tua interfaccia utente puoi fare

if (isEligibleForOfferXYZ(currentUser)) {
    // output button that links to offer order page
}

Puoi usarlo come regola aziendale

if (!isEligibleForOfferXYZ(currentUser)) {
    fail("You are not eligible for this offer, sorry.");
}

Puoi usarlo come regola di convalida con l'API fluente.

Puoi estendere ulteriormente questo aspetto, proprio come i giocatori di Hamcrest:

interface Criterion extends Predicate<T> {
    boolean matches(T item);
    Translation describeMismatch(T item);
}
    
risposta data 26.06.2017 - 12:11
fonte

Leggi altre domande sui tag