Sto lavorando su un sistema che consente agli amministratori di definire i moduli che contengono campi. I moduli definiti vengono quindi utilizzati per immettere dati nel sistema. A volte i moduli sono compilati da un utente tramite una GUI, a volte il modulo viene compilato in base ai valori riportati da un altro sistema.
Per ciascun campo, l'amministratore può definire una regola di convalida che limita i valori consentiti per il campo. Le regole di convalida possono essere qualsiasi cosa, dal "valore inserito nel campo deve essere vero o falso" a "il valore inserito nel campo deve esistere nella colonna A della tabella B nel database". L'amministratore può in qualsiasi momento modificare la regola di convalida per il campo.
In questo scenario, quale a tuo parere è il posto più adatto per convalidare che ogni campo è compilato correttamente? Attualmente ho in mente due approcci principali:
Opzione n. 1: convalida nel modello di dominio
Ogni oggetto Field conterrà la regola di convalida specificata dall'amministratore. Gli oggetti Field avrebbero anche un riferimento a un IValidator. Quando viene effettuato un tentativo di impostare il valore del campo, il campo passerà il valore specificato e la regola di convalida a IValidator. Se il valore dato non è valido, una ValidationException verrebbe generata e gestita in modo appropriato nell'interfaccia utente / interfaccia con l'altro sistema.
Pro:
- Protezione avanzata contro l'assegnazione accidentale di campi ai valori che violano la regola di convalida
Contro:
-
Il livello di accesso ai dati deve essere in grado di bypassare la convalida e costruire campi che violano la regola di convalida corrente. Nonostante l'amministratore abbia modificato la regola di convalida per un campo, dobbiamo comunque essere in grado di costruire oggetti Field in base ai vecchi dati, ad es. quando si esegue il rendering di un modulo compilato anni fa. Questo potrebbe potenzialmente essere risolto memorizzando la regola di convalida corrente ogni volta che memorizziamo il campo.
-
In questa progettazione, il modello Field ha un collegamento indiretto al livello / archivio di accesso ai dati tramite IValidator. L'iniezione di Servizi / Repository su Modelli di dominio sembra essere generalmente aggrottare le sopracciglia su .
Opzione n. 2: convalida in un servizio
Cerca di assicurarti che tutti i tentativi di impostare il valore di un campo passino attraverso un servizio che garantisce la validità della regola di convalida. Se viene violata la regola di convalida, genera una ValidationException.
Naturalmente, il livello di accesso ai dati non utilizzerà il servizio quando si creano oggetti Field precedentemente mantenuti nel DB.
Pro:
-
Non viola il "non iniettare servizi / repository nei tuoi modelli di dominio" - pensieroso.
-
Non è necessario mantenere la regola di convalida corrente quando si mantiene il campo. Il servizio può semplicemente cercare la regola di convalida corrente per il campo; quando guardi i dati storici, il valore del campo non verrà modificato.
Contro:
- Non è garantito che tutta la logica che dovrebbe utilizzare il Servizio per impostare il valore Campo lo faccia effettivamente. Lo vedo come un grosso inconveniente; tutto ciò che sembra prendere è qualcuno che scrive "thisField.setValue (thatField.getValue ())" e la Validation Rule di thisField potrebbe essere violata senza che nessuno ne sia il più saggio. Questo potrebbe potenzialmente essere mitigato assicurandosi che il valore del campo corrisponda alla regola di convalida quando il livello di accesso ai dati sta per persistere nel campo.
Al momento preferisco l'opzione n. 1 rispetto all'opzione n. 2, principalmente perché la considero una logica aziendale e ritengo che l'opzione n. 2 rappresenti un rischio maggiore di introdurre dati errati nel sistema. Quale opzione preferisci o esiste un altro design che si adatti a questo scenario meglio delle due opzioni descritte?
Modifica (complessità delle convalide)
I casi di validazione che sono emersi per ora sono relativamente semplici; il valore del campo deve essere ad es. numerico, una data, una data con un orario o un valore esistente in una colonna del database. Tuttavia, sospetto che la complessità aumenti gradualmente nel tempo. Ad esempio, la soluzione di convalida deve essere costruita tenendo conto dell'internazionalizzazione: elementi come Date possono essere inseriti in una sintassi specifica della locale.
Ho deciso di procedere con l'Opzione 1 per ora, cercando di non assegnare troppe responsabilità al Modello di Dominio. Coloro che affrontano una situazione simile possono anche voler controllare le domande correlate Convalida e autorizzazione in architettura a strati e Validazione dell'input dei dati - Dove? Quanto? .